Backtesting stopps unexpectedly

13 Feb 2018, 04:08Backtesting stopps unexpectedly#1
alexander.n.fedorovposts: 21since: 02 Jan 2018

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.

 

 

 

13 Feb 2018, 10:30#2
Panagiotis Charalampousposts: 508since: 13 Jan 2017

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


Head of Community Management at cTrader
13 Feb 2018, 10:32Backtesting#3
alexander.n.fedorovposts: 21since: 02 Jan 2018

Dear Panagiotis.

I will do in about an hour

 

13 Feb 2018, 10:51Backtesting#4
alexander.n.fedorovposts: 21since: 02 Jan 2018

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

 

13 Feb 2018, 11:10#5
Panagiotis Charalampousposts: 508since: 13 Jan 2017

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


Head of Community Management at cTrader
13 Feb 2018, 11:16Backtesting#6
alexander.n.fedorovposts: 21since: 02 Jan 2018

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