Backtesting Bug: Profit after open Trade not plausible, Support plz assist

Created at 15 Jun 2016, 00:25
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!
Mikro's avatar

Mikro

Joined 20.06.2015

Backtesting Bug: Profit after open Trade not plausible, Support plz assist
15 Jun 2016, 00:25


Hallo all,

I am encontering a strange behaviour Backtesting an EA.

I am using an Algo with different States. Basically the functionality works like this

'State1'
if(TradeConditionsLong == true)
{
ExecuteMarketOrder(...);
SetNextState(State2);
}

'State2'
if (OpenTrade.Position.Pips > BreakSafePips) // BreakSafePips=30
{
     ExecuteMarketOrder(...)
}

The Problem is, that imediately after opening the new Trade, the Position.Pips Value equals 30.6 pips! The Candle itself (EURUSD 02.06.2015 13:03:16) is increasing by over 30 Pips but over a Series of Ticks. The Pips Value should not be that high imediately! This causes a Loop because every new Trade seems to be profitable imediately causing the backtest to hang up ...

Has anybody experienced similar Problems?


@Mikro
Replies

Jiri
15 Jun 2016, 03:27 ( Updated at: 21 Dec 2023, 09:20 )

Yes. I recommend excluding several dates with such a huge negative spreads for you backtests.


@Jiri

Mikro
15 Jun 2016, 23:18

All right,

didn't expect negative Spread to be possible, despite I'd gladly accept a Bonus just for executing a Trade ;)

I added an Condition to the opening parameters for new Trades

If(OpenTrade == true && Symbol.Spread > 0)
{
   ExecuteMarketOrder()
}

That sorts out the bad Spread Data.

 

Why is there negative Spread???


@Mikro

Jiri
15 Jun 2016, 23:35

Again, I advice you to exclude entire day. Position can be executed when spread is above 0 but it can go negative on following tick and make your TakeProfit get hit immediately. Your backtest would give you pretty much the same results.

using System.Collections.Generic;
using System.Linq;

private List<DateTime> excludedDates = new List<DateTime>();

protected override void OnStart()
{
    excludedDates.Add(new DateTime(2015, 6, 2));
    excludedDates.Add(new DateTime(2015, 6, 8));
}

protected override void OnTick()
{
    foreach (DateTime excluded in excludedDates)
    {
        if (Time.Date == excluded.Date)
        {
            return;
        }
    }
}

 

 

 


@Jiri

Mikro
16 Jun 2016, 00:09

Thank you! I'll integrate that

Are those two date to only you have found so far?

Did that happen during real Trading anytime? Would be Bogus for the Broker but anyway, just being curious.


@Mikro

Jiri
16 Jun 2016, 00:41

I quickly wrote this algo which finds all negative spreads and if there is more than defined per day it will save it into collection, when it stops your dates will be printed into log.

Run it as regular backtest with tick data and find all negative spreads. :)

using System;
using System.Collections.Generic;
using System.Linq;
using cAlgo.API;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NegativeSpreadAnalyzer : Robot
    {
        [Parameter(DefaultValue = 10)]
        public int SpreadsToGetFiltered { get; set; }

        public class DateWithNegativeSpread
        {
            public DateTime DateTime { get; set; }
            public int Spreads { get; set; }
        }
        private List<DateWithNegativeSpread> dates = new List<DateWithNegativeSpread>();
        private DateTime last;
        private int negativeSpreads = 0;

        protected override void OnStart()
        {
            last = Time.Date;
        }

        protected override void OnTick()
        {
            if (Time.Date >= last.AddDays(1).Date)
            {
                negativeSpreads = 0;
                last = Time.Date;
            }
            else if (Symbol.Spread < 0)
            {
                negativeSpreads++;
            }

            if (negativeSpreads > SpreadsToGetFiltered)
            {
                if (dates.Exists(x => x.DateTime.Date == Time.Date))
                {
                    dates[dates.FindIndex(x => x.DateTime.Date == Time.Date)].Spreads = negativeSpreads;
                }
                else
                {
                    dates.Add(new DateWithNegativeSpread 
                    {
                        DateTime = Time.Date,
                        Spreads = negativeSpreads
                    });
                }
            }
        }

        protected override void OnStop()
        {
            foreach (var date in dates)
            {
                string text = string.Format("{0}\tNegative spreads: {1}", date.DateTime.ToString("d"), date.Spreads);
                Print(text);
            }
        }
    }
}

 


@Jiri

Jiri
16 Jun 2016, 00:58

Maybe sum of negative spreads in pips per day is even better approach for this solution.

