Color HMA StDev
基于 Hull 移动平均线并结合标准差过滤的策略。
系统监控价格偏离 HMA 的程度。当收盘价突破平均线并超过设定的标准差倍数时开多仓,反之开空仓。 较大的倍数定义退出区间,因此只有在价格明显回到区间内后才会平仓。
这种方法旨在捕捉快速的动量爆发,同时避免噪音。Hull 移动平均线对趋势变化反应迅速,标准差则根据 波动性自动扩展阈值,使策略能在动荡市场中适应变化。策略可双向交易,并不使用固定止损,依靠价格回归 到 HMA 作为退出依据。
细节
- 入场条件:收盘价突破 HMA ± K1 * StdDev。
- 多空方向:双向交易。
- 出场条件:收盘价突破相反方向的 HMA ± K2 * StdDev。
- 止损:无固定止损或止盈。
- 默认参数:
HmaPeriod= 13StdPeriod= 9K1= 1.5mK2= 2.5mCandleType= TimeSpan.FromHours(4)
- 过滤器:
- 分类:趋势,波动性
- 方向:双向
- 指标:HMA,标准差
- 止损:无
- 复杂度:中等
- 时间框架:4 小时
- 季节性:否
- 神经网络:否
- 背离:否
- 风险等级:中等
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>
/// Strategy based on Hull Moving Average with standard deviation filter.
/// Opens positions when price deviates from the HMA by a defined multiplier.
/// </summary>
public class ColorHmaStDevStrategy : Strategy
{
private readonly StrategyParam<int> _hmaPeriod;
private readonly StrategyParam<int> _stdPeriod;
private readonly StrategyParam<decimal> _k1;
private readonly StrategyParam<DataType> _candleType;
public int HmaPeriod { get => _hmaPeriod.Value; set => _hmaPeriod.Value = value; }
public int StdPeriod { get => _stdPeriod.Value; set => _stdPeriod.Value = value; }
public decimal K1 { get => _k1.Value; set => _k1.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ColorHmaStDevStrategy()
{
_hmaPeriod = Param(nameof(HmaPeriod), 13)
.SetDisplay("HMA Period", "Hull Moving Average period", "Indicators")
.SetOptimize(5, 30, 2);
_stdPeriod = Param(nameof(StdPeriod), 9)
.SetDisplay("StdDev Period", "Standard deviation period", "Indicators")
.SetOptimize(5, 20, 1);
_k1 = Param(nameof(K1), 0.5m)
.SetDisplay("Entry Multiplier", "Deviation multiplier for entry", "Parameters")
.SetOptimize(0.5m, 3m, 0.5m);
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to subscribe", "Common");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var hma = new HullMovingAverage { Length = HmaPeriod };
var std = new StandardDeviation { Length = StdPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(hma, std, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, hma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal hmaValue, decimal stdValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (stdValue == 0)
return;
var upperEntry = hmaValue + K1 * stdValue;
var lowerEntry = hmaValue - K1 * stdValue;
if (candle.ClosePrice > upperEntry && Position <= 0)
BuyMarket();
else if (candle.ClosePrice < lowerEntry && Position >= 0)
SellMarket();
}
}
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
from StockSharp.Algo.Indicators import HullMovingAverage, StandardDeviation
from StockSharp.Algo.Strategies import Strategy
class color_hma_st_dev_strategy(Strategy):
def __init__(self):
super(color_hma_st_dev_strategy, self).__init__()
self._hma_period = self.Param("HmaPeriod", 13) \
.SetDisplay("HMA Period", "Hull Moving Average period", "Indicators")
self._std_period = self.Param("StdPeriod", 9) \
.SetDisplay("StdDev Period", "Standard deviation period", "Indicators")
self._k1 = self.Param("K1", 0.5) \
.SetDisplay("Entry Multiplier", "Deviation multiplier for entry", "Parameters")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles to subscribe", "Common")
@property
def hma_period(self):
return self._hma_period.Value
@property
def std_period(self):
return self._std_period.Value
@property
def k1(self):
return self._k1.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnStarted2(self, time):
super(color_hma_st_dev_strategy, self).OnStarted2(time)
hma = HullMovingAverage()
hma.Length = self.hma_period
std = StandardDeviation()
std.Length = self.std_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(hma, std, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, hma)
self.DrawOwnTrades(area)
def process_candle(self, candle, hma_value, std_value):
if candle.State != CandleStates.Finished:
return
hma_value = float(hma_value)
std_value = float(std_value)
if std_value == 0:
return
k1_val = float(self.k1)
upper_entry = hma_value + k1_val * std_value
lower_entry = hma_value - k1_val * std_value
close_price = float(candle.ClosePrice)
if close_price > upper_entry and self.Position <= 0:
self.BuyMarket()
elif close_price < lower_entry and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return color_hma_st_dev_strategy()