Auf GitHub ansehen

ColorXPWMA Digit Multi-Zeitrahmen Strategie

Übersicht

Diese Strategie konvertiert den MetaTrader 5 Expert Advisor Exp_ColorXPWMA_Digit_NN3_MMRec in die StockSharp High-Level-API. Der ursprüngliche Roboter betreibt drei unabhängige Module, die auf verschiedenen Zeitrahmen handeln, indem sie die digitale Färbung des ColorXPWMA gleitenden Durchschnitts analysieren. Der StockSharp-Port behält das gleiche Verhalten bei: Jedes Modul beobachtet seine eigene Kerzenserie, schließt Positionen wenn der Indikator die Farbe wechselt und öffnet optional einen neuen Trade in der erkannten Richtung.

Die Standardkonfiguration folgt der MT5-Vorlage:

Modul Zeitrahmen Stop Loss (Punkte) Take Profit (Punkte)
A 8 Stunden 3000 10000
B 4 Stunden 2000 6000
C 1 Stunde 1000 3000

Jedes Modul kann für Long- und Short-Einstiege oder -Ausstiege durch dedizierte boolesche Parameter aktiviert oder deaktiviert werden. Die Implementierung hält individuelles Positions-Tracking pro Modul aufrecht, damit gleichzeitige Long- und Short-Trades coexistieren können, ohne die Volumen-Abrechnung der anderen Zeitrahmen zu stören.

ColorXPWMA Digit Indikator

Der ColorXPWMA Digit Indikator emuliert den benutzerdefinierten MT5-Indikator. Für jede abgeschlossene Kerze führt der Algorithmus:

  1. Baut einen potenzgewichteten Durchschnitt des ausgewählten angewendeten Preises (Period und Power).
  2. Glättet den Wert mit dem gewählten gleitenden Durchschnitt (SmoothMethods und SmoothLength).
  3. Rundet das Ergebnis auf die konfigurierte Anzahl von Dezimalstellen (Digit).
  4. Weist einen Farbcode zu: 2 wenn der geglättete Wert zunimmt, 0 wenn er abnimmt, andernfalls wird die vorherige Farbe wiederverwendet.

SignalBar steuert, welcher historische Balken inspiziert wird. Wert 0 verwendet die zuletzt geschlossene Kerze, Wert 1 die vorherige Kerze, etc. Eine Kaufgelegenheit erscheint, wenn der beobachtete Balken auf Farbe 2 wechselt, nachdem er auf dem vorherigen Balken anders war. Eine Verkaufsgelegenheit wird generiert, wenn die Farbe 0 wird, nachdem sie auf dem vorherigen Balken anders war.

Glättungsmethoden werden wie folgt auf StockSharp-Indikatoren abgebildet:

  • Sma, Ema, Smma, Lwma, Jjma → entsprechende StockSharp gleitende Durchschnitte.
  • T3 → interne Tillson T3 Implementierung.
  • Vidya → interne VIDYA Implementierung, angetrieben durch den Chande Momentum Oszillator.
  • Ama → Kaufman Adaptive Moving Average.
  • Nicht unterstützte Optionen (JurX, Parabolic) fallen auf den einfachen gleitenden Durchschnitt zurück, was dem Verhalten der ursprünglichen Vorlage entspricht, wenn exotische Glätter nicht verfügbar sind.

Trade-Management und Geldmanagement

Für jedes Modul hält die Strategie zwei unabhängige virtuelle Positionen (Long und Short). Wenn ein Modul ein Schließsignal erhält, sendet die Strategie eine Marktorder gleich dem verbleibenden Volumen dieser virtuellen Position. Eröffnungsorders werden ignoriert, während eine entgegengesetzte Position noch offen ist.

Das Positions-Sizing kopiert den MT5 Money-Management-Helfer:

  • NormalMM definiert das Basisvolumen.
  • SmallMM ersetzt das Basisvolumen, wenn jüngste Trades mindestens LossTrigger Verluste innerhalb der letzten TotalTrigger Trades für diese Richtung aufgezeichnet haben.

Die Logik wird separat für Long- und Short-Sequenzen ausgewertet. Handelsergebnisse werden vom durchschnittlichen gefüllten Preis berechnet, wenn ein Modul seine virtuelle Position vollständig schließt.

