Die Strategie kombiniert die Divergenz des kumulierten Volumen-Deltas (CVD) mit Hull Moving Averages, RSI, MACD und einem Volumenfilter. Ein Trade öffnet sich, wenn Trend, Momentum und Volumen übereinstimmen und das CVD Divergenz oder Fortsetzung in Handelsrichtung zeigt. Positionen schließen bei entgegengesetzten Signalen oder Indikatorkreuzungen.
Details
Einstiegskriterien: Trendausrichtung durch HMA, RSI- und MACD-Bestätigung, hohes Volumen und CVD-Divergenz/-Fortsetzung.
Long/Short: Beide Richtungen.
Ausstiegskriterien: Entgegengesetztes Signal oder Indikatorkreuzung.
Stops: Keine expliziten Stops.
Standardwerte:
HmaFastLength = 20
HmaSlowLength = 50
RsiLength = 14
RsiOverbought = 70
RsiOversold = 30
MacdFast = 12
MacdSlow = 26
MacdSignal = 9
VolumeMaLength = 20
VolumeMultiplier = 1.5m
CvdLength = 14
DivergenceLookback = 5
CandleType = TimeSpan.FromMinutes(1)
Filter:
Kategorie: Divergenz
Richtung: Beide
Indikatoren: HMA, RSI, MACD, Volumen
Stops: Nein
Komplexität: Mittel
Zeitrahmen: Intraday
Saisonalität: Nein
Neuronale Netze: Nein
Divergenz: Ja
Risikolevel: Mittel
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>
/// CvdDivergenceStrategy using EMA crossover for trend timing.
/// Enters long on golden cross, short on death cross.
/// </summary>
public class CvdDivergenceStrategy : 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 CvdDivergenceStrategy()
{
_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_strategy(Strategy):
"""
EMA crossover strategy. Enters long on golden cross, short on death cross.
"""
def __init__(self):
super(cvd_divergence_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_strategy, self).OnReseted()
self._prev_fast_ema = 0.0
self._prev_slow_ema = 0.0
def OnStarted2(self, time):
super(cvd_divergence_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_strategy()