How to do BUY STOP Limit with Stop Loss and Take Profit pre-defined.

Created at 22 Jul 2020, 14:55
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!
AC

ac15x

Joined 22.07.2020

How to do BUY STOP Limit with Stop Loss and Take Profit pre-defined.
22 Jul 2020, 14:55


Hi,

I want my entry 3 pips above the last bar high and stop loss 3 pips below the last bar low. Take profit is equal the number pips between entry and stop loss.

 

Questions/Problem:

1. SL and TP PIP calculation seems off

2. Position not closing even after SL or TP

3. Any better way of doing BUY STOP Limit than monitoring the ASK price

 

 protected override void OnBar()
        {
            if (_longPosition == null && _myOrder == null)
            {
                    SetEntry(trend);
            }
        }

        private void SetEntry(Trend trend)
        {
            if (trend == Trend.Uptrend)
            {
                var entry = Bars.HighPrices.Last(1) + (Symbol.PipSize * 3);
                var stoploss = Math.Abs(entry - (Bars.LowPrices.Last(1) - (Symbol.PipSize * 3)) / Symbol.PipSize);
                var takeProfit = stoploss;

                _myOrder = new MyOrder(entry, stoploss, takeProfit);
            }
        
        }

        protected override void OnTick()
        {
            _longPosition = Positions.Find(InstanceName, this.SymbolName, TradeType.Buy);

            if (_myOrder != null)
            {
                ManagePosition();
            }
        }

        private void ManagePosition()
        {
            if (Ask >= _myOrder.Entry)
            {
                ExecuteMarketOrder(TradeType.Buy, SymbolName, 100000, InstanceName,
                    Math.Round(_myOrder.StopLoss / Symbol.PipSize, 3),
                    Math.Round(_myOrder.TakeProfit / Symbol.PipSize, 3));

                    
                _myOrder = null;
            }
  
        }

public class MyOrder 
    {
        public double Entry { get; set; }

        public double StopLoss { get; set; }

        public double TakeProfit { get; set; }

        public MyOrder(double entry, double stopLoss, double takeProfit)
        {
            Entry = entry;
            StopLoss = stopLoss;
            TakeProfit = takeProfit;
        }
    }

 


@ac15x
Replies

PanagiotisCharalampous
22 Jul 2020, 15:05

Hi ac15x,

You can use PlaceStopLimitOrder.

Best Regards,

Panagiotis 

Join us on Telegram

 


@PanagiotisCharalampous

ac15x
22 Jul 2020, 15:56

RE:

PanagiotisCharalampous said:

Hi ac15x,

You can use PlaceStopLimitOrder.

Best Regards,

Panagiotis 

Join us on Telegram

 

Thanks, that worked well. Still one issue remains seems like my pips calculation is wrong since it is not exiting position even after TP or SL reached.

 

   protected override void OnBar()
        {
            if (LastResult== null ||( LastResult.PendingOrder == null && LastResult.Position == null))
            {
                    SetEntry(trend);
            }
        }

        private void SetEntry(Trend trend)
        {
            if (trend == Trend.Uptrend)
            {
                var entry = Bars.HighPrices.Last(1) + (Symbol.PipSize * 3);
                var stoploss = Math.Abs(entry - (Bars.LowPrices.Last(1) - (Symbol.PipSize * 3)) / Symbol.PipSize);
                var takeProfit = stoploss;

                var result = PlaceStopLimitOrder(TradeType.Buy, SymbolName, 10000, entry, 5, InstanceName, stoploss, takeProfit);
            }
        
        }

 


@ac15x

PanagiotisCharalampous
22 Jul 2020, 15:58

Hi ac15x,

Can you provide the complete cBot code and an example of the issue? You need to explain what you expect the cBot to do and what does it do instead.

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous

ac15x
22 Jul 2020, 16:12 ( Updated at: 21 Dec 2023, 09:22 )

RE:

PanagiotisCharalampous said:

Hi ac15x,

Can you provide the complete cBot code and an example of the issue? You need to explain what you expect the cBot to do and what does it do instead.

Best Regards,

Panagiotis 

Join us on Telegram

