Previous High Low Breakout Strategy
Breakout strategy that monitors the previous candle's high and low on a chosen timeframe. A long position is opened when the new candle closes above the prior high, while a short position is opened when the close falls below the prior low. A trailing stop and fixed take profit manage risk and lock in gains.
The method aims to capture strong directional moves after consolidation. Trailing stops keep risk tight as price moves in the favorable direction.
Details
- Entry Criteria:
- Long:
Close > PreviousHigh - Short:
Close < PreviousLow
- Long:
- Long/Short: Both
- Exit Criteria:
- Stop loss or take profit
- Stops: Absolute with trailing using
StopLossandTakeProfit - Default Values:
StopLoss= 50mTakeProfit= 1000mCandleType= TimeSpan.FromHours(4).TimeFrame()
- Filters:
- Category: Trend following
- Direction: Both
- Indicators: None
- Stops: Yes (trailing)
- Complexity: Beginner
- Timeframe: Long-term
- Seasonality: No
- Neural Networks: No
- Divergence: No
- Risk Level: Medium
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy that trades breakouts of the previous candle's high or low.
/// The strategy uses a trailing stop and take profit for risk management.
/// </summary>
public class PreviousHighLowBreakoutStrategy : Strategy
{
private readonly StrategyParam<decimal> _stopLoss;
private readonly StrategyParam<decimal> _takeProfit;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cooldownCandles;
private decimal _previousHigh;
private decimal _previousLow;
private bool _isFirstCandle = true;
private int _cooldown;
/// <summary>
/// Stop loss in price points.
/// </summary>
public decimal StopLoss
{
get => _stopLoss.Value;
set => _stopLoss.Value = value;
}
/// <summary>
/// Take profit in price points.
/// </summary>
public decimal TakeProfit
{
get => _takeProfit.Value;
set => _takeProfit.Value = value;
}
/// <summary>
/// Candle type for strategy calculations.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Cooldown period between trades in candles.
/// </summary>
public int CooldownCandles
{
get => _cooldownCandles.Value;
set => _cooldownCandles.Value = value;
}
/// <summary>
/// Initializes strategy parameters.
/// </summary>
public PreviousHighLowBreakoutStrategy()
{
_stopLoss = Param(nameof(StopLoss), 50m)
.SetGreaterThanZero()
.SetDisplay("Stop Loss", "Stop loss in price points", "Risk Management");
_takeProfit = Param(nameof(TakeProfit), 1000m)
.SetGreaterThanZero()
.SetDisplay("Take Profit", "Take profit in price points", "Risk Management");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Time frame for candles", "General");
_cooldownCandles = Param(nameof(CooldownCandles), 300)
.SetDisplay("Cooldown", "Cooldown between trades in candles", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_previousHigh = default;
_previousLow = default;
_isFirstCandle = true;
_cooldown = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ProcessCandle).Start();
StartProtection(
new Unit(StopLoss, UnitTypes.Absolute),
new Unit(TakeProfit, UnitTypes.Absolute));
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (_isFirstCandle)
{
_previousHigh = candle.HighPrice;
_previousLow = candle.LowPrice;
_isFirstCandle = false;
return;
}
if (_cooldown > 0)
{
_cooldown--;
_previousHigh = candle.HighPrice;
_previousLow = candle.LowPrice;
return;
}
var price = candle.ClosePrice;
if (price > _previousHigh && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
_cooldown = CooldownCandles;
}
else if (price < _previousLow && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
_cooldown = CooldownCandles;
}
_previousHigh = candle.HighPrice;
_previousLow = candle.LowPrice;
}
}
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.Strategies import Strategy
class previous_high_low_breakout_strategy(Strategy):
def __init__(self):
super(previous_high_low_breakout_strategy, self).__init__()
self._stop_loss = self.Param("StopLoss", 50.0) \
.SetDisplay("Stop Loss", "Stop loss in price points", "Risk Management")
self._take_profit = self.Param("TakeProfit", 1000.0) \
.SetDisplay("Take Profit", "Take profit in price points", "Risk Management")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Time frame for candles", "General")
self._cooldown_candles = self.Param("CooldownCandles", 300) \
.SetDisplay("Cooldown", "Cooldown between trades in candles", "General")
self._previous_high = 0.0
self._previous_low = 0.0
self._is_first_candle = True
self._cooldown = 0
@property
def StopLoss(self):
return self._stop_loss.Value
@StopLoss.setter
def StopLoss(self, value):
self._stop_loss.Value = value
@property
def TakeProfit(self):
return self._take_profit.Value
@TakeProfit.setter
def TakeProfit(self, value):
self._take_profit.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def CooldownCandles(self):
return self._cooldown_candles.Value
@CooldownCandles.setter
def CooldownCandles(self, value):
self._cooldown_candles.Value = value
def OnStarted2(self, time):
super(previous_high_low_breakout_strategy, self).OnStarted2(time)
self.SubscribeCandles(self.CandleType) \
.Bind(self.ProcessCandle) \
.Start()
self.StartProtection(
stopLoss=Unit(self.StopLoss, UnitTypes.Absolute),
takeProfit=Unit(self.TakeProfit, UnitTypes.Absolute)
)
def ProcessCandle(self, candle):
if candle.State != CandleStates.Finished:
return
if self._is_first_candle:
self._previous_high = float(candle.HighPrice)
self._previous_low = float(candle.LowPrice)
self._is_first_candle = False
return
if self._cooldown > 0:
self._cooldown -= 1
self._previous_high = float(candle.HighPrice)
self._previous_low = float(candle.LowPrice)
return
price = float(candle.ClosePrice)
if price > self._previous_high and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._cooldown = self.CooldownCandles
elif price < self._previous_low and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._cooldown = self.CooldownCandles
self._previous_high = float(candle.HighPrice)
self._previous_low = float(candle.LowPrice)
def OnReseted(self):
super(previous_high_low_breakout_strategy, self).OnReseted()
self._previous_high = 0.0
self._previous_low = 0.0
self._is_first_candle = True
self._cooldown = 0
def CreateClone(self):
return previous_high_low_breakout_strategy()