Run explorer to get signals within top rank watchlist using matrix

hi guys,
i am developing a strategy, this strategy will filter a watchlist based on the performance ranking system using the matrix function. Then the buy and sell signals will be applied to this watchlist.
The problem is that i can't test this system using explorer, when i select from-to-date, it only works if the start date and end date are the same. If i select a time period, it will only calculate based on the watchlist created on the end date.
Is there any way to fix this problem


tickerlist =  CategoryGetSymbols( categoryWatchlist, 0 );
sym_num = StrCount(tickerlist, ",")+1;
mat = Matrix(sym_num, 2);

for ( i = 0; ( symbol = StrExtract( TickerList, i ) ) != ""; i++ )
{
	SetForeign(symbol);
	fc = C; 
	Vol = V;
	VolTB = MA(V,50);
	RestorePriceArrays();
	fc = SelectedValue(fc);
	VolTB = SelectedValue(VolTB);
	GTGD = fC*VolTB;
	mat[i][0] = i; 
	mat[i][1] = GTGD; 
}

mat0 = MxSortRows(mat, False, 1); //sort GTGD value
sym_list = "";
topkl = sym_num*0.1;	 
	for ( i = 0; i < topkl ; i++ ) //Top 10% symbols
{
	n0 = mat0[i][0];
	symbol = StrExtract(tickerlist, n0);
	sym_list += symbol+",";
}
sym_list = StrTrim( sym_list, ",", 2 ); // trim separator at the end
//assign new matrix

mat1 = Matrix(topkl,5);
for ( i = 0; ( symbol = StrExtract( sym_list, i ) ) != ""; i++ )
{
	SetForeign(symbol);
	roc1 = ROC(C,10);
	roc2 = ROC(C,20);
	roc3 = ROC(C,65);
	roc4 = ROC(C,125);
	barabovema50 = BarsSince(Close < EMA(Close,50));
	RestorePriceArrays();
	if (SelectedValue(roc1) > 0 AND SelectedValue(roc2) > 5 AND 
	SelectedValue(roc3) > 20 AND SelectedValue(roc4) > 5  AND 
        SelectedValue(barabovema50) >= 20)
	{
	mat1[i][0] = i; 
	mat1[i][1] = SelectedValue(roc1); 
	mat1[i][2] = SelectedValue(roc2);
	mat1[i][3] = SelectedValue(roc3);
	mat1[i][4] = SelectedValue(roc4); 
	}
} 
mat2 = MxSortRows(mat1, False, 1);
toplist = "";
topn = 15;
for ( i = 0; i < topn AND i < sym_num; i++ ) 
{
	n2 = mat2[i][0];	roc1 = mat2[i][1];
symbol = StrExtract(sym_list, n2);
toplist += symbol+",";
}
toplist = StrTrim( toplist, ",", 2 );
toplist = StrSort(toplist);
toplist_num = StrCount(toplist, ",")+1;

Buy = cross(Close, Ref(HHV(C,20),-1)) AND StrFind(toplist,Name());	
Filter = Buy;
AddColumn(C*MA(V,50),"GTGD",1.0);

@hungboss1 what you are trying to do using matrices is normally done using ranking functions.
Please. consult the official documentation (section: How to use StaticVarGenerateRanks in Analysis window) and eventually search the forum for further examples showing an improved/faster way thanks to the possibility of using a "sequence" to perform the ranking using a scan followed by an exploration like this.

In any case there is one thing that I recommend you review in the user guide:
https://www.amibroker.com/guide/afl/selectedvalue.html

SelectedValue() is supposed to be used mostly in charts - carefully read @Tomasz's comment on its correct usage.
The value returned, when used in analysis, is that of the last bar. I guess this is not what you expected and this explains why your code seems to work when you only have one bar in your exploration and it doesn't for a date range.

1 Like

Thank you, i will try to follow your instructions by replacing matrices with staticvargenerateranks. i have tried this before but it seems to be not suitable if running too many rankings. however i will try again maybe the problem lies in my code is not correct.
about using selectedvalue, first i used lastvalue(), however since i can not check the correctness of the result with explorer i decided to use selectedvalue() to check on the graph.

I tried using staticvargenerateranks to run explorer but it still doesn't work as expected.
What I want is:

  1. Rank the trade value and select the top N symbols.
  2. Continue to rank the ROC for 10, 20, 65, 125 days based on the Top N symbols in step 1 and continue to select the top N symbols.
  3. Generate buy and sell signals only in the list of top N symbols in step 2.
  4. Use exploration to filter this signal over a period of time to check the performance of the signal.

