Slow backtesting

Created at 14 Jul 2023, 23:57
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!
MI

mihaiandreana

Joined 29.08.2022

Slow backtesting
14 Jul 2023, 23:57


My cBot is experiencing very slow backtesting after the last update. Backtesting the same cBot on ctrader-ftmo is much faster(just as it was in ctrader-spotware before the update).

I tried backtesting on different computers, diferent versions of Windows but the result is the same. Here is the code sample:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.FullAccess)]
    public class Optimized : Robot
    {
        [Parameter(DefaultValue = 288)]
        public int Period { get; set; }

        double bullD, bearD;
        double bullC, bearC;
        double bullB, bearB;
        double bullA, bearA;
        double bullE, bearE;
        bool validBullD, validBearD;
        bool validBullC, validBearC;
        bool validBullB, validBearB;
        bool validBullA, validBearA;
        bool validBullE, validBearE;
        bool validBullPattern, validBearPattern;
        int allowedPeriod;
        Dictionary<DateTime, double> lowSwings = new();
        Dictionary<DateTime, double> highSwings = new();      

        protected override void OnStart() {
            for (int i = 4; i < Bars.Count-2; i++) {
                if (Bars.Last(i).High > Bars.Last(i + 1).High && Bars.Last(i).High > Bars.Last(i + 2).High && Bars.Last(i).High > Bars.Last(i - 1).High
                && Bars.Last(i).High > Bars.Last(i - 2).High) highSwings.Add(Bars.Last(i).OpenTime, Bars.Last(i).High);

                if (Bars.Last(i).Low < Bars.Last(i + 1).Low && Bars.Last(i).Low < Bars.Last(i + 2).Low && Bars.Last(i).Low < Bars.Last(i - 1).Low
                && Bars.Last(i).Low < Bars.Last(i - 2).Low) lowSwings.Add(Bars.Last(i).OpenTime, Bars.Last(i).Low);
            }
        }
        
        protected override void OnBar() {
            
            allowedPeriod = Math.Min(Period, Bars.Count-1);
            if(highSwings.ContainsKey(Bars.Last(allowedPeriod).OpenTime)) highSwings.Remove(Bars.Last(allowedPeriod).OpenTime);
            if(lowSwings.ContainsKey(Bars.Last(allowedPeriod).OpenTime)) lowSwings.Remove(Bars.Last(allowedPeriod).OpenTime);
            
            if (Bars.Last(3).High == Bars.HighPrices.Maximum(6)) highSwings.Add(Bars.Last(3).OpenTime, Bars.Last(3).High);
            if (Bars.Last(3).Low == Bars.LowPrices.Minimum(6)) lowSwings.Add(Bars.Last(3).OpenTime, Bars.Last(3).Low);
            
        }

        protected override void OnTick()
        {
            validBullPattern = false;
            validBearPattern = false;
            bullD = Symbol.Bid;
            bearD = Symbol.Bid;
            validBullD = bullD == Bars.LowPrices.Minimum(3);
            validBearD = bearD == Bars.HighPrices.Maximum(3);

            // BULL PATTERNS  
            if (validBullD)
            {
                List<DateTime> t2 = highSwings.Keys.ToList();
                foreach (DateTime i in t2)
                {   if(validBullPattern) break;
                        List<DateTime> t1 = lowSwings.Keys.Where(x => x <= i).ToList();

                        bullC = highSwings[i];
                        validBullC = bullC > bullD + 8*Symbol.PipSize && bullD == Bars.LowPrices.Minimum(1 + Bars.Where(x => x.OpenTime >= i).Count()); 

                        if (validBullC && t1.Count() > 0)
                        {
                            foreach (DateTime j in t1) 
                            {   if(validBullPattern) break;

                                    bullB = lowSwings[j];
                                    List<DateTime> filtered_swingsC = t2.Where(x => x >= j).ToList();
                                    validBullB = bullB < bullC && bullC == filtered_swingsC.Max(x => highSwings[x]);
                                    List<DateTime> filtered_swingsA = t2.Where(x => x <= j).ToList(); 
                                    
                                    if (validBullB && filtered_swingsA.Count() > 0) 
                                    {
                                        foreach (DateTime k in filtered_swingsA) 
                                        {   if(validBullPattern) break;

                                                bullA = highSwings[k];
                                                List<DateTime> filtered_swingsB = t1.Where(x => x >= k).ToList();
                                                validBullA = bullA > bullB && bullB == filtered_swingsB.Min(x => lowSwings[x]);
                                                List<DateTime> filtered_swingsE = t1.Where(x => x <= k).ToList();
                                                
                                                if (validBullA && filtered_swingsE.Count() > 0) 
                                                {
                                                    foreach (DateTime l in filtered_swingsE)
                                                    {   if(validBullPattern) break;

                                                            bullE = lowSwings[l]; 
                                                            validBullE = bullE < bullA && bullE ==  filtered_swingsE.Where(x => x >= l).Min(x => lowSwings[x]) && bullA == filtered_swingsA.Where(x => x >= l).Max(x => highSwings[x]);

                                                            if (validBullE)
                                                            {
  
                                                                    // Do something
                                                            }
                                                                    
                                                        }
                                                    }

                                                }

                                            }
                                                                  
                                        }

                                    }
                                }
                                                                    
                            }
                                                                                                                      
            // BEAR PATTERNS   
            if (validBearD)
            {
                List<DateTime> t2 = lowSwings.Keys.ToList();
                foreach (DateTime i in t2)
                {
                    if (validBearPattern) break;
                        List<DateTime> t1 = highSwings.Keys.Where(x => x <= i).ToList();

                        bearC = lowSwings[i];
                        validBearC = bearC < bearD - 8*Symbol.PipSize && bearD == Bars.HighPrices.Maximum(1 + Bars.Where(x => x.OpenTime >= i).Count());

                        if (validBearC && t1.Count() > 0)
                        {
                            foreach (DateTime j in t1)
                            {
                                if (validBearPattern) break;

                                    bearB = highSwings[j];
                                    List<DateTime> filtered_swingsC = t2.Where(x => x >=j).ToList();
                                    validBearB = bearB > bearC && bearC == filtered_swingsC.Min(x => lowSwings[x]);
                                    List<DateTime> filtered_swingsA = t2.Where(x => x <= j).ToList();

                                    if (validBearB && filtered_swingsA.Count() > 0)
                                    {
                                        foreach (DateTime k in filtered_swingsA)
                                        {
                                            if (validBearPattern) break;

                                                bearA = lowSwings[k];
                                                List<DateTime> filtered_swingsB = t1.Where(x => x >= k).ToList();
                                                validBearA = bearA < bearB && bearB == filtered_swingsB.Max(x => highSwings[x]);
                                                List<DateTime> filtered_swingsE = t1.Where(x => x <= k).ToList();

                                                if (validBearA && filtered_swingsE.Count() > 0)
                                                {
                                                    foreach (DateTime l in filtered_swingsE)
                                                    {
                                                        if (validBearPattern) break;

                                                            bearE = highSwings[l];
                                                            validBearE = bearE > bearA && bearE == filtered_swingsE.Where(x => x >= l).Max(x => highSwings[x]) && bearA == filtered_swingsA.Where(x => x >= l).Min(x => lowSwings[x]);

                                                            if (validBearE)
                                                            {
                   
                                                                   // Do something
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }

    } 
} }


@mihaiandreana