Draw rank plot for exploration

Hello

I want to get values of AddRankColumn function for all days to draw a plot showing how an instrument is changing rank among others with a certain period.

i searched for this online and in documentation and didn't find anything that can help.

Example

Exploration on time range 1-1-2017 to 1-1-2018, i expect to get value for each day indicating the rank of the instrument between all other instruments in a certain performance score.

Regards,

Use StaticVargenerateRanks
https://www.amibroker.com/guide/h_ranking.html

1 Like

Dear Team,

2 slight modifications to the above are:

  1. Running ranking on a WATCHLIST. I tried coding it on base example 1 given in the manual at
    Amibroker StaticVar Get Ranks

and

https://www.amibroker.com/guide/h_ranking.html

I just included the WATCHLIST using the following code:

	
/////////////////////////////////
// Example 1. code for normal ranking mode
// (everything done is done in one pass, can be used in indicator):
/////////////////////////////////

//symlist = "C,CAT,DD,GE,IBM,INTC,MSFT";

/// Set symbol list in Analysis Filter - Include
if ( GetOption( "ApplyTo" ) == 2 )
{
     wlnum = GetOption( "FilterIncludeWatchlist" );
     SymList = CategoryGetSymbols( categoryWatchlist, wlnum ) ;
}
else
if ( GetOption( "ApplyTo" ) == 0 )
{
     SymList = CategoryGetSymbols( categoryAll, 0 );
}
else
{
     Error( "The formula works fine if your ApplyTo setting is 'Filter' or 'All' " );
}


// delete static variables - DO NOT forget the asterisk (wildcard) at the end
StaticVarRemove( "ValuesToSort*" );

// fill input static arrays

for ( i = 0; ( sym = StrExtract( symlist, i ) ) != ""; i++ )
{
    SetForeign(sym );
     Value = ROC( C, 10 );
    RestorePriceArrays();
    StaticVarSet( "ValuesToSort" + sym, Value );
}

// perform ranking
StaticVarGenerateRanks( "rank", "ValuesToSort", 0, 1224 ); // normal rank mode

// read ranking
for ( i = 0; ( sym = StrExtract( symlist, i ) ) != ""; i++ )
{
    Plot( StaticVarGet( "RankValuesToSort" + sym ), sym, colorCustom10 + i );
}

So far so good, but the problem starts as the Plot is showing rank chart for all symbols in the watchlist in the same pane.

Ranking Test

What I would like is that Watchlist gets defined in the Filter Window or maybe through PARAM (Not very sure on this), however plot only shows the rank chart of current symbol (if it is part of the watchlist)

  1. The next level is to get RANKS as to calculate the percentage returns for each day with respect to close of a starting date say 01/02/2020.

I tried browsing through the lists under SEARCH, but seem to get onto a roadblock.

@pushkan, in the chart, to plot only the current symbol, change the code to:

// read ranking
Plot( StaticVarGet( "RankValuesToSort" + Name()), "Rank", colorRed);

(There is no plot for symbols that are not in the watchlist - Rank will be {empty})

1 Like

@beppe It worked to same extent, but is throwing up certain pitfalls:

The modified afl is as follows:

	
/// Set symbol list in Analysis Filter - Include, Use SCAN once in Analysis Window

	if ( GetOption( "ApplyTo" ) == 2 )
	{
     wlnum = GetOption( "FilterIncludeWatchlist" );
     SymList = CategoryGetSymbols( categoryWatchlist, wlnum ) ;
	}
	else
	if ( GetOption( "ApplyTo" ) == 0 )
	{
     SymList = CategoryGetSymbols( categoryAll, 0 );
	}	
	else
	{
     Error( "The formula works fine if your ApplyTo setting is 'Filter' or 'All' " );
	}


// From Date
fromdate = StrToDateTime( ParamDate("Start Date", "2020-03-24", 1 ) ); 
fromdatestr = DateTimetoStr(fromdate);
enddate = StrToDateTime( ParamDate("End Date","2022-08-25", 1 ) ); 
enddatestr=DateTimetoStr(enddate);


// delete static variables - DO NOT forget the asterisk (wildcard) at the end
StaticVarRemove( "ValuesToSort*" );

// fill input static arrays

for ( i = 0; ( sym = StrExtract( symlist, i ) ) != ""; i++ )
{
    SetForeign(sym );
      fromC = Lookup( Close, fromdate, -1 ); 
      endC = Lookup( Close, enddate, -1 ); 
	  //absreturn = endC-fromC; 
	  absreturn = C-fromC; 
	  perreturn = absreturn/fromC*100;
      value = perreturn;
      RestorePriceArrays();
      StaticVarSet( "ValuesToSort" + sym, Value );
}

// perform ranking
StaticVarGenerateRanks( "rank", "ValuesToSort", 0, 1224 ); // normal rank mode
Plot( StaticVarGet( "RankValuesToSort" + Name()), "Rank", colorRed);


I need to RUN an explore or a scan everytime I want to plot the chart for a different symbol (Even though part of the watchlist) , as the new symbol shows it as EMPTY or 1. Going back to the same symbol (using left & right arrow) the chart vanishes.

Is there a way to pass the Watchlist or Select as a PARAM and utilise " AFL Function Reference - INWATCHLISTNAME

InWatchListName

The exploration for the same is as follows:

/// Set symbol list in Analysis Filter - Include
if ( GetOption( "ApplyTo" ) == 2 )
{
     wlnum = GetOption( "FilterIncludeWatchlist" );
     List = CategoryGetSymbols( categoryWatchlist, wlnum ) ;
}
else
if ( GetOption( "ApplyTo" ) == 0 )
{
     List = CategoryGetSymbols( categoryAll, 0 );
}
else
{
     Error( "The formula works fine if your ApplyTo setting is 'Filter' or 'All' " );
}


fromdate = StrToDateTime( ParamDate("Start Date", "2020-03-24", 1 ) ); 
fromdatestr = DateTimetoStr(fromdate);
enddate = StrToDateTime( ParamDate("End Date","2022-08-25", 1 ) ); 
enddatestr=DateTimetoStr(enddate);


if ( Status("stocknum") == 0 ) // GENERATE RANKING WHEN WE ARE ON VERY FIRST SYMBOL
{
    StaticVarRemove( "values*" );

    for ( n = 0; ( Symbol = StrExtract( List, n ) )  != "";  n++    )
    {
        SetForeign ( symbol );
        fromC = Lookup( Close, fromdate, -1 ); 
		endC = Lookup( Close, enddate, -1 ); 
		absreturn = endC-fromC; 
		perreturn = absreturn/fromC*100;
        values = perreturn;
        RestorePriceArrays();
        StaticVarSet (  "values"  +  symbol, values );
        _TRACE( symbol );
    }

    StaticVarGenerateRanks( "rank", "values", 0, 1224 );
}

symbol = Name();

values = StaticVarGet ( "values" +  symbol );
rank = StaticVarGet ( "rankvalues" +  symbol );

SetOption("NoDefaultColumns", True);

AddTextColumn(Name(),"Ticker");
AddTextColumn(fromdatestr,"FromDate");
AddColumn(Lookup( Close, fromdate, -1 ),"StartC",1.2);
AddTextColumn(enddatestr,"ToDate");
AddColumn(C,"CurrentC",1.2);
AddColumn ( values, "Per%",1.2 );
AddColumn ( rank, "rank",1.0 );


Filter = 1;

SetSortColumns(7);

I have another afl with similar outlay, though with counter calculation instead of ranking