Thats the entire code basically im just coding automated entry 3 pips above the last bar high and stop loss 3 pips below the last bar low. Take profit is equal the number pips between entry and stop loss.

 

I think the error is calculating the number of pips between entry and stop loss.

var entry = Bars.HighPrices.Last(1) + (Symbol.PipSize * 3);
var stoploss = Math.Abs(entry - (Bars.LowPrices.Last(1) - (Symbol.PipSize * 3)) / Symbol.PipSize);
var takeProfit = stoploss;

 


@ac15x

PanagiotisCharalampous
22 Jul 2020, 16:16

Hi ac15x,

This is not the complete cBot code since I cannot just paste it and build it. Did you try to print the values? What SL and TP is set when the order is placed? Can you post an example?

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous

ac15x
22 Jul 2020, 16:47

RE:

PanagiotisCharalampous said:

Hi ac15x,

This is not the complete cBot code since I cannot just paste it and build it. Did you try to print the values? What SL and TP is set when the order is placed? Can you post an example?

Best Regards,

Panagiotis 

Join us on Telegram

Thanks I fixed it, the formula for stop loss is incorrect. I fixed this with this formula.

var stoploss = Math.Abs((entry - (Bars.LowPrices.Last(1) - (Symbol.PipSize * 3))) / Symbol.PipSize);

 

One last question with PlaceStopLimitOrder., if stop loss get hits first before entry, what is the best way to cancel the order?

 

Thanks,

 


@ac15x

PanagiotisCharalampous
22 Jul 2020, 16:51

Hi ac15x,

You can use the Cancel() method to cancel a pending order.

Best Regards,

Panagiotis 

Join us on Telegram

 


@PanagiotisCharalampous

ac15x
22 Jul 2020, 16:52

RE:

PanagiotisCharalampous said:

Hi ac15x,

You can use the Cancel() method to cancel a pending order.

Best Regards,

Panagiotis 

Join us on Telegram

 

Do I have to watch the ontick event when order is pending to do this? is that the best way of doing it?


@ac15x

PanagiotisCharalampous
22 Jul 2020, 16:56

Hi ac15x,

I am not sure I understand the question. Can you elaborate?

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous

Mcfray
28 Jan 2021, 22:20

RE: RE:

Hi everyone,

I am looking for something like that but that the entry is by crossing the price and sma, Could you help me please?

Question:

1. Add  5 pips above the entry, when price crossover sma.

2. I´m using Nas100 and cannot use less than 1.0 LotSize, the minimun is 0.10 

3. Stop Loss 5 pips below the last bar low.

 

