Estrategia basada en la Media Móvil Hull con un filtro dinámico de desviación estándar.
El sistema observa cuánto se desvía el precio del HMA. Cuando el cierre supera el
promedio en un múltiplo elegido de la desviación estándar, la estrategia entra en largo, y viceversa para posiciones cortas.
Un multiplicador más amplio define una zona de salida para que las posiciones se cierren solo después de un retorno significativo dentro de la banda.
Este enfoque intenta capturar ráfagas rápidas de momentum evitando el ruido. La Media Móvil Hull reacciona rápidamente
a los cambios de tendencia, y la desviación estándar se adapta a la volatilidad permitiendo que los umbrales se expandan durante mercados turbulentos. La estrategia opera en ambas direcciones y no usa stops fijos, confiando en cambio en la
reversión a la media del precio hacia el HMA.
Detalles
Criterios de entrada: Cierre cruzando HMA ± K1 * StdDev.
Largo/Corto: Ambas direcciones.
Criterios de salida: Cierre cruzando HMA ± K2 * StdDev en dirección opuesta.
Stops: Sin stop-loss ni take-profit fijos.
Valores predeterminados:
HmaPeriod = 13
StdPeriod = 9
K1 = 1.5m
K2 = 2.5m
CandleType = TimeSpan.FromHours(4)
Filtros:
Categoría: Tendencia, Volatilidad
Dirección: Ambos
Indicadores: HMA, Desviación estándar
Stops: No
Complejidad: Intermedio
Marco temporal: 4h
Estacionalidad: No
Redes neuronales: No
Divergencia: No
Nivel de riesgo: Medio
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()