Adding Stop Loss and Take Profit - Does not execute entry reason properly anymore

Created at 10 Apr 2021, 16:46
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!
TH

thecaffeinatedtrader

Joined 22.07.2020

Adding Stop Loss and Take Profit - Does not execute entry reason properly anymore
10 Apr 2021, 16:46


Hi,

I am having trouble getting a stop loss and take profit to work properly.

Every time I get it to work and actually execute the market order it messes up the rest of the code and is not entering the trades properly anymore..
Not sure what is going wrong and why it changes the entry parameters?? 

Currently the bot is set to exit on a 2 bar close using the Medium Moving Average as the exit reason. I want to try test it with a set stop loss and take profit instead to see if it increases the results.

 

You will see the parameter for my exit as this:

        [Parameter("Exit Period", DefaultValue = 144)]
        public int ExitPeriod { get; set; }

I would like to change that to this instead:

        [Parameter("Stop Loss", DefaultValue = 20)]
        public int StopLoss { get; set; }
 
        [Parameter("Take Profit", DefaultValue = 40)]
        public int TakeProfit { get; set; }

And then further in you will see the exit reason as this:

        private void Exit(int index)
        {
            var positions = Positions.FindAll(Label);

            foreach (var position in positions)

                if ((position.TradeType == TradeType.Buy && Bars.ClosePrices[index] < ExitMA.Result[index]) || (position.TradeType == TradeType.Sell && Bars.ClosePrices[index] > ExitMA.Result[index]))

                    ClosePosition(position);
        }

 

This is the part where I am having trouble... when I change this to use the stop loss and take profit, they execute properly but it messes up my entry parameters and cannot figure it out. I've tried many different ways but it either changes the entry parameters, or doesn't execute any trades at all....

If someone knows how to actually add these into it that would be greatly appreciated.



