Setting Stop Loss (and profit target) on actual price (based on BB) and not pips

Created at 16 Sep 2020, 18:21
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!
DU

duketv

Joined 16.09.2020

Setting Stop Loss (and profit target) on actual price (based on BB) and not pips
16 Sep 2020, 18:21


Dear readers,

I am working on my first bot and love working on it :)

In the bot I am hoping to set a Stop Loss based on an actual price target (which I want to base on the Bollinger Bands), but if I am correct the stop losse method in the ExecuteMarketOrder only works on pips. Is there a way around it?

I would really appreciate your input :) As I am still a beginner, actual examples helps me understand things best (perhaps you know a bot or indicator with this feature) .

Optional question:
I am hoping to put a second profit target inside the bot (also based on actual price targets instead of pips), and I suspect this can be done through the ModifyTakeProfitPrice method, but don't fully understand how to work with it. Any tutorial, workable code, forum post would be greatly appreciated.

Many thanks for your input in advance


@duketv
Replies

PanagiotisCharalampous
17 Sep 2020, 07:34

Hi duketv,

You can use ModifyStopLossPrice to set your stop loss on the actual price. However if you need to set multiple take profit levels, you will need to program this yourself. The API supports only one profit.

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous

duketv
18 Sep 2020, 13:46

Hi @PanagiotisCharalampous

Thank you for taking the time to reply to my query.

Do you have or know of sample code with ModifyStopLossPrice? I cannot find any snippets on the forum or in the offered robots, but I am sure it must be there..

I did code a workaround for a simple strategy, but it doesn't execute any order. Any ideas?

Many thanks and best wishes for the weekend
 

        protected override void OnBar()
        {
            var bbTop = BollingerBands.Top.LastValue;
            var bbMain = BollingerBands.Main.LastValue;
            double StopLossPips = (bbTop - bbMain) / Symbol.PipSize;

            if (_sma1.Result.LastValue < Symbol.Bid & Macd.MACD.Last(0) > Macd.Signal.Last(0) & Macd.MACD.Last(0) < 0)
                ExecuteMarketOrder(TradeType.Buy, this.SymbolName, Volume, InstanceName, StopLossPips, null);

            if (_sma1.Result.LastValue > Symbol.Bid & Macd.MACD.Last(0) < Macd.Signal.Last(0) & Macd.MACD.Last(0) > 0)
                ExecuteMarketOrder(TradeType.Sell, this.SymbolName, Volume, InstanceName, StopLossPips, null);

 


@duketv

PanagiotisCharalampous
21 Sep 2020, 08:21

Hi duketv,

ModifyStopLossPrice is pretty straight forward, I am not sure what kind of example do you need. Here is a simple one.

Positions[0].ModifyTakeProfitPrice(myTakeProfitPrice);

Regarding

I did code a workaround for a simple strategy, but it doesn't execute any order. Any ideas?

You need to provide the complete cBot code, cBot parameters, backtesting dates and tell us where do you expect to see orders executed but they are not.

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous

duketv
21 Sep 2020, 22:54

Hi PanagiotisCharalampous

 

Thanks for the reply again.

I am still in a beginning stage and learning to code so seeing pieces of code being used in a bot or indicator helps me to read and understand its use better. The bot I am trying to conjure up relies on MACD and a SMA to look for entry signals. I found a snippet of code for a trailing stop which I happily added and now I am trying to set the bottom and top lines of the Bollinger Bands as my stop losses, but that is where I hit a wall.

The code compiels but no orders are executed (backtesting on EURUSD M15), This set up is quite generic and should detect entry signals at least once a day. So if I don't see any trades in my backtest, I know it is not working correctly.

Your help is much appreciated.

Cheers

 

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


/*
Simple Cbot with MACD and a long period Moving Average for entry signals. Bollilinger Band is used for stop Loss
 */

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class GardenStrategy : Robot
    {
        #region User defined parameters

        [Parameter("Instance Name", DefaultValue = "001")]
        public string InstanceName { get; set; }

        [Parameter("Volume", DefaultValue = 1000)]
        public double Volume { get; set; }

        [Parameter("Source SMA #1")]
        public DataSeries SourceSma1 { get; set; }

        [Parameter("Period SMA #1", DefaultValue = 200, MinValue = 1, MaxValue = 300)]
        public int PeriodsSma1 { get; set; }

        [Parameter(DefaultValue = MovingAverageType.Simple)]
        public MovingAverageType MaType { get; set; }

        [Parameter("Period MACD", DefaultValue = 9)]
        public int Period { get; set; }

        [Parameter("Long Cycle MACD", DefaultValue = 26)]
        public int LongCycle { get; set; }

        [Parameter("Short Cycle MACD", DefaultValue = 12)]
        public int ShortCycle { get; set; }

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

        [Parameter("Standart Dev", DefaultValue = 2, Group = "Bollinger Bands")]
        public double BbStdDev { get; set; }

        [Parameter("MA Type", DefaultValue = 0, Group = "Bollinger Bands")]
        public MovingAverageType BbMaType { get; set; }

        [Parameter("Source", Group = "Bollinger Bands")]
        public DataSeries BbSource { get; set; }

        [Parameter("Include Trailing Stop", DefaultValue = true)]
        public bool IncludeTrailingStop { get; set; }

        [Parameter("Trailing Stop Trigger (pips)", DefaultValue = 40)]
        public int TrailingStopTrigger { get; set; }

        [Parameter("Trailing Stop Step (pips)", DefaultValue = 7)]
        public int TrailingStopStep { get; set; }



        #endregion

        #region Indicator declarations

        private SimpleMovingAverage _sma1 { get; set; }
        private BollingerBands BollingerBands { get; set; }
        private MacdCrossOver Macd { get; set; }

        #endregion

        #region cTrader events

        /// <summary>
        /// This is called when the robot first starts, it is only called once.
        /// </summary>
        protected override void OnStart()
        {
            // construct the indicators
            _sma1 = Indicators.SimpleMovingAverage(SourceSma1, PeriodsSma1);
            Macd = Indicators.MacdCrossOver(LongCycle, ShortCycle, Period);
            double Bid = Symbol.Bid;
            double Point = Symbol.TickSize;
        }


        protected override void OnTick()
        {

        }


        protected override void OnBar()
        {
            var bbTop = BollingerBands.Top.LastValue;
            var bbMain = BollingerBands.Main.LastValue;
            var bbBottom = BollingerBands.Bottom.LastValue;

            if (_sma1.Result.LastValue < Symbol.Bid & Macd.MACD.Last(0) > Macd.Signal.Last(0) & Macd.MACD.Last(0) < 0)
                ExecuteMarketOrder(TradeType.Buy, this.SymbolName, Volume, InstanceName, null, null);
            Positions[0].ModifyStopLossPrice(bbBottom);

            if (_sma1.Result.LastValue > Symbol.Bid & Macd.MACD.Last(0) < Macd.Signal.Last(0) & Macd.MACD.Last(0) > 0)
                ExecuteMarketOrder(TradeType.Sell, this.SymbolName, Volume, InstanceName, null, null);
            Positions[0].ModifyStopLossPrice(bbTop);
        }

        protected override void OnStop()
        {

        }

        #endregion


        #region Trailing Stop

        /// <summary>
        /// When the profit in pips is above or equal to Trigger the stop loss will start trailing the spot price.
        /// TrailingStop defines the number of pips the Stop Loss trails the spot price by. 
        /// If Trigger is 0 trailing will begin immediately. 
        /// </summary>
        private void SetTrailingStop()
        {
            var sellPositions = Positions.FindAll(InstanceName, SymbolName, TradeType.Sell);

            foreach (Position position in sellPositions)
            {
                double distance = position.EntryPrice - Symbol.Ask;

                if (distance < TrailingStopTrigger * Symbol.PipSize)
                    continue;

                double newStopLossPrice = Symbol.Ask + TrailingStopStep * Symbol.PipSize;

                if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                }
            }

            var buyPositions = Positions.FindAll(InstanceName, SymbolName, TradeType.Buy);

            foreach (Position position in buyPositions)
            {
                double distance = Symbol.Bid - position.EntryPrice;

                if (distance < TrailingStopTrigger * Symbol.PipSize)
                    continue;

                double newStopLossPrice = Symbol.Bid - TrailingStopStep * Symbol.PipSize;
                if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                }
            }
        }

        #endregion

    }
}

 