Thank you.

 

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


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

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

        [Parameter("Lot Size", DefaultValue = 0.01)]
        public double LotSize { get; set; }

        [Parameter("Stop Loss (pips)", DefaultValue = 20, MinValue = 0)]
        public int sl { get; set; }

        [Parameter("Take Profit (pips)", DefaultValue = 50, MinValue = 0)]
        public int tp { get; set; }

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

        [Parameter("Period SMA #2", DefaultValue = 20, MinValue = 1, MaxValue = 100)]
        public int PeriodsSma2 { get; set; }

        [Parameter("Calculate OnBar", DefaultValue = false)]
        public bool CalculateOnBar { get; set; }

        [Parameter("Include Break-Even", DefaultValue = false)]
        public bool IncludeBreakEven { get; set; }

        [Parameter("Break-Even Trigger (pips)", DefaultValue = 10, MinValue = 1)]
        public int BreakEvenPips { get; set; }

        [Parameter("Break-Even Extra (pips)", DefaultValue = 2, MinValue = 1)]
        public int BreakEvenExtraPips { get; set; }

        #endregion

        #region Indicator declarations

        private SimpleMovingAverage sma2 { 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
            sma2 = Indicators.SimpleMovingAverage(SourceSma2, PeriodsSma2);
        }

        /// <summary>
        /// This method is called every time the price changes for the symbol
        /// </summary>
        protected override void OnTick()
        {
            if (CalculateOnBar)
            {
                return;
            }

            ManagePositions();

            if (IncludeBreakEven)
            {
                BreakEvenAdjustment();
            }

        }

        /// <summary>
        /// This method is called at every candle (bar) close, when it has formed
        /// </summary>
        protected override void OnBar()
        {
            if (!CalculateOnBar)
            {
                return;
            }

            ManagePositions();
        }

        /// <summary>
        /// This method is called when your robot stops, can be used to clean-up memory resources.
        /// </summary>
        protected override void OnStop()
        {
            // unused
        }

        #endregion

        #region Position management


        private void ManagePositions()
        {
            int index = Bars.ClosePrices.Count - 1;
            if (sma2.Result[index - 2] > Bars.ClosePrices[index - 2] && sma2.Result[index - 1] < Bars.ClosePrices[index - 1])
            {
                // if there is no buy position open, open one and close any sell position that is open
                if (!IsPositionOpenByType(TradeType.Buy))
                {
                    OpenPosition(TradeType.Buy);
                }

                ClosePosition(TradeType.Sell);
            }

            // if a sell position is already open and signal is buy do nothing
            if (sma2.Result[index - 2] < Bars.ClosePrices[index - 2] && sma2.Result[index - 1] > Bars.ClosePrices[index - 1])
            {
                // if there is no sell position open, open one and close any buy position that is open
                if (!IsPositionOpenByType(TradeType.Sell))
                {
                    OpenPosition(TradeType.Sell);
                }

                ClosePosition(TradeType.Buy);
            }
        }

        /// <summary>
        /// Opens a new long position
        /// </summary>
        /// <param name="type"></param>
        private void OpenPosition(TradeType tradeType)
        {
            var position = Positions.Find(InstanceName, SymbolName, tradeType);
            var volumeInUnits = Symbol.QuantityToVolumeInUnits(LotSize);

            if (position == null)
                ExecuteMarketOrder(tradeType, SymbolName, volumeInUnits, InstanceName, sl, tp);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        private void ClosePosition(TradeType tradeType)
        {
            var p = Positions.Find(InstanceName, SymbolName, tradeType);

            if (p != null)
            {
                ClosePosition(p);
            }
        }

        #endregion

        #region Position Information

        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private bool IsPositionOpenByType(TradeType tradeType)
        {
            var p = Positions.FindAll(InstanceName, SymbolName, tradeType);

            if (p.Count() >= 1)
            {
                return true;
            }

            return false;
        }

        #endregion

        #region Break Even

        /// <summary>
        /// Adjusts the break even plus (x) pips
        /// </summary>
        /// <param name="tradeType"></param>
        private void BreakEvenAdjustment()
        {
            var allPositions = Positions.FindAll(InstanceName, SymbolName);

            foreach (Position position in allPositions)
            {
                //  if (position.StopLoss != null)
                //      return;

                var entryPrice = position.EntryPrice;
                var distance = position.TradeType == TradeType.Buy ? Symbol.Bid - entryPrice : entryPrice - Symbol.Ask;

                // move stop loss to break even plus and additional (x) pips
                if (distance >= BreakEvenPips * Symbol.PipSize)
                {
                    if (position.TradeType == TradeType.Buy)
                    {
                        if (position.StopLoss <= position.EntryPrice + (Symbol.PipSize * BreakEvenExtraPips) || position.StopLoss == null)
                        {
                            ModifyPosition(position, position.EntryPrice + (Symbol.PipSize * BreakEvenExtraPips), position.TakeProfit);
                            Print("Stop Loss to Break Even set for BUY position {0}", position.Id);
                        }
                    }
                    else
                    {
                        if (position.StopLoss >= position.EntryPrice - (Symbol.PipSize * BreakEvenExtraPips) || position.StopLoss == null)
                        {
                            ModifyPosition(position, entryPrice - (Symbol.PipSize * BreakEvenExtraPips), position.TakeProfit);
                            Print("Stop Loss to Break Even set for SELL position {0}", position.Id);
                        }
                    }
                }
            }
        }

        #endregion
    }
}

 

 


@Mcfray

PanagiotisCharalampous
29 Jan 2021, 08:44

Hi Mcfray,

If you need help with custom development, you can also consider posting a Job.

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous