EMA WMA RSI ist eine Konvertierung des von cmillion erstellten MetaTrader 4-Expertenberaters „EMA WMA RSI“. Der ursprüngliche Roboter vergleicht einen exponentiellen gleitenden Durchschnitt (EMA) und einen linear gewichteten gleitenden Durchschnitt (WMA), der aus Kerzeneröffnungen berechnet wird, und filtert jeden Schnittpunkt mit einem Schwellenwert für den Relative Strength Index (RSI). Der StockSharp-Port behält die gleiche Indikatorlogik bei, arbeitet mit fertigen Kerzen und reproduziert die Geldverwaltungsoptionen: optionale Abflachung der Gegenposition, punktbasierte Stop-Loss-/Take-Profit-Levels und ein Trailing Stop, der festen Abständen, dem neuesten Fraktal oder aktuellen Kerzenextremen folgen kann.
Die Strategie ist für ein einzelnes Symbol und einen einzelnen Zeitrahmen konzipiert, der über den Parameter Candle Type ausgewählt wird. Bei der Umrechnung von Risikoabständen in absolute Preise werden MetaTrader „Punkte“ (der minimale Tick) angenommen. Daher sollten Instrumentenmetadaten wie Security.Step und Security.StepPrice ausgefüllt werden, um optimale Ergebnisse zu erzielen.
Strategielogik
Indikatoren
EMA – durch EMA Period definierter Zeitraum, angewendet auf Kerzenöffnungspreise.
WMA – Zeitraum definiert durch WMA Period, auch gespeist mit Kerzeneröffnungen.
RSI – RSI Period, berechnet auf demselben Open-Price-Stream.
Alle Indikatoren werden einmal pro fertiger Kerze aktualisiert. Der Port spiegelt die ursprüngliche Ausführung „Bar öffnen“ wider, indem er die EMA/WMA-Werte des vorherigen Balkens speichert und sie direkt nach dem Schließen mit dem aktuellen Balken vergleicht.
Einreisebestimmungen
Lange Einrichtung
Der aktuelle EMA-Wert liegt unter dem WMA, während der vorherige Balken EMA über dem WMA hatte (ein Abwärtskreuz).
Der Wert von RSI liegt über 50.
Wenn eine Short-Position vorhanden ist, wird diese optional geschlossen, wenn Close Counter Trades aktiviert ist; andernfalls wird das Signal ignoriert, bis die Strategie flach ist.
Wenn die Bedingungen erfüllt sind, wird eine Marktkauforder entweder mit dem festen Volumen oder mit der risikobasierten Größenbestimmung gesendet.
Short-Setup – symmetrische Logik: EMA kreuzt über WMA, der vorherige Balken zeigte EMA unter WMA, RSI liegt unter 50 und die Strategie flacht entweder einen Long ab oder überspringt den Trade.
Ausgangsregeln
Anfänglicher Schutz – Stop Loss (points) und Take Profit (points) werden anhand der Tick-Größe des Instruments in absolute Entfernungen übersetzt. Jeder Wert kann auf Null gesetzt werden, um ihn zu deaktivieren.
Trailing Stop
Wenn Trailing Stop (points) größer als Null ist, folgt der Stop dem Preis in einem festen Abstand, gemessen vom letzten Schlusskurs (nur Anziehen, niemals Nachgeben).
Wenn die Nachlaufdistanz Null ist, sucht der Algorithmus nach adaptiven Ebenen:
Trailing Source = CandleExtremes blickt auf frühere Kerzenhochs/-tiefs zurück. Ein Long-Stop bewegt sich zum ersten Tief, das mindestens fünf Punkte unter dem aktuellen Preis liegt; Ein kurzer Stopp verwendet Höchstwerte von fünf Punkten darüber.
Trailing Source = Fractals scannt zuvor bestätigte Bill Williams-Fraktale (zwei Kerzen auf jeder Seite). Derselbe Fünf-Punkte-Puffer gilt, um zu vermeiden, dass der Stop zu nahe am aktuellen Preis platziert wird.
Nachlaufende Anpassungen werden erst aktiviert, wenn der Preis über den ursprünglichen Einstiegspreis hinausgeht und das Verhalten von MetaTrader EA reproduziert.
Positionsausstieg – Wenn der Trailing Stop oder Take-Profit innerhalb der Spanne einer Kerze berührt wird, wird die Position mit einer Marktorder geschlossen und der interne Status zurückgesetzt.
Positionsgrößenbestimmung
Fixed Volume liefert die genaue Marktauftragsgröße (Lots/Kontrakte). Dies ist die Standardeinstellung und entspricht dem EA-Parameter Lot.
Wenn Sie Fixed Volume auf Null setzen, wird die risikobasierte Größenanpassung aktiviert. Die Strategie schätzt das monetäre Risiko pro Einheit anhand der verfügbaren Stop-Distanz (entweder dem konfigurierten Stop-Loss oder der effektiven Trailing-Distanz) und Security.StepPrice. Risk % bestimmt, wie viel Portfolio-Eigenkapital pro Trade ausgesetzt ist. Wenn sowohl das feste Volumen als auch der Risikoprozentsatz Null sind, wird das Signal ignoriert.
Parameter
Parameter
Beschreibung
Standard
EMA Period
Zeitraum des exponentiellen gleitenden Durchschnitts, der auf Kerzeneröffnungen angewendet wird.
28
WMA Period
Zeitraum des linear gewichteten gleitenden Durchschnitts bei Eröffnungen.
8
RSI Period
RSI Länge wird als Richtungsfilter verwendet.
14
Stop Loss (points)
Stop-Loss-Offset in MetaTrader Punkten. 0 deaktiviert den Schutzstopp.
0
Take Profit (points)
Take-Profit-Offset in Punkten. 0 deaktiviert das Ziel.
500
Trailing Stop (points)
Nachlaufdistanz in Punkten korrigiert. 0 wechselt zum adaptiven Trailing (Fraktale oder Kerzentiefs/-hochs).
70
Trailing Source
Adaptive Trailing-Methode: CandleExtremes für rohe Hochs/Tiefs, Fractals für Williams Fraktale.
CandleExtremes
Close Counter Trades
Schließen Sie eine entgegengesetzte Position, bevor Sie einen neuen Handel eröffnen.
false
Fixed Volume
Marktauftragsvolumen. Auf 0 setzen, um die risikobasierte Größenanpassung zu aktivieren.
0.1
Risk %
Prozentsatz des zugesagten Portfolio-Eigenkapitals, wenn Fixed Volume Null ist. Erfordert einen gültigen Stoppabstand.
10
Candle Type
Primärer Zeitrahmen für Indikatoren und Signalauswertung.
30-minute candles
Hinweise zur Implementierung
Preisstufenkonvertierungen basieren auf Security.Step (oder Security.PriceStep) und Security.StepPrice. Stellen Sie realistische Instrumentenmetadaten bereit, um Punkt-zu-Preis-Berechnungen korrekt zu halten.
Die Strategie verarbeitet nur fertige Kerzen und verwendet ihre offenen Preise für Indikatoraktualisierungen, entsprechend der „Neuer Balken“-Logik im MQL4-Code.
Nachfolgende Niveaus halten mindestens einen Puffer von fünf Punkten vom aktuellen Preis entfernt, genau wie die ursprüngliche Hilfsfunktion SlLastBar.
Wenn das Schließen von Gegenpositionen deaktiviert ist, sichert die Strategie nie ab – es wird immer nur eine einzige Nettoposition verwaltet.
In diesem Paket ist keine Python-Implementierung enthalten.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// EMA WMA RSI: Dual EMA crossover with RSI filter and ATR stops.
/// </summary>
public class EmaWmaRsiStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastEmaLength;
private readonly StrategyParam<int> _slowEmaLength;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<int> _atrLength;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
public EmaWmaRsiStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_fastEmaLength = Param(nameof(FastEmaLength), 8)
.SetDisplay("Fast EMA", "Fast EMA period.", "Indicators");
_slowEmaLength = Param(nameof(SlowEmaLength), 28)
.SetDisplay("Slow EMA", "Slow EMA period.", "Indicators");
_rsiLength = Param(nameof(RsiLength), 14)
.SetDisplay("RSI Length", "RSI 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 RsiLength { get => _rsiLength.Value; set => _rsiLength.Value = value; }
public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0; _prevSlow = 0; _entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = 0; _prevSlow = 0; _entryPrice = 0;
var fastEma = new ExponentialMovingAverage { Length = FastEmaLength };
var slowEma = new ExponentialMovingAverage { Length = SlowEmaLength };
var rsi = new RelativeStrengthIndex { Length = RsiLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fastEma, slowEma, rsi, 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 rsiVal, 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) || close <= _entryPrice - atrVal * 2m) { SellMarket(); _entryPrice = 0; }
}
else if (Position < 0)
{
if ((fastVal > slowVal && _prevFast <= _prevSlow) || close >= _entryPrice + atrVal * 2m) { BuyMarket(); _entryPrice = 0; }
}
if (Position == 0)
{
if (fastVal > slowVal && _prevFast <= _prevSlow && rsiVal > 50) { _entryPrice = close; BuyMarket(); }
else if (fastVal < slowVal && _prevFast >= _prevSlow && rsiVal < 50) { _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, RelativeStrengthIndex, AverageTrueRange
class ema_wma_rsi_strategy(Strategy):
def __init__(self):
super(ema_wma_rsi_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe.", "General")
self._fast_ema_length = self.Param("FastEmaLength", 8) \
.SetDisplay("Fast EMA", "Fast EMA period.", "Indicators")
self._slow_ema_length = self.Param("SlowEmaLength", 28) \
.SetDisplay("Slow EMA", "Slow EMA period.", "Indicators")
self._rsi_length = self.Param("RsiLength", 14) \
.SetDisplay("RSI Length", "RSI 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 RsiLength(self):
return self._rsi_length.Value
@property
def AtrLength(self):
return self._atr_length.Value
def OnStarted2(self, time):
super(ema_wma_rsi_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._rsi = RelativeStrengthIndex()
self._rsi.Length = self.RsiLength
self._atr = AverageTrueRange()
self._atr.Length = self.AtrLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._fast_ema, self._slow_ema, self._rsi, self._atr, self.ProcessCandle).Start()
def ProcessCandle(self, candle, fast_val, slow_val, rsi_val, atr_val):
if candle.State != CandleStates.Finished:
return
fv = float(fast_val)
sv = float(slow_val)
rv = float(rsi_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) or 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) or 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 and rv > 50:
self._entry_price = close
self.BuyMarket()
elif fv < sv and self._prev_fast >= self._prev_slow and rv < 50:
self._entry_price = close
self.SellMarket()
self._prev_fast = fv
self._prev_slow = sv
def OnReseted(self):
super(ema_wma_rsi_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
def CreateClone(self):
return ema_wma_rsi_strategy()