Auto RXD v1.67 ist eine regelbasierte Strategie, die den gleichnamigen Expert Advisor MetaTrader emuliert. Der Ansatz verwendet drei lineare Perzeptrone: einen Supervisor, der entscheidet, ob nach bullischen oder bärischen Signalen gesucht wird, sowie ein eigenes Perzeptron für jede Richtung. Jedes Perzeptron arbeitet mit linear gewichteten gleitenden Durchschnitten (LWMAs), die aus Kerzenschluss und Robbie Ruans „gewichteten Preis“-Eingaben (Hoch + Tief + 2 × Schluss) berechnet werden. Der Port StockSharp wird nur bei abgeschlossenen Kerzen ausgeführt und verwendet den High-Level-Datenfluss BindEx, um die Indikatorberechnungen mit der Handelsschleife synchronisiert zu halten.
Marktdaten und Indikatoren
Kerzen – Der Standardzeitraum beträgt 30-Minuten-Kerzen. Der Zeitrahmen kann über den Parameter CandleType geändert werden.
Average True Range (ATR) – Bietet sowohl adaptive Take-Profit- als auch Stop-Loss-Distanzen, wenn UseAtrTargets aktiviert ist. Der Zeitraum von ATR wird von AtrPeriod gesteuert.
Relative Strength Index (RSI) – Optionaler Filter, der Long-Trades über der neutralen 50-Marke und Short-Trades unter 50 erzwingt, wenn UseRsiFilter wahr ist.
Commodity Channel Index (CCI) – Optionaler Trendfilter, der Werte über +100 für Long-Positionen und unter -100 für Short-Positionen erfordert, wenn UseCciFilter aktiv ist.
Moving Average Convergence Divergence (MACD) – Optionale Impulsbestätigung. Lange Einträge erfordern die Linie MACD über der Signallinie, während kurze Einträge die Linie MACD unter der Signallinie benötigen, wenn UseMacdFilter wahr ist.
Durchschnittlicher Richtungsindex (ADX) – Optionaler Stärkefilter, der prüft, ob ADX über dem konfigurierten Schwellenwert liegt und ob +DI gegenüber -DI mit der gewünschten Richtung übereinstimmt, wenn UseAdxFilter aktiviert ist.
Handelslogik
Perceptron-Datenvorbereitung – Für jede Kerze aktualisiert die Strategie die Puffer mit den neuesten Schluss- und gewichteten Preisen. Die Puffer füttern LWMA-Snapshots und erzeugen vier verzögerte Features, getrennt durch die konfigurierten Step-Werte für kurze, lange und Supervisor-Perzeptrone.
Supervisor-Entscheidung – Das Supervisor-Perzeptron bewertet die verzögerten Deltas anhand der Gewichtsparameter SupervisorX1…X4 und SupervisorThreshold. Eine positive Punktzahl schaltet das lange Perzeptron frei; Ein negativer Wert schaltet das kurze Perzeptron frei. Wenn der Supervisor-Score Null ist oder nicht verfügbar ist (nicht genügend Daten), wird die Kerze übersprungen.
Richtungsspezialisten – Das passende Perzeptron (lang oder kurz) validiert seine eigene Punktzahl unter Verwendung desselben LWMA-Funktionssatzes und richtungsspezifischer Gewichtungen (LongX* oder ShortX*). Ein positiver Wert löst die nächste Validierungsstufe aus.
Indikatorfilter – Wenn UseIndicatorFilters falsch ist, handelt die Strategie ausschließlich auf dem Perzeptronsignal. Wenn „true“, muss jeder aktivierte Filter (RSI, CCI, MACD, ADX) mit der vorgeschlagenen Richtung übereinstimmen. Fehlende Indikatordaten oder fehlerhafte Bedingungen löschen das Signal.
Auftragsausführung – Die Strategie stellt sicher, dass es keine aktiven Aufträge gibt, glättet jegliches gegenteiliges Risiko und geht mit Marktaufträgen der Größe OrderVolume ein. Die Einstiegspreise entsprechen standardmäßig dem besten Angebot, sofern verfügbar, andernfalls schließt die Kerze.
Risikomanagement
Schutzaufträge – Nach dem Ausfüllen eines Eintrags berechnet die Strategie sofort Take-Profit- und Stop-Loss-Abstände bis CalculateProtectiveDistances. Wenn UseAtrTargets wahr ist, werden die Entfernungen um ATR mit den konfigurierten Multiplikatoren (AtrTakeProfitFactor, AtrStopLossFactor) und mit den ursprünglichen MQL punktbasierten TP/SL-Größen skaliert. Wenn das ATR-Targeting deaktiviert ist, werden Festpunktentfernungen in Preisschritte umgewandelt.
Auftragsverwaltung – Der Helfer SetProtectiveOrders übersetzt Rohdistanzen in Preisschrittzahlen und registriert Stop-Loss- und Take-Profit-Aufträge im Verhältnis zum Einstiegspreis. Die Strategie vermeidet doppelte Aufträge, indem sie HasActiveOrders() überprüft, bevor neue Geschäfte übermittelt werden.
Schutz starten – StartProtection() wird einmal in OnStarted aufgerufen und aktiviert die integrierte Schutzbehandlung des Frameworks, wenn die Position ungleich Null wird.
Parameter
Die StockSharp-Implementierung stellt den vollständigen MQL-Parametersatz gruppiert zur Optimierung und Klarheit der Benutzeroberfläche bereit. Zu den wichtigsten Parametern gehören:
Handel
OrderVolume – Losgröße für neue Positionen.
CandleType – Kerzendatentyp, der für die Bindung verwendet wird.
Risiko
UseAtrTargets – Umschalten zwischen ATR-basierten und Festpunkt-Schutzabständen.
AtrPeriod, AtrTakeProfitFactor, AtrStopLossFactor – ATR Konfiguration für adaptive Ziele.
LongTakeProfitPoints, LongStopLossPoints, ShortTakeProfitPoints, ShortStopLossPoints – Punktbasierte TP/SL-Referenzen, die sowohl im ATR- als auch im festen Modus wiederverwendet werden.
Indikatorfilter
UseIndicatorFilters – Hauptschalter für alle Filter.
Alle numerischen Parameter spiegeln die MQL-Standardwerte wider und ermöglichen ein vergleichbares Verhalten zwischen dem ursprünglichen Expert Advisor und diesem StockSharp-Port, während die Konfiguration über das StrategyParam-System für Optimierungskampagnen verfügbar gemacht wird.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Auto RXD V1.67: RSI + CCI momentum with EMA trend filter.
/// </summary>
public class AutoRXDV167Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<int> _cciLength;
private readonly StrategyParam<int> _emaLength;
private readonly StrategyParam<int> _atrLength;
private decimal _prevRsi;
private decimal _entryPrice;
public AutoRXDV167Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_rsiLength = Param(nameof(RsiLength), 14)
.SetDisplay("RSI Length", "RSI period.", "Indicators");
_cciLength = Param(nameof(CciLength), 14)
.SetDisplay("CCI Length", "CCI period.", "Indicators");
_emaLength = Param(nameof(EmaLength), 50)
.SetDisplay("EMA Length", "EMA trend filter.", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "ATR period for stops.", "Indicators");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int RsiLength
{
get => _rsiLength.Value;
set => _rsiLength.Value = value;
}
public int CciLength
{
get => _cciLength.Value;
set => _cciLength.Value = value;
}
public int EmaLength
{
get => _emaLength.Value;
set => _emaLength.Value = value;
}
public int AtrLength
{
get => _atrLength.Value;
set => _atrLength.Value = value;
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevRsi = 0;
_entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevRsi = 0;
_entryPrice = 0;
var rsi = new RelativeStrengthIndex { Length = RsiLength };
var cci = new CommodityChannelIndex { Length = CciLength };
var ema = new ExponentialMovingAverage { Length = EmaLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(rsi, cci, ema, atr, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal rsiVal, decimal cciVal, decimal emaVal, decimal atrVal)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevRsi == 0 || atrVal <= 0)
{
_prevRsi = rsiVal;
return;
}
var close = candle.ClosePrice;
if (Position > 0)
{
if (close <= _entryPrice - atrVal * 2m || close >= _entryPrice + atrVal * 3m || (rsiVal > 70 && cciVal > 100))
{
SellMarket();
_entryPrice = 0;
}
}
else if (Position < 0)
{
if (close >= _entryPrice + atrVal * 2m || close <= _entryPrice - atrVal * 3m || (rsiVal < 30 && cciVal < -100))
{
BuyMarket();
_entryPrice = 0;
}
}
if (Position == 0)
{
if (rsiVal > 50 && cciVal > 0 && close > emaVal && _prevRsi <= 50)
{
_entryPrice = close;
BuyMarket();
}
else if (rsiVal < 50 && cciVal < 0 && close < emaVal && _prevRsi >= 50)
{
_entryPrice = close;
SellMarket();
}
}
_prevRsi = rsiVal;
}
}
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 RelativeStrengthIndex, CommodityChannelIndex, ExponentialMovingAverage, AverageTrueRange
class auto_rxdv167_strategy(Strategy):
def __init__(self):
super(auto_rxdv167_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe.", "General")
self._rsi_length = self.Param("RsiLength", 14) \
.SetDisplay("RSI Length", "RSI period.", "Indicators")
self._cci_length = self.Param("CciLength", 14) \
.SetDisplay("CCI Length", "CCI period.", "Indicators")
self._ema_length = self.Param("EmaLength", 50) \
.SetDisplay("EMA Length", "EMA trend filter.", "Indicators")
self._atr_length = self.Param("AtrLength", 14) \
.SetDisplay("ATR Length", "ATR period for stops.", "Indicators")
self._prev_rsi = 0.0
self._entry_price = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@property
def RsiLength(self):
return self._rsi_length.Value
@property
def CciLength(self):
return self._cci_length.Value
@property
def EmaLength(self):
return self._ema_length.Value
@property
def AtrLength(self):
return self._atr_length.Value
def OnStarted2(self, time):
super(auto_rxdv167_strategy, self).OnStarted2(time)
self._prev_rsi = 0.0
self._entry_price = 0.0
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self.RsiLength
self._cci = CommodityChannelIndex()
self._cci.Length = self.CciLength
self._ema = ExponentialMovingAverage()
self._ema.Length = self.EmaLength
self._atr = AverageTrueRange()
self._atr.Length = self.AtrLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._rsi, self._cci, self._ema, self._atr, self.ProcessCandle).Start()
def ProcessCandle(self, candle, rsi_val, cci_val, ema_val, atr_val):
if candle.State != CandleStates.Finished:
return
rv = float(rsi_val)
cv = float(cci_val)
ev = float(ema_val)
av = float(atr_val)
if self._prev_rsi == 0 or av <= 0:
self._prev_rsi = rv
return
close = float(candle.ClosePrice)
if self.Position > 0:
if close <= self._entry_price - av * 2.0 or close >= self._entry_price + av * 3.0 or (rv > 70 and cv > 100):
self.SellMarket()
self._entry_price = 0.0
elif self.Position < 0:
if close >= self._entry_price + av * 2.0 or close <= self._entry_price - av * 3.0 or (rv < 30 and cv < -100):
self.BuyMarket()
self._entry_price = 0.0
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_rsi = rv
return
if self.Position == 0:
if rv > 50 and cv > 0 and close > ev and self._prev_rsi <= 50:
self._entry_price = close
self.BuyMarket()
elif rv < 50 and cv < 0 and close < ev and self._prev_rsi >= 50:
self._entry_price = close
self.SellMarket()
self._prev_rsi = rv
def OnReseted(self):
super(auto_rxdv167_strategy, self).OnReseted()
self._prev_rsi = 0.0
self._entry_price = 0.0
def CreateClone(self):
return auto_rxdv167_strategy()