Decimal OverflowException on cBot optimization when using multi timeframe

Created at 20 Aug 2023, 17:21
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!
MA

Marisco

Joined 11.07.2023

Decimal OverflowException on cBot optimization when using multi timeframe
20 Aug 2023, 17:21


Hello folks,

When optimizing a scalping bot I'm getting the following exception:

Where's a snippet:

It also happens when ExponentialMovingAverage is used, although it's more frequent with HullMovingAverage. It does not happen if SimpleMovingAverage is used instead.

It only happens when using the Bars from a different timeframe (line 66).

In this instance, EmaTimeFrame is 6 hours while the optimization is running on 2 minutes.

There a log entry about the crash:

15/05/2023 21:01:00.070 | CBot instance [RsiSeller, AUDCHF, m1] crashed with error #FDDE36C4.

I checked the ema values and bars using breakpoints and Print statements, all seems fine.

OnException method is never called, even tried a breakpoint on line 77, but nothing.

Am I going about this wrong ?


@Marisco
Replies

firemyst
21 Aug 2023, 01:41

Everything you've done seems legit to me. The OnException probably isn't being called because it might not be anything to do with your code, but rather a bug in cTrader itself.

There are two more things you can try:

  1. put individual try/catch blocks around each assignment statement in your OnStart method to see if that does anything in terms of catching something. I doubt it, but you never know. 

Example:

protected override void OnStart()
{
    try {
        emaBars = MarketData.GetBars(EmaTimeFrame);
    }
    catch (Exception e) {
        print ("EXCEPTION 1! {0}", e.ToString());
    }
    try {
        ema = Indicators.HullMovingAverage(emaBars.OpenPrices, EmaPeriods);
    }
    catch (Exception e) {
        print ("EXCEPTION 2! {0}", e.ToString());
    }
    
    //etc etc
}

 

2. look in your Windows Event view logs for the big red ERROR indication. There might be a clue in there on what's happened. Either way, it would be great to post that information too because that will also help @Spotware @cTraderTeam in investigating/fixing the issue if it is indeed a bug with cTrader itself.

 

 


@firemyst

PanagiotisChar
21 Aug 2023, 05:09

Hi there,

Better share the complete cBot code and exact steps to reproduce (optimization parameters, dates etc). It's hard to advise you with only a snippet.

Aieden Technologies

Need help? Join us on Telegram


 

 


@PanagiotisChar

Marisco
21 Aug 2023, 15:38

@firemyst

Event Viewer doesn't show any errors related to this problem… but I've found a workaround.

I figured it only happens when Stop Out is reached, so if I stop the bot before that (line 114), then there's no exception.

Not sure if the exception is related to the multi timeframe part at all anymore.

Thanks for the tips, appreciate it.

@PanagiotisChar

Ok, posting the code below.

Line 114 seems to solve the issue.

Dates are between 08/05/2023 and 13/08/2023.

