How can I write my own "Cum profit" in CBT?

Hi, I am newbie trying to understand the basic element of CBT.

I tried to write High-level CBT for Cum. Profit but I've failed
Can you suggest me (or give an example) how to code to get this one.

Thank you,

What have you tried?
If you just write "I've failed" we don't know what you have actually done making your code to fail.

function MyCBTColumns() {
	/// example to user question being asked here 
	/// @link http://forum.amibroker.com/t/how-can-i-wrtie-my-own-cum-profit-in-cbt/1153
	global bo;
	
	sumprofit = 0; // initialize cum. profit
	caption1 = "My Cum.Profit"; // column description    

	// Iterating through closed trades
	for ( trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade() ) {      
		profit  = trade.GetProfit(); // get P/L of closed trade
		sumprofit += profit;  // sum up P/L   
		column_output1 = sumprofit;   
		trade.AddCustomMetric( caption1, column_output1, DecPlaces = 2 );
	}

	// Iterating through open trades
	for (trade = bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos()) {      
		profit  = trade.GetProfit(); // get P/L of open trade
		sumprofit += profit;  // sum up P/L  
		column_output1 = sumprofit;       
		trade.AddCustomMetric( caption1, column_output1, DecPlaces );
	}
}


SetPositionSize( 1, spsShares );
SetOption("ExtraColumnsLocation", column = 13 ); // set column location of custom column

//----------------------------------------------------------------------------------------------

// First enabling custom backtest procedure and telling AB to use current formula
SetCustomBacktestProc("");

// Custom-backtest procedure follows
if ( Status( "action" ) == actionPortfolio ) {
	bo = GetBacktesterObject(); // Retrieving the interface to portfolio backtester
	bo.Backtest( 1 ); // Set to 1 to turn off automatic calling of trade list so per-trade variables can be added

	MyCBTColumns();// My column(s) output function

	bo.ListTrades(); // calling the trade list procedure after adding the variables wanted
}

//----------------------------------------------------------------------------------------------

// DUMMY SYSTEM CODE HERE

// Buy and Sell Code
period = 20; // number of averaging periods 
m = MA( Close, period ); // simple moving average
Buy = Cross( Close, m ); // buy when close crosses ABOVE moving average
Sell = Cross( m, Close ); // sell when closes crosses BELOW moving average

Short = Cover = 0;

Again what have you tried?

https://www.amibroker.com/guide/a_custombacktest.html
https://www.amibroker.com/guide/a_custommetrics.html

2 Likes

Thank you very much for your help

"I’ve failed"
I mean I’ve tried CBT many ways and all of them are completely wrong.
(the most close is same as your example but

  1. not do in function style
  2. missed the “sumprofit += profit;” )

After 5hours tried, now I know what is wrong,
because my formula is missing the “sumprofit += profit;” (never use “+=” before)

sorry for my slowly respond, I’ve woke up 45+ hours this 2days and didn’t sleep yet (working and bought a new car last 2 hours ago), I just arrived home.
I’ve to sleep now, and tomorrow I will try to fix my Error code then I will report my process again.

thank you,

For what it is worth

sumprofit += profit;

is just a shortcut notation for simple addition and assignment:

sumprofit = sumproft + profit;

The += compound assignment notation has been invented by Dennis Ritchie in the “C” programming language so programmers could save few keystrokes when typing cumulative sums and compiler was given a hint to produce faster code (by keeping sumprofit in register called ‘accumulator’).

1 Like

very thank you, all of answers are absolutely right thing what i want

Hi,

Can you help me to modify the code for the Intraday Profit instead of cumulative Profit.

and also is it possible exit the trades once the intraday profit is reached.

// DUMMY SYSTEM CODE HERE

Intraday_Profit = Param ( "Intraday Profit " , 2000 , 100 , 10000 , 100 ) ;
Intraday_Loss = Param ( "Intraday Loss " , 2000 , 100 , 10000 , 100 ) ;

// Buy and Sell Code
period = 20; // number of averaging periods 
m = MA( Close, period ); // simple moving average
Buy = Cross( Close, m ) AND TimeNum() < 150000; // buy when close crosses ABOVE moving average
Sell = Cross( m, Close ) OR TimeNum() > 150000; // sell when closes crosses BELOW moving average

