Partial Close of trade not being tallied in Backtesting or Optimization

Created at 28 Nov 2020, 06:33
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!
PR

prosteel1

Joined 04.07.2018

Partial Close of trade not being tallied in Backtesting or Optimization
28 Nov 2020, 06:33


Hi I am backtesting and optimizing a cbot with a partial close of the position.

In the below example a trade of 1 Lot is opened and half of it is closed using ClosePosition(position, newVol).

The Backtesting results show the Trade Statistics not including the partial closes in it's calculations. While the Net Profit circled in green is correct.

The Optimization results show the Trade Statistics not including the partial closes in it's calculations. While the Net Profit circled in yellow is incorrect, while the ending balance and equity circled in green is correct.

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SampleRSIcBot : Robot
    {
        [Parameter("Quantity (Lots)", Group = "Volume", DefaultValue = 1, MinValue = 0.01, Step = 0.01)]
        public double Quantity { get; set; }

        [Parameter("Source", Group = "RSI")]
        public DataSeries Source { get; set; }

        [Parameter("Periods", Group = "RSI", DefaultValue = 14)]
        public int Periods { get; set; }

        [Parameter("Partial Close offset", DefaultValue = 10, MinValue = 10, Step = 10)]
        public int Offset { get; set; }

        private RelativeStrengthIndex rsi;

        protected override void OnStart()
        {
            rsi = Indicators.RelativeStrengthIndex(Source, Periods);
        }
        protected override void OnStop()
        {
            foreach (var position in Positions)
            {
                ClosePosition(position);
            }
        }

        protected override void OnTick()
        {
            if (rsi.Result.LastValue < 30)
            {
                Close(TradeType.Sell);
                Open(TradeType.Buy);
            }
            else if (rsi.Result.LastValue > 70)
            {
                Close(TradeType.Buy);
                Open(TradeType.Sell);
            }
            if (rsi.Result.LastValue < 30 + Offset)
            {
                PartialClose(TradeType.Sell);
            }
            if (rsi.Result.LastValue > 70 - Offset)
            {
                PartialClose(TradeType.Buy);
            }
        }

        private void Close(TradeType tradeType)
        {
            foreach (var position in Positions.FindAll("SampleRSI", SymbolName, tradeType))
                ClosePosition(position);
        }

        private void PartialClose(TradeType tradeType)
        {

            foreach (var position in Positions.FindAll("SampleRSI", SymbolName, tradeType))
            {
                double newVol = Symbol.NormalizeVolumeInUnits((position.VolumeInUnits / 2), RoundingMode.Up);
                if (position.Quantity == Quantity)
                {
                    ClosePosition(position, newVol);
                    Print("Partial closing " + newVol + " of " + position + " due to RSI = " + rsi.Result.LastValue);
                }
            }
        }

        private void Open(TradeType tradeType)
        {
            var position = Positions.Find("SampleRSI", SymbolName, tradeType);
            var volumeInUnits = Symbol.QuantityToVolumeInUnits(Quantity);

            if (position == null)
                ExecuteMarketOrder(tradeType, SymbolName, volumeInUnits, "SampleRSI");
        }
    }
}

 


@prosteel1
Replies

PanagiotisCharalampous
30 Nov 2020, 15:31

Hi prosteel1,

I have forwarded this issue to the product team for investigation.

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous