// top-ranked-symbols.afl
// Part 13 - StaticVarGenerateRanks() and Top-N Selection
//
// A chart pane that names the strongest and weakest symbols of a small
// universe at the bar you click on. It follows the documented one-pass
// indicator pattern: clear, score, generate, read - all in one execution.
//
// Assumptions declared up front:
//   - This re-ranks the entire list on EVERY chart redraw. The documentation
//     measures the ranking function at roughly 20 ms per 15,000 bars and 7
//     symbols, so keep the list short. Twenty symbols is comfortable; five
//     hundred is not, and belongs in an Analysis run instead.
//   - Top and bottom mode store INDEXES into a companion list, not scores and
//     not tickers. StaticVarGetRankedSymbols does that lookup for you.
//   - Ranks count from ONE.
//   - The list is taken from a watch list unless you type symbols yourself.

_SECTION_BEGIN( "Top ranked symbols" );

InputPrefix  = "P13ChartScore";
NormalPrefix = "P13ChartRank";
TopPrefix    = "P13ChartTop";
BottomPrefix = "P13ChartBottom";

TypedList    = ParamStr( "Symbols (comma separated, blank = watch list)", "" );
WatchListNum = Param( "Watch list number", 0, 0, 200, 1 );
ScorePeriod  = Param( "Momentum lookback (bars)", 126, 20, 500, 1 );
HowMany      = Param( "How many at each end", 3, 1, 20, 1 );

if( TypedList == "" )
    SymbolList = CategoryGetSymbols( categoryWatchlist, WatchListNum );
else
    SymbolList = TypedList;

// Clear first. Every one of these names is shared with every other formula in
// this AmiBroker, so a stale entry is not a local problem.
StaticVarRemove( InputPrefix + "*" );
StaticVarRemove( NormalPrefix + InputPrefix + "*" );
StaticVarRemove( TopPrefix    + InputPrefix + "*" );
StaticVarRemove( BottomPrefix + InputPrefix + "*" );

for( i = 0; ( Sym = StrExtract( SymbolList, i ) ) != ""; i++ )
{
    if( SetForeign( Sym ) )
    {
        SymbolScore = ROC( Close, ScorePeriod );
        RestorePriceArrays();
        StaticVarSet( InputPrefix + Sym, SymbolScore );
    }
}

// Three calls, three modes. Normal mode gives every symbol its own rank array;
// positive topranks builds the top-N table; negative topranks builds the
// bottom-N table.
StaticVarGenerateRanks( NormalPrefix, InputPrefix, 0, 1224 );
StaticVarGenerateRanks( TopPrefix,    InputPrefix,  HowMany, 1224 );
StaticVarGenerateRanks( BottomPrefix, InputPrefix, -HowMany, 1224 );

OwnRank = StaticVarGet( NormalPrefix + InputPrefix + Name() );

Plot( OwnRank, "Rank of " + Name(), colorBlue, styleLine | styleThick );

// The ranked-symbol lookup is per date/time, not per array, so it answers for
// the bar you have selected on the chart and no other.
SelectedDate = SelectedValue( DateTime() );

Title =
    "Universe: " + NumToStr( StrCount( SymbolList, "," ) + 1, 1.0 ) + " symbols   " +
    "lookback " + NumToStr( ScorePeriod, 1.0 ) + " bars" + "\n" +
    Name() + " rank: " + WriteVal( OwnRank, 1.0 ) + "\n" +
    "Strongest: " + StaticVarGetRankedSymbols( TopPrefix, InputPrefix, SelectedDate ) + "\n" +
    "Weakest: "   + StaticVarGetRankedSymbols( BottomPrefix, InputPrefix, SelectedDate );

_SECTION_END();
