Gross Profit Calculation on Backtesting

Created at 17 Sep 2017, 17:50
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
CA

cauedotnet

Joined 15.07.2017

Gross Profit Calculation on Backtesting
17 Sep 2017, 17:50


Hi!

Can anyone explain to me how the Gross Profit is calculated on Backtesting?

See my example of a historic position:

USDPJY - SELL

Entry Price: 76.195     -     Entry DT: 02/02/2012 00:00

Exit Price: 76.095,      -      Exit DT: 02/02/2012 09:41

Vol: 10k                      -      Leverage: 500:1

User Currency: USD -      Gross Profit: $12.81 (How?)

 

My Question: What formula is used so the Gross Profit is $12.81?

 

 

I think is something like (entry/exit) * volume * (1/exit), but my result for this formula is $13.14. Maybe backtesting put some splipage.. Please explain to me. Im comparing some strategies made by a friend in excel, and i need the same results.

Thanks.


@cauedotnet
Replies

Spotware
18 Sep 2017, 10:47

Dear cauedotnet,

Thanks for posting your question. Can you please post your backtesting settings? Did you set any commision?

Best Regards,

cTrader Team

 


@Spotware

cauedotnet
18 Sep 2017, 16:58

Sure I can. Here are my backtesting settings:

Data: Tick Data from Server (acurate)

Comission: 30 per million.

Starting Capital: 1000

 

But the comission is not only calculated on the Net Profit? In my example, the comission is 0.60. The Gross is $12.81, and the Net Profit was $12.21. So what I understand is that the diference between grofit and net is the comission here. But I really don't know how I got the Gross Profit.

 

Thanks.

 


@cauedotnet

Spotware
19 Sep 2017, 12:33

Dear cauedotnet,

Is it possible to provide us with the necessary information so that we can reproduce this behavior and provide an explanation? We will need a cBot, backtesting parameters and backtesting period. 

Best Regards,

cTrader Team


@Spotware

cauedotnet
29 Sep 2017, 19:01 ( Updated at: 21 Dec 2023, 09:20 )

RE: Here is the info you need

Sure I can.

I build a simple calgo bot, only so i can compare your backtesting with my spreadsheet backtesting. I will post all the code here. 

My spreadsheet system produces the same trades, in the same moment (date/time), same comission, but the gross profit is sligly diferent, only by some dolars. But I need to understand why.

Here is the CBOT to test:

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Requests;
using cAlgo.Indicators;
namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SimpleBot : Robot
    {
        [Parameter("Initial Volume", DefaultValue = 10000, MinValue = 0)]
        public int InitialVolume { get; set; }
        [Parameter("Stop Loss", DefaultValue = 40)]
        public int StopLoss { get; set; }
        [Parameter("Take Profit", DefaultValue = 40)]
        public int TakeProfit { get; set; }
        private Random random = new Random();
        private Position position;
        private string label = "simpleBot";
        protected override void OnStart()
        {
            ExecuteOrder(InitialVolume, GetDiffTradeCommand());
            this.Positions.Opened += Positions_Opened;
            this.Positions.Closed += Positions_Closed;
        }

        void Positions_Closed(PositionClosedEventArgs obj)
        {
            OnPositionClosed(obj.Position);
        }

        void Positions_Opened(PositionOpenedEventArgs obj)
        {
            OnPositionOpened(obj.Position);
        }

        protected override void OnStop()
        {
            Positions.Where(pos => pos.Label == label).ToList().ForEach(pos => { ClosePosition(pos); });
        }

        private void ExecuteOrder(int volume, TradeType tradeType)
        {
            ExecuteMarketOrder(tradeType, Symbol, volume, label, StopLoss, TakeProfit);
        }
        protected override void OnPositionOpened(Position openedPosition)
        {
            position = openedPosition;
        }
        protected override void OnPositionClosed(Position closedPosition)
        {
            if (closedPosition.GrossProfit > 0)
            {
                ExecuteOrder(InitialVolume, position.TradeType);
            }
            else
            {
                ExecuteOrder((int)position.Volume * 2, GetDiffTradeCommand(position.TradeType));
            }
        }

        protected override void OnError(Error error)
        {
            if (error.Code == ErrorCode.BadVolume)
                Stop();
        }
        private TradeType GetDiffTradeCommand(TradeType type = TradeType.Sell)
        {
            return type == TradeType.Sell ? TradeType.Buy : TradeType.Sell;
        }
    }
}

Here are the config and results:

My spreadsheet give me this result for the same test period.

First Trade:

  • Entry Price 76.207
  • Close Price 76.107
  • Entry Time 02/02/2012 00:00
  • Close Time 02/02/2012 06:30
  • Commission -0.06
  • Gross Profit -1.31
  • Net Profit -1.37
  • Vol 1000