Short = Cover = 0;

SetPositionSize( 50000, spsValue );
SetOption("ExtraColumnsLocation", column = 13 ); // set column location of custom column

function MyCBTColumns() {
	/// example to user question being asked here 
	/// @link http://forum.amibroker.com/t/how-can-i-wrtie-my-own-cum-profit-in-cbt/1153
	global bo;
	
	sumprofit = 0; // initialize cum. profit
	Newday = Day() !=Ref(Day(),-1);
	
	caption1 = "Intraday Profit"; // column description    

	// Iterating through closed trades
	for ( trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade() ) {      
		profit  = trade.GetProfit(); // get P/L of closed trade
		sumprofit += profit;  // sum up P/L   
		column_output1 = sumprofit;   
		trade.AddCustomMetric( caption1, column_output1, DecPlaces = 2 );
	}

	// Iterating through open trades
	for (trade = bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos()) {      
		profit  = trade.GetProfit(); // get P/L of open trade
		sumprofit += profit;  // sum up P/L  
		column_output1 = sumprofit;       
		trade.AddCustomMetric( caption1, column_output1, DecPlaces );
	}
}

//----------------------------------------------------------------------------------------------

// First enabling custom backtest procedure and telling AB to use current formula
SetCustomBacktestProc("");

// Custom-backtest procedure follows
if ( Status( "action" ) == actionPortfolio ) {
	bo = GetBacktesterObject(); // Retrieving the interface to portfolio backtester
	bo.Backtest( 1 ); // Set to 1 to turn off automatic calling of trade list so per-trade variables can be added

	MyCBTColumns();// My column(s) output function

	bo.ListTrades(); // calling the trade list procedure after adding the variables wanted
}

//----------------------------------------------------------------------------------------------

See here


But you could also use dynamic variables.

Instead of converting to year via Datetimeconvert you convert to Datenum.
And instead of +1 you use trade.GetProfit().

Dear fxshrat,

thank you for valuable support.
can you please help me for exit the trades based on the Param PNL function(Intraday Profit).
and no trades for rest of the day.

Intraday_Profit = Param ( "Intraday Profit " , 2000 , 100 , 10000 , 100 ) ;
Intraday_Loss = Param ( "Intraday Loss " , 2000 , 100 , 10000 , 100 ) ;

SetPositionSize( 100, spsShares );
m = MA( Close, 20 ); 
Buy = Cross( Close, m ) AND TimeNum() < 150000 AND TimeNum() > 091500;
Sell =  TimeNum() > 150000;
Short = Cover = 0;


function CBT_DailyProfit(trade, i) {
	// https://forum.amibroker.com/t/backtest-result-with-daily-p-l/23186/2
	// by fxshrat@gmail.com
	dn = DateTimeConvert(0, trade.EntryDateTime);
	if ( i > 0 && i < BarCount ) {
		dn_arr[ i ] = dn;
		if ( dn_arr[ i ] != dn_arr[ i-1 ] ) cs = 0; 
		cs += trade.GetProfit();
		cs_prof[ i ] = cs;
	} else {
		cs_prof[ 0 ] = cs = trade.GetProfit();
		dn_arr[ 0 ] = dn;
	}
	return cs_prof;
}

SetCustomBacktestProc("");
if ( Status( "action" ) == actionPortfolio ) {
	bo = GetBacktesterObject(); 
	bo.Backtest( 1 ); 
	// iterate closed trades
	for(trade = bo.GetFirstTrade(), i = 0; trade; trade = bo.GetNextTrade() ) {
		cs_prof = CBT_DailyProfit(trade, i);
        trade.AddCustomMetric("Daily Cum.Profit", cs_prof[i], DecPlaces = 2 );
        i++;
	}
	// iterate open positions
	for (trade = bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos() ) {
		cs_prof = CBT_DailyProfit(trade, i);
		trade.AddCustomMetric("Daily Cum.Profit", cs_prof[i], DecPlaces = 2);
		i++;
	}  
	bo.ListTrades();  
}