Auf GitHub ansehen

EA OBJPROP Diagramm-ID-Strategie

Überblick

Die EA OBJPROP-Diagramm-ID-Strategie stellt das diagrammorientierte Verhalten des ursprünglichen MetaTrader 5-Beispiels wieder her, indem sie Donchian-Kanalumschläge in drei synchronisierten Zeitrahmen anzeigt. Das primäre Diagramm zeigt den Handelszeitrahmen, während zwei Hilfsfelder den H4- und Tageskontext visualisieren. Dieses Setup spiegelt den ursprünglichen Expert Advisor wider, der mehrere Diagramme und Indikatoren in einem einzigen Arbeitsbereich zur visuellen Analyse stapelte.

Hauptmerkmale

  • Multi-Timeframe-Visualisierung – abonniert automatisch Primär-, H4- und Tageskerzen für das ausgewählte Wertpapier.
  • Einheitliche Donchian-Kanallänge – wendet auf jeden Zeitrahmen die gleiche Kanalperiode an, um die Umschläge vergleichbar zu halten.
  • High-Level-Chart-Integration – basiert auf StockSharp Diagrammbereichen, um Preisreihen, Donchian-Kanäle und ausgeführte Trades darzustellen, wobei das MQL-Layout ohne Objektmanipulation auf niedriger Ebene reproduziert wird.
  • Erweiterbare Grundlage – speichert die neuesten Kanalgrenzen für jeden Zeitrahmen, sodass die Strategie in Zukunft problemlos um Breakout- oder Bestätigungslogik erweitert werden kann.

Parameter

Parameter Beschreibung Kategorie Standard
ChannelLength Länge des Donchian-Kanals, der über alle abonnierten Zeiträume hinweg verwendet wird. Indikatoren 22
PrimaryCandleType Hauptzeitrahmen, der für den Handel und als oberes Diagrammfeld verwendet wird. Allgemein 30-Minuten-Kerzen
H4CandleType Zusätzlicher H4-Zeitrahmen, der in einem sekundären Bereich angezeigt wird. Allgemein 4-Stunden-Kerzen
DailyCandleType Zusätzlicher täglicher Zeitrahmen, der in einem tertiären Bereich angezeigt wird. Allgemein 1-Tages-Kerzen

Alle Parameter sind über die Parameter-Benutzeroberfläche von StockSharp verfügbar, unterstützen die Optimierung und können ohne Änderung des Codes feinabgestimmt werden.

Strategielogik

  1. Initialisiert drei Donchian-Kanalindikatoren mit demselben Längenparameter.
  2. Abonniert die ausgewählte Primär-, H4- und Tageskerzenserie für das aktuelle Wertpapier.
  3. Bindet jedes Abonnement mithilfe des übergeordneten API an seinen jeweiligen Kanalindikator und stellt so sicher, dass die Indikatorwerte inkrementell berechnet werden.
  4. Erstellt einen Hauptdiagrammbereich und bis zu zwei Hilfsbereiche, in denen Kerzen, Kanäle und die Trades der Strategie gezeichnet werden.
  5. Speichert die aktuellsten oberen und unteren Kanalgrenzen für jeden Zeitrahmen, sodass später benutzerdefinierte Entscheidungsregeln hinzugefügt werden können.

Die aktuelle Implementierung dient nur der Visualisierung und sendet keine Bestellungen. Dies spiegelt den ursprünglichen MetaTrader-Code wider, der sich auf die Erstellung eines Dashboards mit Diagrammen ohne automatisierte Handelslogik konzentrierte.

Nutzungshinweise

  • Stellen Sie sicher, dass das ausgewählte Wertpapier über historische Daten für jeden von der Strategie verwendeten Zeitrahmen verfügt, um alle Diagrammbereiche zu füllen.
  • Sie können jeden der Zeitrahmenparameter in andere TimeFrame-Datentypen (z. B. 15 Minuten oder wöchentliche Kerzen) ändern, wenn andere Kontextbereiche erforderlich sind.
  • Zusätzliche Handelslogik kann in den Verarbeitungsmethoden (ProcessPrimary, ProcessH4, ProcessDaily) geschichtet werden, indem auf die gespeicherten Kanalebenen reagiert wird.

Konvertierungshinweise

  • Das MetaTrader-Beispiel erstellte untergeordnete Diagramme über OBJ_CHART-Objekte; Die StockSharp-Version ersetzt dies durch Diagrammbereiche, die von der übergeordneten API-Version erstellt wurden, die besser in die Plattform integriert ist.
  • Die Indikatorverwaltung erfolgt über BindEx-Aufrufe anstelle der manuellen Handle-Erstellung, um sicherzustellen, dass die Werte mit eingehenden Kerzen synchronisiert werden.
  • Routinen zum Löschen von Objekten sind nicht erforderlich, da StockSharp Abonnements und Diagrammbindungen automatisch verwirft, wenn die Strategie stoppt.
namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// EA Objprop Chart Id strategy: Standard Deviation breakout.
/// Buys when StdDev crosses above threshold with bullish candle, sells on bearish cross.
/// </summary>
public class EaObjpropChartIdStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _period;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private decimal _prevStdDev;
	private decimal _prevRange;
	private int _candlesSinceTrade;
	private bool _hasPrev;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int Period { get => _period.Value; set => _period.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public EaObjpropChartIdStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_period = Param(nameof(Period), 50)
			.SetGreaterThanZero()
			.SetDisplay("Period", "EMA period", "Indicators");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 4)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevStdDev = 0;
		_prevRange = 0;
		_candlesSinceTrade = SignalCooldownCandles;
		_hasPrev = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevStdDev = 0;
		_prevRange = 0;
		_candlesSinceTrade = SignalCooldownCandles;
		_hasPrev = false;
		var stdDev = new ExponentialMovingAverage { Length = Period };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(stdDev, ProcessCandle).Start();
	}

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

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		var range = candle.HighPrice - candle.LowPrice;
		if (range <= 0)
			return;

		if (_hasPrev && stdDevValue > 0 && _prevRange > 0)
		{
			var expanding = range > _prevRange * 1.2m;
			var bullish = candle.ClosePrice > candle.OpenPrice;
			var bearish = candle.ClosePrice < candle.OpenPrice;

			if (expanding && bullish && candle.ClosePrice > stdDevValue && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
			else if (expanding && bearish && candle.ClosePrice < stdDevValue && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
		}

		_prevStdDev = stdDevValue;
		_prevRange = range;
		_hasPrev = true;
	}
}