Previous High Low Breakout 策略
该策略监控所选周期上一根K线的最高价和最低价。当新的K线收盘价突破前高时开多单,收盘价跌破前低时开空单。使用固定的止盈和带追踪的止损来控制风险。
该方法旨在捕捉整理后的强趋势行情。追踪止损在价格朝有利方向移动时保持风险可控。
细节
- 入场条件:
- 多头:
Close > PreviousHigh - 空头:
Close < PreviousLow
- 多头:
- 多空:双向
- 出场条件:
- 触发止损或止盈
- 止损:通过
StopLoss与TakeProfit设置的绝对值追踪止损 - 默认值:
StopLoss= 50mTakeProfit= 1000mCandleType= TimeSpan.FromHours(4).TimeFrame()
- 过滤器:
- 类别:趋势跟随
- 方向:双向
- 指标:无
- 止损:有(追踪)
- 复杂度:初级
- 周期:长周期
- 季节性:无
- 神经网络:无
- 背离:无
- 风险等级:中等
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()