Auf GitHub ansehen

CDC PL RSI Strategie

Überblick

Die CDC PL RSI-Strategie repliziert den MQL Expert Advisor Expert_ADC_PL_RSI innerhalb des StockSharp-Ökosystems. Das System durchsucht fertige Kerzen nach japanischen Candlestick-Umkehrmustern und bestätigt Eingaben mit dem Relative Strength Index (RSI). Long-Trades basieren auf dem Piercing Line-Muster bei überverkauften RSI-Bedingungen, während Short-Trades das Dark Cloud Cover-Muster in Kombination mit überkauften RSI-Werten erfordern. Der Ansatz hält das ursprüngliche Money-Management-Konzept einfach, indem er das Strategievolumen verwendet und StockSharp die Positionsgrößenbestimmung überlässt.

Muster- und Indikatorlogik

  • Kerzenmuster: Die Strategie rekonstruiert die MetaTrader-Logik durch die Analyse zweier zuletzt abgeschlossener Kerzen. Die Regeln für Piercing Line und Dark Cloud Cover spiegeln den ursprünglichen Code wider, einschließlich Prüfungen auf Lücken, lange Körper im Verhältnis zu einem adaptiven Körperdurchschnitt und die zugrunde liegende Trendrichtung.
  • RSI-Filter: Ein 20-Perioden-RSI (optimierbar) bestätigt die Dynamik. Überverkaufte Werte (RSI < 40) schalten Long-Einträge frei, und überkaufte Werte (RSI > 60) schalten Short-Einträge frei. Der RSI-Verlauf wird auch verwendet, um Ausgänge zu erkennen, wenn der Oszillator die 30- oder 70-Ebenen in die entgegengesetzte Richtung überschreitet.
  • Körperdurchschnitt und Trendfilter: Ein einfacher gleitender Durchschnitt der Kerzenkörpergrößen und weitere SMA der Schlusskurse replizieren die MetaTrader-Hilfsfunktionen (AvgBody und CloseAvg). Diese Durchschnittswerte verhindern Signale während des Rauschens und sorgen dafür, dass die Muster nach einer klaren Bewegung erscheinen.

Handelsregeln

Lange Einrichtung

  1. Erkennen Sie ein Piercing-Line-Muster bei den letzten beiden abgeschlossenen Kerzen.
  2. Erfordern, dass RSI von der vorherigen fertigen Kerze unter 40 liegt.
  3. Wenn die Bedingungen bestehen, kaufen Sie zum Marktpreis. Wenn eine Gegenposition vorhanden ist, kehrt sich die Strategie um, indem die absolute Positionsgröße plus das konfigurierte Volumen gekauft wird.

Kurze Einrichtung

  1. Erkennen Sie bei den beiden letzten Kerzen ein Muster einer dunklen Wolkendecke.
  2. Erfordern, dass RSI von der vorherigen fertigen Kerze über 60 liegt.
  3. Wenn die Bedingungen bestehen, verkaufen Sie zum Marktpreis. Eine entgegengesetzte Position wird mit derselben Volumenlogik geschlossen und umgekehrt.

Ausstiegsbedingungen

  • Schließen Sie Long-Positionen, wenn RSI 70 nach unten oder 30 nach oben kreuzt, was signalisiert, dass die Dynamik nachgelassen hat oder umgekehrt ist.
  • Schließen Sie Short-Positionen, wenn RSI 30 nach oben oder 70 nach unten überschreitet, was der MetaTrader-Implementierung entspricht.

Parameter

Name Standard Beschreibung
RsiPeriod 20 RSI Lookback-Länge. Optimierbar zwischen 10 und 40 in 5er-Schritten.
BodyAveragePeriod 14 Zeitraum sowohl für die durchschnittliche Kerzenkörpergröße als auch für den Schlusspreistrendfilter. Optimierbar zwischen 10 und 30 in 5er-Schritten.
CandleType 1-stündiger Zeitrahmen Für Berechnungen verwendete Kerzenreihe. Jeder von StockSharp unterstützte Kerzentyp kann ausgewählt werden.
Volume (Basisklasse) Handelsvolumen, das vor dem Start für die Strategieinstanz festgelegt wird.

