Logic for Stop Loss / Take profit
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
}
}
}
Replies
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
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
amusleh
30 May 2022, 10:06
Hi,
What help you need? please be precise on what you are asking.
@amusleh