Cbot problem. Please help me!

Created at 31 May 2021, 13: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!
AH

ahmedm181099

Joined 31.05.2021

Cbot problem. Please help me!
31 May 2021, 13:25


Hello, I've downloaded this cbot for free from here. I've emailed the bot's creator but he did not respond.

Cbot works fine in backtest but it doesnt place trades in live testing. Here is an image which shows the log:

This cbot draws a box around the candles of the asian session and place a trade if the market goes below or above the box and sets sl and tp X pips away from current market price where X is the height of the box in pips (highest candle in asian session - lowest candle in asian session).

For example if the box height is 28 pips, it sets sl and tp 28 pips away from current price.

The main problem is that the cbot sets the sl and tp at an invalid market price as shown in the image above.

I'am not a programmer so I cannot help myself unfortunately and I want someone to spot the mistake regarding these invalid stop loss and take profit levels.

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
    }
}


@ahmedm181099
Replies

amusleh
01 Jun 2021, 16:18

Hi,

I think there is an issue with rounding of Stop loss and take profit levels, you have to round them to symbol digits if its in price level.

If you can't do it by yourself you can post a job request or contact one of our consultants.


@amusleh

ahmedm181099
04 Jun 2021, 04:17

RE:

amusleh said:

Hi,

I think there is an issue with rounding of Stop loss and take profit levels, you have to round them to symbol digits if its in price level.

If you can't do it by yourself you can post a job request or contact one of our consultants.

Thanks! I've contacted the bot creator and he solved the issue. As you said, He had to round the SL and TP to symbol digits and that indeed solved the issue.


@ahmedm181099