Backtesting stopps unexpectedly

Created at 13 Feb 2018, 04:08
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!
alexander.n.fedorov's avatar

alexander.n.fedorov

Joined 02.01.2018

Backtesting stopps unexpectedly
13 Feb 2018, 04:08


Here is the cBot log I got

 

01/11/2017 03:00:00.000 | Backtesting started
01/11/2017 03:00:00.000 | symbol pipsize 0.0001 
01/11/2017 03:00:00.000 | _ATR is 0.000903659654142933
01/11/2017 15:25:00.000 | Executing Market Order to Sell 10000 EURUSD (SL: 26)
01/11/2017 15:25:00.000 | → Executing Market Order to Sell 10000 EURUSD (SL: 26) SUCCEEDED, Position PID1
02/11/2017 04:20:00.000 | Closing position PID1
02/11/2017 04:20:00.000 | → Closing position PID1 SUCCEEDED, Position PID1
02/11/2017 04:20:00.000 | Sorry
02/11/2017 04:20:00.000 | There have to be a second try stop order (Buy of Sell)
02/11/2017 04:20:00.000 | Placing Stop Order to Sell 10000 EURUSD (Price: 1.16356, SL: 6.45015692013447, ExpireTime: 04.11.2017 16:20:00)
02/11/2017 04:20:00.000 | → Placing Stop Order to Sell 10000 EURUSD (Price: 1.16356, SL: 6.45015692013447, ExpireTime: 04.11.2017 16:20:00) SUCCEEDED, PendingOrder OID2
02/11/2017 04:20:00.000 | Second Try order ID is 2
02/11/2017 04:20:00.000 | Backtesting was stopped

 

