Esta estrategia combina Hull Moving Averages, RSI, MACD, filtro de volumen y divergencia del delta de volumen acumulado (CVD) para identificar oportunidades de tendencia.
Las posiciones largas se abren cuando HMA20 está por encima de HMA50, el RSI muestra momentum alcista, el histograma MACD sube, el volumen supera su media y el CVD forma divergencia alcista o aumenta. Las posiciones cortas reflejan estas condiciones de forma inversa.
Detalles
Criterios de entrada:
Largo: HMA20 > HMA50 y precio > HMA20; RSI entre 40 y RsiOverbought; línea MACD sobre señal e histograma subiendo; volumen > SMA * VolumeMultiplier; divergencia CVD alcista o CVD creciente.
Corto: HMA20 < HMA50 y precio < HMA20; RSI entre RsiOversold y 60; línea MACD bajo señal e histograma bajando; volumen > SMA * VolumeMultiplier; divergencia CVD bajista o CVD decreciente.
Largo/Corto: Ambos lados.
Criterios de salida:
Largo: Precio < HMA20 o RSI > RsiOverbought o línea MACD cruza bajo señal.
Corto: Precio > HMA20 o RSI < RsiOversold o línea MACD cruza sobre señal.
Stops: No.
Valores predeterminados:
Hma20Length = 20
Hma50Length = 50
RsiLength = 14
RsiOverbought = 70
RsiOversold = 30
MacdFast = 12
MacdSlow = 26
MacdSignal = 9
VolumeMaLength = 20
VolumeMultiplier = 1.5
CvdLength = 14
DivergenceLookback = 5
CandleType = TimeSpan.FromMinutes(5)
Filtros:
Categoría: Mixto
Dirección: Ambos
Indicadores: HMA, RSI, MACD, Volumen, CVD
Stops: No
Complejidad: Avanzado
Marco temporal: Intradía
Estacionalidad: No
Redes neuronales: No
Divergencia: Sí
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>
/// CvdDivergenceVolumeHmaRsiMacdStrategy using EMA crossover for trend timing.
/// Enters long on golden cross, short on death cross.
/// </summary>
public class CvdDivergenceVolumeHmaRsiMacdStrategy : Strategy
{
private readonly StrategyParam<int> _fastEmaPeriod;
private readonly StrategyParam<int> _slowEmaPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFastEma;
private decimal _prevSlowEma;
public int FastEmaPeriod { get => _fastEmaPeriod.Value; set => _fastEmaPeriod.Value = value; }
public int SlowEmaPeriod { get => _slowEmaPeriod.Value; set => _slowEmaPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public CvdDivergenceVolumeHmaRsiMacdStrategy()
{
_fastEmaPeriod = Param(nameof(FastEmaPeriod), 120)
.SetGreaterThanZero()
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowEmaPeriod = Param(nameof(SlowEmaPeriod), 450)
.SetGreaterThanZero()
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).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();
_prevFastEma = 0m;
_prevSlowEma = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fastEma = new ExponentialMovingAverage { Length = FastEmaPeriod };
var slowEma = new ExponentialMovingAverage { Length = SlowEmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastEma, slowEma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastEma);
DrawIndicator(area, slowEma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fastEmaValue, decimal slowEmaValue)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevFastEma == 0m || _prevSlowEma == 0m)
{
_prevFastEma = fastEmaValue;
_prevSlowEma = slowEmaValue;
return;
}
if (_prevFastEma <= _prevSlowEma && fastEmaValue > slowEmaValue && Position <= 0)
{
BuyMarket();
}
else if (_prevFastEma >= _prevSlowEma && fastEmaValue < slowEmaValue && Position >= 0)
{
SellMarket();
}
_prevFastEma = fastEmaValue;
_prevSlowEma = slowEmaValue;
}
}
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class cvd_divergence_volume_hma_rsi_macd_strategy(Strategy):
"""
EMA crossover strategy. Enters long on golden cross, short on death cross.
"""
def __init__(self):
super(cvd_divergence_volume_hma_rsi_macd_strategy, self).__init__()
self._fast_ema_period = self.Param("FastEmaPeriod", 120) .SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_ema_period = self.Param("SlowEmaPeriod", 450) .SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))) .SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_fast_ema = 0.0
self._prev_slow_ema = 0.0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(cvd_divergence_volume_hma_rsi_macd_strategy, self).OnReseted()
self._prev_fast_ema = 0.0
self._prev_slow_ema = 0.0
def OnStarted2(self, time):
super(cvd_divergence_volume_hma_rsi_macd_strategy, self).OnStarted2(time)
fast_ema = ExponentialMovingAverage()
fast_ema.Length = self._fast_ema_period.Value
slow_ema = ExponentialMovingAverage()
slow_ema.Length = self._slow_ema_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast_ema, slow_ema, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_ema)
self.DrawIndicator(area, slow_ema)
self.DrawOwnTrades(area)
def on_process(self, candle, fast_val, slow_val):
if candle.State != CandleStates.Finished:
return
if self._prev_fast_ema == 0.0 or self._prev_slow_ema == 0.0:
self._prev_fast_ema = fast_val
self._prev_slow_ema = slow_val
return
if self._prev_fast_ema <= self._prev_slow_ema and fast_val > slow_val and self.Position <= 0:
self.BuyMarket()
elif self._prev_fast_ema >= self._prev_slow_ema and fast_val < slow_val and self.Position >= 0:
self.SellMarket()
self._prev_fast_ema = fast_val
self._prev_slow_ema = slow_val
def CreateClone(self):
return cvd_divergence_volume_hma_rsi_macd_strategy()