Logic for Stop Loss / Take profit

Created at 30 May 2022, 07:06
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!
TU

tuanpham1208

Joined 19.04.2022

Logic for Stop Loss / Take profit
30 May 2022, 07:06


Hi guys,

I'm working on a bot with rules as follow:

Only open 1 trade at a time

Buy when EMA20 crosses above EMA50 and EMA100 and price above Ichimoku Cloud

Sell when EMA20 crosses below EMA 50 and EMA100 and price below Ichimoku Cloud

Take profit is ATR and Stop loss is 1.5ATR. Basically SL/TP is just a number of pips.

However I would like to change Stop loss to whenever EMA20 crosses in other direction. So for ex. Long position will be closed when EMA20 crosses below EMA50, and Short position will be closed when EMA20 crosses above EMA50.

I also would like to change Take profit to whenever price reach the High of previous range of time (last 24hrs for ex.). I don't know what function would be appropriated for this. Maybe Max of # previous bars.

Please take a look of what I have and give me some help. Thank you all

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.UTC, AccessRights = AccessRights.None)]
    public class Crossover : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }

        private ExponentialMovingAverage ema20, ema50, ema100;
        private SimpleMovingAverage sma10;
        private AverageTrueRange atr;
        private IchimokuKinkoHyo ichimoku;
        private int longPositions = 0;
        private int shortPositions = 0;

        [Parameter("Short Trades", DefaultValue = 2, MinValue = 0)]
        public int MaxShortTrades { get; set; }

        [Parameter("Long Trades", DefaultValue = 2, MinValue = 0)]
        public int MaxLongTrades { get; set; }

        protected override void OnStart()
        {
            // Load indicators on start up
            sma10 = Indicators.SimpleMovingAverage(Bars.ClosePrices, 10);
            ema20 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 20);
            ema50 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 50);
            ema100 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 100);
            atr = Indicators.AverageTrueRange(14, MovingAverageType.Exponential);
            ichimoku = Indicators.IchimokuKinkoHyo(9, 26, 52);
        }


        protected override void OnBar()
        {

            // Calculate Trade Amount based on ATR
            var PrevATR = Math.Round(atr.Result.Last(1) / Symbol.PipSize);
            var TradeAmount = (Account.Equity * 0.02) / (1.5 * PrevATR * Symbol.PipValue);
            TradeAmount = Symbol.NormalizeVolumeInUnits(TradeAmount, RoundingMode.Down);

            var price = Bars.ClosePrices.Last(0);
            var Prevprice = Bars.ClosePrices.Last(1);
            var ema_20 = ema20.Result.Last(0);
            var ema_50 = ema50.Result.Last(0);
            var ema_100 = ema100.Result.Last(0);

            var senkouA = ichimoku.SenkouSpanA;
            var senkouB = ichimoku.SenkouSpanB;
            var cloudUpper = Math.Max(senkouA.Last(26), senkouB.Last(26));
            var cloudLower = Math.Min(senkouA.Last(26), senkouB.Last(26));


            var shortPositionsCount = Positions.Count(p => p.TradeType == TradeType.Sell);
            var longPositionsCount = Positions.Count(p => p.TradeType == TradeType.Buy);

            if (Positions.Count == 0)
            {
                if (longPositions < MaxLongTrades & ema20.Result.HasCrossedAbove(ema100.Result, 0) & ema_50 > ema_100 & price > cloudUpper)
                {
                    ExecuteMarketOrder(TradeType.Buy, SymbolName, TradeAmount, "BOT", 1.5 * PrevATR, PrevATR);
                }
                else if (shortPositions < MaxShortTrades & ema20.Result.HasCrossedBelow(ema100.Result, 0) & ema_50 < ema_100 & price < cloudLower)
                {
                    ExecuteMarketOrder(TradeType.Sell, SymbolName, TradeAmount, "BOT", 1.5 * PrevATR, PrevATR);
                }
            }
        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}


@tuanpham1208
Replies