The ranking part seems to be calculated based on the watchlist at the most recent bar. If I replace lastvalue with selectedvalue, the ranking will be calculated at the last time as described in the lastvalue function's instructions.
I understand why it is like that thanks to your explanation but can't think of any other way to handle it to get more accurate results when using the from-to-date range in exploration instead of just selecting a single date.

This is my updated code


List = CategoryGetSymbols( categoryGroup, 3 ) ;

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 );
        values = C*MA(V,50);
        roc1 = ROC(C,10);
        roc2 = ROC(C,20);
        roc3 = ROC(C,65);
        roc4 = ROC(C,125);
        abovema50 = BarsSince(Close < EMA(Close,50));
        RestorePriceArrays();
        StaticVarSet (  "values"  +  symbol, values );
        
        _TRACE( symbol );
    }

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

symbol = Name();

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

if ( Status("stocknum") == 0 ) // GENERATE RANKING WHEN WE ARE ON VERY FIRST SYMBOL
{
	StaticVarRemove( "roc*" );
	for ( i = 0; ( Symbol = StrExtract( List, i ) )  != "";  i++    )
	{
		if (LastValue(StaticVarGet ( "rankvalues" +  symbol )) < 165)
			{
				SetForeign ( symbol );
				roc1 = Nz(ROC(C,10));
				roc2 = Nz(ROC(C,20));
				roc3 = Nz(ROC(C,65));
				roc4 = Nz(ROC(C,125));
				
				RestorePriceArrays();
				
				StaticVarSet (  "roc1"  +  symbol, roc1 );
				StaticVarSet (  "roc2"  +  symbol, roc2 );
				StaticVarSet (  "roc3"  +  symbol, roc3 );
				StaticVarSet (  "roc4"  +  symbol, roc4 );
			}
	}
		StaticVarGenerateRanks( "rank", "roc1",0, 1224 );
		StaticVarGenerateRanks( "rank", "roc2",0, 1224 );
		StaticVarGenerateRanks( "rank", "roc3",0, 1224 );
		StaticVarGenerateRanks( "rank", "roc4",0, 1224 );

}
rankroc1 = StaticVarGet ( "rankroc1" +  symbol );
rankroc2 = StaticVarGet ( "rankroc2" +  symbol );
rankroc3 = StaticVarGet ( "rankroc3" +  symbol );
rankroc4 = StaticVarGet ( "rankroc4" +  symbol );
Buy = cross(Close, Ref(HHV(C,20),-1)) AND BarsSince(Close < EMA(Close,50)) > 20;

Filter = Buy ==1 AND (rankroc1 <= 15 OR rankroc2 <= 15 OR rankroc3 <= 15 OR rankroc4 <= 15);
AddColumn(ROC(C,10),"ROC 10",1.0);
AddColumn(ROC(C,20),"ROC 20",1.0);
AddColumn(ROC(C,65),"ROC 65",1.0);
AddColumn(ROC(C,125),"ROC 125",1.0);
AddColumn(Buy,"Signal",1.0);

@hungboss1, you should NOT use LastValue() in the ranking phases.

The code also include some lines that are not used (not a big deal but it is better to remove them):

        // remove these unused lines
        roc1 = ROC(C,10);
        roc2 = ROC(C,20);
        roc3 = ROC(C,65);
        roc4 = ROC(C,125);
        abovema50 = BarsSince(Close < EMA(Close,50));

Most importantly, in the second phase of yuor ranking process you should do something like this:

        rankValues = StaticVarGet( "rankvalues" +  symbol );
        condition = rankValues <= 165; 
        roc1 = iif( condition, ROC(C, 10), -10000 ); // if not in the top values assign a large negative value so its rank will be very low
        roc2 = iif( condition, ROC(C, 20), -10000 );
        // etc.

Finally, I suggest testing your code using a small bar range (like 4/5 days) until you have fully debugged it and understand how it works using an exploration where you print all the static arrays and values calculated (both ranks and the associated values) sorted by the main rank (similar to turnover in the first loop) and the individual signal components used to generate the BUY array.
You should try to get something like this:

In the explorer set the Filter = 1; to see all the stocks and check their values ​​to make sure everything is working as expected.

2 Likes