CTrader hanging/crashing when bot is stopped or finishes back test

Created at 26 Aug 2022, 12:58
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!
JA

jaydcrowe1989

Joined 11.08.2022

CTrader hanging/crashing when bot is stopped or finishes back test
26 Aug 2022, 12:58


Hi,

I think I am missing something because my bot doesn't seem to stop in a graceful way. It will run through the back tests fine, over 2 years for example, but when it gets to the end of the back test, CTrader seems to hang for ages as if the bot is still running. This also happens when I stop the bot using the stop button in the top right.

Has anyone had any issues with this?

Regards,

Jay


@jaydcrowe1989
Replies

PanagiotisCharalampous
26 Aug 2022, 14:27

Hi Jay,

Can you share the cBot code so that we can have a look?

Best Regards,

Panagiotis 

Join us on Telegram and Facebook

 


@PanagiotisCharalampous

jaydcrowe1989
26 Aug 2022, 15:17

RE:

PanagiotisCharalampous said:

Hi Jay,

Can you share the cBot code so that we can have a look?

Best Regards,

Panagiotis 

Join us on Telegram and Facebook

 

Here is the code...I have taken out the criteria for a trade because I want to protect this code...

 

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.GMTStandardTime, AccessRights = AccessRights.FullAccess)]
    public class ParabolicSARcBot : Robot
    {
        private ParabolicSAR _parabolicSAR;
        private RelativeStrengthIndex _rsi;
        private static bool _running;

        protected override void OnStart()
        {
            System.Diagnostics.Debugger.Launch();

            _running = false;
            _parabolicSAR = Indicators.ParabolicSAR(0.02, 0.2);
            _rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, 6);
        }

        protected override void OnTick()
        {
            if (!_running)
            {
                _running = true;

                Bar previousBar = Bars.Last(1);
                double previousPSar = _parabolicSAR.Result.Last(1);
                double previousRsi = _rsi.Result.Last(1);

                double latestPSar = _parabolicSAR.Result.LastValue;                

                bool trade = true;
                TimeSpan timeNow = Server.Time.TimeOfDay;

                if (Time.DayOfWeek == DayOfWeek.Friday && timeNow >= new TimeSpan(21, 0, 0))
                {
                    trade = false;
                }
                else if (timeNow >= new TimeSpan(20, 0, 0) && timeNow <= new TimeSpan(23, 59, 59))
                {
                    trade = false;
                }
                else if (timeNow >= new TimeSpan(0, 0, 0) && timeNow <= new TimeSpan(2, 00, 00))
                {
                    trade = false;
                }

                List<Position> currentPositions = Positions.Where(x => x.SymbolName == SymbolName).ToList();

                if (!currentPositions.Any())
                {
                    Print($"Time: {Server.Time.TimeOfDay}, Previous Bar Open: {previousBar.OpenTime}, Previous Dot: {previousPSar}, Current Price: {Symbol.Bid}, Current Dot: {latestPSar}");
                    
                    if (** Sell Criteria Met ** && trade)
                    {
                        if (TryGetVolume(TradeType.Sell, _parabolicSAR.Result.LastValue, out double stopLossPips, out double volume))
                        {
                            ExecuteMarketOrder(TradeType.Sell, SymbolName, volume, nameof(ParabolicSARcBot), stopLossPips, null);
                        }
                    }

                    if (** Buy Criteria Met **&& trade)
                    {
                        if (TryGetVolume(TradeType.Sell, _parabolicSAR.Result.LastValue, out double stopLossPips, out double volume))
                        {
                            ExecuteMarketOrder(TradeType.Buy, SymbolName, volume, nameof(ParabolicSARcBot), stopLossPips, null);
                        }
                    }
                }

                double latestRsi = _rsi.Result.LastValue;

                if (** Close Buy Criteria Met **)
                {
                    Print($"Close buy positions...time: {Server.Time.TimeOfDay}");
                    CloseBuyPositions(currentPositions);
                }

                if (** Close Sell Criteria Met **)
                {
                    Print($"Close sell positions...time: {Server.Time.TimeOfDay}");
                    CloseSellPositions(currentPositions);
                }

                _running = false;
            }
        }

        private void CloseBuyPositions(List<Position> currentPositions)
        {
            List<Position> buyPositions = currentPositions.Where(x => x.SymbolName == SymbolName && x.TradeType == TradeType.Buy).ToList();

            if (buyPositions.Any())
            {
                foreach (Position position in buyPositions)
                {
                    position.Close();
                }
            }
        }

        private void CloseSellPositions(List<Position> currentPositions)
        {
            List<Position> sellPositions = currentPositions.Where(x => x.SymbolName == SymbolName && x.TradeType == TradeType.Sell).ToList();

            if (sellPositions.Any())
            {
                foreach (Position position in sellPositions)
                {
                    position.Close();
                }
            }
        }

        private bool TryGetVolume(TradeType tradeType, double stopLoss, out double stopLossPips, out double volume)
        {
            bool success = false;

            double maxAmountRisked = Account.Balance * 0.01;

            double price = tradeType == TradeType.Buy ? Symbol.Bid : Symbol.Ask;
            stopLossPips = Math.Round((double)Math.Abs(price - stopLoss) / Symbol.PipSize, 1);
            volume = 0;

            if (stopLossPips > 0)
            {
                double noOfPips = (stopLossPips * Symbol.PipValue);
                double lotSize = maxAmountRisked / noOfPips;
                volume = Symbol.NormalizeVolumeInUnits(lotSize, RoundingMode.Down);
                Print($"Volume: {volume}...");
                success = true;
            }
            else
            {
                Print($"Failed to get Volume: {volume}...Stop loss pips: {stopLossPips}");
            }

            return success;
        }
    }
}


