Custom metric annual trades, wins and losses

I am trying to get more granular data in the backtest reports to give myself a bit more insight into my trading systems. I'm simply trying to count trades per year and determine win ratio. I'm not sure if my attempt at the code below is correct or not but at the moment I'm getting this:

Error 16: too many arguments with window pointing to this line:
exitdate = datenum( trade.ExitDateTime )

I've searched the forums and read through the CBT manual but I'm out of ideas. Any help is much appreciated!

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

	if(BarCount > 252) // only execute if more than 1 year
	{
		
 		//counting total wins, losses and trades per year
		for ( Years = 2000; 2020; Years++)
		{
			//Reset counters
			YrTrades = 0; 
			YrWin = 0;
			YrLoss = 0;
							
			// iterate through closed trades first
			for( trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade() )
			{
				PL = trade.Getprofit();
				exitdate = datenum( trade.ExitDateTime );
											
				if( Years == exitdate)
				{
				yearTrades++;
					if (PL >= 0)
						YrWin_++; 
					else
						YrLoss++;
					}
				VarSet("Year-"+Years, YrTrades);
				VarSet("Year-"+Years, YrWin);
				VarSet("Year-"+Years, YrLoss);
				
				bo.AddCustomMetric( "Year-"+Years, LastValue(YrTrades) );
				bo.AddCustomMetric( "Year-"+Years, LastValue(YrWin) );
				bo.AddCustomMetric( "Year-"+Years, LastValue(YrLoss) ); 
			} 
				
						
		}
		
	}
}	

Your code is not correct on many levels.
DateNum() is an array and does not have any function arguments.
Overall the way you use it is not correct.
Also your looping is incorrect not to mention that you do not require nested loop at all.

procedure vgWinLossPerYear(YrWin, YrLoss, Yrcnt, trade, mode ) {
	/// by AmiBroker.com and fxshrat@gmail.com
	dt = IIf(mode == 1, trade.ExitDateTime, trade.EntryDateTime);
	n = floor(DateTimeConvert(8, dt));   
	if( trade.GetProfit() >= 0 ) // profit only
		VarSet(YrWin+n, Nz(VarGet(YrWin+n))+1);
	else  // loss only
		VarSet(YrLoss+n, Nz(VarGet(YrLoss+n))+1);   
	// cnt all per year
	VarSet(Yrcnt+n, Nz(VarGet(Yrcnt+n))+1);
}

/// Per year Win/Loss ratio and number of trades, code source at:
/// @link https://forum.amibroker.com/t/custom-metric-annual-trades-wins-and-losses/20241/2
SetCustomBacktestProc("");
if ( Status( "action" ) == actionPortfolio ) {
	bo = GetBacktesterObject();
	bo.Backtest();

	yr = Year();
	fbr = Status("FirstBarInRange");
	lbr = Status("LastBarInRange");
	first_yr = LastValue(ValueWhen(fbr, yr));
	last_yr = LastValue(ValueWhen(lbr, yr));
   
	// iterate closes trades
	for ( trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade() ) 
		vgWinLossPerYear("YrWin", "YrLoss", "Yrcnt", trade, 0 );

	// iterate open trades
	for ( trade = bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos() )
		vgWinLossPerYear("YrWin", "YrLoss", "Yrcnt", trade, 0 );

	// Output per year stats to report file
	for ( i = first_yr; i <= last_yr; i++ ) {
		YrCnt = VarGet("Yrcnt"+i);
		bo.AddCustomMetric( StrFormat( "Year%g (%g trades): WinRatio %1.2f%%, LossRatio %1.2f%%", 
							i, YrCnt, VarGet("YrWin"+i) / YrCnt * 100, VarGet("YrLoss"+i) / YrCnt * 100) ); 
    }
}

m = MA( Close, 20 ); 
Buy = Cross( Close, m );
Sell = Cross( m, Close ); 
Short = Cover = 0;

results in sample output

14

3 Likes

@fxshrat I appreciate your help. studying your code now and learning a lot. many many thanks.