Average value for the n best ranked tickers from a watchlist

Hello,

I would need to calculate an average value for the n best tickers of a watchlist, for example the average ROC for the 10 tickers with the highest ROC from the list.

I am able to calculate the average value for the whole list and also rank the tickers according to its ROC, the code could be the following one:


WatchList  = GetOption("FilterIncludeWatchlist");
List       = GetCategorySymbols(categoryWatchlist, WatchList);

// --- Ranking ---

if (Status("Stocknum") == 0 )
  { 
  StaticVarRemove("Score*" );
  for (n = 0;(Symbol = StrExtract(List, n)) != ""; n++) 
  	{ 
  	SetForeign (Symbol);
  	ROCValue = ROC(Close, 12);
  	RestorePriceArrays();
  	StaticVarSet ("Score" + Symbol, ROCValue);
  	} 
  StaticVarGenerateRanks("Ranking","Score", 0, 1224); 
  } 
  	
Symbol        = Name();
SymbolROC     = StaticVarGet ("Score" + Symbol); 
SymbolRanking = StaticVarGet ("RankingScore" + Symbol);

// --- Average ROC for the entire watchlist ---

if(Status("stocknum") == 0)
  {
  StaticVarRemove("~ROC*" );	
  for (n = 0;(Symbol = StrExtract(List, n)) != ""; n++) 
  	{
  	SetForeign (Symbol);
  	ROCValue = ROC(Close, 12);
  	RestorePriceArrays(); 
  	StaticVarAdd("~ROCTotal", ROCValue);	
  	StaticVarAdd("~ROCQuantity", 1);
  	} 	
  } 	
  
AverageROC = StaticVarGet("~ROCTotal") / StaticVarGet("~ROCQuantity");

// --- Average ROC for the best 10 tickers from the watchlist ---

// ??????

However, I am unable to find the way to combine both conditions to make it work properly. I should appreciate it if someone would help with this.

Thank you berforehand.

Best regards.

1 Like

I can't write and test the code right now but i would not use your approach.

step 1: You are using Normal ranking mode, StaticVarGenerateRanks("Ranking","Score", 0, 1224);
Instead,
StaticVarGenerateRanks("Ranking","Score", 10, 1224);
// top-N mode from the Manual
but the For loop is the same

step 2: Again from the manual

ldt = LastValue( DateTime() );
strSymRanked = StaticVarGetRankedSymbols( "top", "ValuesToSort", ldt );

Retrieves the comma-separated list of symbols from static variables generated using StaticVarGenerateRanks

step 3:
for( i = 0; ( sym = StrExtract( strSymRanked, i ) ) != ""; i++ )
Iterate over the retrieved list which is Top-10 ranked and compute the average or anything desired.

Upper code is incorrect.
It looks like copy&pasting incorrect code floating around here.
Please follow AB help.

StaticVarAdd is not supposed to be used within loop iterating symbol list.

In addition example of creating average of a selected category via StaticVarAdd has been posted here.
https://forum.amibroker.com/t/how-to-calculate-daily-average-return-of-a-group-sector-sub-sector-and-show-in-exploration/18174/2

nsm51,

Thank you for your answer. I have made the changes you proposed and now it works properly. The tested code would be the following one:


WatchList  = GetOption("FilterIncludeWatchlist");
List       = GetCategorySymbols(categoryWatchlist, WatchList);

// --- Ranking ---

if (Status("Stocknum") == 0 )
  { 
  StaticVarRemove("Score*" );
  for (n = 0;(Symbol = StrExtract(List, n)) != ""; n++) 
  	{ 
  	SetForeign (Symbol);
  	ROCValue = ROC(Close, 12);
  	RestorePriceArrays();
  	StaticVarSet ("Score" + Symbol, ROCValue);
  	} 
  StaticVarGenerateRanks("Ranking","Score", 0, 1224); 
  StaticVarGenerateRanks("Top","Score", 10, 1224); 
  } 
  	
Symbol        = Name();
SymbolROC     = StaticVarGet ("Score" + Symbol); 
SymbolRanking = StaticVarGet ("RankingScore" + Symbol);

// --- Average ROC for the Top 10 Symbols ---

ldt = LastValue( DateTime() );
strSymRanked = StaticVarGetRankedSymbols( "Top", "Score", ldt );