and here is the breakout cBot based on Doncian channels

 

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

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.RussianStandardTime, AccessRights = AccessRights.FullAccess)]
    public class Donci2a : Robot
    {
        #region Parameter Declarations
        [Parameter("Instance Name", DefaultValue = "Blue")]
        public string InstanceName { get; set; }

        //[Parameter("Source")]
        //public DataSeries Source { get; set; }

        [Parameter("SL ATR multiple", DefaultValue = 1.5)]
        public double ATRfactor { get; set; }

        [Parameter("Hi Periods", DefaultValue = 20)]
        public int HiPer { get; set; }

        [Parameter("Low Periods", DefaultValue = 10)]
        public int LowPer { get; set; }

        [Parameter("Quantity (Lots)", DefaultValue = 0.1, MinValue = 0.01, Step = 0.01)]
        public double Quantity { get; set; }

        [Parameter("Include Break-Even", DefaultValue = true)]
        public bool IncludeBreakEven { get; set; }

        [Parameter("Break-Even Trigger (ATR)", DefaultValue = 1.6)]
        public double Trigger { get; set; }

        [Parameter("Break-Even Extra (pips)", DefaultValue = 1.0, MinValue = 0.0)]
        public double ExtraPips { get; set; }

        [Parameter("Include Trailing Stop", DefaultValue = true)]
        public bool IncludeTrailingStop { get; set; }

        [Parameter("Trailing Stop Trigger (ATR)", DefaultValue = 1.9, MinValue = 1.0, Step = 0.1)]
        public double TrailingStopTrigger { get; set; }

        [Parameter("Trailing Stop Step (ATR)", DefaultValue = 1.2, MinValue = 0.5, Step = 0.1)]
        public double TrailingStopStep { get; set; }

        [Parameter("Second Try ", DefaultValue = false)]
        public bool SecondTry { get; set; }

        [Parameter("Secon Try ATR factor", DefaultValue = 1)]
        public double _ATR_FactorST { get; set; }




        public double SL;
        private double _ATR;
        private DonchianChannel DCH;
        private DonchianChannel DCL;
        private AverageTrueRange ATR;
        private DateTime BarOpenTime;
        private int _ID;
        private DateTime expiry;
        private double _price;
        private TradeType _tradetype;
        private bool StoppedByRobot = false;

        #endregion

        #region cTrader events
        protected override void OnStart()
        {
            Print("symbol pipsize {0} ", Symbol.PipSize);
            Positions.Closed += PositionsOnClosed;
            ATR = Indicators.AverageTrueRange(LowPer, MovingAverageType.Exponential);
            DCH = Indicators.DonchianChannel(HiPer);
            DCL = Indicators.DonchianChannel(LowPer);
            _ATR = ATR.Result.LastValue;
            Print("_ATR is {0}", _ATR);
        }

        protected override void OnTick()
        {

            var position = Positions.Find(InstanceName, Symbol);
            if (position == null)
            {
                //            if (InstanceName == "Blue")
                //          {
                if (DCH.Top.LastValue < Symbol.Bid)
                {
                    InstanceName = "Blue";
                    _tradetype = TradeType.Buy;
                    StoppedByRobot = false;
                    Open(_tradetype);
                }
                else if (DCH.Bottom.LastValue > Symbol.Bid)
                {
                    InstanceName = "Blue";
                    _tradetype = TradeType.Sell;
                    StoppedByRobot = false;
                    Open(_tradetype);
                }
                //        }

            }
            else if (position != null)
            {
                if (position.Label == "Blue")
                {
                    if ((position.TradeType == TradeType.Buy && DCL.Bottom.LastValue > Symbol.Bid) || (position.TradeType == TradeType.Sell && DCL.Top.LastValue < Symbol.Bid))
                    {
                        StoppedByRobot = false;
                        ClosePosition(position);
                    }
                }
                if (position.Label == "Red")
                {
                    if ((position.TradeType == TradeType.Sell && DCH.Bottom.LastValue >= Symbol.Bid) || (position.TradeType == TradeType.Buy && DCH.Bottom.LastValue <= Symbol.Bid))
                    {
                        StoppedByRobot = true;
                        ClosePosition(position);
                    }
                }
            }
            if (IncludeBreakEven == true)
                GoToBreakEven();
            if (IncludeTrailingStop == true)
                SetTrailingStop();
            // TrailStopOrders();
        }
        #endregion

        #region Open trade
        void Open(TradeType tradeType)
        {

            var volumeInUnits = Symbol.QuantityToVolume(Quantity);
            SL = ATR.Result.LastValue * ATRfactor / Symbol.PipSize;
            ExecuteMarketOrder(tradeType, Symbol, volumeInUnits, InstanceName, SL, null);

        }
        #endregion

        #region Break Even
        void GoToBreakEven()
        {
            var position = Positions.Find(InstanceName, Symbol);
            if (position != null)
            {
                var entryPrice = position.EntryPrice;
                var distance = 0.0;
                var adjEntryPrice = 0.0;

                if (position.TradeType == TradeType.Buy)
                {
                    adjEntryPrice = entryPrice + ExtraPips * Symbol.PipSize;
                    distance = Symbol.Bid - entryPrice;
                }
                else
                {
                    adjEntryPrice = entryPrice - ExtraPips * Symbol.PipSize;
                    distance = entryPrice - Symbol.Ask;
                }
                // Print("Distance {0}", distance);
                if (distance >= Trigger * ATR.Result.LastValue)
                {
                    if (position.TradeType == TradeType.Sell && position.StopLoss > adjEntryPrice)
                        ModifyPosition(position, adjEntryPrice, null);
                    if (position.TradeType == TradeType.Buy && position.StopLoss < adjEntryPrice)
                        ModifyPosition(position, adjEntryPrice, null);
                }

            }
        }
        #endregion

        #region Position Closed
        private void PositionsOnClosed(PositionClosedEventArgs args)
        {
            var position = args.Position;
            if ((position.Pips > (1 + 0.1) * -SL && position.Pips < (1 - 0.1) * -SL) || (position.Pips > (1 + 0.1) * SL && position.Pips < (1 - 0.1) * SL))
                StoppedByRobot = true;

            if (StoppedByRobot == false)
            {
                Print("Sorry");
                Stop();
            }
            if (SecondTry == true)
            {
                if (PendingOrders.Count == 0)
                {
                    if (InstanceName == "Blue")
                    {

                        BarOpenTime = MarketSeries.OpenTime.LastValue;
                        Print("There have to be a second try stop order (Buy of Sell)");

                        _ATR = ATR.Result.LastValue;
                        expiry = Server.Time.AddHours(60);
                        var volumeInUnits = Symbol.QuantityToVolume(Quantity);
                        _price = position.TradeType == TradeType.Buy ? Symbol.Ask + _ATR / 2 : Symbol.Bid - _ATR / 2;
                        InstanceName = "Red";
                        var result = PlaceStopOrder(position.TradeType, Symbol, volumeInUnits, _price, InstanceName, _ATR / 2 / Symbol.PipSize, null, expiry);
                        var order = result.PendingOrder;
                        _ID = order.Id;
                        Print("Second Try order ID is {0}", _ID);
                    }
                    else if (position.Label == "Red")
                    {
                        Print("The second try is over for the {0} ", position.Id);
                        StoppedByRobot = true;
                    }
                }
            }
        }
        #endregion

        #region Trailing Stop
        private void SetTrailingStop()
        {
            var sellPositions = Positions.FindAll(InstanceName, Symbol, TradeType.Sell);

            foreach (Position position in sellPositions)
            {
                double distance = position.EntryPrice - Symbol.Ask;

                if (distance < TrailingStopTrigger * _ATR)
                    continue;

                double newStopLossPrice = Symbol.Ask + TrailingStopStep * _ATR;

                if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                }
            }

            var buyPositions = Positions.FindAll(InstanceName, Symbol, TradeType.Buy);

            foreach (Position position in buyPositions)
            {
                double distance = Symbol.Bid - position.EntryPrice;

                if (distance < TrailingStopTrigger * _ATR)
                    continue;

                double newStopLossPrice = Symbol.Bid - TrailingStopStep * _ATR;
                if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                }
            }

        }
        #endregion

        #region Trail Stop Orders
        //private void TrailStopOrders()
        //{

        //    if (PendingOrders.Count > 0)
        //    {
        //        if (BarOpenTime == MarketSeries.OpenTime.LastValue)
        //            foreach (var order in PendingOrders)
        //            {
        //                expiry = Server.Time.AddHours(12);

        //                _priceShift = order.TradeType == TradeType.Buy ? _ATR / 2 : -_ATR / 2;
        //                _price = Symbol.Bid + _priceShift;
        //                // if (order.TradeType == TradeType.Sell && Symbol.Bid - _ATR / 2 > order.TargetPrice)
        //                ModifyPendingOrder(order, _price, _ATR / Symbol.PipSize / 2, _ATR / Symbol.PipSize / 2, expiry);
        //                //else if (order.TradeType == TradeType.Buy && Symbol.Bid + _ATR / 2 < order.TargetPrice)
        //                //    ModifyPendingOrder(order, Symbol.Bid + _ATR / 2, order.StopLoss, order.TakeProfitPips, expiry);
        //            }
        //    }

    }
    #endregion
}

