Sort Symbols Based On Performance Metrics Such As %Winners for each symbol

Sorry for the basic question. There has to be an easy way to do this, but I can't find it. I want to simply run my formula against a watchlist, then sort the symbols and create a new watchlist based on things like %winners, profit factor, etc for EACH symbol. The information is there, of course, when Summary is selected and only one symbol at a time is backtested. I guess I could export to a spreadsheet each summary, then sort. Must be a better way.

Thanks for your help.

This can be similarly done to this

In the example below only symbols with %Winners above 50 will be added to a set new WL.
(Don't forget to run Individual backtest.)

(If you want to add top N symbols to WL then this can be done too. Via static variables.)

// Add only symbols to a new WL which pass performance metric test
// https://forum.amibroker.com/t/sort-symbols-based-on-performance-metrics-such-as-winners-for-each-symbol/27594
// Store symbol to pass to CBT
if (Status( "action" ) == actionBacktest)
	StaticVarSetText("CBT_Symbol", Name());
	
wl_number = 60;// add filtered symbols to new watchlist number

SetCustomBacktestProc( "" );  
if ( Status( "action" ) == actionPortfolio ) {
	bo = GetBacktesterObject();
	bo.Backtest(); // run default backtest procedure 
	stats = bo.GetPerformanceStats(0);	
	metric = stats.GetValue("WinnersPercent");
	metric_check_OK = metric > 50;	// % winners above 50
	
	if ( metric_check_OK ) {
		nm = StaticVarGetText("CBT_Symbol");
		// only add symbols to new WL which pass the test
		CategoryAddSymbol(nm, categoryWatchlist, wl_number);
	}
	
}

// Dummy system start
SetPositionSize(1, spsShares);
per = Optimize("per", 20, 5, 20, 1);
m = MA( Close, per );
Buy = Cross( Close, m ); 
Sell = Cross( m, Close ); 
Short = Cover = 0;
// Dummy system end

Here is code to do that

First run individual backtest on a WL then run Scan on SINGLE symbol

/// Only add topN metric symbols to a WL
/// First run individual backtest on a WL 
/// Then run Scan on SINGLE symbol
/// by fxshrat@gmail.com
/// @link https://forum.amibroker.com/t/sort-symbols-based-on-performance-metrics-such-as-winners-for-each-symbol/27594/3
topN = 10;
wl_number = 60;// add topN metric symbols to new watchlist number
if (Status( "action" ) == actionBacktest) {
	if ( Status("stocknum") == 0 ) {
		StaticVarRemove("CBT_Symbol");
		StaticVarRemove("CBT_WinnersList");
	}
	if ( inWatchlist(wl_number))
		CategoryRemoveSymbol("", categoryWatchlist,wl_number);
	StaticVarSetText("CBT_Symbol", Name());
}	

SetCustomBacktestProc( "" );  
if ( Status( "action" ) == actionPortfolio ) {
	bo = GetBacktesterObject();
	bo.Backtest(); // run default backtest procedure 
	stats = bo.GetPerformanceStats(0);	
	metric = stats.GetValue("WinnersPercent");
	
	nm = StaticVarGetText("CBT_Symbol");	
	get_list = StaticVarGetText("CBT_WinnersList") + "," + metric + "_" + nm;	
	StaticVarSetText("CBT_WinnersList", get_list);	
	_TRACE(get_list);	
}

EnableTextOutput(0);

get_list = StaticVarGetText("CBT_WinnersList");
get_list = StrSort(StrTrim(get_list, ","));
cnt = StrCount(get_list, ",")+1;
is_scan = Status("action") == actionScan;

printf("%g Symbols in Test\n\n", cnt);
for ( i = cnt-1, n = 0; i >= 0; i-- ) {
    if ( n < topN ) {
		top_sym_val = StrExtract(get_list, i);
		printf( "%g: %s\n", n+1, top_sym_val );
		if ( is_scan ) {
			top_sym = StrExtract(top_sym_val, 1, '_');
			CategoryAddSymbol(top_sym, categoryWatchlist, wl_number);
		}
	}
	n++;
}

// Dummy system start
SetPositionSize(1, spsShares);
m = MA( Close, 20);
Buy = Cross( Close, m ); 
Sell = Cross( m, Close ); 
Short = Cover = 0;
// Dummy system end

30

WL content after individual Backtest runs plus single scan.

31

1 Like

Thanks FX! This helps greatly. I was trying some CBT code, but couldn't quite put it together.

Regards

Instead of upper one it is better to clear entire WL at start of BT.
So here is update

/// Only add topN metric symbols to a WL
/// First run individual backtest on a WL -> Filter - Include Watchlist
/// Then run Scan on SINGLE symbol
/// by fxshrat@gmail.com
/// @link https://forum.amibroker.com/t/sort-symbols-based-on-performance-metrics-such-as-winners-for-each-symbol/27594/5
topN = 10;
wl_number = 60;// add topN metric symbols to new watchlist number
if (Status( "action" ) == actionBacktest) {
	if ( Status("stocknum") == 0 ) {
		StaticVarRemove("CBT_Symbol");
		StaticVarRemove("CBT_WinnersList");		
		// Clear TopN metric WL at start ot BT
		list = CategoryGetSymbols( categoryWatchlist, wl_number );    
		for ( i = 0; ( sym = StrExtract(list, i ) ) != ""; i++ ) {
			CategoryRemoveSymbol(sym, categoryWatchlist,wl_number);
		}
	}
	StaticVarSetText("CBT_Symbol", Name());
}	

SetCustomBacktestProc( "" );  
if ( Status( "action" ) == actionPortfolio ) {
	bo = GetBacktesterObject();
	bo.Backtest(); // run default backtest procedure 
	stats = bo.GetPerformanceStats(0);	
	metric = stats.GetValue("WinnersPercent");
	
	nm = StaticVarGetText("CBT_Symbol");	
	get_list = StaticVarGetText("CBT_WinnersList") + "," + metric + "_" + nm;	
	StaticVarSetText("CBT_WinnersList", get_list);	
	_TRACE(get_list);	
}

EnableTextOutput(0);

get_list = StaticVarGetText("CBT_WinnersList");
get_list = StrSort(StrTrim(get_list, ","));
cnt = StrCount(get_list, ",")+1;
is_scan = Status("action") == actionScan;

printf("%g Symbols in Test\n\n", cnt);
for ( i = cnt-1, n = 0; i >= 0; i-- ) {
    if ( n < topN ) {
		top_sym_val = StrExtract(get_list, i);
		printf( "%g: %s\n", n+1, top_sym_val );
		if ( is_scan ) {
			top_sym = StrExtract(top_sym_val, 1, '_');
			CategoryAddSymbol(top_sym, categoryWatchlist, wl_number);
		}
	}
	n++;
}

// Dummy system start
SetPositionSize(1, spsShares);
m = MA( Close, 20);
Buy = Cross( Close, m ); 
Sell = Cross( m, Close ); 
Short = Cover = 0;
// Dummy system end

30

WL content after individual Backtest runs plus single scan.

31


Same to first code

Instead of

->

// Add only symbols to a new WL (see wl_number) which pass performance metric test
// Run individual backtest on a WL -> Filter - Include Watchlist
// https://forum.amibroker.com/t/sort-symbols-based-on-performance-metrics-such-as-winners-for-each-symbol/27594/5
wl_number = 60;// add filtered symbols to new watchlist number
if (Status( "action" ) == actionBacktest) {	
	if ( Status("stocknum") == 0 ) {
		// Clear metric WL at start ot BT
		list = CategoryGetSymbols( categoryWatchlist, wl_number );    
		for ( i = 0; ( sym = StrExtract(list, i ) ) != ""; i++ ) {
			CategoryRemoveSymbol(sym, categoryWatchlist,wl_number);
		}
	}
	StaticVarSetText("CBT_Symbol", Name());
}

SetCustomBacktestProc( "" );  
if ( Status( "action" ) == actionPortfolio ) {
	bo = GetBacktesterObject();
	bo.Backtest(); // run default backtest procedure 
	stats = bo.GetPerformanceStats(0);	
	metric = stats.GetValue("WinnersPercent");
	metric_check_OK = metric > 50;	// % winners above 50	
	if ( metric_check_OK ) {
		nm = StaticVarGetText("CBT_Symbol");
		// only add symbols to new WL which pass the test
		CategoryAddSymbol(nm, categoryWatchlist, wl_number);
	}	
}

// Dummy system start
SetPositionSize(1, spsShares);
per = Optimize("per", 20, 5, 20, 1);
m = MA( Close, per );
Buy = Cross( Close, m ); 
Sell = Cross( m, Close ); 
Short = Cover = 0;
// Dummy system end
1 Like

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