Auf GitHub ansehen

RSI Trader-Aligned-Averages-Strategie

Zusammenfassung

Diese Strategie reproduziert den „RSI-Händler“ MetaTrader Expert Advisor. Es richtet zwei Trendfilter – gleitende Preisdurchschnitte und geglättete RSI-Durchschnitte – so aus, dass sie in die Richtung des vorherrschenden Trends eintreten und austreten, wenn die Filter auseinanderlaufen (Seitwärtsregime). Der StockSharp-Port funktioniert auf jedem Instrument mit Kerzendatenunterstützung und verwendet standardmäßig stündliche Kerzen, wie in der Originalbeschreibung.

Wie es funktioniert

  1. Berechnen Sie RSI mit dem durch RSI Zeitraum angegebenen Zeitraum (Standard 14).
  2. Glätten Sie den RSI-Stream mit zwei einfachen gleitenden Durchschnitten: einem kurzen (Short RSI MA) und einem langen (Long RSI MA).
  3. Glatte Schlusskurse mit zwei gleitenden Durchschnitten: einem kurzen einfachen MA (Short Price MA) und einem langen linear gewichteten MA (Long Price MA).
  4. Signale nur für fertige Kerzen generieren:
    • Long – beide Short-Durchschnitte (Preis und RSI) liegen über ihren Long-Gegenstücken.
    • Short – beide Short-Durchschnitte liegen unter ihren Long-Gegenstücken.
    • Seitwärts – die Durchschnittswerte stimmen nicht überein (einer zeigt einen Aufwärtstrend und der andere einen Abwärtstrend an). In diesem Fall wird jede offene Position geschlossen.
  5. Bestellungen werden mit BuyMarket / SellMarket erteilt. Gegensätzliche Positionen werden abgeflacht, bevor eine neue Richtung eingeschlagen wird.

Parameter

Name Beschreibung Standard Optimierbar
RSI Period RSI Berechnungslänge. 14 Ja (7…28, Schritt 1)
Short Price MA Länge des kurzen einfachen gleitenden Durchschnitts des Preises. 9 Ja (5…20, Schritt 1)
Long Price MA Länge des langen linear gewichteten gleitenden Durchschnitts des Preises. 45 Ja (30…90, Schritt 5)
Short RSI MA Länge des kurzen Glättungsdurchschnitts, der auf RSI angewendet wird. 9 Ja (5…20, Schritt 1)
Long RSI MA Länge des langen Glättungsdurchschnitts, der auf RSI angewendet wird. 45 Ja (30…90, Schritt 5)
Candle Type Für Kerzen verwendeter Datentyp. Standardmäßig ist der Zeitrahmen 1 Stunde. H1 Nein

Notizen

  • Der Handel wird erst dann durchgeführt, wenn alle Indikatoren gebildet sind.
  • Das Original EA verwendete Lots und Slippage-Einstellungen. StockSharp verwendet die Strategieeigenschaft Volume für die Ordergröße und überlässt die Ausführungs-Slippage-Verwaltung dem Handelsadapter.
  • Es ist kein eingebauter Stop-Loss oder Take-Profit definiert; Ausgänge hängen von der seitlichen Erkennung ab. Zusätzliches Risikomanagement kann extern hinzugefügt werden.
  • Diagramme zeichnen sowohl den Preis als auch RSI gleitende Durchschnitte, wenn der Diagrammdienst verfügbar ist.
using System;
using System.Collections.Generic;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// RSI Trader strategy combining price SMA crossover with RSI trend confirmation.
/// Buy when short SMA crosses above long SMA with RSI above 50.
/// Sell when short SMA crosses below long SMA with RSI below 50.
/// </summary>
public class RsiTraderAlignedAveragesStrategy : Strategy
{
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<int> _shortMaPeriod;
	private readonly StrategyParam<int> _longMaPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevShort;
	private decimal _prevLong;
	private bool _hasPrev;

	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public int ShortMaPeriod { get => _shortMaPeriod.Value; set => _shortMaPeriod.Value = value; }
	public int LongMaPeriod { get => _longMaPeriod.Value; set => _longMaPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public RsiTraderAlignedAveragesStrategy()
	{
		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetDisplay("RSI Period", "RSI calculation period", "Indicators");

		_shortMaPeriod = Param(nameof(ShortMaPeriod), 9)
			.SetDisplay("Short MA", "Short moving average period", "Indicators");

		_longMaPeriod = Param(nameof(LongMaPeriod), 26)
			.SetDisplay("Long MA", "Long moving average period", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

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

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

		_prevShort = 0m;
		_prevLong = 0m;
		_hasPrev = false;
	}

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

		_hasPrev = false;

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var shortMa = new SimpleMovingAverage { Length = ShortMaPeriod };
		var longMa = new SimpleMovingAverage { Length = LongMaPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(rsi, shortMa, longMa, ProcessCandle)
			.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal rsiValue, decimal shortMa, decimal longMa)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!_hasPrev)
		{
			_prevShort = shortMa;
			_prevLong = longMa;
			_hasPrev = true;
			return;
		}

		var bullCross = _prevShort <= _prevLong && shortMa > longMa;
		var bearCross = _prevShort >= _prevLong && shortMa < longMa;

		if (Position <= 0 && bullCross && rsiValue > 50)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		else if (Position >= 0 && bearCross && rsiValue < 50)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevShort = shortMa;
		_prevLong = longMa;
	}
}