LLVBars and HHVBars with BarsInTrade custom backtest REPORT metric help request

Good afternoon to all, after having exhaustively searched this forum as well as the broader web for clues I come kindly requesting your assistance.

I currently have a custom trade metric which outputs data to the trade list report.

	trade.AddCustomMetric("LoB", loB);
	trade.AddCustomMetric("HiB", hiB);

My goal is to get the sum of trade list data and output the values to the custom backtest report.

    bo.AddCustomMetric( "LoBT", loBT);
    bo.AddCustomMetric( "HiBT", hiBT);

Full code is listed below. Any assistance will be much appreciated.

SetCustomBacktestProc(""); 

function processTrade( trade )
{
   
	SetForeign( trade.Symbol );
	 
	 if ( trade.IsLong() )
		{
			loB = (trade.BarsInTrade - Lookup( LLVBars( Low, trade.BarsInTrade + 1), trade.ExitDateTime ))/trade.BarsInTrade;
			hiB = (trade.BarsInTrade - Lookup( HHVBars( High, trade.BarsInTrade + 1), trade.ExitDateTime ))/trade.BarsInTrade;
		}
		else
		{
			loB = (trade.BarsInTrade - Lookup( HHVBars( High, trade.BarsInTrade + 1), trade.ExitDateTime ))/trade.BarsInTrade;
			hiB = (trade.BarsInTrade - Lookup( LLVBars( Low, trade.BarsInTrade + 1 ), trade.ExitDateTime ))/trade.BarsInTrade;
		} 

	RestorePriceArrays();
		
	trade.AddCustomMetric("LoB", loB);
	trade.AddCustomMetric("HiB", hiB);
}

if( Status("action") == actionPortfolio ) 
{
	bo = GetBacktesterObject(); 

    bo.Backtest(1); 
        
	loBT = hiBT = 0;
    
	for( trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade() )
    {
  
         if ( trade.IsLong() )
			{
				loB = ((trade.BarsInTrade - Lookup( LLVBars( Low, trade.BarsInTrade + 1), trade.ExitDateTime ))/trade.BarsInTrade);
				hiB = (trade.BarsInTrade - Lookup( HHVBars( High, trade.BarsInTrade + 1), trade.ExitDateTime ))/trade.BarsInTrade;
			}
			else
			{
				loB = (trade.BarsInTrade - Lookup( HHVBars( High, trade.BarsInTrade + 1), trade.ExitDateTime ))/trade.BarsInTrade;
				hiB = (trade.BarsInTrade - Lookup( LLVBars( Low, trade.BarsInTrade + 1 ), trade.ExitDateTime ))/trade.BarsInTrade;
			} 
		
		loBT += loB;
		hiBT += hiB;
        
      processTrade( trade );
    }
    
    for ( trade = bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos() )
    {
      processTrade( trade );
    }
     
    bo.AddCustomMetric( "LoBT", loBT);
    bo.AddCustomMetric( "HiBT", hiBT);
    
    bo.ListTrades( );
} 
    

SetChartOptions(0,chartShowArrows|chartShowDates);
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 

StopLevel = Param("trailing stop %", 3, 0.1, 10, 0.1 );
ApplyStop(stopTypeLoss, stopModePercent, StopLevel, 2, True, 0, 0, -1 );

Buy = Cross( MA(C, 10), MA(C,100) );
Short = Cross( MA(C,100), MA(C,10) );
Sell = Cover = 0;

 BuyPrice = SellPrice = ShortPrice = CoverPrice = Close;

First of all if you copy code from elsewhere then you should add link to original creation and add info about modification.

The actual original code is this one.
http://www.amibroker.com/kb/2015/02/04/how-to-add-mae-mfe-dates-to-the-backtest-report/


In your code modification you do things twice so simply return variables in function if they are supposed to be used several times.

Also you forgot SetForeign / RestorePriceArrays in the duplicate non function code.

Also you had just loss exit but no actual exit in case of profit.

function processTrade( trade )
{
    /// derived from
    /// @link http://www.amibroker.com/kb/2015/02/04/how-to-add-mae-mfe-dates-to-the-backtest-report/
    /// first modification
    /// @link https://forum.amibroker.com/t/llvbars-and-hhvbars-with-barsintrade-custom-backtest-report-metric-help-request/13068
    /// 2nd modification
    /// @link https://forum.amibroker.com/t/llvbars-and-hhvbars-with-barsintrade-custom-backtest-report-metric-help-request/13068/2
    local bars, dt, loB, hiB, result;
    SetForeign( trade.Symbol );

		bars = trade.BarsInTrade;
		dt = trade.ExitDateTime;

		if( trade.IsLong() )
		{
			loB = ( bars - Lookup( LLVBars( Low, bars + 1 ), dt ) ) / bars;
			hiB = ( bars - Lookup( HHVBars( High, bars + 1 ), dt ) ) / bars;
		}
		else
		{
			loB = ( bars - Lookup( HHVBars( High, bars + 1 ), dt ) ) / bars;
			hiB = ( bars - Lookup( LLVBars( Low, bars + 1 ), dt ) ) / bars;
		}

    RestorePriceArrays();

    trade.AddCustomMetric( "LoB", loB );
    trade.AddCustomMetric( "HiB", hiB );

    result = Matrix( 1, 2 );
    result[0][0] = loB;
    result[0][1] = hiB;
    return result;
}

/// first version
/// @link https://forum.amibroker.com/t/llvbars-and-hhvbars-with-barsintrade-custom-backtest-report-metric-help-request/13068
/// modification
/// @link https://forum.amibroker.com/t/llvbars-and-hhvbars-with-barsintrade-custom-backtest-report-metric-help-request/13068/2
SetCustomBacktestProc(""); 
if( Status( "action" ) == actionPortfolio )
{
    bo = GetBacktesterObject();

    bo.Backtest( 1 );

    loBT = hiBT = 0;

    for( trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade() )
    {
        mat = processTrade( trade );
        loB = mat[0][0];
        hiB = mat[0][1];

        loBT += loB;
        hiBT += hiB;        
    }

    for( trade = bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos() )
    {
        mat = processTrade( trade );
        //loB = mat[0][0];
        //hiB = mat[0][1];
    }

    bo.AddCustomMetric( "LoBT", loBT );
    bo.AddCustomMetric( "HiBT", hiBT );

    bo.ListTrades( );
}


SetChartOptions(0,chartShowArrows|chartShowDates);
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 

StopLevel = Param("trailing stop %", 3, 0.1, 10, 0.1 );

BuyPrice = SellPrice = ShortPrice = CoverPrice = Close;

ma1 = MA(C, 10);
ma2 = MA(C,100);

Buy = Cross( ma1, ma2 );
Short = Cross( ma2, ma1 );
Sell = Cover = 0;

ApplyStop(stopTypeProfit, stopModePercent, 1.5*StopLevel, 2, True, 0, 0, -1 );
ApplyStop(stopTypeLoss, stopModePercent, StopLevel, 2, True, 0, 0, -1 );
2 Likes

You are the man! I love you!

Yes, that link is the original source of the code. Your instructions with regards to referencing original source is well noted and will be implemented in any future occurrences.