Auf GitHub ansehen

Absolut verzögerungsfreie LWMA-Strategie

Überblick

Die Strategie repliziert den MetaTrader-Expertenberater Exp_AbsolutelyNoLagLwma, indem ein doppelter gewichteter gleitender Durchschnitt (LWMA) auf Kerzendaten angewendet wird. Die Indikatorausgabe ist farbcodiert: Grün (2) für eine aufwärtsgerichtete Steigung, Grau (1) für flach und Magenta (0) für eine abwärtsgerichtete Steigung. Handelsentscheidungen basieren auf Übergängen zwischen diesen Farbzuständen. Die StockSharp-Implementierung verwendet die High-Level-API, abonniert Zeitrahmen-Kerzen und sendet Marktaufträge gemäß der erkannten Trendrichtung.

Handelslogik

Indikator-Pipeline

  1. Die gewünschte Preisserie auswählen, die durch den Parameter Preistyp definiert wird.
  2. Einen gewichteten gleitenden Durchschnitt (LWMA) mit der konfigurierten LWMA-Länge anwenden.
  3. Das Ergebnis mit einem zweiten LWMA gleicher Länge glätten.
  4. Den geglätteten LWMA-Wert mit dem vorherigen Wert vergleichen, um die Steigungsrichtung zu klassifizieren:
    • 2 (Aufwärtstrend) – aktueller Wert ist größer als der vorherige Wert.
    • 1 (neutral) – aktueller Wert entspricht dem vorherigen Wert.
    • 0 (Abwärtstrend) – aktueller Wert ist kleiner als der vorherige Wert.

Signalauswertung

  • Nur abgeschlossene Kerzen werden verarbeitet. Der Parameter Signalbalken verschiebt die Signalauswertung auf historische Kerzen (1 = vorherige abgeschlossene Kerze, 2 = die Kerze davor, etc.). Die Strategie merkt sich auch die Farbe des Balkens, der der ausgewählten Signalkerze vorausgeht, um doppelte Einstiege zu vermeiden.
  • Bullischer Übergang: Die ausgewählte Signalkerze ist Farbe 2 und die vorherige Kerze ist nicht 2. Dies öffnet Longs (wenn aktiviert) und schließt bestehende Shorts.
  • Bärischer Übergang: Die ausgewählte Signalkerze ist Farbe 0 und die vorherige Kerze ist nicht 0. Dies öffnet Shorts (wenn aktiviert) und schließt bestehende Longs.

Positionsverwaltung

  • Aufträge werden mit Marktaufträgen ausgeführt. Das angeforderte Volumen ist Volume + |Position|, wenn die Richtung umgekehrt wird, sodass die entgegengesetzte Position automatisch geschlossen wird.
  • Ausstiegssignale können unabhängig von Einstiegen umgeschaltet werden, was nur-Signal- oder nur-Ausstiegs-Verhalten ermöglicht.
  • StartProtection() wird aktiviert, um die gemeinsame StockSharp-Schutzlogik einzuschalten, sobald die Strategie startet.

Parameter

  • LWMA-Länge – Länge der zwei für die Glättung verwendeten LWMAs.
  • Preistyp – Preisquelle, die den LWMA speist (Schluss, Eröffnung, Hoch, Tief, Median, typisch, gewichtet, vereinfacht, Viertel, Trendfolge-Variationen oder Demark-Preis).
  • Signalbalken – Anzahl der zurückliegenden abgeschlossenen Kerzen für die Signalauswertung.
  • Long-Einstiege aktivieren – erlaubt das Öffnen von Long-Positionen bei bullischen Übergängen.
  • Short-Einstiege aktivieren – erlaubt das Öffnen von Short-Positionen bei bärischen Übergängen.
  • Long-Ausstiege aktivieren – schließt Long-Positionen wenn der Indikator bärisch wird.
  • Short-Ausstiege aktivieren – schließt Short-Positionen wenn der Indikator bullisch wird.
  • Kerzentyp – Zeitrahmen des Kerzenabonnements, das vom Indikator verwendet wird.
  • Volumen (eingebautes Strategy-Property) – Handelsgröße für neue Einstiege.

Hinweise

  • Der Standard-Zeitrahmen beträgt 4 Stunden, was der ursprünglichen Expertenkonfiguration entspricht, kann aber über den Parameter Kerzentyp angepasst werden.
  • Es werden keine Take-Profit- oder Stop-Loss-Aufträge automatisch platziert; Benutzer können die Strategie bei Bedarf mit StockSharp-Risikomanagementkomponenten kombinieren.
  • Der Python-Port wird absichtlich ausgelassen, wie angefordert.
namespace StockSharp.Samples.Strategies;

using System;

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

/// <summary>
/// Absolutely No Lag LWMA strategy (simplified).
/// Uses two EMAs of different periods to detect trend direction changes.
/// </summary>
public class AbsolutelyNoLagLwmaStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;

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

	public int FastPeriod
	{
		get => _fastPeriod.Value;
		set => _fastPeriod.Value = value;
	}

	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.Value = value;
	}

	public AbsolutelyNoLagLwmaStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Source candles", "General");

		_fastPeriod = Param(nameof(FastPeriod), 9)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast EMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 21)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow EMA period", "Indicators");
	}

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

		var fastEma = new ExponentialMovingAverage { Length = FastPeriod };
		var slowEma = new ExponentialMovingAverage { Length = SlowPeriod };

		decimal prevFast = 0, prevSlow = 0;
		bool hasPrev = false;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fastEma, slowEma, (ICandleMessage candle, decimal fastValue, decimal slowValue) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!hasPrev)
				{
					prevFast = fastValue;
					prevSlow = slowValue;
					hasPrev = true;
					return;
				}

				if (!IsFormedAndOnlineAndAllowTrading())
				{
					prevFast = fastValue;
					prevSlow = slowValue;
					return;
				}

				if (prevFast <= prevSlow && fastValue > slowValue && Position <= 0)
				{
					BuyMarket();
				}
				else if (prevFast >= prevSlow && fastValue < slowValue && Position >= 0)
				{
					SellMarket();
				}

				prevFast = fastValue;
				prevSlow = slowValue;
			})
			.Start();

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