Closed trade equity curve

I would like to obtain (and plot) my closed trade equity and draw down after a back test. Is there a way to do this in the report tab? I am under the impression I cannot call the CBT procedure after the system is back tested / at the report generation stage.

I do know that I can access the number of open positions from the Equity symbols OpenInt field however this does not really tell me if I closed a trade (does it?). I could close a trade and then open a new trade on the same bar.

Perhaps I could use the OpenInt and a change in cash (Low field) to mark a buy/sell?

Any ideas appreciated.

If I have understood your issue properly then you could store the data to matrix in CBT mode and then plot that matrix either in Exploration mode via XY chart feature (see links here How do I get the Full name versus Ticker in the risk yield map Yes, instead of scatter you can also plot line style) or you may use Gfx. First option is simplest one of both.

Why storing to matrix? It is independent from symbol's 1D array so you can plot stored data points of same bar or day ... side by side as you are looking for.

In example below you have 16 closed trades of four closing days. You want to output first one. No problem.

1

Output in Exploration via XY chart feature:

3

2

1 Like

Hi rb

If you want to display the closed equity as a chart on the backtest report, you'll need to calculate a value for each data point in the time series, which you can do inside the CBT. You can use the high-level CBT which allows you to perform just such calculations after the backtest is executed but before the report is compiled.

There a few ways to code it, here's just one. First loop through the closed trade list to gather the P&L value for each trade. Then loop through the bars and fill in blank values and accumulate the closed equity values on top of the initial equity, at each point a trade is closed. Finally store the result in a static variable.

SetCustomBacktestProc(""); 
if( Status("action") == actionPortfolio ) 
{ 
    bo = GetBacktesterObject(); 
	bo.Backtest(); // run default backtest procedure 

	dt = DateTime();
	ClosedEquity = 0; // initialise array
	ClosedEquity[0] = bo.InitialEquity; // set first array element to initial equity
	
	for (trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade())
    {
		ClosedEquity += IIf(dt == trade.ExitDateTime, trade.GetProfit(), 0); // store cumulative trade profit values at exit date points
    }
    
    for( i = 1; i < BarCount; i++ ) // loop through bars to fill in blank values and accumulate closed equity values
	{
		if (ClosedEquity[i] == 0)
			ClosedEquity[i] = ClosedEquity[i - 1];
		else
			ClosedEquity[i] += ClosedEquity[i - 1];
	}
	
	StaticVarSet("ClosedEquity", ClosedEquity);

}

Then to get it to display on the report as a separate chart, you'll need to create a new formula in the Formulas\Report Charts folder. The number you give it in the file name is the order in which it will display on the report, eg 4. Closed Equity.afl. The content of the formula is a Plot statement calling the static variable created above as the input.

Title = "Closed Equity";
SetGradientFill( colorLightBlue, colorPink  );
Plot( StaticVarGet("ClosedEquity"), "Closed Equity", ColorBlend( colorLightBlue, colorBlack ), styleGradient | styleLine, Null, Null, 0, -1 );

Then when you run a backtest and pull up the report you'll have something like this:
image

I'll leave you to figure out how to create the drawdown chart from there. Clue: Study the contents of the default Underwater Equity formula in the Report Charts folder.

8 Likes

@HelixTrader I can find most of the the explanations for the Methods here,

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

For example,
image

But I don’t understand why you need to loop through every bar after you have stored the cumulative value in your ClosedEquity variable?

    for( i = 1; i < BarCount; i++ ) // loop through bars to fill in blank values and accumulate closed equity values

Is it strictly to help create the chart? i.e. create a bar-by-bar value that can be charted?

Thanks.

The way I’ve done it, the trade loop only populates values for array elements that fall on trade exit dates. That’s what the IIF does, note: dt == trade.ExitDateTime. If it’s not a trade exit date, zero is assigned as the addition value.

ClosedEquity += IIf(dt == trade.ExitDateTime, trade.GetProfit(), 0);

The bar loop then starts with the initial equity and then either assigns the last bar’s value for zeroed value elements, or adds the profit calculated from the trade loop. Ultimately the Plot statement to create the chart needs a value for every bar.

I did say there was more than one way to code it. Another way would be to place the trade loop inside the bar loop. That way you could populate the value for each bar as you go, but it will be slower as you would have to loop through the closed trade list on every bar. If there are a lot of trades in the backtest this would slow things right down. Having separate trade and bar loops is slightly more efficient, but by no means the only way to skin this particular cat.

3 Likes

That code will plot the data of the last closed trade of a bar but not all closed trades of a bar side by side if there are multiple closed trades per bar. As far as I understand the first post he wants to plot an equity showing all closed trades.

1 Like

Yes, the code does account for all closed trades, even if they close on the same bar. In the trade loop the trade profits are accumulated. If more than one trade has the same ExitDateTime, their profits will be summed.

ClosedEquity += IIf(dt == trade.ExitDateTime, trade.GetProfit(), 0);

1 Like

Yes, sure. That’s not what I meant. Again, it will plot the state of cum.profit at the LAST closed trade even if there are more than one closed ones at same bar. Look at the first picture of 2nd post. Your code will plot the states of cum profit at 18.32 of exit date 2006-01-05, at 60.35 of exit date 2006-01-09, at 469.95 of exit date 2006-01-11 and so on… but it will not include the states of all other occurrences at same bar as in the result list.

The way I understand the first post (which is not clear) he seems to be looking for plot output of all states at same bar. For that you would have to store the data to matrix. Then you can plot all occurring states side by side.

1 Like

Yes, I see what you’re getting at now, and your method certainly achieves that. I agree the OP wasn’t super clear on which he wanted, but at least if anyone comes searching for closed trade equity curve in future, this thread will provide them with both methods to choose from.

1 Like

Thank you for all the replies. The solution @HelixTrader provided was exactly what I am looking for. Thank you again.

2 Likes

@HelixTrader This solution was exactly what I was looking for. However my report shows results in yearly. How can I convert it to the monthly view or even a weekly view?

Title = "Closed Equity";
SetGradientFill( colorLightBlue, colorPink  );
Plot( StaticVarGet("ClosedEquity"), "Closed Equity", ColorBlend( colorLightBlue, colorBlack ), styleGradient | styleLine, Null, Null, 0, -1 );
StaticVarRemove("ClosedEquity");

For what it is worth, the code in presented earlier in this thread is total waste of time and computing resources. Closed Equity is available directly without calculation at all:

SetCustomBacktestProc(""); 
if( Status("action") == actionPortfolio ) 
{ 
 bo = GetBacktesterObject(); 
 bo.Backtest(); // run default backtest procedure 

 ClosedEquity = bo.EquityArray; // directly available
} 
3 Likes