Plot hit ratio code

Hello, not so good here with custom backtester. I use the code below after my backtest code to calculate hit ratio by trade and plot it as a foreign security. It only plots the final value of the hit ratio although the added column has the correct values per trade.

SetOption( "ExtraColumnsLocation", 9 ); 
SetCustomBacktestProc( "" ); 
if ( Status( "action" ) == actionPortfolio ) { 
    bo = GetBacktesterObject(); 
    bo.Backtest(1); 

    sumprofit = 0; 
    trades = 0; 
    
    // iterate through closed trades
    for ( trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade() ) { 
        profit = trade.GetProfit(); 
        trades++; 
        if ( profit > 0 ) { 
            sumprofit++; 
        } 
        Hitratio = sumprofit / trades * 100; 
        trade.AddCustomMetric( "HitRatio(%)", Hitratio, DecPlaces = 2 ); 
           Plot(Hitratio, "Win Rate", colorBlack, styleLine);  
    } 
    // iterate through open positions 
    for ( trade = bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos() ) { 
        profit = trade.GetProfit(); 
        trades++; 
        if ( profit > 0 ) { 
            sumprofit++; 
        }         
        Hitratio = sumprofit / trades * 100; 
        trade.AddCustomMetric( "HitRatio(%)", Hitratio, DecPlaces );   
      
    } 
    bo.ListTrades(); 
    AddToComposite( Hitratio,"~~~HitRatio", "X",
atcFlagDeleteValues | atcFlagEnableInPortfolio );
} 

It is not correct. Hit Ratio in your posted code is not array.

Also Plot does not belong there in CBT not to mention within loop.

Please read KB article to store metrics as array.
http://www.amibroker.com/kb/2008/05/19/historical-portfolio-backtest-metrics/

/// code source:
/// @link http://www.amibroker.com/kb/2008/05/19/historical-portfolio-backtest-metrics/
SetOption( "UseCustomBacktestProc", True );
if( Status( "action" ) == actionPortfolio )
{
    bo = GetBacktesterObject();
    bo.PreProcess(); // Initialize backtester

    // initialize with null
    // you can have as many historical metrics as you want
    // (just duplicate line below for many metrics you want)
    MyHistStat1 = Null;
    //MyHistStat2 = Null; // add your own

    for( bar = 0; bar < BarCount; bar++ )
    {
        bo.ProcessTradeSignals( bar );

        // recalculate built-in stats on EACH BAR
        stats = bo.GetPerformanceStats( 0 );

        // the line below reads the metric and stores it as array element
        // you can add many lines for each metric of your choice
        MyHistStat1[ bar ] = stats.GetValue( "WinnersPercent" ); // add your own
        // MyHistStat2[ bar ] = /*...*/
    }

    bo.PostProcess(); // Finalize backtester

    // now STORE the historical data series representing the metric of your choice
    // duplicate the line below for as many metrics as you want
	AddToComposite( MyHistStat2, "~~~WP_HISTORICAL", "X", atcFlagEnableInPortfolio | atcFlagDefaults );
	
    // you can add your own as shown below
    //AddToComposite( MyHistStat2, "~~~WP_HISTORICAL", "X", atcFlagEnableInPortfolio | atcFlagDefaults );    
}

Note: alternatively to AddToComposite (and Foreign() for call) you may use StaticVarSet() to store in CBT and in Chart pane or elsewhere StaticVarGet() to call variable.

1 Like

Thanks @fxshrat, it works well. Just a note to anyone who wants t use it, obviously change

AddToComposite( MyHistStat2, ....

to

AddToComposite( MyHistStat1,