Die ADX Simple Trend Strategy ist eine direkte Portierung des klassischen MetaTrader Expert Advisors „ADX Simple“. Es folgt der Richtung des durchschnittlichen Richtungsindex (ADX), indem es die positiven und negativen Richtungsbewegungsindikatoren (DI+ und DI-) vergleicht und erfordert, dass die Hauptlinie ADX ansteigt, bevor ein Handel eröffnet wird. Die StockSharp-Version behält den minimalistischen Charakter des ursprünglichen Systems bei und passt es gleichzeitig an übergeordnete API-Muster und Risikokontrollen an.
Indikatorstapel
Durchschnittlicher Richtungsindex (ADX) mit konfigurierbarem Zeitraum (Standard 25).
Stellt die Hauptzeile ADX zur Bestätigung der Trendstärke bereit.
Liefert DI+- und DI--Werte, die bullische oder bärische Dominanz definieren.
Zeitrahmen kann über CandleType ausgewählt werden (standardmäßig 15-Minuten-Kerzen).
Signalerzeugung
Langer Eintrag
Warten Sie auf eine fertige Kerze und einen endgültigen ADX-Wert.
Stellen Sie sicher, dass DI+ über DI- auf derselben Leiste liegt.
Erfordern, dass die Hauptlinie ADX unbedingt größer als ihr vorheriger Wert ist (der Trend verstärkt sich).
Wenn keine offene Position vorhanden ist, senden Sie eine Marktkauforder mit dem Strategievolumen.
Kurzer Eintrag
Warten Sie auf eine fertige Kerze und einen abgeschlossenen Messwert von ADX.
Bestätigen Sie, dass DI- über DI+ liegt.
Erfordern, dass die Hauptzeile ADX größer als ihr vorheriger Wert ist.
Wenn der Kurs flach ist, senden Sie einen Marktverkaufsauftrag mit dem Strategievolumen.
Exit-Logik
Close Long: Wenn DI- über DI+ kreuzt (Trenddynamik wird bärisch).
Close Short: Wenn DI+ DI- überschreitet (Trendmomentum wird bullisch).
Die ADX-Steigungsprüfung ist für Exits nicht erforderlich und spiegelt die ursprüngliche EA wider, bei der Positionen unmittelbar nach einem DI-Crossover geschlossen wurden.
Positionsmanagement
Die Strategie ist immer entweder Flat, Long oder Short; es hält niemals gleichzeitige Positionen in beide Richtungen.
Die Größe von Marktaufträgen wird mithilfe der integrierten Eigenschaft Strategy.Volume (Standard 1) bestimmt. Passen Sie diese Eigenschaft an, wenn Sie die Strategieinstanz so konfigurieren, dass sie zu Ihrer Instrumentengröße passt.
Es gibt keine automatischen Stop-Loss- oder Take-Profit-Orders. Das Risiko sollte extern oder durch Änderung der Strategie kontrolliert werden.
Parameter
Parameter
Typ
Standard
Beschreibung
AdxPeriod
int
25
Lookback-Länge für ADX-, DI+- und DI--Berechnungen.
CandleType
DataType
15-minütiger Zeitrahmen
Kerzenabonnement zur Steuerung von Indikatorberechnungen.
Unterschiede zur Originalversion MQL
Geldverwaltung: Die ursprünglichen EA-Lots wurden basierend auf dem Kontostand in der Größe geändert; Die StockSharp-Strategie verwendet Strategy.Volume und überlässt die Kapitalverwaltung der Hosting-Umgebung.
Auftragsverfolgung: Anstatt MetaTrader Auftragspools zu durchlaufen, verlässt sich StockSharp auf den integrierten Position-Wert.
Datenverarbeitung: Die Strategie ignoriert unfertige Kerzen und handelt nur mit endgültigen Daten.
Protokollierungs- und Visualisierungs-Hooks sind über die Hilfsprogramme CreateChartArea, DrawCandles und DrawIndicator verfügbar, um das Debuggen zu erleichtern.
Nutzungsrichtlinien
Hängen Sie die Strategie an ein Instrument mit ausreichender Trendbewegung an (z. B. FX-Majors oder Indizes).
Stellen Sie den gewünschten Kerzentyp und die ADX-Länge über Parameter ein, bevor Sie mit der Strategie beginnen.
Aktivieren Sie optional das Risikomanagement auf Portfolioebene (Stop-Outs, Drawdown-Limits) über die Hosting-Anwendung.
Überwachen Sie DI-Überkreuzungen und die ADX-Steigung in der Diagrammvisualisierung, um das Verhalten zu überprüfen.
Erweiterung der Strategie
Fügen Sie Volatilitätsfilter (ATR, Standardabweichung) hinzu, um Bedingungen mit geringer Volatilität zu vermeiden.
Führen Sie eine Stop-Loss-/Take-Profit-Automatisierung ein, indem Sie StartProtection oder eine benutzerdefinierte Orderlogik in ProcessCandle aufrufen.
Kombinieren Sie es mit Filtern mit höherem Zeitrahmen, indem Sie zusätzliche Kerzen-Streams abonnieren.
Ziel dieser Dokumentation ist es, einen umfassenden Überblick über die Simple Trend Strategy von ADX zu geben, damit Sie sie sicher innerhalb des StockSharp-Frameworks bereitstellen und erweitern können.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// ADX Simple: Trend following with EMA crossover and ATR momentum filter.
/// </summary>
public class AdxSimpleStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastEmaLength;
private readonly StrategyParam<int> _slowEmaLength;
private readonly StrategyParam<int> _atrLength;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
public AdxSimpleStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(2).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_fastEmaLength = Param(nameof(FastEmaLength), 10)
.SetDisplay("Fast EMA", "Fast EMA period.", "Indicators");
_slowEmaLength = Param(nameof(SlowEmaLength), 30)
.SetDisplay("Slow EMA", "Slow EMA period.", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "ATR period.", "Indicators");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastEmaLength
{
get => _fastEmaLength.Value;
set => _fastEmaLength.Value = value;
}
public int SlowEmaLength
{
get => _slowEmaLength.Value;
set => _slowEmaLength.Value = value;
}
public int AtrLength
{
get => _atrLength.Value;
set => _atrLength.Value = value;
}
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fastEma = new ExponentialMovingAverage { Length = FastEmaLength };
var slowEma = new ExponentialMovingAverage { Length = SlowEmaLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastEma, slowEma, atr, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastEma);
DrawIndicator(area, slowEma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal slowVal, decimal atrVal)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevFast == 0 || _prevSlow == 0 || atrVal <= 0)
{
_prevFast = fastVal;
_prevSlow = slowVal;
return;
}
var close = candle.ClosePrice;
if (Position > 0)
{
if (fastVal < slowVal && _prevFast >= _prevSlow)
{
SellMarket();
_entryPrice = 0;
}
else if (close <= _entryPrice - atrVal * 2m)
{
SellMarket();
_entryPrice = 0;
}
}
else if (Position < 0)
{
if (fastVal > slowVal && _prevFast <= _prevSlow)
{
BuyMarket();
_entryPrice = 0;
}
else if (close >= _entryPrice + atrVal * 2m)
{
BuyMarket();
_entryPrice = 0;
}
}
if (Position == 0)
{
if (fastVal > slowVal && _prevFast <= _prevSlow)
{
_entryPrice = close;
BuyMarket();
}
else if (fastVal < slowVal && _prevFast >= _prevSlow)
{
_entryPrice = close;
SellMarket();
}
}
_prevFast = fastVal;
_prevSlow = slowVal;
}
}
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.Strategies import Strategy
from StockSharp.Algo.Indicators import ExponentialMovingAverage, AverageTrueRange
class adx_simple_strategy(Strategy):
def __init__(self):
super(adx_simple_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(2))) \
.SetDisplay("Candle Type", "Timeframe.", "General")
self._fast_ema_length = self.Param("FastEmaLength", 10) \
.SetDisplay("Fast EMA", "Fast EMA period.", "Indicators")
self._slow_ema_length = self.Param("SlowEmaLength", 30) \
.SetDisplay("Slow EMA", "Slow EMA period.", "Indicators")
self._atr_length = self.Param("AtrLength", 14) \
.SetDisplay("ATR Length", "ATR period.", "Indicators")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastEmaLength(self):
return self._fast_ema_length.Value
@property
def SlowEmaLength(self):
return self._slow_ema_length.Value
@property
def AtrLength(self):
return self._atr_length.Value
def OnStarted2(self, time):
super(adx_simple_strategy, self).OnStarted2(time)
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._fast_ema = ExponentialMovingAverage()
self._fast_ema.Length = self.FastEmaLength
self._slow_ema = ExponentialMovingAverage()
self._slow_ema.Length = self.SlowEmaLength
self._atr = AverageTrueRange()
self._atr.Length = self.AtrLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._fast_ema, self._slow_ema, self._atr, self.ProcessCandle).Start()
def ProcessCandle(self, candle, fast_val, slow_val, atr_val):
if candle.State != CandleStates.Finished:
return
fv = float(fast_val)
sv = float(slow_val)
av = float(atr_val)
if self._prev_fast == 0 or self._prev_slow == 0 or av <= 0:
self._prev_fast = fv
self._prev_slow = sv
return
close = float(candle.ClosePrice)
if self.Position > 0:
if fv < sv and self._prev_fast >= self._prev_slow:
self.SellMarket()
self._entry_price = 0.0
elif close <= self._entry_price - av * 2.0:
self.SellMarket()
self._entry_price = 0.0
elif self.Position < 0:
if fv > sv and self._prev_fast <= self._prev_slow:
self.BuyMarket()
self._entry_price = 0.0
elif close >= self._entry_price + av * 2.0:
self.BuyMarket()
self._entry_price = 0.0
if self.Position == 0:
if fv > sv and self._prev_fast <= self._prev_slow:
self._entry_price = close
self.BuyMarket()
elif fv < sv and self._prev_fast >= self._prev_slow:
self._entry_price = close
self.SellMarket()
self._prev_fast = fv
self._prev_slow = sv
def OnReseted(self):
super(adx_simple_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
def CreateClone(self):
return adx_simple_strategy()