Auf GitHub ansehen

Experten RSI Stochastic MA Strategie

Überblick

Die Experten RSI Stochastic MA Strategie ist eine Konvertierung des MetaTrader 5-Expertenberaters Expert_RSI_Stochastic_MA.mq5. Die C#-Implementierung nutzt StockSharp's High-Level-Strategie-API und reproduziert dabei die ursprüngliche Logik: ein Trendfilter basierend auf einem konfigurierbaren gleitenden Durchschnitt, Momentum-Bestätigung durch RSI, und ein Dual-Line-Stochastic-Oszillator für präzises Timing. Das Schutzverhalten repliziert den Quellalgorithmus mit einer optionalen festen Verlustschwelle und einem Stochastic-gesteuerten Trailing-Ausstieg.

Indikatoren und Parameter

Die Strategie bietet dieselben Eingaben wie die MetaTrader-Version und behält deren Standardwerte bei. Alle Parameter sind für die Optimierung über die StockSharp-UI verfügbar.

Kategorie Parameter Standard Beschreibung
Allgemein CandleType 15-Minuten-Zeitrahmen Kerzen-Aggregation für Indikatorberechnungen.
Trading TradeVolume 0.01 Basisauftragsgröße in Lots/Kontrakten.
RSI RsiPeriod 3 Anzahl der Balken für die RSI-Berechnung.
RSI RsiPriceType Schluss Angewendeter Preis für RSI (Schluss, Eröffnung, Hoch, Tief, Median, Typisch, Gewichtet).
RSI RsiUpperLevel 80 Überkauft-Schwelle, die Short-Bedingungen auslöst.
RSI RsiLowerLevel 20 Überverkauft-Schwelle, die Long-Bedingungen auslöst.
Stochastic StochKPeriod 6 Periode der %K-Linie.
Stochastic StochDPeriod 3 Periode der %D-Glättungslinie.
Stochastic StochSlowing 3 Zusätzlicher Verlangsamungsfaktor für %K.
Stochastic StochUpperLevel 70 Überkauft-Niveau für beide Stochastic-Linien.
Stochastic StochLowerLevel 30 Überverkauft-Niveau für beide Stochastic-Linien.
Gleitender Durchschnitt MaMethod Einfach Typ des gleitenden Durchschnitts (einfach, exponentiell, geglättet, gewichtet).
Gleitender Durchschnitt MaPriceType Schluss Angewendeter Preis für den gleitenden Durchschnitt.
Gleitender Durchschnitt MaPeriod 150 Länge des gleitenden Durchschnitts.
Gleitender Durchschnitt MaShift 0 Anzahl abgeschlossener Balken zur Rückverschiebung des gleitenden Durchschnittwerts.
Risiko AllowLossPoints 30 Maximale negative Kursabweichung in Punkten vor dem Ausstieg aus einem Verlusthandel (0 deaktiviert).
Risiko TrailingStopPoints 30 Abstand in Punkten für den Stochastic-basierten Trailing-Stop (0 schließt bei Stochastic ohne Trailing).

Punktberechnung – Die Implementierung konvertiert die Parameter AllowLoss und TrailingStop in absolute Preise mithilfe von Security.PriceStep. Bei Instrumenten mit 3 oder 5 Dezimalstellen wird der Wert mit 10 multipliziert, um MetaTrader's Pip-Behandlung zu emulieren.

Handelslogik

Long-Setup

  1. Trendfilter – Kerzenschluss muss über dem verschobenen gleitenden Durchschnitt bleiben.
  2. Momentum-Bestätigung – RSI muss unter RsiLowerLevel liegen.
  3. Timing – Beide Stochastic-Linien (%K und %D) müssen unter StochLowerLevel liegen.
  4. Positionsfilter – Long-Orders werden nur platziert, wenn keine Long-Exposition vorhanden ist (Position <= 0). Die Auftragsgröße ist TradeVolume plus jede Menge, die zum Schließen einer bestehenden Short-Position erforderlich ist.

Short-Setup

  1. Trendfilter – Kerzenschluss muss unter dem verschobenen gleitenden Durchschnitt liegen.
  2. Momentum-Bestätigung – RSI muss RsiUpperLevel überschreiten.
  3. Timing – Beide Stochastic-Linien müssen über StochUpperLevel liegen.
  4. Positionsfilter – Neue Short-Positionen erfordern Position >= 0. Die Strategie gleicht bestehende Longs automatisch aus, falls nötig.