@jaydcrowe1989

PanagiotisCharalampous
26 Aug 2022, 16:10

Hi Jay,

It is possible to provide something that runs, so that I can run it and see the error immediatelly? 

The code you provided has errors and I cannot be guessing.

Best Regards,

Panagiotis 

Join us on Telegram and Facebook


@PanagiotisCharalampous

jaydcrowe1989
26 Aug 2022, 16:35

RE:

PanagiotisCharalampous said:

Hi Jay,

It is possible to provide something that runs, so that I can run it and see the error immediatelly? 

The code you provided has errors and I cannot be guessing.

Best Regards,

Panagiotis 

Join us on Telegram and Facebook

Correct the code will not run as is above because I have removed some code I want to protect and do not want to put it into the public domain. 

If you replace all of the code above marked up with asterix for example if (** Sell Criteria Met ** && trade) and just replace them with true this should then work

 

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.GMTStandardTime, AccessRights = AccessRights.FullAccess)]
    public class ParabolicSARcBot : Robot
    {
        private ParabolicSAR _parabolicSAR;
        private RelativeStrengthIndex _rsi;
        private static bool _running;

        protected override void OnStart()
        {
#if DEBUG
            System.Diagnostics.Debugger.Launch();
#endif

            _running = false;
            _parabolicSAR = Indicators.ParabolicSAR(0.02, 0.2);
            _rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, 6);
        }

        protected override void OnTick()
        {
            if (!_running)
            {
                _running = true;

                double previousRsi = _rsi.Result.Last(1);
                double latestPSar = _parabolicSAR.Result.LastValue;

                Position position = Positions.Find(nameof(ParabolicSARcBot), SymbolName);

                if (position == null)
                {
                    Bar previousBar = Bars.Last(1);
                    double previousPSar = _parabolicSAR.Result.Last(1);

                    Print($"Time: {Server.Time.TimeOfDay}, Previous Bar Open: {previousBar.OpenTime}, Previous Dot: {previousPSar}, Current Price: {Symbol.Bid}, Current Dot: {latestPSar}");

                    bool trade = true;
                    TimeSpan timeNow = Server.Time.TimeOfDay;

                    if (Time.DayOfWeek == DayOfWeek.Friday && timeNow >= new TimeSpan(21, 0, 0))
                    {
                        Print("Skipping trade as it is Friday past 9pm...");
                        trade = false;
                    }
                    else if (timeNow >= new TimeSpan(20, 0, 0) && timeNow <= new TimeSpan(23, 59, 59))
                    {
                        Print("Oh hell no...we are not trading right now...shit gonna get cray...");
                        trade = false;
                    }
                    else if (timeNow >= new TimeSpan(0, 0, 0) && timeNow <= new TimeSpan(2, 00, 00))
                    {
                        Print("Oh hell no...we are not trading right now...shit gonna get cray...");
                        trade = false;
                    }


                    if (true)
                    {
                        if (TryGetVolume(TradeType.Sell, _parabolicSAR.Result.LastValue, out double stopLossPips, out double volume))
                        {
                            TradeResult result = ExecuteMarketOrder(TradeType.Sell, SymbolName, volume, nameof(ParabolicSARcBot), stopLossPips, null);
                            result.Position.ModifyStopLossPrice(_parabolicSAR.Result.LastValue);
                        }
                    }

                    if (false)
                    {
                        if (TryGetVolume(TradeType.Sell, _parabolicSAR.Result.LastValue, out double stopLossPips, out double volume))
                        {
                            TradeResult result = ExecuteMarketOrder(TradeType.Buy, SymbolName, volume, nameof(ParabolicSARcBot), stopLossPips, null);
                            result.Position.ModifyStopLossPrice(_parabolicSAR.Result.LastValue);
                        }
                    }
                }
                else
                {
                    if (position.TradeType == TradeType.Buy)
                    {
                        if (true)
                        {
                            Print($"Close buy position...time: {Server.Time.TimeOfDay}");
                            position.Close();
                        }
                    }
                    else
                    {
                        if (false)
                        {
                            Print($"Close sell position...time: {Server.Time.TimeOfDay}");
                            position.Close();
                        }
                    }
                }

                _running = false;
            }
        }

        private void CloseBuyPositions(List<Position> currentPositions)
        {
            List<Position> buyPositions = currentPositions.Where(x => x.SymbolName == SymbolName && x.TradeType == TradeType.Buy).ToList();

            if (buyPositions.Any())
            {
                foreach (Position position in buyPositions)
                {
                    position.Close();
                }
            }
        }

        private void CloseSellPositions(List<Position> currentPositions)
        {
            List<Position> sellPositions = currentPositions.Where(x => x.SymbolName == SymbolName && x.TradeType == TradeType.Sell).ToList();

            if (sellPositions.Any())
            {
                foreach (Position position in sellPositions)
                {
                    position.Close();
                }
            }
        }

        private bool TryGetVolume(TradeType tradeType, double stopLoss, out double stopLossPips, out double volume)
        {
            bool success = false;

            double maxAmountRisked = Account.Balance * 0.01;

            double price = tradeType == TradeType.Buy ? Symbol.Bid : Symbol.Ask;
            stopLossPips = Math.Round((double)Math.Abs(price - stopLoss) / Symbol.PipSize, 1);
            volume = 0;

            if (stopLossPips > 0)
            {
                double noOfPips = (stopLossPips * Symbol.PipValue);
                double lotSize = maxAmountRisked / noOfPips;
                volume = Symbol.NormalizeVolumeInUnits(lotSize, RoundingMode.Down);
                Print($"Volume: {volume}...");
                success = true;
            }
            else
            {
                Print($"Failed to get Volume: {volume}...Stop loss pips: {stopLossPips}");
            }

            return success;
        }
    }
}


@jaydcrowe1989

PanagiotisCharalampous
29 Aug 2022, 09:44

Hi Jay,

I tried this both on 4.2.22 and 4.3.9 and works fine for me. The cBot terminates without problems.

Best Regards,

Panagiotis 

Join us on Telegram and Facebook


@PanagiotisCharalampous