Understanding "How to use StaticVarGenerateRanks in Analysis window"

Hello everybody,
I try to understand "How to use StaticVarGenerateRanks in Analysis window" example from Amibroker Help and not sure if I get the rankig part right. Would apprichiate if someone could agree, disagree and/or comment.

01. if ( Status("stocknum")== 0 ) //GENERATE RANKING WHEN WE ARE ON VERY FIRST SYMBOL 
02. { 
03.    StaticVarRemove( "values*" ); 
04.
05.    for (n = 0; ( Symbol = StrExtract(List, n ) )  != "";  n++    ) 
06.    { 
07.        SetForeign (symbol ); 
08.        values = RSI(); 
09.        RestorePriceArrays(); 
10.        StaticVarSet (  "values"  +  symbol,values ); 
11.        _TRACE(symbol ); 
12.    } 
13.
14.    StaticVarGenerateRanks( "rank", "values", 0, 1224 ); 
15. }

Line 01.: we are making sure, that ranking is done only if symbol with index 0 (first symbol in the database or in selected watchlist) is selected. Without it the following for-loop (5. - 12.) would be executed for every symbol in database or watchlist, which is not neccesary as we would get exactly the same rankings.

Line 03.: remove all static variables

Line 05.: we initialize a loop over all tickers in database/watchlist and assign them to a variable Symbol one after other.

Line 07.: we replace current price arrays with arrays form ticker stored in variable Symbol.
My questions here are, why do we call "symbol" instead of "Symbol" and in case of n=0 we actually do not have to replace arrays as we have them already?

Line 08.: calculate RSI array

Line 09.: restore price arrays. With this we get price arrays from first ticker from database or watchlist. My question here is, why we have to do this? Would it not be enough to get new arrays with SetForeign(symbol) for next n in the for-loop?

Line 10.: we assing RSI values to valuesSymbol. My question here is, is valuesSymbol ticker an array and if so can I operate on it like on default price arrays, e.g. calculate avarages, etc.?

Line 11.: ouput symbol to log window. My question here is, why I do not see any output in my log window even though Preferences > AFL > _TRACE() output > Internal is activated

Line 14.: generate ranking and store it in rank. Also here, is this an array and if so can I operate on it like on default price arrays?

Sorry for my long post but I feel it is essential to understannd the basic concepts before takling complex tasks like becktesting.

Thanks in advance!

1 Like

I get the impression that people tend to copy-paste codes from the web without thinking and reading the docs.

Please DO READ Users' Guide on ranking

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

It must be stressed out that StaticVarGenerateRanks is NOT intended to be used for backtesting when you have just one "score" (in this case RSI). For that purpose you should use PositionScore - it is the "first kind of ranking" and it is fastest, easiest and recommended over everything else if you just have one score (like in this case).

If you used PositionScore as you should, the entire formula for ranking in the backtest would be just one line:

PositionScore = RSI(); // that is all you need for ranking in backtest

StaticVarGenerateRanks is "last resort" function, that should be used if and only if, there is no other way.

By all means, copy-pasting codes using StaticVarGenerateRanks everywhere is bad and should be avoided. Use simpler and faster method (PositionScore) whenever possible.

Good morning Tomasz,
Thank you for your response and sorry for my maybe misleading sentence about backtesting. As you stated out and I already read in the docu, general ranking is not the recommended way to do ranking in a backtest and once should use PositionScore instead. My goal here is to rank a universe of stocks and to plot this ranks as indicator below price chart. So no backtesting with general ranking.

Regarding ranking with PositionScore, another idea I had was to generate a buy signal with condition Close > 0 (to make sure every stock will have a buy on every bar) and then plot PositionScore values below the price chart. Would you recommend to go this way?

With my post I hope to get some help in understanding of general AFL concepts (therefore my comments and questions line by line) and I really appreciate your and everyone's help

Thanks in advance!

Your first post talked about "backtesting". The subject line is also using ranking in ANALYSIS window.

Now you talk about chart. Chart != Analysis. Charts generally don't use Analysis-specific variables (like those explained here Scan vs Exploration vs Backtest - summary of differences)

As I wrote - PositionScore is for backtesting, not for charts. Ranking is an built-in process during backtesting. It does not occur in chart because in chart you are just using ONE symbol (currently selected).
If you want to Plot rankings, you should follow the manual Ranking features that clearly says:

WARNING: this function is computationally and memory intensive. It takes about 20ms per 15K bars and 7 symbols. Try to call it just once per scan/exploration/backtest using if( Status("stocknum")==0) or better yet, use separate scan just once to pre-calculate ranks and use it later (like composite creation scan).

So as advised, you should have TWO SEPARATE formulas. One formula that generates ranks and it is used JUST ONCE and creates static variable. And second formula that plots previously per-calculated values. You should NOT be calculating ranks non-stop in single formula.

Formulas are given in the manual. Just divide them into two parts. The second part (for chart) should just read pre-calculated value:

// just read the ranking - don't do any calculation
Plot( StaticVarGet( "RankItemScore" +Name() ), "Ranking", colorDefault ); 

Hello Tomasz,
thank you for your clarification. I see, that I should be more specific in my postings. Will try to do so :wink:

Have you perhaps an idea why I do not see any output in log window from _TRACE(symbol) function?
In a first step I stripped down the code form help to:

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' " );
}

for ( n = 0; ( Symbol = StrExtract( List, n ) )  != "";  n++    )
{
    _TRACE(symbol);        
}

and ran an exploration on a watchlist with 10 symbols. Like mentioned above Preferences > AFL > _TRACE() output > Internal is activated. There is no output in log window. Using DebugView I can see _TRACE(symbol) output as expected.

If DebugView works, so internal window should too. In fact you can enable both at the same time. As for internal window Make sure you switch to "Trace" tab

Have not seen the forest for the trees ... In Trace tab everything works as expected!

Thanks!

This topic was automatically closed 100 days after the last reply. New replies are no longer allowed.