amusleh
30 May 2022, 10:06

Hi,

What help you need? please be precise on what you are asking.


@amusleh

tuanpham1208
30 May 2022, 10:24

RE:

amusleh said:

Hi,

What help you need? please be precise on what you are asking.

Hi,

As I said in the beginning of my post. I would like to know how to express Stop Loss / Take Profit as logics in stead of simple number of pips.

So for example, 

ExecuteMarketOrder(TradeType.Buy, SymbolName, TradeAmount, "BOT", 1.5 * PrevATR, PrevATR)

How do I replace 1.5*PrevATR (i.e my SL) with EMA20 crosses below EMA50.

Thank you 


@tuanpham1208

amusleh
30 May 2022, 10:26

Hi,

You can use the EMA value as your position stop loss / take profit, ema20.Result.LastValue will give the latest value of EMA.


@amusleh

tuanpham1208
30 May 2022, 14:19

RE:

amusleh said:

Hi,

You can use the EMA value as your position stop loss / take profit, ema20.Result.LastValue will give the latest value of EMA.

Yes. Thank you. I know how to express it as a variable. But how do I express it as a condition for Stop Loss. Because I cannot insert ema20.Result.LastValue < ema50.Result.LastValue into ExecuteMarketOrder(), can I ? So for example 

ExecuteMarketOrder(TradeType.Buy, SymbolName, TradeAmount, "BOT", ema20.Result.LastValue < ema50.Result.LastValue, PrevATR)

It shows these errors:

Error CS1502: The best overloaded method match for 'cAlgo.API.Robot.ExecuteMarketOrder(cAlgo.API.TradeType, string, double, string, double?, double?)' has some invalid arguments

Error CS1503: Argument 5: cannot convert from 'bool' to 'double?'

Much appreciated

 


@tuanpham1208

amusleh
31 May 2022, 10:58

RE: RE:

tuanpham1208 said:

amusleh said:

Hi,

You can use the EMA value as your position stop loss / take profit, ema20.Result.LastValue will give the latest value of EMA.

Yes. Thank you. I know how to express it as a variable. But how do I express it as a condition for Stop Loss. Because I cannot insert ema20.Result.LastValue < ema50.Result.LastValue into ExecuteMarketOrder(), can I ? So for example 

ExecuteMarketOrder(TradeType.Buy, SymbolName, TradeAmount, "BOT", ema20.Result.LastValue < ema50.Result.LastValue, PrevATR)

It shows these errors:

Error CS1502: The best overloaded method match for 'cAlgo.API.Robot.ExecuteMarketOrder(cAlgo.API.TradeType, string, double, string, double?, double?)' has some invalid arguments

Error CS1503: Argument 5: cannot convert from 'bool' to 'double?'

Much appreciated

 

Hi,

So you want to close a position when EMA cross happens? you can't put a logic on a position stop loss, to close a position when certain criteria meets you have to keep checking the criteria on OnBar or OnTick methods.


@amusleh

tuanpham1208
01 Jun 2022, 09:23

RE: RE: RE:

amusleh said:

tuanpham1208 said:

amusleh said:

Hi,

You can use the EMA value as your position stop loss / take profit, ema20.Result.LastValue will give the latest value of EMA.

Yes. Thank you. I know how to express it as a variable. But how do I express it as a condition for Stop Loss. Because I cannot insert ema20.Result.LastValue < ema50.Result.LastValue into ExecuteMarketOrder(), can I ? So for example 

ExecuteMarketOrder(TradeType.Buy, SymbolName, TradeAmount, "BOT", ema20.Result.LastValue < ema50.Result.LastValue, PrevATR)

It shows these errors:

Error CS1502: The best overloaded method match for 'cAlgo.API.Robot.ExecuteMarketOrder(cAlgo.API.TradeType, string, double, string, double?, double?)' has some invalid arguments

Error CS1503: Argument 5: cannot convert from 'bool' to 'double?'

Much appreciated

 

Hi,