SecondTrade:

  • Entry Price 76.107
  • Close Price 76.216
  • Entry Time 02/02/2012 06:30
  • Close Time 02/02/2012 19:46
  • Commission -0.12
  • Gross Profit -2.86
  • Net Profit -2.98
  • Vol 2000

 

Please help me how to figure out the gross profit formula. Me and my friend want to pass a lot of strategies from excel to cbot, but the formula need to match so we can choose the best strategies.

 

Thank you very much for your help.

 

 


@cauedotnet

PanagiotisCharalampous
02 Oct 2017, 09:17

Hi cauedotnet,

Can we also have the broker you are using in order to use the same historical data for backtesting?

Best Regards,

Panagiotis


@PanagiotisCharalampous

cauedotnet
02 Oct 2017, 19:04

My Broker

Hi Panagiotis.

I'm using FxPro.

As I said before, I'm trying to figure out what is the Gross Profit correct formula used by CTrader.

I was thinking that the formula was (entry/exit) * volume * (1/exit) => 76.207/76.107 * 100000 * 1/76.107 => -1.3156... But in CAlgo Results, the Gross was -1.00. I think my formula is wrong, maybe the last part is (1/pairRate).. But I don't know how to calculate this rate. How can I get it? Or maybe there is a deposit rate too. Im really lost in these calculations.

Thanks


@cauedotnet

PanagiotisCharalampous
03 Oct 2017, 17:09

Hi cauedotnet,

We have investigated the issue and the discrepancy is caused because in cAlgo's profit calculation equation, the conversion rate (the ... * 1/76.107 ... part) is not taken from the position's closing price, instead a single value is used which taken from the backtesting period's last day. It has been implemented this way to facilitate the need to convert the profit to any currency account, for which the conversion rate is not available for every single point in time. However, as your calculations show it might lead to confusion when the account's currency is one of the Symbol's currencies and the conversion rate is available in real time. Therefore, the cAlgo team is considering changing this logic for such cases. We will keep you posted.

In a nutshell your calculations are correct, it is just the fact that cAlgo uses a different formula to calculate P&L and might lead to these small discrepancies.

Best Regards,

Panagiotis

 

 

 


@PanagiotisCharalampous

BeardPower
20 Nov 2017, 16:01

RE:

Panagiotis Charalampous said:

It has been implemented this way to facilitate the need to convert the profit to any currency account, for which the conversion rate is not available for every single point in time.

How comes? Just use the most recent quote for any point in time. Regardless of the aggregation type (ticks or time periods), there is always a most recent quote,

In a nutshell your calculations are correct, it is just the fact that cAlgo uses a different formula to calculate P&L and might lead to these small discrepancies.

On the contrary. The discrepancies can be huge! A discrepancy of 2% is all but small.
As seen here:
/forum/cbot-support/12146?page=2#18
 


@BeardPower

PanagiotisCharalampous
21 Nov 2017, 11:44

Hi BeardPower,

How comes? Just use the most recent quote for any point in time. Regardless of the aggregation type (ticks or time periods), there is always a most recent quote,

This is not always the case. Let's suppose you are running a backtest on EURGBP using USD account. Profit from GBP needs to be converted to USD. The way that is implemented now is that we take quote for GBPUSD from last backtest date and use it along whole backtesting. We do not make the conversion using the GBPUSD at each given moment since we will need to also download the tick data for that pair as well. So now for convenience we just take an indicative conversion rate and use it all along. However it seems that the current behavior causes confusion, therefore we are planning to change this behaviour.

Best Regards,

Panagiotis


@PanagiotisCharalampous

BeardPower
21 Nov 2017, 14:06

RE:

Panagiotis Charalampous said:

This is not always the case. Let's suppose you are running a backtest on EURGBP using USD account. Profit from GBP needs to be converted to USD. The way that is implemented now is that we take quote for GBPUSD from last backtest date and use it along whole backtesting. We do not make the conversion using the GBPUSD at each given moment since we will need to also download the tick data for that pair as well. So now for convenience we just take an indicative conversion rate and use it all along. 

So it is not always the case, not because there is no conversion rate at any point in time, but because you are just not using it (not downloading it).
I was a little confused by your previous statement. There's a big difference in not using something, although its there to not using it because it doesn't exist :)

However it seems that the current behavior causes confusion, therefore we are planning to change this behaviour.

Thanks. This behavior needs to be addressed by Spotware. It's not only confusing, but it also renders backtesting meaningless, as it does not show the user the real outcome. There isn't even the used conversion rate noted anywhere on the chart or the log.


@BeardPower

ctidmarkowski
04 Sep 2022, 19:06

Status of backtesting exchange rate

Hi,

After crafting my first program and comparing it to my MQL5, I noticed substantial differences in the outcome of the same code. The previous discussion may explain why that is. As BeardPower rightfully states, this way of working by cTrader is not only confusing but it renders backtesting meaningless.

Has this been addressed by Spotware? Can someone give my an update on the status of this topic?

Thank you


@ctidmarkowski