Diese Strategie ist eine C#-Konvertierung des "Macd Diver and RSI" MetaTrader 5 Expert Advisors. Es bleibt bei der ursprünglichen zweistufigen Signalidee: Der Relative Strength Index (RSI) erkennt überverkaufte oder überkaufte Extreme, während das MACD-Histogramm bestätigt, dass sich die Dynamik wieder in Richtung des Handels dreht. Long- und Short-Seiten werden unabhängig voneinander konfiguriert, sodass das Verhalten separat auf bullische und bärische Setups abgestimmt werden kann.
Die Strategie basiert auf einem Einzelkerzenabonnement (konfigurierbarer Zeitrahmen) und handelt das gecharterte Wertpapier direkt über Marktaufträge. Die gesamte Indikatorverarbeitung verwendet die übergeordnete StockSharp API über BindEx, entsprechend den Projektregeln.
Handelslogik
Indikatorvorbereitung
Es werden zwei RSI-Indikatoren erstellt, einer für den langen Zweig und einer für den kurzen Zweig, mit individuellen Längen und Schwellenwerten.
Zwei MovingAverageConvergenceDivergenceSignal-Indikatoren spiegeln die MACD-Einstellungen für Long- und Short-Trades wider. Ihre Histogrammkomponente wird zur Bestätigung von Impulsumkehrungen verwendet.
Eintrittsregeln
Long-Setup: Wenn der Long-RSI-Wert bei oder unter dem überverkauften Schwellenwert liegt und das Long-MACD-Histogramm über Null geht (das Vorzeichen von negativ zu positiv ändert), wird eine bullische Position eröffnet. Wenn eine Short-Position aktiv ist, wird sie in derselben Marktorder geschlossen und rückgängig gemacht.
Short-Setup: Wenn der Short-RSI-Wert bei oder über der überkauften Schwelle liegt und das Short-MACD-Histogramm unter Null fällt, wird eine rückläufige Position eröffnet. Das bestehende Long-Engagement wird abgeflacht, bevor das neue Short-Engagement etabliert wird.
Risikomanagement
Nach jedem Einstieg zeichnet die Strategie den Schlusskurs des Signalbalkens als Referenzpreis auf.
Stop-Loss- und Take-Profit-Niveaus werden anhand dieses Preises anhand von Pip-Abständen prognostiziert, die für Long- und Short-Trades separat definiert werden.
Pips werden mit dem Instrument PriceStep in Preiseinheiten umgewandelt und für Symbole mit 3 oder 5 Dezimalstellen automatisch um 10 skaliert, um das MT5-Verhalten widerzuspiegeln.
Bei jeder abgeschlossenen Kerze wird der Hoch-/Tief-Bereich mit diesen Niveaus verglichen. Bei Erreichen eines dieser Level wird die Position sofort mit einer Marktorder geschlossen.
Handelsmanagement
Der Positionsstatus wird gelöscht, wenn die Positionsgröße auf Null zurückkehrt (entweder weil ein Stop/Take-Profit erreicht wurde oder die Strategie durch ein entgegengesetztes Signal umgekehrt wurde).
Es werden keine teilweisen Exits oder nachgestellten Anpassungen durchgeführt; Die Positionssteuerung erfolgt ausschließlich über die statischen Stop-Loss- und Take-Profit-Level.
Parameter
Parameter
Beschreibung
CandleType
Zeitrahmen des für Signale verwendeten Kerzenabonnements.
LongRsiPeriod, ShortRsiPeriod
RSI Längen für lange und kurze Erkennung.
LongRsiThreshold, ShortRsiThreshold
RSI Schwellenwerte, die Einstiege ermöglichen (überverkauft für Long-Positionen, überkauft für Short-Positionen).
Handelsvolumen pro Signal. Beim Umkehren addiert die Strategie das absolute Eröffnungsvolumen, sodass die einzelne Order den Abschluss und die neue Eröffnung durchführt.
Abstand von Stop-Loss- und Take-Profit-Orders in Pips. Null deaktiviert die jeweilige Stufe.
Notizen
Die Strategie erfordert Instrumente mit einem PriceStep ungleich Null. Wenn der Schritt fehlt, fällt die Pip-Berechnung auf 0,0001 zurück, um eine Division durch Null zu verhindern.
Da beide Seiten unabhängige Indikatorinstanzen verwenden, können Sie bullisches und bärisches Verhalten separat anpassen, indem Sie beispielsweise die überkaufte Schwelle verschärfen und gleichzeitig die überverkaufte Seite freizügiger halten.
Der Code fügt englische Kommentare und Dokumentation hinzu, um den Handelsprozess zu verdeutlichen und die Projektrichtlinien zu erfüllen.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// MACD Diver And RSI strategy: RSI extremes + MACD histogram crossover.
/// Buys when RSI below 30 and MACD histogram crosses above zero.
/// Sells when RSI above 70 and MACD histogram crosses below zero.
/// </summary>
public class MacdDiverAndRsiStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private decimal _prevHistogram;
private decimal _prevRsi;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public MacdDiverAndRsiStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevHistogram = 0;
_prevRsi = 0;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var macd = new MovingAverageConvergenceDivergenceSignal
{
Macd = { ShortMa = { Length = 12 }, LongMa = { Length = 26 } },
SignalMa = { Length = 9 }
};
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.BindEx(macd, rsi, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdValue, IIndicatorValue rsiValue)
{
if (candle.State != CandleStates.Finished) return;
if (!macdValue.IsFinal || !rsiValue.IsFinal) return;
if (macdValue is not MovingAverageConvergenceDivergenceSignalValue typed) return;
if (typed.Macd is not decimal macdMain || typed.Signal is not decimal signal) return;
var histogram = macdMain - signal;
var rsi = rsiValue.ToDecimal();
if (_hasPrev)
{
if (_prevHistogram <= 0 && histogram > 0 && _prevRsi < 35 && Position <= 0)
BuyMarket();
else if (_prevHistogram >= 0 && histogram < 0 && _prevRsi > 65 && Position >= 0)
SellMarket();
}
_prevHistogram = histogram;
_prevRsi = rsi;
_hasPrev = true;
}
}
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 MovingAverageConvergenceDivergenceSignal, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class macd_diver_and_rsi_strategy(Strategy):
def __init__(self):
super(macd_diver_and_rsi_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._rsi_period = self.Param("RsiPeriod", 14)
self._prev_histogram = 0.0
self._prev_rsi = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def RsiPeriod(self):
return self._rsi_period.Value
@RsiPeriod.setter
def RsiPeriod(self, value):
self._rsi_period.Value = value
def OnReseted(self):
super(macd_diver_and_rsi_strategy, self).OnReseted()
self._prev_histogram = 0.0
self._prev_rsi = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(macd_diver_and_rsi_strategy, self).OnStarted2(time)
self._has_prev = False
macd = MovingAverageConvergenceDivergenceSignal()
macd.Macd.ShortMa.Length = 12
macd.Macd.LongMa.Length = 26
macd.SignalMa.Length = 9
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(macd, rsi, self._process_candle).Start()
def _process_candle(self, candle, macd_value, rsi_value):
if candle.State != CandleStates.Finished:
return
if not macd_value.IsFinal or not rsi_value.IsFinal:
return
if macd_value.Macd is None or macd_value.Signal is None:
return
macd_main = float(macd_value.Macd)
signal = float(macd_value.Signal)
histogram = macd_main - signal
rsi_val = float(rsi_value)
if self._has_prev:
if self._prev_histogram <= 0 and histogram > 0 and self._prev_rsi < 35 and self.Position <= 0:
self.BuyMarket()
elif self._prev_histogram >= 0 and histogram < 0 and self._prev_rsi > 65 and self.Position >= 0:
self.SellMarket()
self._prev_histogram = histogram
self._prev_rsi = rsi_val
self._has_prev = True
def CreateClone(self):
return macd_diver_and_rsi_strategy()