if(Status("stocknum") == 0)
  {
  StaticVarRemove("~ROC*" );	
  for (n = 0;(Symbol = StrExtract(strSymRanked, n)) != ""; n++) 
  	{
  	SetForeign (Symbol);
  	ROCValue = ROC(Close, 12);
  	RestorePriceArrays(); 
  	StaticVarAdd("~ROCTotal", ROCValue);	
  	StaticVarAdd("~ROCQuantity", 1);
  	} 	
  } 	
  
AverageROC = StaticVarGet("~ROCTotal") / StaticVarGet("~ROCQuantity");

// --- Filter ---

Filter = SymbolRanking <= 10; 
AddColumn(SymbolRanking, "Rank", 1.2);
AddColumn(SymbolROC, "ROC", 1.2);
AddColumn(AverageROC, "Average", 1.2);

I have made a quick exploration just to be sure of the results, and I got the right average value for the top 10 symbols as intended.

Image 001

Best regards.

fxshrat,

Thank you for your answer. I'm no sure if I have understood about StaticVarAdd not being supposed to be used within loop iterating symbol list.

If cancel the loop and keep the code as in https://www.amibroker.com/guide/afl/staticvaradd.html, for each symbol I would get the average value which was calculated until that symbol, wouldn't I? At least if a do an exploration I would find that. For example:

ROCValue = ROC(Close, 12);

if(Status("stocknum") == 0)
  {
  StaticVarRemove("~ROC*" );	
  }

StaticVarAdd("~ROCTotal", ROCValue);	
StaticVarAdd("~ROCQuantity", 1);
  
AverageROC = StaticVarGet("~ROCTotal") / StaticVarGet("~ROCQuantity");

// --- Filter ---

Filter = 1; 
AddColumn(ROCValue, "ROC", 1.2);
AddColumn(AverageROC, "Average", 1.2);

Image 002

I've revised the proposed entry How to calculate daily average return of a group (sector, sub sector) and show in exploration, but If I've understood it correctly, in that occasion you were calculating an average for a whole category. What I'm trying now is calculing the average value for a limited number of symbols within a category. Probably there is a connection between both cases, but I'm unable to figure it out.

Best regards.

No! I have posted link to creating average using StaticVarAdd. Obviously you don't really care and rather try to be (newbie) smart instead of actually listen. That's why you continue to create code from hell.

Rather listen to said words and please read carefully.

Your code is still incorrect.
As Tomasz wrote here...What you do is abuse!

But I guess you want to try to be smarter than the developer of AmiBroker in addition.

I know exactly what you try to do.
And it does not make any difference.
You just don't know what you are doing and how to solve it properly.
E.g. have you ever head of e.g. CategoryAddSymbol?

And even if you remain using Setforeign within loop you still do not need Staticvaradd and worse you do not put inside loop!

// .... 
// Snippet

ldt = LastValue( DateTime() );
strSymRanked = StaticVarGetRankedSymbols( "Top", "Score", ldt );

if( Status( "stocknum" ) == 0 )
{
    ROCValue = 0;
    for( n = 0; ( Symbol = StrExtract( strSymRanked, n ) ) != ""; n++ )
    {
        SetForeign( Symbol );
        ROCValue += SelectedValue(ROC( Close, 12 ));
        RestorePriceArrays();
    }    
    StaticVarSet("~ROCTotal", ROCValue);
}	
  
n = StrCount(strSymRanked,",")+1;
AverageROC = Nz(StaticVarGet("~ROCTotal")) / n;

/// .....

But again... it can be done without looping.

Please eventually understand that. Please listen and follow advice to create proper code.
Right now your attempts create rather nightmarish code.

1 Like

fxshrat,

Thank you for answer, although I think all the value judgments were innecessary.

Sorry for creating code from hell, I'm learning. I don't pretend to be smarter than anyone, let alone pretending to be smarter than the developper of Amibroker...

You have to take into account that something that is obvious for an expert like you could be completely out of knowledge for a newbie like me. Consequently, if I reach wrong conclusions it doesn't mean that I don't care what I was answered. Sometimes it's difficult to me to understand because I haven't got the necessary knowledge yet. That's why I am here trying to get the answers that I'm unable to get on my own, after reading the related entries in the manual and looking for examples in this forum.

Anyway, thank you for the further explanation and the given code, of course it works perfectly.

Best regards.

I already wrote here the first time...

... that what you did is incorrect. But still you repeated it in next post.
So to me you gave impression that you did not care nor did not believe that it is incorrect.
Otherwise you would not have repeated the same mistake again but would have given more effort in using forum search.

1 Like

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