Das Risikomanagement spiegelt die MT5-Stops in Preispunkten wider:

  • Wenn eine Long-Position offen ist und Kerzen-Tiefs entry - StopLoss * PriceStep kreuzen, wird die Long-Position sofort geschlossen.
  • Wenn Kerzen-Hochs entry + TakeProfit * PriceStep berühren, werden Gewinne genommen.
  • Die Regeln werden für Shorts gespiegelt (entry + StopLoss für Schutz, entry - TakeProfit für Ziele).

Parameter

Alle Parameter werden durch StrategyParam<T> Objekte exponiert und können vom StockSharp-Designer aus optimiert werden. Sie sind pro Modul (A, B, C) gruppiert. Die folgende Tabelle listet die Einstellungen für ein beliebiges Modul X auf:

Parameter Beschreibung
X_CandleType Zu abonnierende Kerzenserie (Standard-Zeitrahmen oben gezeigt).
X_Period, X_Power Potenzgewichtetes Fenster zum Aufbau des Basis-XPWMA-Werts.
X_SmoothMethod, X_SmoothLength, X_SmoothPhase Auf den gewichteten Preis angewendeter Glätter. SmoothPhase wird für Kompatibilität mit MT5 JJMA-Benutzern beibehalten.
X_AppliedPrice Preisquelle (close, open, high, low, median, typical, weighted, simple, quarter, TrendFollow, DeMark).
X_Digit Rundungspräzision auf den geglätteten Wert angewendet.
X_SignalBar Historischer Balken für Signalauswertung.
X_BuyMagic, X_SellMagic Für Nachverfolgbarkeit beibehalten (in Order-Kommentaren verwendet).
X_BuyTotalTrigger, X_BuyLossTrigger Long-seitige Geldmanagement-Schwellenwerte.
X_SellTotalTrigger, X_SellLossTrigger Short-seitige Geldmanagement-Schwellenwerte.
X_SmallMM, X_NormalMM Vom Geldmanagement-Regelwerk verwendete Volumen.
X_MarginMode, X_Deviation Für Feature-Parität beigehaltene reservierte Felder; ändern StockSharp-Orders nicht.
X_StopLoss, X_TakeProfit In Preisschritten auf die virtuelle Modulposition angewendete Abstände.
X_BuyOpen, X_SellOpen, X_SellClose, X_BuyClose Berechtigungsschalter für Modulaktionen.

Hinweise

  • Jede Marktorder ist mit A|BuyOpen, B|SellClose, etc. annotiert, damit Fills auf ihr Modul zurückverfolgt werden können.
  • Die Strategie operiert ausschließlich auf fertigen Kerzen und reproduziert daher automatisch den von der High-Level-API bereitgestellten MT5 IsNewBar-Schutz.
  • Wenn mehrere Module auf demselben Balken auslösen, werden ihre Volumen sequenziell mit den virtuellen Positionspuffern pro Modul verarbeitet.
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>
/// ColorXPWMA Digit Multi-Timeframe strategy. Uses WMA crossover.
/// </summary>
public class ColorXpWmaDigitMultiTimeframeStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;

	private decimal? _prevFast;
	private decimal? _prevSlow;

	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 ColorXpWmaDigitMultiTimeframeStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe", "General");

		_fastPeriod = Param(nameof(FastPeriod), 8)
			.SetGreaterThanZero()
			.SetDisplay("Fast WMA", "Fast WMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 25)
			.SetGreaterThanZero()
			.SetDisplay("Slow WMA", "Slow WMA period", "Indicators");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = null;
		_prevSlow = null;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_prevFast = null;
		_prevSlow = null;

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, slow, ProcessCandle)
			.Start();

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			return;
		}

		if (_prevFast == null || _prevSlow == null)
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			return;
		}

		var prevAbove = _prevFast.Value > _prevSlow.Value;
		var currAbove = fastVal > slowVal;

		_prevFast = fastVal;
		_prevSlow = slowVal;

		if (!prevAbove && currAbove && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		else if (prevAbove && !currAbove && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
	}
}