Could you please help me understand why the backtesting is stopped and what shall I do to prevent it from stopping.

As you can see from the log the pending order is placed and has an ID, and then something happens.

Please, help me.

 

 

 


@alexander.n.fedorov
Replies

PanagiotisCharalampous
13 Feb 2018, 10:30

Hi Alexander,

Can I have your exact backtesting configuration (broker, timeframe, start and end dates, cbot parameters, starting volume etc) so that I can reproduce and see if I can advise you on this?

Best Regards,

Panagiotis


@PanagiotisCharalampous

alexander.n.fedorov
13 Feb 2018, 10:32

Backtesting

Dear Panagiotis.

I will do in about an hour

 


@alexander.n.fedorov

alexander.n.fedorov
13 Feb 2018, 10:51

Backtesting

In addition to timing info, which was tonight and is available from the cBot log, broker is ICMarkets, timeframe -  1 hr, lot=0.01

 


@alexander.n.fedorov

PanagiotisCharalampous
13 Feb 2018, 11:10

Hi Alexander,

The cBot stops because of this condition

            if (StoppedByRobot == false)
            {
                Print("Sorry");
                Stop();
            }

What was your intention writing this part?

Best Regards,

Panagiotis


@PanagiotisCharalampous

alexander.n.fedorov
13 Feb 2018, 11:16

Backtesting

I am trying to not stop the order or position  manually, but when I did have the above part, when I closed position by hand, it started to generate orders, because of event

I tryied to protect against closing by Stop Loss and Take Profit

I think it was either breakeven, or trailing, which I think I now should try how to handle.  In any case, you very good, and thank's a lot.

But I will be righting to you in the future

 

Alexander

 

 


@alexander.n.fedorov