Auf GitHub ansehen

KWAN RDP Trend-Strategie

Diese Strategie ist eine StockSharp-Konvertierung des MetaTrader-Experten Exp_KWAN_RDP. Die Logik berechnet den KWAN RDP-Oszillator durch Kombination dreier Standardindikatoren und Glättung ihres Produkts:

  1. DeMarker — misst die Beziehung zwischen zuletzt aufgetretenen Hochs und Tiefs, um die Momentum-Erschöpfung zu beurteilen.
  2. Money Flow Index — bewertet Preis und Volumen, um überkaufte oder überverkaufte Bedingungen zu erkennen.
  3. Momentum — erfasst die Geschwindigkeit von Preisänderungen mit dem gewählten Zeitraum.
  4. Der Rohwert 100 * DeMarker * MFI / Momentum wird mit einem konfigurierbaren gleitenden Durchschnitt (SMA, EMA, SMMA, WMA oder Jurik) geglättet.

Die Steigung des geglätteten Oszillators erzeugt Handelssignale:

  • Bullische Wende (steigende Steigung): Short-Positionen schließen und optional eine Long-Position eröffnen.
  • Bärische Wende (fallende Steigung): Long-Positionen schließen und optional eine Short-Position eröffnen.
  • Neutrale Balken (flache Steigung) lösen keine Aktionen aus.

Parameter

  • CandleType — Kerzenserie für Indikatorberechnungen (Standard: H1-Zeitrahmen).
  • DeMarkerPeriod — Periode des DeMarker-Indikators.
  • MfiPeriod — Periode des Money Flow Index.
  • MomentumPeriod — Periode des Momentum-Indikators.
  • SmoothingLength — Länge des glättenden gleitenden Durchschnitts.
  • Smoothing — Glättungsmethode (Simple, Exponential, Smoothed, Weighted, Jurik).
  • EnableLongEntries / EnableShortEntries — Eröffnung von Long- oder Short-Positionen erlauben.
  • CloseLongsOnReverse / CloseShortsOnReverse — Gegenpositionen schließen, wenn ein Umkehrsignal erscheint.
  • TakeProfitPercent / StopLossPercent — optionaler prozentualer Schutz, angewendet über StartProtection.

Handelsregeln

  1. Die konfigurierte Kerzenserie abonnieren und DeMarker, MFI, Momentum und den geglätteten KWAN-Wert auf jeder abgeschlossenen Kerze berechnen.
  2. Die Steigungsrichtung des neuesten Oszillatorwerts gegenüber dem vorherigen erkennen.
  3. Wenn die Steigung aufwärts dreht, Shorts schließen (wenn aktiviert) und ein Long eröffnen, wenn Long-Trading erlaubt ist und keine Long-Position aktiv ist.
  4. Wenn die Steigung abwärts dreht, Longs schließen (wenn aktiviert) und ein Short eröffnen, wenn Short-Trading erlaubt ist und keine Short-Position aktiv ist.
  5. Die optionalen Stop-Loss- und Take-Profit-Prozentsätze verwenden, um Positionen mit Platform-Schutz abzusichern.

Hinweise

  • Signale werden nur auf abgeschlossenen Kerzen verarbeitet, um Intrabar-Rauschen zu vermeiden.
  • Die DeMarker-Berechnung verwendet interne Glättung, um der MetaTrader-Implementierung zu entsprechen.
  • Alle Kommentare im C#-Code sind gemäß den Projektrichtlinien auf Englisch verfasst.
namespace StockSharp.Samples.Strategies;

using System;

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

/// <summary>
/// KWAN RDP trend strategy converted from MetaTrader version.
/// Combines DeMarker and Momentum indicators to detect trend reversals.
/// Opens long when DeMarker rises and momentum is positive, short when DeMarker falls and momentum is negative.
/// </summary>
public class KwanRdpStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _deMarkerPeriod;
	private readonly StrategyParam<int> _momentumPeriod;

	private decimal _prevDem;
	private decimal _prevMom;
	private bool _initialized;

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

	public int DeMarkerPeriod
	{
		get => _deMarkerPeriod.Value;
		set => _deMarkerPeriod.Value = value;
	}

	public int MomentumPeriod
	{
		get => _momentumPeriod.Value;
		set => _momentumPeriod.Value = value;
	}

	public KwanRdpStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Primary candle series", "General");

		_deMarkerPeriod = Param(nameof(DeMarkerPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("DeMarker Period", "DeMarker indicator length", "Indicators");

		_momentumPeriod = Param(nameof(MomentumPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("Momentum Period", "Momentum indicator length", "Indicators");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevDem = 0m;
		_prevMom = 0m;
		_initialized = false;
	}

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

		_prevDem = 0;
		_prevMom = 0;
		_initialized = false;

		var deMarker = new DeMarker { Length = DeMarkerPeriod };
		var momentum = new Momentum { Length = MomentumPeriod };

		var subscription = SubscribeCandles(CandleType);

		subscription
			.Bind(deMarker, momentum, (ICandleMessage candle, decimal demValue, decimal momValue) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				if (!_initialized)
				{
					_prevDem = demValue;
					_prevMom = momValue;
					_initialized = true;
					return;
				}

				var demUp = demValue > _prevDem;
				var demDown = demValue < _prevDem;
				var momUp = momValue > _prevMom;
				var momDown = momValue < _prevMom;

				// Long when DeMarker and Momentum both turn up
				if (demUp && momUp && Position <= 0)
				{
					BuyMarket();
				}
				// Short when DeMarker and Momentum both turn down
				else if (demDown && momDown && Position >= 0)
				{
					SellMarket();
				}

				_prevDem = demValue;
				_prevMom = momValue;
			})
			.Start();

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