Starting capital: 1000 USD; Commission: 35; Tick data with additional symbols; Grid method

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

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.FullAccess)]
    public class RsiSeller : Robot
    {
        [Parameter("Volume (Lots)", DefaultValue = 0.2)]
        public double VolumeInLots { get; set; }

        [Parameter("Label", DefaultValue = "RsiBot")]
        public string Label { get; set; }

        [Parameter("Max Open Positions", DefaultValue = 3, MinValue = 1)]
        public int MaxPositions { get; set; }

        [Parameter("CoolDown Periods", DefaultValue = 15, MinValue = 0)]
        public int CooldownPeriods { get; set; }

        [Parameter("Take Profit", Group = "Stop Loss / Take Profit", DefaultValue = 30)]
        public int TakeProfit { get; set; }

        [Parameter("BreakEven Trigger %", Group = "Stop Loss / Take Profit", DefaultValue = 0.5)]
        public double BreakEvenTrigger { get; set; }

        [Parameter("BreakEven Add Pips", Group = "Stop Loss / Take Profit", DefaultValue = 2)]
        public int BreakEvenAddPips { get; set; }

        [Parameter("BreakEven Volume", Group = "Stop Loss / Take Profit", DefaultValue = 0.1)]
        public double BreakEvenVolume { get; set; }

        [Parameter("Risk Ratio", Group = "Stop Loss / Take Profit", DefaultValue = 1)]
        public double RiskRatio { get; set; }

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

        [Parameter("RSI High Level", Group = "RSI", DefaultValue = 70)]
        public int RsiHigh { get; set; }

        [Parameter("MA Active", Group = "EMA", DefaultValue = true)]
        public bool IsEmaActive { get; set; }

        [Parameter("MA Timeframe", Group = "EMA")]
        public TimeFrame EmaTimeframe { get; set; }

        [Parameter("MA Periods", Group = "EMA", DefaultValue = 20)]
        public int EmaPeriods { get; set; }

        private RelativeStrengthIndex rsi;

        private HullMovingAverage ema;

        private Bars emaBars;


        protected override void OnStart()
        {
#if DEBUG
            System.Diagnostics.Debugger.Launch();
#endif
            emaBars = MarketData.GetBars(EmaTimeframe);

            ema = Indicators.HullMovingAverage(emaBars.OpenPrices, EmaPeriods);

            rsi = Indicators.RelativeStrengthIndex(Bars.OpenPrices, RsiPeriods);

            Timer.Start(TimeSpan.FromHours(1));
        }

        protected override void OnBar()
        {
            var positions = Positions.FindAll(Label, SymbolName, TradeType.Sell);

            //Breakeven and TP1
            foreach (var position in positions)
            {
                if (position.Pips < BreakEvenTrigger * TakeProfit || position.VolumeInUnits < Symbol.QuantityToVolumeInUnits(VolumeInLots)) 
                    continue;

                ClosePositionAsync(position, Symbol.QuantityToVolumeInUnits(BreakEvenVolume));

                var breakevenStopLoss = RoundPrice(position.EntryPrice - BreakEvenAddPips * Symbol.PipSize, TradeType.Sell);
                ModifyPositionAsync(position, breakevenStopLoss, position.TakeProfit);
            }

            // Opens new position
            if (IsRsiFalling() && IsEmaFalling() && IsCooledDown())
            {
                var volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots);

                ExecuteMarketOrderAsync(TradeType.Sell, SymbolName, volumeInUnits, Label, TakeProfit * RiskRatio, TakeProfit);
            }
        }

        private double RoundPrice(double price, TradeType tradeType)
        {
            var multiplier = Math.Pow(10, Symbol.Digits);

            if (tradeType == TradeType.Buy)
                return Math.Ceiling(price * multiplier) / multiplier;

            return Math.Floor(price * multiplier) / multiplier;
        }

        protected override void OnTimer()
        {
            //Print("{0} - {1} = {2}", ema.Result.Last(1), ema.Result.Last(0), emaBars.LastBar.OpenTime);

            //if (Account.Equity < 300) Stop();

            //var positions = Positions.FindAll(Label, SymbolName, TradeType.Sell);

            //if (IsEmaRising())
            //{
            //    foreach (var positon in positions)
            //    {
            //        ClosePositionAsync(positon);
            //    }
            //}
        }

        private Boolean IsRsiFalling()
        {
            return rsi.Result.Last(1) > RsiHigh && rsi.Result.Last(0) < RsiHigh;
        }

        private Boolean IsEmaRising()
        {
            if (!IsEmaActive) return false;

            return ema.Result.Last(1) < ema.Result.Last(0);
        }

        private Boolean IsEmaFalling()
        {
            if(!IsEmaActive) return true;

            return ema.Result.Last(1) > ema.Result.Last(0);
        }

        private Boolean IsCooledDown()
        {
            var positions = Positions.FindAll(Label, SymbolName, TradeType.Sell);

            if (positions.Length == 0) return true;

            if (positions.Length == MaxPositions) return false;

            var timeframeMinutes = Int32.Parse(TimeFrame.ShortName.Substring(1));

            return positions.Last().EntryTime.AddMinutes(timeframeMinutes * CooldownPeriods) < Time;
        }

        protected override void OnStop()
        {
            foreach (var position in Positions.FindAll(Label, SymbolName, TradeType.Sell)) 
                position.Close();
        }

        protected override void OnException(Exception exception)
        {
            if (exception is OverflowException)
            {
                Print(exception.Message);
            }
        }

        protected override double GetFitness(GetFitnessArgs args)
        {

            double[] criteriaValuesToMaximize = new double[] { args.NetProfit, args.WinningTrades };
            double[] criteriaValuesToMinimize = new double[] { args.MaxBalanceDrawdownPercentages, args.LosingTrades };

            double numerator = 1.0;
            double denominator = 1.0;

            if (criteriaValuesToMaximize.Length > 0)
                numerator = Math.Abs(criteriaValuesToMaximize.Aggregate((acc, cur) => acc * cur));

            if (criteriaValuesToMinimize.Length > 0)
                denominator += Math.Abs(criteriaValuesToMinimize.Aggregate((acc, cur) => acc * cur));

            int sign = criteriaValuesToMinimize.Concat(criteriaValuesToMaximize).Any(v => v < 0) ? -1 : 1;

            return sign * numerator / denominator;
        }

    }
}

@Marisco

Marisco
21 Aug 2023, 15:39

Optset:

{
  "Parameters": [
    {
      "Name": "c02b25309272471b89a4de3831c473c5",
      "Value": "m1",
      "ParameterType": "TimeFrame",
      "Optimize": true,
      "Values": [
        "m2",
        "m4"
      ]
    },
    {
      "Name": "VolumeInLots",
      "Value": "0.3",
      "ParameterType": "Double",
      "Optimize": false,
      "Min": "-0.3",
      "Max": "0.51",
      "Step": "0.1"
    },
    {
      "Name": "Label",
      "Value": "RsiSeller",
      "ParameterType": "String",
      "Optimize": false
    },
    {
      "Name": "MaxPositions",
      "Value": "3",
      "ParameterType": "Integer",
      "Optimize": false,
      "Min": "3",
      "Max": "4",
      "Step": "1"
    },
    {
      "Name": "CooldownPeriods",
      "Value": "20",
      "ParameterType": "Integer",
      "Optimize": true,
      "Min": "0",
      "Max": "30",
      "Step": "15"
    },
    {
      "Name": "TakeProfit",
      "Value": "34",
      "ParameterType": "Integer",
      "Optimize": true,
      "Min": "28",
      "Max": "34",
      "Step": "2"
    },
    {
      "Name": "BreakEvenTrigger",
      "Value": "0.6",
      "ParameterType": "Double",
      "Optimize": true,
      "Min": "0.5",
      "Max": "0.7",
      "Step": "0.2"
    },
    {
      "Name": "BreakEvenAddPips",
      "Value": "6",
      "ParameterType": "Integer",
      "Optimize": false,
      "Min": "4",
      "Max": "7",
      "Step": "2"
    },
    {
      "Name": "BreakEvenVolume",
      "Value": "0.15",
      "ParameterType": "Double",
      "Optimize": false,
      "Min": "0.1",
      "Max": "0.6",
      "Step": "0.1"
    },
    {
      "Name": "RiskRatio",
      "Value": "1",
      "ParameterType": "Double",
      "Optimize": true,
      "Min": "0.7",
      "Max": "1",
      "Step": "0.3"
    },
    {
      "Name": "RsiPeriods",
      "Value": "14",
      "ParameterType": "Integer",
      "Optimize": true,
      "Min": "16",
      "Max": "24",
      "Step": "2"
    },
    {
      "Name": "RsiHigh",
      "Value": "70",
      "ParameterType": "Integer",
      "Optimize": true,
      "Min": "56",
      "Max": "66",
      "Step": "2"
    },
    {
      "Name": "IsEmaActive",
      "Value": "True",
      "ParameterType": "Boolean",
      "Optimize": false
    },
    {
      "Name": "EmaTimeframe",
      "Value": "h6",
      "ParameterType": "TimeFrame",
      "Optimize": false
    },
    {
      "Name": "EmaPeriods",
      "Value": "20",
      "ParameterType": "Integer",
      "Optimize": false,
      "Min": "1000",
      "Max": "55",
      "Step": "200"
    }
  ]
}

@Marisco

Marisco
21 Aug 2023, 15:47

BTW, the real problem with the crash is the cTrader tries to re-run the offending pass indefinitely, thus “blocking” a CPU thread and wasting resources.

 

Another thing, is there a way to select multiple timeframes for the MTF part?

That option is non-selectable in the Parameters.


@Marisco

Spotware
22 Aug 2023, 05:30

Dear Marisco,

Thank you for reporting this issue. We were able to reproduce it and and we will fix it in an upcoming update.

Best regards,

cTrader Team


@Spotware

dave.anderson.consulting
22 Aug 2023, 21:35 ( Updated at: 22 Aug 2023, 21:36 )

RE: Decimal OverflowException on cBot optimization when using multi timeframe

Spotware said: 

Dear Marisco,

Thank you for reporting this issue. We were able to reproduce it and and we will fix it in an upcoming update.

Best regards,

cTrader Team

Actually the optimization feature is broken. I hope this gets some priority.

By the way, this issue also occurs on single timeframe cBots.


@dave.anderson.consulting

dave.anderson.consulting
23 Aug 2023, 11:13

RE: Decimal OverflowException on cBot optimization when using multi timeframe

Spotware said: 

Dear Marisco,

Thank you for reporting this issue. We were able to reproduce it and and we will fix it in an upcoming update.

Best regards,

cTrader Team

Any workaround for this until your next update?
I can't tell my customer to wait for Spotware to come out with an update someday.


@dave.anderson.consulting

... Deleted by UFO ...

acrigney
24 Aug 2023, 03:08

I am getting this problem as well

02/08/2023 10:21:00.000 | CBot instance  crashed with error #FDDE36C4

It seems to be related to loading more data for my bots.

dave.anderson.consulting said: 

Spotware said: 

Dear Marisco,

Thank you for reporting this issue. We were able to reproduce it and and we will fix it in an upcoming update.

Best regards,

cTrader Team

Any workaround for this until your next update?
I can't tell my customer to wait for Spotware to come out with an update someday.

 


@acrigney

acrigney
24 Aug 2023, 03:20

RE: I am getting this problem as well

acrigney said: Hopefully you can put in a hotfix for this asap? Its pretty urgent!!

02/08/2023 10:21:00.000 | CBot instance  crashed with error #FDDE36C4

It seems to be related to loading more data for my bots.

dave.anderson.consulting said: 

Spotware said: 

Dear Marisco,

Thank you for reporting this issue. We were able to reproduce it and and we will fix it in an upcoming update.

Best regards,

cTrader Team

Any workaround for this until your next update?
I can't tell my customer to wait for Spotware to come out with an update someday.

 

 


@acrigney

Spotware
24 Aug 2023, 04:59

Dear traders,

An update for this issue will be released soon.

Best regards,

cTrader Team


@Spotware

ricokoff
24 Aug 2023, 08:05 ( Updated at: 25 Aug 2023, 05:00 )

RE: Decimal OverflowException on cBot optimization when using multi timeframe

Spotware said: 

Dear traders,

An update for this issue will be released soon.

Best regards,

cTrader Team

Hi cTrader team,

Do you have any idea how soon we could expect this update? Like a day, week or month? My bot also stopped working because of this errorcode, while it runs perfectly fine on old cTrader versions. Judging by the amount if people that seem to encounter this issue and the impact of broken cBots, I think this is pretty urgent.

Thanks for your efforts though and I hope that you are able to fix this soon.

Kind regards,

Rico


@ricokoff

Spotware
25 Aug 2023, 05:01

Dear traders,

The new update (v4.8.23) was released on Cross Broker cTrader and some brokers. Please let us know if you still experience this problem with this version.

Best regards,

cTrader Team


@Spotware

dave.anderson.consulting
29 Aug 2023, 15:52

I no longer experience this. Thanks for quick update and hopefully a better testing process in the future.


@dave.anderson.consulting

dave.anderson.consulting
29 Aug 2023, 15:53

RE: Decimal OverflowException on cBot optimization when using multi timeframe

Spotware said: 

Dear traders,

The new update (v4.8.23) was released on Cross Broker cTrader and some brokers. Please let us know if you still experience this problem with this version.

Best regards,

cTrader Team

I no longer experience this. Thanks for quick update and hopefully a better testing process in the future.


@dave.anderson.consulting