@pushkan I think you must isolate the scan/explore code (used to create the ranks) from the indicator (using the value of Status("action"); in such a way you'll NOT reset (invalidate) the saved staticvars and each symbol that is part of the playlist used to create the ranking will be able to retrieve the saved static vars and display that values in a chart.

By the way, if you have upgraded Amibroker to version >= 6.40.2 you can use the new #pragma sequence(scan,explore) (see this example) to perform the task faster without the need of SetForeign().
In the "scan" part (when 'stocknum' is zero) clear the static vars and then do the calculations/save the static vars; in the "explore" (again when 'stocknum' is zero) do the ranking.
Finally, add a section for action=actionIndicator that will only plot the retrieved static vars in a chart.
Do run the "sequence once", then apply the formula to a chart to execute the "indicator" code.

Moreover, I suggest using the scan/exploration "from" date to evaluate the relative performance.
Check also your calculation formula; IMO it should be:

  fromClose = Lookup( Close, fromDate, -1 );  // a scalar value
  absReturn = Close - fromClose;              // an array
  relPerformancePercent = absReturn / fromClose * 100;  // an array

In both approaches, it is opportune to "nullify" the calculated values that are outside the scan/explore selected date range for plotting purposes.

@beppe just a quick check, am reproducing the code from stocks above a moving average

https://forum.amibroker.com/t/percentage-stock-price-nyse-above-the-200-day-moving-average/19377/8

/// Set symbol list in Analysis Filter - Include
/// And enable pad&align
/// Set Periodicity in analysis General settings
/// Create composite ARRAY via SCAN 
/// @link https://forum.amibroker.com/t/percentage-stock-price-nyse-above-the-200-day-moving-average/19377/8
/// by AmiBroker.com and fxshrat@gmail.com
list_name = CategoryGetName(categoryGroup, 5);
symbol_name = "~AboveMA_"+list_name;
cnt = "~cnt_"+list_name;
periods = MxFromString("[20;50;200]");// MA periods
rows = MxGetSize(periods, 0);
persist = False;
if ( Status( "action" ) == actionScan ) 
{
    /// derived from AB manual
    /// @link https://www.amibroker.com/guide/afl/staticvaradd.html
    if ( Status( "stocknum" ) == 0 ) 
    {
        // remove any earier composite values
        StaticVarRemove(symbol_name+"*");
        StaticVarRemove(cnt);
    }   
    // Iterating periods
    for ( i = 0; i < rows; i++ ) 
		StaticVarAdd(symbol_name+"_"+ i, C >= MA(C, periods[i][0]), True, persist);
		StaticVarAdd(cnt, 1, True, persist);
    Buy = 0;
}

AddColumn(C,"Close",1.2);
colors = "colorGreen,colorBlue,colorRed";
// Iterating periods
for ( i = 0; i < rows; i++ ) 
{
	Stocks_aboveMA = Nz(StaticVarGet(symbol_name+"_"+i));
	WeekStocks=ValueWhen(DayOfWeek() > Ref( DayOfWeek(),1),Stocks_aboveMA);
	pcnt_aboveMA = Nz(StaticVarGet(symbol_name+"_"+i) / StaticVarGet(cnt))*100;
	titles = StrFormat("Percentage > %g-day MA", periods[i][0]);
	Plot(pcnt_aboveMA, titles, VarGet(StrExtract(colors,i)), styleThick);
	Filter = 1;
	AddColumn(Stocks_aboveMA,"Count+"+periods[i][0],1.0);
	AddColumn(pcnt_aboveMA,"Percent"+periods[i][0],1.2);
}
Plot(10,"10 L",colorBlack,styleLine | styleNoTitle);
Plot(30,"30 L",colorBlue,styleLine | styleNoTitle | styleDashed);
Plot(50,"50 L",colorBlack,styleLine | styleNoTitle);
Plot(70,"70 L",colorBlue,styleLine | styleNoTitle | styleDashed);
Plot(90,"90 L",colorBlack,styleLine | styleNoTitle);


SetSortColumns(-2);


Would putting in similar loop help?

@pushkan, essentially yes.

You will use a "scan" to create/calculate some staticVars and reuse them in other formula sections (using conditionals based on the 'action'). Scan, using all the available threads, is faster than looping over one watchlist's symbols using 'foreign()' (that is constrained to a single thread).

As said, if you need also to do some ranking, you can use an "explore" section to perform it (when 'stocknum' is zero).

Finally your formula can contain another section (actionIndicator) with additional specific code to plot results.