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
Initialisiert drei Donchian-Kanalindikatoren mit demselben Längenparameter.
Abonniert die ausgewählte Primär-, H4- und Tageskerzenserie für das aktuelle Wertpapier.
Bindet jedes Abonnement mithilfe des übergeordneten API an seinen jeweiligen Kanalindikator und stellt so sicher, dass die Indikatorwerte inkrementell berechnet werden.
Erstellt einen Hauptdiagrammbereich und bis zu zwei Hilfsbereiche, in denen Kerzen, Kanäle und die Trades der Strategie gezeichnet werden.
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;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class ea_objprop_chart_id_strategy(Strategy):
def __init__(self):
super(ea_objprop_chart_id_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._period = self.Param("Period", 50)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 4)
self._prev_std_dev = 0.0
self._prev_range = 0.0
self._candles_since_trade = 4
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def Period(self):
return self._period.Value
@Period.setter
def Period(self, value):
self._period.Value = value
@property
def SignalCooldownCandles(self):
return self._signal_cooldown_candles.Value
@SignalCooldownCandles.setter
def SignalCooldownCandles(self, value):
self._signal_cooldown_candles.Value = value
def OnReseted(self):
super(ea_objprop_chart_id_strategy, self).OnReseted()
self._prev_std_dev = 0.0
self._prev_range = 0.0
self._candles_since_trade = self.SignalCooldownCandles
self._has_prev = False
def OnStarted2(self, time):
super(ea_objprop_chart_id_strategy, self).OnStarted2(time)
self._prev_std_dev = 0.0
self._prev_range = 0.0
self._candles_since_trade = self.SignalCooldownCandles
self._has_prev = False
ema = ExponentialMovingAverage()
ema.Length = self.Period
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema, self._process_candle).Start()
def _process_candle(self, candle, std_dev_value):
if candle.State != CandleStates.Finished:
return
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
close = float(candle.ClosePrice)
open_price = float(candle.OpenPrice)
high = float(candle.HighPrice)
low = float(candle.LowPrice)
std_val = float(std_dev_value)
range_val = high - low
if range_val <= 0:
return
if self._has_prev and std_val > 0 and self._prev_range > 0:
expanding = range_val > self._prev_range * 1.2
bullish = close > open_price
bearish = close < open_price
if expanding and bullish and close > std_val and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
elif expanding and bearish and close < std_val and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
self._prev_std_dev = std_val
self._prev_range = range_val
self._has_prev = True
def CreateClone(self):
return ea_objprop_chart_id_strategy()