Ausstiegsverwaltung

  • Verlusthandel
    • Wenn AllowLossPoints null ist, wartet die Strategie, bis die Stochastic-Hauptlinie in das entgegengesetzte Extrem wechselt (StochUpperLevel für Longs, StochLowerLevel für Shorts), bevor negative Trades geschlossen werden.
    • Wenn AllowLossPoints positiv ist, konvertiert die Strategie den Wert in einen Preisoffset und schließt den Trade, sobald der Verlust diesen Schwellenwert überschreitet und der Stochastic in die neutrale Zone zurückkehrt (stochMain > StochLowerLevel für Longs, < StochUpperLevel für Shorts).
  • Trailing-Ausstieg
    • Mit TrailingStopPoints > 0 wird bei jedem abgeschlossenen Kerze ein Trailing-Stop gesetzt, sobald ein Trade profitabel ist und der Stochastic seine Extremzone erreicht. Bei Long-Trades verfolgt der Stop den Preis von unten; bei Short-Trades von oben.
    • Mit TrailingStopPoints = 0 werden profitable Trades sofort geschlossen, wenn der Stochastic das Extremniveau erreicht (entspricht dem Verhalten des ursprünglichen EAs).
  • Trailing-Auslöser – Trailing-Updates erfolgen nur bei abgeschlossenen Kerzen und spiegeln die MQL-Implementierung wider, die Updates auf eine pro Balken beschränkte.

Implementierungshinweise

  • Die Verschiebung des gleitenden Durchschnitts wird durch Speichern aktueller Werte und Lesen des Werts MaShift Balken zurück behandelt, was MetaTrader's shift-Parameter reproduziert.
  • RSI- und gleitende Durchschnitt-Eingaben unterstützen mehrere angewendete Preise, um MetaTrader-Optionen abzugleichen. Stochastic-Berechnungen stützen sich auf StockSharp's integrierten Oszillator (Low/High-Modus) und berücksichtigen die konfigurierten Glättungslängen.
  • Trailing- und Verlust-Schwellenwerte werden in Punkten gemessen. Der Helfer skaliert den Wert automatisch für typische FX-Tick-Größen (3 oder 5 Dezimalstellen) und verwendet standardmäßig einen PriceStep.
  • Die Chartausgabe enthält Kerzen, den gleitenden Durchschnitt, RSI und Stochastic-Indikatoren, was eine visuelle Validierung ähnlich der ursprünglichen Vorlage ermöglicht.
  • Es gibt keine Python-Begleitversion auf Anfrage; nur die C#-Implementierung wird bereitgestellt.

Verwendungshinweise

  • Beim Einsatz auf Wertpapieren mit unkonventionellen Tick-Größen stellen Sie sicher, dass Security.PriceStep ausgefüllt ist; andernfalls wird die Standardkonvertierung verwendet (1 Punkt = 1 Preiseinheit).
  • Kombinieren Sie den integrierten StartProtection oder zusätzliche Risikomodule, wenn weitere Stop-Loss- oder Take-Profit-Verwaltung erforderlich ist.
  • Optimieren Sie Indikatorlängen und Risikoschwellenwerte zusammen – die Strategie bietet absichtlich alle primären Einstellregler des MetaTrader-Experten.
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>
/// Combines an SMA trend filter with RSI and Stochastic oscillators.
/// Enters long when price is above SMA, RSI is oversold and Stochastic is oversold.
/// Enters short when price is below SMA, RSI is overbought and Stochastic is overbought.
/// </summary>
public class ExpertRsiStochasticMaStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _rsiUpperLevel;
	private readonly StrategyParam<decimal> _rsiLowerLevel;
	private readonly StrategyParam<int> _stochKPeriod;
	private readonly StrategyParam<int> _stochDPeriod;
	private readonly StrategyParam<decimal> _stochUpperLevel;
	private readonly StrategyParam<decimal> _stochLowerLevel;
	private readonly StrategyParam<int> _maPeriod;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int RsiPeriod
	{
		get => _rsiPeriod.Value;
		set => _rsiPeriod.Value = value;
	}

	public decimal RsiUpperLevel
	{
		get => _rsiUpperLevel.Value;
		set => _rsiUpperLevel.Value = value;
	}

	public decimal RsiLowerLevel
	{
		get => _rsiLowerLevel.Value;
		set => _rsiLowerLevel.Value = value;
	}

	public int StochKPeriod
	{
		get => _stochKPeriod.Value;
		set => _stochKPeriod.Value = value;
	}

	public int StochDPeriod
	{
		get => _stochDPeriod.Value;
		set => _stochDPeriod.Value = value;
	}

	public decimal StochUpperLevel
	{
		get => _stochUpperLevel.Value;
		set => _stochUpperLevel.Value = value;
	}

	public decimal StochLowerLevel
	{
		get => _stochLowerLevel.Value;
		set => _stochLowerLevel.Value = value;
	}

	public int MaPeriod
	{
		get => _maPeriod.Value;
		set => _maPeriod.Value = value;
	}

	public ExpertRsiStochasticMaStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Time frame used for calculations", "General");

		_rsiPeriod = Param(nameof(RsiPeriod), 3)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "Number of bars for RSI", "RSI");

		_rsiUpperLevel = Param(nameof(RsiUpperLevel), 80m)
			.SetDisplay("RSI Overbought", "Upper RSI threshold", "RSI");

		_rsiLowerLevel = Param(nameof(RsiLowerLevel), 20m)
			.SetDisplay("RSI Oversold", "Lower RSI threshold", "RSI");

		_stochKPeriod = Param(nameof(StochKPeriod), 6)
			.SetGreaterThanZero()
			.SetDisplay("%K Period", "Length of Stochastic %K", "Stochastic");

		_stochDPeriod = Param(nameof(StochDPeriod), 3)
			.SetGreaterThanZero()
			.SetDisplay("%D Period", "Length of Stochastic %D", "Stochastic");

		_stochUpperLevel = Param(nameof(StochUpperLevel), 70m)
			.SetDisplay("Stoch Overbought", "Upper Stochastic threshold", "Stochastic");

		_stochLowerLevel = Param(nameof(StochLowerLevel), 30m)
			.SetDisplay("Stoch Oversold", "Lower Stochastic threshold", "Stochastic");

		_maPeriod = Param(nameof(MaPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("MA Period", "Length of moving average", "Moving Average");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var sma = new SMA { Length = MaPeriod };
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var stoch = new StochasticOscillator();
		stoch.K.Length = StochKPeriod;
		stoch.D.Length = StochDPeriod;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(sma, rsi, stoch, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, sma);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue smaValue, IIndicatorValue rsiValue, IIndicatorValue stochValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!smaValue.IsFinal || !rsiValue.IsFinal || !stochValue.IsFinal)
			return;

		var sma = smaValue.IsEmpty ? (decimal?)null : smaValue.GetValue<decimal>();
		var rsiVal = rsiValue.IsEmpty ? (decimal?)null : rsiValue.GetValue<decimal>();

		if (sma is not decimal smaDecimal || rsiVal is not decimal rsiDecimal)
			return;

		var stoch = (StochasticOscillatorValue)stochValue;
		if (stoch.K is not decimal stochK || stoch.D is not decimal stochD)
			return;

		var price = candle.ClosePrice;

		// Long entry: price above SMA, RSI oversold, Stochastic oversold
		if (price > smaDecimal && rsiDecimal < RsiLowerLevel && stochK < StochLowerLevel && stochD < StochLowerLevel)
		{
			if (Position <= 0)
				BuyMarket();
		}
		// Short entry: price below SMA, RSI overbought, Stochastic overbought
		else if (price < smaDecimal && rsiDecimal > RsiUpperLevel && stochK > StochUpperLevel && stochD > StochUpperLevel)
		{
			if (Position >= 0)
				SellMarket();
		}
		// Exit long: Stochastic overbought
		else if (Position > 0 && stochK > StochUpperLevel)
		{
			SellMarket();
		}
		// Exit short: Stochastic oversold
		else if (Position < 0 && stochK < StochLowerLevel)
		{
			BuyMarket();
		}
	}
}