So you want to close a position when EMA cross happens? you can't put a logic on a position stop loss, to close a position when certain criteria meets you have to keep checking the criteria on OnBar or OnTick methods.

Hi,

Sorry. I'm very new to CTrader and API in general. In fact I only picked up pieces from Youtube and forums, here and there. Could you please elaborate more or give me a brief example on how to structure such criteria ? Thank you so much


@tuanpham1208

amusleh
01 Jun 2022, 10:22

Hi,

You have to learn C# and read Automate API documentation.

You can find Automate API documentation at: cTrader Automate | cTrader Help Center

Here is an example that might help you (read my added comments):

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.UTC, AccessRights = AccessRights.None)]
    public class Crossover : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }

        private ExponentialMovingAverage ema20, ema50, ema100;
        private SimpleMovingAverage sma10;
        private AverageTrueRange atr;
        private IchimokuKinkoHyo ichimoku;
        private int longPositions = 0;
        private int shortPositions = 0;

        [Parameter("Short Trades", DefaultValue = 2, MinValue = 0)]
        public int MaxShortTrades { get; set; }

        [Parameter("Long Trades", DefaultValue = 2, MinValue = 0)]
        public int MaxLongTrades { get; set; }

        protected override void OnStart()
        {
            // Load indicators on start up
            sma10 = Indicators.SimpleMovingAverage(Bars.ClosePrices, 10);
            ema20 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 20);
            ema50 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 50);
            ema100 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 100);
            atr = Indicators.AverageTrueRange(14, MovingAverageType.Exponential);
            ichimoku = Indicators.IchimokuKinkoHyo(9, 26, 52);
        }

        protected override void OnBar()
        {
            // Calculate Trade Amount based on ATR
            var PrevATR = Math.Round(atr.Result.Last(1) / Symbol.PipSize);
            var TradeAmount = (Account.Equity * 0.02) / (1.5 * PrevATR * Symbol.PipValue);
            TradeAmount = Symbol.NormalizeVolumeInUnits(TradeAmount, RoundingMode.Down);

            var price = Bars.ClosePrices.Last(0);
            var Prevprice = Bars.ClosePrices.Last(1);
            var ema_20 = ema20.Result.Last(0);
            var ema_50 = ema50.Result.Last(0);
            var ema_100 = ema100.Result.Last(0);

            var senkouA = ichimoku.SenkouSpanA;
            var senkouB = ichimoku.SenkouSpanB;
            var cloudUpper = Math.Max(senkouA.Last(26), senkouB.Last(26));
            var cloudLower = Math.Min(senkouA.Last(26), senkouB.Last(26));

            var shortPositionsCount = Positions.Count(p => p.TradeType == TradeType.Sell);
            var longPositionsCount = Positions.Count(p => p.TradeType == TradeType.Buy);

            if (Positions.Count == 0)
            {
                if (longPositions < MaxLongTrades & ema20.Result.HasCrossedAbove(ema100.Result, 0) & ema_50 > ema_100 & price > cloudUpper)
                {
                    ExecuteMarketOrder(TradeType.Buy, SymbolName, TradeAmount, "BOT", 1.5 * PrevATR, PrevATR);
                }
                else if (shortPositions < MaxShortTrades & ema20.Result.HasCrossedBelow(ema100.Result, 0) & ema_50 < ema_100 & price < cloudLower)
                {
                    ExecuteMarketOrder(TradeType.Sell, SymbolName, TradeAmount, "BOT", 1.5 * PrevATR, PrevATR);
                }
            }

            // This will give you all the positions with label "BOT"
            var botPositions = Positions.FindAll("BOT");

            // Then we iterate over BOT positions
            foreach (var position in botPositions)
            {
                // Close the position if trade type is buy and ema_20 < ema_50
                // Close the position if trade type is sell and ema_20 > ema_50
                if ((position.TradeType == TradeType.Buy && ema_20 < ema_50) || (position.TradeType == TradeType.Sell && ema_20 > ema_50))
                {
                    ClosePosition(position);
                }
            }
        }
    }
}

 