But here is the entire code with the sections highlighted that need to be changed so you can see what I'm dealing with:

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.EasternStandardTime, AccessRights = AccessRights.None)]
    public class ThreeSessionsMaTypeSlowBiasWithExit : Robot
    {

        [Parameter("London Start", DefaultValue = 2)]
        public double StartTime { get; set; }

        [Parameter("London Stop", DefaultValue = 4)]
        public double StopTime { get; set; }

        [Parameter("New York Start", DefaultValue = 8)]
        public double StartTime2 { get; set; }

        [Parameter("New York Stop", DefaultValue = 10)]
        public double StopTime2 { get; set; }

        [Parameter("Asia Start", DefaultValue = 19)]
        public double StartTime3 { get; set; }

        [Parameter("Asia Stop", DefaultValue = 21)]
        public double StopTime3 { get; set; }

        [Parameter("Source")]
        public DataSeries SourceSeries { get; set; }

        [Parameter("MA Type")]
        public MovingAverageType MAType { get; set; }

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

        [Parameter("Bias Period", DefaultValue = 233)]
        public int BiasPeriod { get; set; }

        [Parameter("Exit Period", DefaultValue = 144)]
        public int ExitPeriod { get; set; }


        [Parameter("Medium Period", DefaultValue = 55)]
        public int MediumPeriod { get; set; }

        [Parameter("Fast Period", DefaultValue = 21)]
        public int FastPeriod { get; set; }
        
        [Parameter("Stop Loss", DefaultValue = 20)]
        public int StopLoss { get; set; }
 
        [Parameter("Take Profit", DefaultValue = 40)]
        public int TakeProfit { get; set; }


        [Parameter("Quantity (Lots)", DefaultValue = 1, MinValue = 0.01, Step = 0.01)]
        public double Quantity { get; set; }


        private double _volumeInUnits;
        private MovingAverage ExitMA;
        private MovingAverage slowMa;
        private MovingAverage mediumMa;
        private MovingAverage fastMa;
        private DateTime _startTime;
        private DateTime _stopTime;
        private DateTime _startTime2;
        private DateTime _stopTime2;
        private DateTime _startTime3;
        private DateTime _stopTime3;

        protected override void OnStart()
        {
            fastMa = Indicators.MovingAverage(SourceSeries, FastPeriod, MAType);
            mediumMa = Indicators.MovingAverage(SourceSeries, MediumPeriod, MAType);
            slowMa = Indicators.MovingAverage(SourceSeries, BiasPeriod, MAType);
            ExitMA = Indicators.MovingAverage(SourceSeries, ExitPeriod, MAType);
            _volumeInUnits = Symbol.QuantityToVolumeInUnits(Quantity);
            _startTime = Server.Time.Date.AddHours(StartTime);
            _stopTime = Server.Time.Date.AddHours(StopTime);
            _startTime2 = Server.Time.Date.AddHours(StartTime2);
            _stopTime2 = Server.Time.Date.AddHours(StopTime2);
            _startTime3 = Server.Time.Date.AddHours(StartTime3);
            _stopTime3 = Server.Time.Date.AddHours(StopTime3);
        }

        protected override void OnBar()
        {
            int index = Bars.Count - 1;
            Entry(index);
            Exit(index);
        }

        private void Exit(int index)
        {
            var positions = Positions.FindAll(Label);

            foreach (var position in positions)

                if ((position.TradeType == TradeType.Buy && Bars.ClosePrices[index] < ExitMA.Result[index]) || (position.TradeType == TradeType.Sell && Bars.ClosePrices[index] > ExitMA.Result[index]))

                    ClosePosition(position);
        }



        private void Entry(int index)
        {
            var currentHours = Server.Time.TimeOfDay.TotalHours;
            bool istimecorrect = currentHours > StartTime && currentHours < StopTime;
            var currentHours2 = Server.Time.TimeOfDay.TotalHours;
            bool istimecorrect2 = currentHours2 > StartTime2 && currentHours < StopTime2;
            var currentHours3 = Server.Time.TimeOfDay.TotalHours;
            bool istimecorrect3 = currentHours3 > StartTime3 && currentHours3 < StopTime3;
            if (!istimecorrect & !istimecorrect2 & !istimecorrect3)
                return;

            // Buy Only
            if (Bars.ClosePrices[index] > slowMa.Result[index])
            {
                // if fast crosses medium upward
                if (fastMa.Result[index] > mediumMa.Result[index] && fastMa.Result[index - 1] < mediumMa.Result[index - 1])
                {
                    ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label);
                }
            }
            // Sell only
            else if (Bars.ClosePrices[index] < slowMa.Result[index])
            {
                // if fast crosses medium downward
                if (fastMa.Result[index] < mediumMa.Result[index] && fastMa.Result[index - 1] > mediumMa.Result[index - 1])
                {
                    ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label);
                }
            }
        }
    }
}


@thecaffeinatedtrader
Replies

amusleh
11 Apr 2021, 13:57

Just remove the Exit method from your cBot, and use the ExecuteMarketOrder overload that gets stop loss and take profit in Pips parameters:

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.EasternStandardTime, AccessRights = AccessRights.None)]
    public class ThreeSessionsMaTypeSlowBiasWithExit : Robot
    {

        [Parameter("London Start", DefaultValue = 2)]
        public double StartTime { get; set; }

        [Parameter("London Stop", DefaultValue = 4)]
        public double StopTime { get; set; }

        [Parameter("New York Start", DefaultValue = 8)]
        public double StartTime2 { get; set; }

        [Parameter("New York Stop", DefaultValue = 10)]
        public double StopTime2 { get; set; }

        [Parameter("Asia Start", DefaultValue = 19)]
        public double StartTime3 { get; set; }

        [Parameter("Asia Stop", DefaultValue = 21)]
        public double StopTime3 { get; set; }

        [Parameter("Source")]
        public DataSeries SourceSeries { get; set; }

        [Parameter("MA Type")]
        public MovingAverageType MAType { get; set; }

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

        [Parameter("Bias Period", DefaultValue = 233)]
        public int BiasPeriod { get; set; }

        [Parameter("Medium Period", DefaultValue = 55)]
        public int MediumPeriod { get; set; }

        [Parameter("Fast Period", DefaultValue = 21)]
        public int FastPeriod { get; set; }
        
        [Parameter("Stop Loss", DefaultValue = 20)]
        public int StopLoss { get; set; }
 
        [Parameter("Take Profit", DefaultValue = 40)]
        public int TakeProfit { get; set; }

        [Parameter("Quantity (Lots)", DefaultValue = 1, MinValue = 0.01, Step = 0.01)]
        public double Quantity { get; set; }


        private double _volumeInUnits;
        private MovingAverage slowMa;
        private MovingAverage mediumMa;
        private MovingAverage fastMa;
        private DateTime _startTime;
        private DateTime _stopTime;
        private DateTime _startTime2;
        private DateTime _stopTime2;
        private DateTime _startTime3;
        private DateTime _stopTime3;

        protected override void OnStart()
        {
            fastMa = Indicators.MovingAverage(SourceSeries, FastPeriod, MAType);
            mediumMa = Indicators.MovingAverage(SourceSeries, MediumPeriod, MAType);
            slowMa = Indicators.MovingAverage(SourceSeries, BiasPeriod, MAType);

            _volumeInUnits = Symbol.QuantityToVolumeInUnits(Quantity);
            _startTime = Server.Time.Date.AddHours(StartTime);
            _stopTime = Server.Time.Date.AddHours(StopTime);
            _startTime2 = Server.Time.Date.AddHours(StartTime2);
            _stopTime2 = Server.Time.Date.AddHours(StopTime2);
            _startTime3 = Server.Time.Date.AddHours(StartTime3);
            _stopTime3 = Server.Time.Date.AddHours(StopTime3);
        }

        protected override void OnBar()
        {
            int index = Bars.Count - 1;
            Entry(index);
        }

        private void Entry(int index)
        {
            var currentHours = Server.Time.TimeOfDay.TotalHours;
            bool istimecorrect = currentHours > StartTime && currentHours < StopTime;
            var currentHours2 = Server.Time.TimeOfDay.TotalHours;
            bool istimecorrect2 = currentHours2 > StartTime2 && currentHours < StopTime2;
            var currentHours3 = Server.Time.TimeOfDay.TotalHours;
            bool istimecorrect3 = currentHours3 > StartTime3 && currentHours3 < StopTime3;
            if (!istimecorrect & !istimecorrect2 & !istimecorrect3)
                return;

            // Buy Only
            if (Bars.ClosePrices[index] > slowMa.Result[index])
            {
                // if fast crosses medium upward
                if (fastMa.Result[index] > mediumMa.Result[index] && fastMa.Result[index - 1] < mediumMa.Result[index - 1])
                {
                    ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLoss, TakeProfit);
                }
            }
            // Sell only
            else if (Bars.ClosePrices[index] < slowMa.Result[index])
            {
                // if fast crosses medium downward
                if (fastMa.Result[index] < mediumMa.Result[index] && fastMa.Result[index - 1] > mediumMa.Result[index - 1])
                {
                    ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLoss, TakeProfit);
                }
            }
        }
    }
}

Instead of asking this type of questions in forum you have to read the API references or check sample cBot codes.


@amusleh

thecaffeinatedtrader
11 Apr 2021, 15:15

RE:

amusleh said:

Just remove the Exit method from your cBot, and use the ExecuteMarketOrder overload that gets stop loss and take profit in Pips parameters:

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.EasternStandardTime, AccessRights = AccessRights.None)]
    public class ThreeSessionsMaTypeSlowBiasWithExit : Robot
    {

        [Parameter("London Start", DefaultValue = 2)]
        public double StartTime { get; set; }

        [Parameter("London Stop", DefaultValue = 4)]
        public double StopTime { get; set; }

        [Parameter("New York Start", DefaultValue = 8)]
        public double StartTime2 { get; set; }

        [Parameter("New York Stop", DefaultValue = 10)]
        public double StopTime2 { get; set; }

        [Parameter("Asia Start", DefaultValue = 19)]
        public double StartTime3 { get; set; }

        [Parameter("Asia Stop", DefaultValue = 21)]
        public double StopTime3 { get; set; }

        [Parameter("Source")]
        public DataSeries SourceSeries { get; set; }

        [Parameter("MA Type")]
        public MovingAverageType MAType { get; set; }

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

        [Parameter("Bias Period", DefaultValue = 233)]
        public int BiasPeriod { get; set; }

        [Parameter("Medium Period", DefaultValue = 55)]
        public int MediumPeriod { get; set; }

        [Parameter("Fast Period", DefaultValue = 21)]
        public int FastPeriod { get; set; }
        
        [Parameter("Stop Loss", DefaultValue = 20)]
        public int StopLoss { get; set; }
 
        [Parameter("Take Profit", DefaultValue = 40)]
        public int TakeProfit { get; set; }

        [Parameter("Quantity (Lots)", DefaultValue = 1, MinValue = 0.01, Step = 0.01)]
        public double Quantity { get; set; }


        private double _volumeInUnits;
        private MovingAverage slowMa;
        private MovingAverage mediumMa;
        private MovingAverage fastMa;
        private DateTime _startTime;
        private DateTime _stopTime;
        private DateTime _startTime2;
        private DateTime _stopTime2;
        private DateTime _startTime3;
        private DateTime _stopTime3;

        protected override void OnStart()
        {
            fastMa = Indicators.MovingAverage(SourceSeries, FastPeriod, MAType);
            mediumMa = Indicators.MovingAverage(SourceSeries, MediumPeriod, MAType);
            slowMa = Indicators.MovingAverage(SourceSeries, BiasPeriod, MAType);

            _volumeInUnits = Symbol.QuantityToVolumeInUnits(Quantity);
            _startTime = Server.Time.Date.AddHours(StartTime);
            _stopTime = Server.Time.Date.AddHours(StopTime);
            _startTime2 = Server.Time.Date.AddHours(StartTime2);
            _stopTime2 = Server.Time.Date.AddHours(StopTime2);
            _startTime3 = Server.Time.Date.AddHours(StartTime3);
            _stopTime3 = Server.Time.Date.AddHours(StopTime3);
        }

        protected override void OnBar()
        {
            int index = Bars.Count - 1;
            Entry(index);
        }

        private void Entry(int index)
        {
            var currentHours = Server.Time.TimeOfDay.TotalHours;
            bool istimecorrect = currentHours > StartTime && currentHours < StopTime;
            var currentHours2 = Server.Time.TimeOfDay.TotalHours;
            bool istimecorrect2 = currentHours2 > StartTime2 && currentHours < StopTime2;
            var currentHours3 = Server.Time.TimeOfDay.TotalHours;
            bool istimecorrect3 = currentHours3 > StartTime3 && currentHours3 < StopTime3;
            if (!istimecorrect & !istimecorrect2 & !istimecorrect3)
                return;

            // Buy Only
            if (Bars.ClosePrices[index] > slowMa.Result[index])
            {
                // if fast crosses medium upward
                if (fastMa.Result[index] > mediumMa.Result[index] && fastMa.Result[index - 1] < mediumMa.Result[index - 1])
                {
                    ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLoss, TakeProfit);
                }
            }
            // Sell only
            else if (Bars.ClosePrices[index] < slowMa.Result[index])
            {
                // if fast crosses medium downward
                if (fastMa.Result[index] < mediumMa.Result[index] && fastMa.Result[index - 1] > mediumMa.Result[index - 1])
                {
                    ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLoss, TakeProfit);
                }
            }
        }
    }
}

Instead of asking this type of questions in forum you have to read the API references or check sample cBot codes.

Wow... thank you! I was making that way more complicated than it needed to be. I did have the ExecuteMarketOrder overload at the right place, but I thought I needed to keep the Exit method so I kept attempting different ways to rewrite it.


@thecaffeinatedtrader