Hull MA 傾斜ブレイクアウト戦略
Hull MA 傾斜ブレイクアウト戦略は、Hull の変化率を追跡します。異常に急な傾斜は、新しいトレンドが形成されつつあることを示唆します。
テストでは年平均リターン約121%を示しています。暗号通貨市場で最もよく機能します。
傾斜が標準偏差の倍数によって典型的なレベルを超えると、加速の方向にトレードが行われ、保護ストップが付きます。
早期のトレンド参入を望む積極的なトレーダーに向いています。傾斜が正常な値に戻るとポジションは終了します。デフォルト HullLength = 9。
詳細
- エントリー条件: インジケーターが偏差乗数分だけ平均を上回る。
- ロング/ショート: 両方向。
- エグジット条件: インジケーターが平均に戻る。
- ストップ: はい。
- デフォルト値:
HullLength= 9LookbackPeriod= 20DeviationMultiplier= 2mStopLoss= new Unit(2CandleType= TimeSpan.FromMinutes(5)
- フィルター:
- カテゴリ: ブレイクアウト
- 方向: 両方
- インジケーター: Hull
- ストップ: はい
- 複雑さ: 中級
- 時間軸: 短期
- 季節性: いいえ
- ニューラルネットワーク: いいえ
- ダイバージェンス: いいえ
- リスクレベル: 中
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Hull Moving Average slope breakout.
/// Enters in the direction of the slope when it exceeds its average by a standard deviation multiplier
/// and exits when the slope returns to its average.
/// </summary>
public class HullMaSlopeBreakoutStrategy : Strategy
{
private readonly StrategyParam<int> _hullLength;
private readonly StrategyParam<int> _lookbackPeriod;
private readonly StrategyParam<decimal> _deviationMultiplier;
private readonly StrategyParam<Unit> _stopLoss;
private readonly StrategyParam<DataType> _candleType;
private SimpleMovingAverage _slopeAverage;
private StandardDeviation _slopeStdDev;
private decimal? _prevHull;
/// <summary>
/// Hull Moving Average length.
/// </summary>
public int HullLength
{
get => _hullLength.Value;
set => _hullLength.Value = value;
}
/// <summary>
/// Lookback period for slope statistics.
/// </summary>
public int LookbackPeriod
{
get => _lookbackPeriod.Value;
set => _lookbackPeriod.Value = value;
}
/// <summary>
/// Standard deviation multiplier for breakout detection.
/// </summary>
public decimal DeviationMultiplier
{
get => _deviationMultiplier.Value;
set => _deviationMultiplier.Value = value;
}
/// <summary>
/// Stop-loss value.
/// </summary>
public Unit StopLoss
{
get => _stopLoss.Value;
set => _stopLoss.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initialize <see cref="HullMaSlopeBreakoutStrategy"/>.
/// </summary>
public HullMaSlopeBreakoutStrategy()
{
_hullLength = Param(nameof(HullLength), 9)
.SetGreaterThanZero()
.SetDisplay("Hull MA Length", "Period for Hull Moving Average", "Indicator Parameters")
.SetOptimize(5, 20, 1);
_lookbackPeriod = Param(nameof(LookbackPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("Lookback Period", "Period for slope statistics calculation", "Strategy Parameters")
.SetOptimize(10, 50, 5);
_deviationMultiplier = Param(nameof(DeviationMultiplier), 2m)
.SetGreaterThanZero()
.SetDisplay("Deviation Multiplier", "Standard deviation multiplier for breakout detection", "Strategy Parameters")
.SetOptimize(1m, 3m, 0.5m);
_stopLoss = Param(nameof(StopLoss), new Unit(2, UnitTypes.Percent))
.SetDisplay("Stop Loss", "Protective stop-loss", "Risk Management");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_slopeAverage = null;
_slopeStdDev = null;
_prevHull = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var hull = new HullMovingAverage { Length = HullLength };
_slopeAverage = new SimpleMovingAverage { Length = LookbackPeriod };
_slopeStdDev = new StandardDeviation { Length = LookbackPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(hull, ProcessCandle)
.Start();
StartProtection(takeProfit: null, stopLoss: StopLoss);
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, hull);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal hullValue)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevHull is not decimal prev)
{
_prevHull = hullValue;
return;
}
_prevHull = hullValue;
var slope = hullValue - prev;
var avgSlope = _slopeAverage.Process(slope, candle.ServerTime, true).ToDecimal();
var stdSlope = _slopeStdDev.Process(slope, candle.ServerTime, true).ToDecimal();
if (!_slopeAverage.IsFormed || !_slopeStdDev.IsFormed)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (slope > avgSlope + DeviationMultiplier * stdSlope && Position <= 0)
{
BuyMarket(Volume + Math.Abs(Position));
}
else if (slope < avgSlope - DeviationMultiplier * stdSlope && Position >= 0)
{
SellMarket(Volume + Math.Abs(Position));
}
else if (Position > 0 && slope < avgSlope)
{
SellMarket(Position);
}
else if (Position < 0 && slope > avgSlope)
{
BuyMarket(-Position);
}
}
}
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 HullMovingAverage, SimpleMovingAverage, StandardDeviation
from StockSharp.Algo.Strategies import Strategy
from indicator_extensions import *
class hull_ma_slope_breakout_strategy(Strategy):
"""
Hull Moving Average slope breakout.
Enters in the direction of the slope when it exceeds its average by a standard deviation multiplier
and exits when the slope returns to its average.
"""
def __init__(self):
super(hull_ma_slope_breakout_strategy, self).__init__()
self._hull_length = self.Param("HullLength", 9) \
.SetGreaterThanZero() \
.SetDisplay("Hull MA Length", "Period for Hull Moving Average", "Indicator Parameters") \
.SetOptimize(5, 20, 1)
self._lookback_period = self.Param("LookbackPeriod", 20) \
.SetGreaterThanZero() \
.SetDisplay("Lookback Period", "Period for slope statistics calculation", "Strategy Parameters") \
.SetOptimize(10, 50, 5)
self._deviation_multiplier = self.Param("DeviationMultiplier", 2.0) \
.SetGreaterThanZero() \
.SetDisplay("Deviation Multiplier", "Standard deviation multiplier for breakout detection", "Strategy Parameters") \
.SetOptimize(1.0, 3.0, 0.5)
self._stop_loss = self.Param("StopLoss", Unit(2, UnitTypes.Percent)) \
.SetDisplay("Stop Loss", "Protective stop-loss", "Risk Management")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._slope_average = None
self._slope_std_dev = None
self._prev_hull = None
@property
def CandleType(self):
return self._candle_type.Value
def GetWorkingSecurities(self):
return [(self.Security, self.CandleType)]
def OnReseted(self):
super(hull_ma_slope_breakout_strategy, self).OnReseted()
self._slope_average = None
self._slope_std_dev = None
self._prev_hull = None
def OnStarted2(self, time):
super(hull_ma_slope_breakout_strategy, self).OnStarted2(time)
hull = HullMovingAverage()
hull.Length = self._hull_length.Value
self._slope_average = SimpleMovingAverage()
self._slope_average.Length = self._lookback_period.Value
self._slope_std_dev = StandardDeviation()
self._slope_std_dev.Length = self._lookback_period.Value
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(hull, self._process_candle).Start()
self.StartProtection(None, self._stop_loss.Value)
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, hull)
self.DrawOwnTrades(area)
def _process_candle(self, candle, hull_value):
if candle.State != CandleStates.Finished:
return
hull_value = float(hull_value)
if self._prev_hull is None:
self._prev_hull = hull_value
return
slope = hull_value - self._prev_hull
self._prev_hull = hull_value
avg_slope = float(process_float(self._slope_average, slope, candle.ServerTime, True))
std_slope = float(process_float(self._slope_std_dev, slope, candle.ServerTime, True))
if not self._slope_average.IsFormed or not self._slope_std_dev.IsFormed:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
k = float(self._deviation_multiplier.Value)
if slope > avg_slope + k * std_slope and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
elif slope < avg_slope - k * std_slope and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
elif self.Position > 0 and slope < avg_slope:
self.SellMarket(self.Position)
elif self.Position < 0 and slope > avg_slope:
self.BuyMarket(-self.Position)
def CreateClone(self):
return hull_ma_slope_breakout_strategy()