Nutzung

  1. Fügen Sie die Strategie einem Portfolio und einer Sicherheit in StockSharp Designer, Shell oder Runner hinzu.
  2. Konfigurieren Sie Kerzentyp und -volumen entsprechend dem gehandelten Markt.
  3. Passen Sie optional die Perioden RSI und Körperdurchschnitt an, um sie an die Volatilität des Instruments anzupassen, oder führen Sie Optimierungen mit dem StockSharp-Optimierer durch.
  4. Starten Sie die Strategie und überwachen Sie die Diagrammüberlagerungen (Kerzen, RSI und Schlussdurchschnittslinie), um Musterbestätigungen und ausgeführte Trades zu überprüfen.

Notizen

  • Die Strategie ruft StartProtection() auf, sodass bei Bedarf integrierte Schutzroutinen konfiguriert werden können (Stop-Loss, Take-Profit, Trailing usw.).
  • Es werden nur abgeschlossene Kerzen verarbeitet, wobei die Logik mit dem MQL Expert Advisor konsistent bleibt.
  • Es werden keine zusätzlichen Sammlungen gespeichert; Indikatorinstanzen enthalten die für die Musterprüfungen erforderlichen Schiebefensterberechnungen.
namespace StockSharp.Samples.Strategies;

using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// CDC PL RSI strategy: Dark Cloud Cover and Piercing Line candlestick patterns
/// confirmed by RSI levels.
/// </summary>
public class CdcPlRsiStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _oversoldLevel;
	private readonly StrategyParam<decimal> _overboughtLevel;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private readonly List<ICandleMessage> _candles = new();
	private decimal _prevRsi;
	private bool _hasPrevRsi;
	private int _candlesSinceTrade;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public decimal OversoldLevel { get => _oversoldLevel.Value; set => _oversoldLevel.Value = value; }
	public decimal OverboughtLevel { get => _overboughtLevel.Value; set => _overboughtLevel.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public CdcPlRsiStrategy()
	{
		_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");
		_oversoldLevel = Param(nameof(OversoldLevel), 40m)
			.SetDisplay("Oversold Level", "RSI below this for long entry", "Signals");
		_overboughtLevel = Param(nameof(OverboughtLevel), 60m)
			.SetDisplay("Overbought Level", "RSI above this for short entry", "Signals");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_candles.Clear();
		_prevRsi = 0m;
		_hasPrevRsi = false;
		_candlesSinceTrade = SignalCooldownCandles;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_candles.Clear();
		_hasPrevRsi = false;
		_candlesSinceTrade = SignalCooldownCandles;
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(rsi, ProcessCandle).Start();

		StartProtection(
			takeProfit: new Unit(2, UnitTypes.Percent),
			stopLoss: new Unit(1, UnitTypes.Percent)
		);
	}

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

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		_candles.Add(candle);
		if (_candles.Count > 5)
			_candles.RemoveAt(0);

		if (_candles.Count >= 2 && _hasPrevRsi)
		{
			var curr = _candles[^1];
			var prev = _candles[^2];

			// Piercing Line
			var isPiercing = prev.OpenPrice > prev.ClosePrice
				&& curr.ClosePrice > curr.OpenPrice
				&& curr.OpenPrice < prev.LowPrice
				&& curr.ClosePrice > (prev.OpenPrice + prev.ClosePrice) / 2m;

			// Dark Cloud Cover
			var isDarkCloud = prev.ClosePrice > prev.OpenPrice
				&& curr.OpenPrice > curr.ClosePrice
				&& curr.OpenPrice > prev.HighPrice
				&& curr.ClosePrice < (prev.OpenPrice + prev.ClosePrice) / 2m;

			if (isPiercing && rsiValue < OversoldLevel && Position == 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
			else if (isDarkCloud && rsiValue > OverboughtLevel && Position == 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
		}

		_prevRsi = rsiValue;
		_hasPrevRsi = true;
	}
}