@duketv

PanagiotisCharalampous
22 Sep 2020, 08:04 ( Updated at: 21 Dec 2023, 09:22 )

Hi duketv,

If you check your log you will see an exception.

This happens because you have not initialized your Bollinger Bands indicator anywhere. Add this in OnStart()

 BollingerBands = Indicators.BollingerBands(Bars.ClosePrices, BbPeriods, BbStdDev, BbMaType);

On top of that, you are trying to modify a position that does not exist

        protected override void OnBar()
        {
            var bbTop = BollingerBands.Top.LastValue;
            var bbMain = BollingerBands.Main.LastValue;
            var bbBottom = BollingerBands.Bottom.LastValue;

            if (_sma1.Result.LastValue < Symbol.Bid & Macd.MACD.Last(0) > Macd.Signal.Last(0) & Macd.MACD.Last(0) < 0)
                ExecuteMarketOrder(TradeType.Buy, this.SymbolName, Volume, InstanceName, null, null);
            Positions[0].ModifyStopLossPrice(bbBottom);

            if (_sma1.Result.LastValue > Symbol.Bid & Macd.MACD.Last(0) < Macd.Signal.Last(0) & Macd.MACD.Last(0) > 0)
                ExecuteMarketOrder(TradeType.Sell, this.SymbolName, Volume, InstanceName, null, null);
            Positions[0].ModifyStopLossPrice(bbTop);
        }

Try this instead

        protected override void OnBar()
        {
            var bbTop = BollingerBands.Top.LastValue;
            var bbMain = BollingerBands.Main.LastValue;
            var bbBottom = BollingerBands.Bottom.LastValue;

            if (_sma1.Result.LastValue < Symbol.Bid & Macd.MACD.Last(0) > Macd.Signal.Last(0) & Macd.MACD.Last(0) < 0)
            {
                var position = ExecuteMarketOrder(TradeType.Buy, this.SymbolName, Volume, InstanceName, null, null).Position;
                position.ModifyStopLossPrice(bbBottom);
            }

            if (_sma1.Result.LastValue > Symbol.Bid & Macd.MACD.Last(0) < Macd.Signal.Last(0) & Macd.MACD.Last(0) > 0)
            {
                var position = ExecuteMarketOrder(TradeType.Sell, this.SymbolName, Volume, InstanceName, null, null).Position;
                position.ModifyStopLossPrice(bbTop);
            }
        }

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous