Replies

darkoliveinthepasta
09 Jul 2022, 00:22 ( Updated at: 09 Jul 2022, 00:29 )

RE:

PanagiotisCharalampous said:

Hi there,

You also need to provide me with examples from backtesting where the SL and TP do not execute correctly. I need to be able to see the symbol and broker as well.

Also make sure you are testing using tick data.

Best Regards,

Panagiotis 

Join us on Telegram and Facebook

Hi again, so the symbol I'm using is EURUSD on the 1 minute timeframe and the broker is Pepperstone with Razor.

Here are some examples:

the first one is the trade History tab where you can see a tp being hit (which is the same trade the second screenshot shows), also a few stop losses executed at random prices, even if my stop loss is set at 0.8 pips.

As I said, the second one shows a tp being hit but as you can see it doesn't respect the variable I use for it (which checks if the previous candle closed under the lower Bollinger Band), I really can't understand why it closes where it does when it had multiple opportunities to close it correctly.

The third one is an extreme example of a wrong stop loss, it closes in a seemingly random point that the price doesn't even reach.

The fourth one is a normal example of a wrong stop loss, it closes at -1.3 pips instead of 0.8 pips. If I look at the Events tab, the stop loss is always set correctly at 0.8 pips.

 


@darkoliveinthepasta

darkoliveinthepasta
08 Jul 2022, 14:26

RE:

PanagiotisCharalampous said:

Hi there,

Please provide the complete cBot code and steps to reproduce this behavior.

Best Regards,

Panagiotis 

Join us on Telegram and Facebook

Hi, this is the code, and the spread settings I was using is 0.2 since that's the most common spread I've seen with my broker in the time sessions I want it to run in.

You should see the stop loss is never executed correctly after 0.8 pips but is most often beyond that. The take profit is also never at the first close after crossing the band.

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.WEuropeStandardTime, AccessRights = AccessRights.None)]
    public class BollingerBot : Robot // v0.4
    {
        #region Session
        [Parameter("Start Hour", DefaultValue = 6.0)]
        public double StartTime { get; set; }

        [Parameter("Stop Hour", DefaultValue = 23.0)]
        public double StopTime { get; set; }
        #endregion

        #region Bollinger Bands Parameters Input
        [Parameter("Periods", DefaultValue = 20, Group = "Bollinger Bands")]
        public int Periods { get; set; }

        [Parameter("Deviation", DefaultValue = 2, Group = "Bollinger Bands")]
        public double Deviation { get; set; }
        #endregion

        #region Trade Parameters Input
        [Parameter("Risk in percent", DefaultValue = 0.08, Group = "Risk Paramaters")]
        public double Risk { get; set; }

        [Parameter("Stop Loss in pips", DefaultValue = 0.8, Group = "Risk Paramaters")]
        public double StopLoss { get; set; }

        [Parameter("Take Profit in pips", DefaultValue = 0, Group = "Risk Paramaters")]
        public double TakeProfit { get; set; }
        #endregion

        private double _volumeInUnits;

        private DateTime _startTime;
        private DateTime _stopTime;

        private BollingerBands _bollingerBands;

        public string Label = "BollingerBot";
        
        public bool buyConditionA = false;
        public bool buyConditionB = false;
        
        public bool sellConditionA = false;
        public bool sellConditionB = false;

        protected override void OnStart()
        {
            _startTime = Server.Time.Date.AddHours(StartTime);
            _stopTime = Server.Time.Date.AddHours(StopTime);

            _bollingerBands = Indicators.BollingerBands(Bars.ClosePrices, Periods, Deviation, MovingAverageType.Simple);
        }

        protected override void OnBar()
        {
            var currentHours = Server.Time.TimeOfDay.TotalHours;
            bool tradeTime = StartTime < StopTime ? currentHours > StartTime && currentHours < StopTime : currentHours < StopTime || currentHours > StartTime;

            if (!tradeTime)
                return;

            double SLVolume = StopLoss * 1.25;
            double riskSource = Account.Balance;
            _volumeInUnits = CalculateVolume(SLVolume, Risk, riskSource);

            #region Entry Conditions
            var buyProfit = Bars.ClosePrices.Last(1) > _bollingerBands.Top.Last(1);
            var buyTriggerA = Bars.ClosePrices.Last(1) < _bollingerBands.Bottom.Last(1);
            var buyTriggerB = Bars.ClosePrices.Last(1) > _bollingerBands.Bottom.Last(1);

            var sellProfit = Bars.ClosePrices.Last(1) < _bollingerBands.Bottom.Last(1);
            var sellTriggerA = Bars.ClosePrices.Last(1) > _bollingerBands.Top.Last(1);
            var sellTriggerB = Bars.ClosePrices.Last(1) < _bollingerBands.Top.Last(1);

            var isClosedCandleUp = Bars.ClosePrices.Last(1) > Bars.OpenPrices.Last(1);
            #endregion

            #region Long Conditions Check
            if (buyTriggerA && !buyConditionA)
            {
                buyConditionA = true;
                return;
            }

            if (buyTriggerB && buyConditionA)
            {
                buyConditionB = true;
                buyConditionA = false;
            }
            #endregion

            if (buyConditionB && isClosedCandleUp)
            {
                buyConditionB = false;
                OpenPosition(TradeType.Buy, StopLoss);
            }

            #region Short Conditions Check
            if (sellTriggerA && !sellConditionA)
            {
                sellConditionA = true;
                return;
            }
            
            if (sellTriggerB && sellConditionA)
            {
                sellConditionB = true;
                sellConditionA = false;
            }
            #endregion

            if (sellConditionB && !isClosedCandleUp)
            {
                sellConditionB = false;
                OpenPosition(TradeType.Sell, StopLoss);
            }
            
            #region Close Open Positions
            var openedPosition = Positions.FirstOrDefault(p => p.SymbolName == SymbolName && p.Label == Label);

            if (openedPosition == null)
                return;

            if (buyProfit && openedPosition.TradeType == TradeType.Buy)
            {
                ClosePosition(openedPosition);
            }

            if (sellProfit && openedPosition.TradeType == TradeType.Sell)
            {
                ClosePosition(openedPosition);
            }
            #endregion
        }

        protected override void OnTick()
        {
        }

        private void OpenPosition(TradeType side, double StopLoss)
        {
            if (Positions.Any(p => p.SymbolName == SymbolName && p.Label == Label))
                return;

            ExecuteMarketOrder(side, SymbolName, _volumeInUnits, Label, StopLoss, null);
        }

        private double CalculateVolume(double StopLoss, double Risk, double riskSource)
        {
            double riskPerTrade = riskSource * Risk / 100;

            double totalPips = StopLoss;

            double _volume;

            double exactVolume = riskPerTrade / (Symbol.PipValue * totalPips);

            if (exactVolume >= Symbol.VolumeInUnitsMin)
            {
                _volume = Symbol.NormalizeVolumeInUnits(exactVolume);
            }
            else
            {
                _volume = -1;
                Print("Not enough Equity to place minimum trade, exactVolume " + exactVolume + " is not >= Symbol.VolumeInUnitsMin " + Symbol.VolumeInUnitsMin);
            }

            return _volume;
        }
    }
}

 


@darkoliveinthepasta