@amusleh

tuanpham1208
23 Jun 2022, 19:30

RE:

amusleh said:

Hi,

You have to learn C# and read Automate API documentation.

You can find Automate API documentation at: cTrader Automate | cTrader Help Center

Here is an example that might help you (read my added comments):

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.UTC, AccessRights = AccessRights.None)]
    public class Crossover : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }

        private ExponentialMovingAverage ema20, ema50, ema100;
        private SimpleMovingAverage sma10;
        private AverageTrueRange atr;
        private IchimokuKinkoHyo ichimoku;
        private int longPositions = 0;
        private int shortPositions = 0;

        [Parameter("Short Trades", DefaultValue = 2, MinValue = 0)]
        public int MaxShortTrades { get; set; }

        [Parameter("Long Trades", DefaultValue = 2, MinValue = 0)]
        public int MaxLongTrades { get; set; }

        protected override void OnStart()
        {
            // Load indicators on start up
            sma10 = Indicators.SimpleMovingAverage(Bars.ClosePrices, 10);
            ema20 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 20);
            ema50 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 50);
            ema100 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 100);
            atr = Indicators.AverageTrueRange(14, MovingAverageType.Exponential);
            ichimoku = Indicators.IchimokuKinkoHyo(9, 26, 52);
        }

        protected override void OnBar()
        {
            // Calculate Trade Amount based on ATR
            var PrevATR = Math.Round(atr.Result.Last(1) / Symbol.PipSize);
            var TradeAmount = (Account.Equity * 0.02) / (1.5 * PrevATR * Symbol.PipValue);
            TradeAmount = Symbol.NormalizeVolumeInUnits(TradeAmount, RoundingMode.Down);

            var price = Bars.ClosePrices.Last(0);
            var Prevprice = Bars.ClosePrices.Last(1);
            var ema_20 = ema20.Result.Last(0);
            var ema_50 = ema50.Result.Last(0);
            var ema_100 = ema100.Result.Last(0);

            var senkouA = ichimoku.SenkouSpanA;
            var senkouB = ichimoku.SenkouSpanB;
            var cloudUpper = Math.Max(senkouA.Last(26), senkouB.Last(26));
            var cloudLower = Math.Min(senkouA.Last(26), senkouB.Last(26));

            var shortPositionsCount = Positions.Count(p => p.TradeType == TradeType.Sell);
            var longPositionsCount = Positions.Count(p => p.TradeType == TradeType.Buy);

            if (Positions.Count == 0)
            {
                if (longPositions < MaxLongTrades & ema20.Result.HasCrossedAbove(ema100.Result, 0) & ema_50 > ema_100 & price > cloudUpper)
                {
                    ExecuteMarketOrder(TradeType.Buy, SymbolName, TradeAmount, "BOT", 1.5 * PrevATR, PrevATR);
                }
                else if (shortPositions < MaxShortTrades & ema20.Result.HasCrossedBelow(ema100.Result, 0) & ema_50 < ema_100 & price < cloudLower)
                {
                    ExecuteMarketOrder(TradeType.Sell, SymbolName, TradeAmount, "BOT", 1.5 * PrevATR, PrevATR);
                }
            }

            // This will give you all the positions with label "BOT"
            var botPositions = Positions.FindAll("BOT");

            // Then we iterate over BOT positions
            foreach (var position in botPositions)
            {
                // Close the position if trade type is buy and ema_20 < ema_50
                // Close the position if trade type is sell and ema_20 > ema_50
                if ((position.TradeType == TradeType.Buy && ema_20 < ema_50) || (position.TradeType == TradeType.Sell && ema_20 > ema_50))
                {
                    ClosePosition(position);
                }
            }
        }
    }
}

 

Thank you amusleh. Quick question. How to I express "or" condition. I know that we use "&" for "and". But what if I want to express, for example, RSI smaller than or equal  to 70? rsi.Result.Last(0) =< 70. Thank you


@tuanpham1208