CBot works well when backtesting but it does not place trades when i test it on live or demo accounts.

Created at 18 May 2021, 11:16
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!
AH

AhmedMoh181099

Joined 05.03.2021

CBot works well when backtesting but it does not place trades when i test it on live or demo accounts.
18 May 2021, 11:16


Hello, I've downloaded the night breakout bot which is available for free here. The bot is working well when backtesting in visual or non visual mod but when I test it in demo and live accounts, it doesn't place trades.

 

Here in the visual backtest, a trade is executed today:

 

But at the same time in both demo and live accounts, no trades were executed although the bot and ctrader were left active the moment a trade should've been executed.

 

Here is the full code:

 

 

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


namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NightBreakoutcBot : Robot
    {
        // ======================================================================

        [Parameter("GMT start hour", Group = "Box hours and size", DefaultValue = 22, MinValue = 0, MaxValue = 23)]
        public int ParamStartHour { get; set; }

        [Parameter("GMT start minute", Group = "Box hours and size", DefaultValue = 0, MinValue = 0, MaxValue = 59)]
        public int ParamStartMinute { get; set; }

        [Parameter("GMT end hour", Group = "Box hours and size", DefaultValue = 2, MinValue = 0, MaxValue = 23)]
        public int ParamEndHour { get; set; }

        [Parameter("GMT end minute", Group = "Box hours and size", DefaultValue = 0, MinValue = 0, MaxValue = 59)]
        public int ParamEndMinute { get; set; }

        [Parameter("Adjust summer time", Group = "Box hours and size", DefaultValue = true)]
        public bool ParamAdjustSummerTime { get; set; }

        [Parameter("Min box size (pips)", Group = "Box hours and size", DefaultValue = 15, MinValue = 0)]
        public int ParamMinBoxHeight { get; set; }

        [Parameter("Max box size (pips)", Group = "Box hours and size", DefaultValue = 45, MinValue = 0)]
        public int ParamMaxBoxHeight { get; set; }

        // ======================================================================

        // Choose fixed lot size or risk
        [Parameter("Method", Group = "Money management", DefaultValue = MMType.FIXED_LOT)]
        public MMType ParamMoneyMgmntType { get; set; }

        // Fixed lot size
        [Parameter("Lot size", Group = "Money management", DefaultValue = 0.01, MinValue = 0.01)]
        public double ParamLotSize { get; set; }

        // Percent of risk
        [Parameter("Risk %", Group = "Money management", DefaultValue = 2, MinValue = 0.1, MaxValue = 50.0)]
        public double ParamRisk { get; set; }

        // ===============================================================================

        [Parameter("Draw boxes in chart", Group = "Chart", DefaultValue = true)]
        public bool ParamDrawBoxes { get; set; }


        private string label = "NightBreakoutcBot";
        private string version = "1.0";

        private Status status;

        private double volume;

        private double hightakeProfitPrice;
        private double highStopLossPrice;
        private double highEntryPrice;
        private double lowtakeProfitPrice;
        private double lowStopLossPrice;
        private double lowEntryPrice;


        protected override void OnStart()
        {
            try
            {
                Positions.Closed += onPositionClosed;

                this.volume = Symbol.QuantityToVolumeInUnits(this.ParamLotSize);

                if (this.ParamDrawBoxes && (this.RunningMode == RunningMode.RealTime || this.RunningMode == RunningMode.VisualBacktesting))
                {
                    this.drawPastBoxes();
                }
                this.status = Status.IDLE;

                this.hightakeProfitPrice = 0.0;
                this.highStopLossPrice = 0.0;
                this.highEntryPrice = 0.0;
                this.lowtakeProfitPrice = 0.0;
                this.lowStopLossPrice = 0.0;
                this.lowEntryPrice = 0.0;

                if (this.RunningMode == RunningMode.RealTime || this.RunningMode == RunningMode.VisualBacktesting)
                {
                    Chart.DrawStaticText("version", "NightBreakout cBot " + this.version, VerticalAlignment.Bottom, HorizontalAlignment.Left, Chart.ColorSettings.ForegroundColor);
                }
                Print("Started " + this.label + " version " + this.version);

            } catch (Exception exc)
            {
                Print(exc.Message + " " + exc.StackTrace);
                throw exc;
            }
        }

        private void drawPastBoxes()
        {
            int finalIndex = Bars.Count - 1;
            for (int i = 30; i <= finalIndex; i++)
            {
                BoxHours boxHours = this.getBoxHours(Bars.OpenTimes[i]);
                int firstindex = 0;
                if (Bars.OpenTimes[i].Hour == boxHours.endHour && Bars.OpenTimes[i].Minute == this.ParamStartMinute)
                {
                    for (int j = i - 1; j > 0; j--)
                    {
                        if (Bars.OpenTimes[j].Hour == boxHours.startHour && Bars.OpenTimes[j].Minute == this.ParamEndMinute)
                        {
                            firstindex = j;
                            break;
                        }
                    }

                    double high = Bars.HighPrices[firstindex];
                    double low = Bars.LowPrices[firstindex];
                    for (int k = firstindex; k <= i; k++)
                    {
                        high = Math.Max(high, Bars.HighPrices[k]);
                        low = Math.Min(low, Bars.LowPrices[k]);
                    }
                    double delta = high - low;

                    Color color = Color.Lime;
                    if (delta < this.ParamMinBoxHeight * Symbol.PipSize || delta > this.ParamMaxBoxHeight * Symbol.PipSize)
                    {
                        color = Color.Red;
                    }

                    Chart.DrawRectangle(Guid.NewGuid().ToString(), firstindex, high, i, low, color, 2);
                    Chart.DrawTrendLine(Guid.NewGuid().ToString(), i, high + delta, i + 20, high + delta, color);
                    Chart.DrawTrendLine(Guid.NewGuid().ToString(), i, low - delta, i + 20, low - delta, color);
                }
            }
        }

        protected override void OnBar()
        {
            try
            {
                BoxHours boxHours = this.getBoxHours(Bars.OpenTimes.LastValue);
                if (this.status != Status.IDLE && Bars.OpenTimes.LastValue.Hour == boxHours.startHour && Bars.OpenTimes.LastValue.Minute == this.ParamStartMinute)
                {
                    this.status = Status.IDLE;
                }


                if (Bars.OpenTimes.LastValue.Hour == boxHours.endHour && Bars.OpenTimes.LastValue.Minute == this.ParamEndMinute)
                {
                    int lastIndex = Bars.OpenTimes.GetIndexByTime(Bars.OpenTimes.Last(1));
                    int firstIndex = 0;
                    for (int j = lastIndex - 1; j > 0; j--)
                    {
                        if (Bars.OpenTimes[j].Hour == boxHours.startHour && Bars.OpenTimes[j].Minute == this.ParamStartMinute)
                        {
                            firstIndex = j;
                            break;
                        }
                    }

                    double high = Bars.HighPrices[firstIndex];
                    double low = Bars.LowPrices[firstIndex];
                    for (int k = firstIndex; k <= lastIndex; k++)
                    {
                        high = Math.Max(high, Bars.HighPrices[k]);
                        low = Math.Min(low, Bars.LowPrices[k]);
                    }
                    double delta = high - low;

                    this.hightakeProfitPrice = high + delta;
                    this.highStopLossPrice = high - delta;
                    this.highEntryPrice = high;

                    this.lowtakeProfitPrice = low - delta;
                    this.lowStopLossPrice = low + delta;
                    this.lowEntryPrice = low;

                    this.status = Status.WAITING;

                    Color color = Color.Lime;
                    if (delta < this.ParamMinBoxHeight * Symbol.PipSize || delta > this.ParamMaxBoxHeight * Symbol.PipSize)
                    {
                        color = Color.Red;
                        this.status = Status.IDLE;
                    }
                    if (this.ParamDrawBoxes && (this.RunningMode == RunningMode.RealTime || this.RunningMode == RunningMode.VisualBacktesting))
                    {
                        Chart.DrawRectangle(Guid.NewGuid().ToString(), firstIndex, high, lastIndex, low, color, 2);
                        Chart.DrawTrendLine(Guid.NewGuid().ToString(), lastIndex, high + delta, lastIndex + 20, high + delta, color);
                        Chart.DrawTrendLine(Guid.NewGuid().ToString(), lastIndex, low - delta, lastIndex + 20, low - delta, color);
                    }
                }


                if (this.status == Status.WAITING)
                {
                    if (Bars.ClosePrices.LastValue > this.highEntryPrice && Bars.ClosePrices.Last(1) > this.highEntryPrice)
                    {
                        double deltaPips = (this.highEntryPrice - this.lowEntryPrice) / Symbol.PipSize;
                        TradeResult result = ExecuteMarketOrder(TradeType.Buy, Symbol.Name, this.calculateVolume(deltaPips), this.label, deltaPips, deltaPips);
                        if (result.IsSuccessful)
                        {
                            this.status = Status.TRADING;
                        }
                    }
                    if (Bars.ClosePrices.LastValue < this.lowEntryPrice && Bars.ClosePrices.Last(1) < this.lowEntryPrice)
                    {
                        double deltaPips = (this.highEntryPrice - this.lowEntryPrice) / Symbol.PipSize;
                        TradeResult result = ExecuteMarketOrder(TradeType.Sell, Symbol.Name, this.calculateVolume(deltaPips), this.label, deltaPips, deltaPips);
                        if (result.IsSuccessful)
                        {
                            this.status = Status.TRADING;
                        }
                    }
                }

            } catch (Exception exc)
            {
                Print(exc.Message + " " + exc.StackTrace);
                throw exc;
            }
        }

        private void onPositionClosed(PositionClosedEventArgs args)
        {
            if (args.Position.SymbolName.Equals(Symbol.Name) && this.label.Equals(args.Position.Label))
            {
                this.status = Status.IDLE;
            }
        }

        private BoxHours getBoxHours(DateTime dt)
        {
            BoxHours bh = new BoxHours();
            if (this.ParamAdjustSummerTime)
            {
                if (this.isSummer(dt))
                {
                    bh.startHour = this.ParamStartHour - 1;
                    if (bh.startHour < 0)
                    {
                        bh.startHour += 24;
                    }
                    bh.endHour = this.ParamEndHour - 1;
                    if (bh.endHour < 0)
                    {
                        bh.endHour += 24;
                    }
                }
                else
                {
                    bh.startHour = this.ParamStartHour;
                    bh.endHour = this.ParamEndHour;
                }
            }
            else
            {
                bh.startHour = this.ParamStartHour;
                bh.endHour = this.ParamEndHour;
            }
            return bh;
        }

        private bool isSummer(DateTime dt)
        {
            // Winter: November to March
            // Summer: April to October
            return dt.Month >= 4 && dt.Month <= 10;
        }

        private double calculateVolume(double stopLossPips)
        {
            double vol = this.volume;
            switch (this.ParamMoneyMgmntType)
            {
                case MMType.FIXED_LOT:
                    vol = this.volume;
                    break;

                case MMType.RISK:
                    double conversionRate = 1.0;
                    if (Account.Currency.Equals("EUR"))
                    {
                        Symbol symbolEURYYY = Symbols.GetSymbol("EUR" + Symbol.Name.Substring(3, 3));
                        conversionRate = symbolEURYYY.Bid;
                    }
                    vol = this.normalizeVolume(Account.Equity * this.ParamRisk * conversionRate / (100.0 * stopLossPips * Symbol.PipSize));
                    break;
            }
            return vol;
        }

        private double normalizeVolume(double vol)
        {
            double result = 1000;
            while (result + 1000 < vol)
            {
                result += 1000;
            }
            return result;
        }
    }

    public class BoxHours
    {
        public int startHour { get; set; }
        public int endHour { get; set; }
    }

    public enum Status
    {
        IDLE,
        WAITING,
        TRADING
    }

    public enum MMType
    {
        FIXED_LOT,
        RISK
    }
}


@AhmedMoh181099
Replies

firemyst
22 May 2021, 10:19

For starters it would help to know what parameter values you're using as they make a big difference.


@firemyst

cchee0324
06 Aug 2024, 14:27 ( Updated at: 07 Aug 2024, 05:28 )

hi, i also facing the same problem, can i know how you solve it?


@cchee0324