Ten Pips Strategy
This hedging strategy opens long and short positions at the same time. Each position uses fixed take profit and stop loss levels measured in price units and can be protected by a trailing stop. When one side closes, the strategy immediately opens a new position in the same direction to keep both sides active.
Parameters
TakeProfitBuy– take profit distance for long positions.StopLossBuy– stop loss distance for long positions.TrailingStopBuy– trailing stop distance for long positions.TakeProfitSell– take profit distance for short positions.StopLossSell– stop loss distance for short positions.TrailingStopSell– trailing stop distance for short positions.Volume– order size used for all trades.
Notes
- Positions are opened with market orders.
- Protective orders are registered for each side separately.
- Trailing stops are updated when the market moves in a favourable direction.
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Simple breakout strategy that enters on momentum moves
/// with fixed take profit and stop loss protection.
/// </summary>
public class TenPipsStrategy : Strategy
{
private readonly StrategyParam<decimal> _takeProfit;
private readonly StrategyParam<decimal> _stopLoss;
private readonly StrategyParam<int> _lookback;
private readonly StrategyParam<DataType> _candleType;
private decimal _entryPrice;
private decimal _previousRoc;
private bool _hasPreviousRoc;
/// <summary>Take profit distance.</summary>
public decimal TakeProfit { get => _takeProfit.Value; set => _takeProfit.Value = value; }
/// <summary>Stop loss distance.</summary>
public decimal StopLoss { get => _stopLoss.Value; set => _stopLoss.Value = value; }
/// <summary>Lookback period for momentum.</summary>
public int Lookback { get => _lookback.Value; set => _lookback.Value = value; }
/// <summary>Candle type.</summary>
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
/// <summary>
/// Initializes a new instance of the strategy.
/// </summary>
public TenPipsStrategy()
{
_takeProfit = Param(nameof(TakeProfit), 500m)
.SetDisplay("Take Profit", "Take profit distance", "Risk")
.SetGreaterThanZero();
_stopLoss = Param(nameof(StopLoss), 300m)
.SetDisplay("Stop Loss", "Stop loss distance", "Risk")
.SetGreaterThanZero();
_lookback = Param(nameof(Lookback), 30)
.SetDisplay("Lookback", "Momentum lookback period", "Indicators")
.SetGreaterThanZero();
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_entryPrice = 0m;
_previousRoc = 0m;
_hasPreviousRoc = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_entryPrice = 0;
_previousRoc = 0m;
_hasPreviousRoc = false;
var roc = new RateOfChange { Length = Lookback };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(roc, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, roc);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal rocValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
var buySignal = _hasPreviousRoc && _previousRoc <= 4m && rocValue > 4m;
var sellSignal = _hasPreviousRoc && _previousRoc >= -4m && rocValue < -4m;
if (Position == 0)
{
if (buySignal)
{
BuyMarket();
_entryPrice = close;
}
else if (sellSignal)
{
SellMarket();
_entryPrice = close;
}
}
else if (Position > 0)
{
if (close >= _entryPrice + TakeProfit || close <= _entryPrice - StopLoss)
{
SellMarket(Math.Abs(Position));
}
}
else if (Position < 0)
{
if (close <= _entryPrice - TakeProfit || close >= _entryPrice + StopLoss)
{
BuyMarket(Math.Abs(Position));
}
}
_previousRoc = rocValue;
_hasPreviousRoc = true;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Indicators import RateOfChange
from StockSharp.Algo.Strategies import Strategy
class ten_pips_strategy(Strategy):
def __init__(self):
super(ten_pips_strategy, self).__init__()
self._take_profit = self.Param("TakeProfit", 500.0)
self._stop_loss = self.Param("StopLoss", 300.0)
self._lookback = self.Param("Lookback", 30)
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1)))
self._entry_price = 0.0
self._previous_roc = 0.0
self._has_previous_roc = False
@property
def TakeProfit(self):
return self._take_profit.Value
@TakeProfit.setter
def TakeProfit(self, value):
self._take_profit.Value = value
@property
def StopLoss(self):
return self._stop_loss.Value
@StopLoss.setter
def StopLoss(self, value):
self._stop_loss.Value = value
@property
def Lookback(self):
return self._lookback.Value
@Lookback.setter
def Lookback(self, value):
self._lookback.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(ten_pips_strategy, self).OnStarted2(time)
self._entry_price = 0.0
self._previous_roc = 0.0
self._has_previous_roc = False
roc = RateOfChange()
roc.Length = self.Lookback
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(roc, self.ProcessCandle).Start()
self.StartProtection(
Unit(2000.0, UnitTypes.Absolute),
Unit(1000.0, UnitTypes.Absolute))
def ProcessCandle(self, candle, roc_value):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
roc_val = float(roc_value)
buy_signal = self._has_previous_roc and self._previous_roc <= 4.0 and roc_val > 4.0
sell_signal = self._has_previous_roc and self._previous_roc >= -4.0 and roc_val < -4.0
tp = float(self.TakeProfit)
sl = float(self.StopLoss)
if self.Position == 0:
if buy_signal:
self.BuyMarket()
self._entry_price = close
elif sell_signal:
self.SellMarket()
self._entry_price = close
elif self.Position > 0:
if close >= self._entry_price + tp or close <= self._entry_price - sl:
self.SellMarket()
elif self.Position < 0:
if close <= self._entry_price - tp or close >= self._entry_price + sl:
self.BuyMarket()
self._previous_roc = roc_val
self._has_previous_roc = True
def OnReseted(self):
super(ten_pips_strategy, self).OnReseted()
self._entry_price = 0.0
self._previous_roc = 0.0
self._has_previous_roc = False
def CreateClone(self):
return ten_pips_strategy()