using System;
using System.Collections.Generic;
using System.Linq;
using cAlgo.API;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NegativeSpreadAnalyzer : Robot
    {
        [Parameter(DefaultValue = 100)]
        public int MinNegativeSpreadInPipsPerDay { get; set; }

        public class DateWithNegativeSpread
        {
            public DateTime DateTime { get; set; }
            public double NegativeSpreadInPips { get; set; }
        }
        private List<DateWithNegativeSpread> dates = new List<DateWithNegativeSpread>();
        private DateTime lastDay;
        private double negativeSpreadInPipsThisDay = 0;

        protected override void OnStart()
        {
            lastDay = Time.Date;
        }

        protected override void OnTick()
        {
            if (Time.Date >= lastDay.AddDays(1).Date)
            {
                negativeSpreadInPipsThisDay = 0;
                lastDay = Time.Date;
            }
            else if (Symbol.Spread < 0)
            {
                negativeSpreadInPipsThisDay -= Symbol.Spread / Symbol.PipSize;
            }

            if (negativeSpreadInPipsThisDay >= MinNegativeSpreadInPipsPerDay)
            {
                if (dates.Exists(x => x.DateTime.Date == Time.Date))
                {
                    dates[dates.FindIndex(x => x.DateTime.Date == Time.Date)].NegativeSpreadInPips = negativeSpreadInPipsThisDay;
                }
                else
                {
                    dates.Add(new DateWithNegativeSpread 
                    {
                        DateTime = Time.Date,
                        NegativeSpreadInPips = negativeSpreadInPipsThisDay
                    });
                }
            }
        }

        protected override void OnStop()
        {
            foreach (var date in dates)
            {
                string text = string.Format("{0}\tNegative spread: {1} pips", date.DateTime.ToString("d"), Math.Round(date.NegativeSpreadInPips, 1));
                Print(text);
            }
        }
    }
}

 


@Jiri

Jiri
16 Jun 2016, 01:05 ( Updated at: 21 Dec 2023, 09:20 )

Results for unnamed broker. 

Filter set to 10000 pips.

19/01/2014 22:01:00.784 | Backtesting started
13/06/2016 23:59:59.747 | 25/05/2015	Negative spread: 63373.4 pips
13/06/2016 23:59:59.747 | 26/05/2015	Negative spread: 218132.6 pips
13/06/2016 23:59:59.747 | 27/05/2015	Negative spread: 202081.6 pips
13/06/2016 23:59:59.747 | 28/05/2015	Negative spread: 11550.1 pips
13/06/2016 23:59:59.747 | 29/05/2015	Negative spread: 290066.3 pips
13/06/2016 23:59:59.747 | 01/06/2015	Negative spread: 234630.1 pips
13/06/2016 23:59:59.747 | 02/06/2015	Negative spread: 377209.2 pips
13/06/2016 23:59:59.747 | 03/06/2015	Negative spread: 310437.4 pips
13/06/2016 23:59:59.747 | 04/06/2015	Negative spread: 390877.4 pips
13/06/2016 23:59:59.747 | 08/06/2015	Negative spread: 840852.4 pips
13/06/2016 23:59:59.747 | 09/06/2015	Negative spread: 10165.3 pips
13/06/2016 23:59:59.747 | 10/06/2015	Negative spread: 321649.7 pips
13/06/2016 23:59:59.747 | 11/06/2015	Negative spread: 233851.6 pips
13/06/2016 23:59:59.747 | 12/06/2015	Negative spread: 356911.1 pips
13/06/2016 23:59:59.747 | 15/06/2015	Negative spread: 302088.4 pips
13/06/2016 23:59:59.747 | 16/06/2015	Negative spread: 241474.1 pips
13/06/2016 23:59:59.747 | 17/06/2015	Negative spread: 518948.3 pips
13/06/2016 23:59:59.747 | 22/06/2015	Negative spread: 295252.5 pips
13/06/2016 23:59:59.747 | 23/06/2015	Negative spread: 261165 pips
13/06/2016 23:59:59.747 | 24/06/2015	Negative spread: 290066.6 pips
13/06/2016 23:59:59.747 | 25/06/2015	Negative spread: 207009.1 pips
13/06/2016 23:59:59.747 | 26/06/2015	Negative spread: 122347.6 pips
13/06/2016 23:59:59.747 | 01/07/2015	Negative spread: 257227 pips
13/06/2016 23:59:59.747 | 02/07/2015	Negative spread: 382292.1 pips
13/06/2016 23:59:59.747 | 03/07/2015	Negative spread: 94580.1 pips
13/06/2016 23:59:59.747 | 05/07/2015	Negative spread: 38531.3 pips
13/06/2016 23:59:59.747 | 06/07/2015	Negative spread: 163594.2 pips
13/06/2016 23:59:59.747 | 09/07/2015	Negative spread: 122429.8 pips
13/06/2016 23:59:59.747 | 10/07/2015	Negative spread: 139864.2 pips
13/06/2016 23:59:59.747 | 13/07/2015	Negative spread: 256186.6 pips
13/06/2016 23:59:59.747 | 14/07/2015	Negative spread: 276936.4 pips
13/06/2016 23:59:59.747 | 15/07/2015	Negative spread: 171471.6 pips
13/06/2016 23:59:59.747 | 16/07/2015	Negative spread: 108603.5 pips
13/06/2016 23:59:59.747 | 17/07/2015	Negative spread: 124232.1 pips
13/06/2016 23:59:59.747 | Backtesting finished

 


@Jiri