Setting Stop Loss (and profit target) on actual price (based on BB) and not pips
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
Replies
duketv
18 Sep 2020, 13:46
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
@PanagiotisCharalampous
duketv
21 Sep 2020, 22:54
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
@PanagiotisCharalampous
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