How do I get symbol specific values to work in the backtester?

I cannot see to get symbol specific values to work when a backtest is done on one symbol.

I am running a backtest on the current selected symbol (this is QQQ, and Apply to = Current).

symbolspecificvalue should be 500000, but when I backtest as specified, it is zero (ie. the initialized amount) - and "SymbolName" column in the CBT comes out as: ~~~EQUITY, not QQQ.

How do I change the code so that it works on the current symbol, eg-QQQ?

Buy=Sell = Short=Cover =0;

symbolspecificvalue = 0;

switch(Name())
{
	case "QQQ":
		symbolspecificvalue = 500000;
		break;       
}

// Rest of Buy/Sell code here, that should execute on QQQ

StaticVarSetText("test", Name());


SetCustomBacktestProc("");
   
if( Status("action") == actionPortfolio )
{
    bo = GetBacktesterObject();
    bo.Backtest();
    
	bo.AddCustomMetric("SymbolName", StaticVarGetText("test"));
}

First you have no entry rules in upper code (all entry/exit variables are set to zero in your code).

Secondly to output in BT report you have to do differently by iterating trade list to find symbols that actually traded and Name() being part of static var name to then call specific value per symbol via trade.Symbol in StaticVarGet().

procedure cbtSymbolList( trade ) {
    /// derived from
    /// @link http://www.amibroker.com/kb/2014/10/13/per-symbol-profitloss-in-a-portfolio-backtest/
    global tradedSymbols;
    symbol = trade.Symbol; 
    //    
    if ( ! StrFind( tradedSymbols, "," + symbol + "," ) ) { 
        value = StaticVarGet("test_"+ symbol );   
        if ( ! IsNull(value) )
			tradedSymbols += StrFormat("%s:%g,", symbol, value);
    }
}

Buy = Sell = Short = Cover = 0;

switch(Name())
{
	case "QQQ":
		symbolspecificvalue = 500000;
		break;   
		
	case "SPY":
		symbolspecificvalue = 100000;
		break;   
	default:   
		symbolspecificvalue = 0;
		break;
}

if ( Status("stocknum") == 0 )
	StaticVarRemove("test_*");

if ( symbolspecificvalue > 0 )
	StaticVarSet("test_"+Name(), symbolspecificvalue);

PositionSize = -1;

// Rest of Buy/Sell code here, that should execute on QQQ
Buy = 1;

SetCustomBacktestProc("");   
if( Status("action") == actionPortfolio )
{
    bo = GetBacktesterObject();
    bo.Backtest();
    
    tradedSymbols = ",";
    //
    //iterate through closed trades
    for ( trade = bo.GetFirstTrade( ); trade; trade = bo.GetNextTrade( ) )
        cbtSymbolList( trade );
    //
    //iterate through open positions
    for ( trade = bo.GetFirstOpenPos( ); trade; trade = bo.GetNextOpenPos( ) )
        cbtSymbolList( trade ); 
    
    //bo.AddCustomMetric("SymbolList", StrTrim(tradedSymbols, ","));

    /// see 
    /// @link http://www.amibroker.com/kb/2014/10/13/per-symbol-profitloss-in-a-portfolio-backtest/
    for ( i = 1; ( sym = StrExtract( tradedSymbols, i ) ) != ""; i++ ) 
        bo.AddCustomMetric( "Specific value for " + sym );
} 

14

1 Like

Thanks fxshrat - perfect answer, and so helpful as always :smiley: