Generate ranks on subset of list

Hi Guys,

I'm trying to generate ranks for a subset of stocks that pass a certain filter. The code I have pasted below is just dummy code to help me ask my question. If I want to rank stocks based on my 'Rank' variable but I only want to rank stocks that pass the 'Cond' filter, the code below achieves that but it requires me to duplicate code i.e. I need to define my 'Cond' filter both inside and outside the loop that saves the static variables. I feel like there must be a more efficient way to do this so that I don't need to duplicate code. Can anyone offer any insights?

Regards,
William

MyATR = ATR(30);
Cond = MyATR > 0.33;

List = CategoryGetSymbols( categoryWatchlist, 18 );
 
if ( Status("stocknum") == 0 ) // Generate ranking when we are on the very first symbol
{
     StaticVarRemove( "values*" );

     for ( n = 0; ( Symbol = StrExtract( List, n ) )  != "";  n++    )
     {
         SetForeign ( symbol );
        
		 Vol = ATR(10);
		 Rank = PercentRank(Vol,10);
		 
		 MyATR = ATR(30);
		 Cond = MyATR > 0.33;
		 
		 RankFiltered = IIf(Cond,Rank, -10000); 
		 
         RestorePriceArrays();
         StaticVarSet (  "values"  +  symbol, Rank );
       
     }

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

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

AddColumn(MyATR,"MyATR");

The answer depends somewhat on why you're doing StaticVarGenerateRanks in the first place, but if we assume that you want to use the rank outside the loop then your condition is already inherent in the rank itself, right? In other words, if you have a Buy condition that requires the rank to be in the Top N, then that is unlikely to be true for any symbol that did not satisfy cond.

Notice that I said "is unlikely" and not "cannot". If you think it's possible to have a symbol with an acceptable rank but which did not meet the condition cond, then you will either need to save it in a static variable during the ranking loop, or you will need to calculate it twice.

By the way, I think that this:

StaticVarSet (  "values"  +  symbol, Rank );

should probably be:

StaticVarSet (  "values"  +  symbol, RankFiltered);

which also solves your problem. When you retrieve values using this:

values = StaticVarGet ( "values" +  symbol );

it will always be the case that when values < 0 then cond was false, correct?

1 Like

Hi Mradtke,

Yes you're right, the stocks that are top ranked are most likely to have passed Cond so from the point of view of a backtest there is no problem. If I run an exploration, however, and I want to see the values of MyATR (for example) I either have to define it twice or save it to a static variable in the loop and retrieve it again afterwards. If this is the way that it is typically done then I'm fine with that, I just wanted to make sure I wasn't missing something.

You're also right about the fact that it should be RankFiltered but this was essentially just a typo when I created this code to post.

Thanks for your help!

Regards

Yes, in that scenario I think your choices are "save and retrieve" or "recalculate". Which of those is preferable will depend on how many symbols you're processing (i.e. how much memory will be consumed with the extra static variables) as well as how "expensive" the recalculation is.

1 Like

Hello,

I'm trying to programing your code, but i need to include 5 diferents watchlist with diferent ROC and price crossing de SMA 7. Ej

Watchlist 1 (ROC 3) and price cross SMA(C,7)
Watchlist 2 (ROC 3) and price cross SMA(C,7)
Watchlist 3 (ROC 6) and price cross SMA(C,7)
Watchlist 4 (ROC 9) and price cross SMA(C,7)
Watchlist 5 (ROC 9) and price cross SMA(C,7)

And after that is calculated, i need to score and make a ranking of TOP10 best ROC crossing SMA7.

  1. For include in your formula more watchlist, jus i write more AFL ? like this:
List = CategoryGetSymbols( categoryWatchlist, 1 );
 
if ( Status("stocknum") == 0 ) // Generate ranking when we are on the very first symbol
{
     StaticVarRemove( "values*" );

     for ( n = 0; ( Symbol = StrExtract( List, n ) )  != "";  n++    )
     {
         SetForeign ( symbol );
        
		ROC3= ROC(C,3)
                 SMA=(C,7)
                 cross=(C,SMA)
		
		 
         RestorePriceArrays();
         StaticVarSet (  "values"  +  symbol, Rank );
       
     }

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

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

List2 = CategoryGetSymbols( categoryWatchlist, 2 );
 
if ( Status("stocknum") == 0 ) // Generate ranking when we are on the very first symbol
{
     StaticVarRemove( "values*" );

     for ( n = 0; ( Symbol = StrExtract( List, n ) )  != "";  n++    )
     {
         SetForeign ( symbol );
        
		ROC6= ROC(C,6)
                 SMA=(C,7)
                 cross=(C,SMA)
		
		 
         RestorePriceArrays();
         StaticVarSet (  "values"  +  symbol, Rank );
       
     }

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

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

//Programing several times as watchlist we have like above????
.
.
.
.
.

//Now score the ranking TOP10 best ROC simbols >0 and cross C, SMA7

PositionScore = xxxxx; //THIS IS REQUIRED , but i don't know how can i score the best 10 symbol of 5 watchlist

``


Thanks verymuch for you big information,

Best

It will take time for the Full version of the post, but while you are at it, this is absolutely not the right approach.

  1. Using Two separate blocks of if ( Status("stocknum") == 0 ) does not serve any purpose.

  2. In the First single thread, doing this SetForeign ( symbol ); is computationally very inefficient

  3. Two separate stocknum == 0 blocks will just add to the misery

ROC6= ROC(C,6)
SMA=(C,7)

and

ROC3= ROC(C,3)
SMA=(C,7)

If you make 5 such, its an overkill. Haven't tried it, but today I sure will to see what the AFL Engine does.

  1. Also, the syntax isn't correct, need to terminate each line with :

  2. Running so many symbols as Foreign() has the risk of re-aligning original data thereby distorting the results

You are better off running a separate AFL in multithread way (as is by default) with all the symbols, no need of Foreign().
and then apply The ROC and MA check for each case, that is ROC 3,6,9 and add them programmatically to a Watchlist.

In the 2nd AFL, you can use the ready watchlist and generate Ranks in a single thread.

Running multiple AFL can be achieved using Batch processing.

1 Like

Thanks por your quick reply,

Just I need programing a "Rotational TOP10 System" calulating diferents ROC for any 5 wachlist symbols (ETFs) group, and crossing MA7 for all 5 Watchlis group.

May be i'm not doing the correct AFL codification... and is more easy than my last menssage.

Do you know other way to do it?

Best

Doing that simple code is posible get the same?

if (inWatchlist(1))
{
   ROC3 = (C ,3);
MA7=(C,7);
cross=(C,MA7)
}
if (inWatchlist(2))
{
    ROC6 = (C ,6);
MA7=(C,7);
cross=(C,MA7)
}
.
.
.
watchlist3
.
.
.
watchlist4
// the same in all watchlist a need to calculate diferents ROC