Diese Strategie repliziert den Expertenberater Exp_XRSIDeMarker_Histogram. Sie handelt Umkehrungen, die von einem benutzerdefinierten Oszillator erkannt werden, der einen Relative Strength Index (RSI) mit dem DeMarker-Indikator kombiniert und das Ergebnis dann glättet. Das System kann Long- und Short-Trades unabhängig voneinander öffnen oder schließen, und optionale Schutz-Stops, ausgedrückt in Preisschritten, werden unterstützt.
Indikatoraufbau
Angewandter Preis – der RSI wird auf dem ausgewählten Eingang (Schlusskurs, Eröffnung, Hoch, Tief, Median, typisch oder gewichtet) mit dem konfigurierten Zeitraum berechnet.
DeMarker-Komponente – für jede abgeschlossene Kerze misst die Strategie den Aufwärts- (deMax) und Abwärtsdruck (deMin):
deMax = max(High_t - High_{t-1}, 0)
deMin = max(Low_{t-1} - Low_t, 0)
Beide Serien werden mit einem einfachen gleitenden Durchschnitt geglättet, dessen Länge dem RSI-Zeitraum entspricht.
DeMarker = deMaxAvg / (deMaxAvg + deMinAvg) (skaliert auf den Bereich 0–100).
Zusammengesetzter Oszillator – der Endwert ist (RSI + 100 * DeMarker) / 2.
Glättung – der zusammengesetzte Oszillator wird durch einen der unterstützten gleitenden Durchschnitte (SMA, EMA, SMMA, LWMA oder Jurik) geleitet. Wenn ein nicht unterstützter Glättungsmodus der ursprünglichen MQL-Version ausgewählt wird, fällt der Indikator auf eine EMA mit der angeforderten Länge zurück. Die Jurik-Option berücksichtigt auch den Phasenparameter.
Signalhistorie – die Strategie speichert historische Werte und wertet Signale auf der durch SignalBar definierten Balken aus, was das ursprüngliche EA nachahmt, das auf die nächste Kerze wartete, bevor Trades ausgeführt wurden.
Handelslogik
Bullische Umkehr
Bedingung: Wert bei SignalBar+1 liegt unter SignalBar+2 (Abwärtsneigung) und der Wert bei SignalBar dreht wieder nach oben (>=).
Aktionen:
Bestehende Short-Trades schließen, wenn CloseShortOnLongSignal wahr ist.
Einen neuen Long-Trade mit TradeVolume öffnen (plus die für eine Umkehr von einem Short benötigte Menge), wenn AllowBuyEntries aktiviert ist.
Bärische Umkehr
Bedingung: Wert bei SignalBar+1 liegt über SignalBar+2 (Aufwärtsneigung) und der Wert bei SignalBar dreht nach unten (<=).
Aktionen:
Bestehende Long-Trades schließen, wenn CloseLongOnShortSignal wahr ist.
Einen neuen Short-Trade öffnen, wenn AllowSellEntries aktiviert ist.
Signale werden ignoriert, bis der Indikator und die DeMarker-Komponenten vollständig gebildet sind, und Aufträge werden nur platziert, wenn die Strategie online ist und der Handel erlaubt ist.
Risikomanagement
StopLossTicks und TakeProfitTicks repräsentieren Abstände in Preisschritten. Die Strategie multipliziert diese Werte mit Security.PriceStep (auf 1 zurückgreifend, wenn der Instrumentenschritt unbekannt ist) und schließt die Position, wenn der Abstand innerhalb des Kerzenbereichs erreicht wird.
Die Übergabe von 0 deaktiviert den jeweiligen Schutz.
Der Parameter TradeVolume wird als Standard-Auftragsgröße verwendet und auch zur Berechnung von Umkehrungen (die entgegengesetzte Position wird geschlossen, bevor eine neue eröffnet wird).
Parameter
Parameter
Beschreibung
Standard
TradeVolume
Volumen beim Öffnen neuer Positionen.
0.1
StopLossTicks
Schutz-Stop in Preisschritten.
1000
TakeProfitTicks
Gewinnziel in Preisschritten.
2000
AllowBuyEntries
Long-Trades aktivieren/deaktivieren.
true
AllowSellEntries
Short-Trades aktivieren/deaktivieren.
true
CloseLongOnShortSignal
Longs schließen wenn ein Short-Signal erscheint.
true
CloseShortOnLongSignal
Shorts schließen wenn ein Long-Signal erscheint.
true
CandleType
Zeitrahmen für die Analyse (Standard 4-Stunden-Kerzen).
H4
IndicatorPeriod
Rückblick für RSI- und DeMarker-Komponenten.
14
AppliedPriceSelection
Angewandter Preis für die RSI-Berechnung.
Close
SmoothingMethodSelection
Gleitender Durchschnitt für die Glättung (SMA/EMA/SMMA/LWMA/Jurik/Adaptive).
Sma
SmoothingLength
Zeitraum des Glättungsdurchschnitts.
5
SmoothingPhase
Phasenargument für die Jurik-Glättung.
15
SignalBar
Anzahl der geschlossenen Balken zurück für die Signalauswertung.
1
Hinweise vs. Original-EA
Geldverwaltungsmodi der MQL-Version (balancebasiert, freie-Margin-basiert, etc.) werden durch einen direkten TradeVolume-Parameter ersetzt.
Auftragsslippage (Deviation) ist nicht erforderlich, da StockSharp Marktaufträge verwendet.
Fortgeschrittene Glättungsalgorithmen (Parabolischer MA, T3, VIDYA, AMA) sind in StockSharp nicht verfügbar und werden über die Adaptive-Option zur EMA zugeordnet.
Alle Kommentare im C#-Quellcode sind auf Englisch verfasst, und die Logik läuft nur auf abgeschlossenen Kerzen, genau wie die ursprüngliche Implementierung.
namespace StockSharp.Samples.Strategies;
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// XRSI DeMarker Histogram strategy (simplified).
/// Uses RSI combined with momentum to detect reversals.
/// Buys on RSI reversal from oversold, sells on reversal from overbought.
/// </summary>
public class XrsidDeMarkerHistogramStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _smaPeriod;
private decimal _prevRsi;
private decimal _prevPrevRsi;
private bool _initialized;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
public int SmaPeriod
{
get => _smaPeriod.Value;
set => _smaPeriod.Value = value;
}
public XrsidDeMarkerHistogramStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Source candles", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI indicator period", "Indicators");
_smaPeriod = Param(nameof(SmaPeriod), 5)
.SetGreaterThanZero()
.SetDisplay("SMA Period", "Smoothing period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevRsi = 0m;
_prevPrevRsi = 0m;
_initialized = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevRsi = 0;
_prevPrevRsi = 0;
_initialized = false;
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var sma = new SimpleMovingAverage { Length = SmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(rsi, sma, (ICandleMessage candle, decimal rsiValue, decimal smaValue) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!_initialized)
{
_prevPrevRsi = rsiValue;
_prevRsi = rsiValue;
_initialized = true;
return;
}
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevPrevRsi = _prevRsi;
_prevRsi = rsiValue;
return;
}
// Buy on RSI reversal from oversold (V-bottom)
var buySignal = _prevPrevRsi > _prevRsi && rsiValue >= _prevRsi && _prevRsi < 35m;
// Sell on RSI reversal from overbought (inverse V)
var sellSignal = _prevPrevRsi < _prevRsi && rsiValue <= _prevRsi && _prevRsi > 65m;
if (buySignal && Position <= 0)
{
BuyMarket();
}
else if (sellSignal && Position >= 0)
{
SellMarket();
}
_prevPrevRsi = _prevRsi;
_prevRsi = rsiValue;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, rsi);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
}
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 RelativeStrengthIndex, SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class xrsid_de_marker_histogram_strategy(Strategy):
def __init__(self):
super(xrsid_de_marker_histogram_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Source candles", "General")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI indicator period", "Indicators")
self._sma_period = self.Param("SmaPeriod", 5) \
.SetDisplay("SMA Period", "Smoothing period", "Indicators")
self._prev_rsi = 0.0
self._prev_prev_rsi = 0.0
self._initialized = False
@property
def CandleType(self):
return self._candle_type.Value
@property
def RsiPeriod(self):
return self._rsi_period.Value
@property
def SmaPeriod(self):
return self._sma_period.Value
def OnReseted(self):
super(xrsid_de_marker_histogram_strategy, self).OnReseted()
self._prev_rsi = 0.0
self._prev_prev_rsi = 0.0
self._initialized = False
def OnStarted2(self, time):
super(xrsid_de_marker_histogram_strategy, self).OnStarted2(time)
self._prev_rsi = 0.0
self._prev_prev_rsi = 0.0
self._initialized = False
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
sma = SimpleMovingAverage()
sma.Length = self.SmaPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription \
.Bind(rsi, sma, self._on_process) \
.Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, rsi)
self.DrawIndicator(area, sma)
self.DrawOwnTrades(area)
def _on_process(self, candle, rsi_value, sma_value):
if candle.State != CandleStates.Finished:
return
rv = float(rsi_value)
if not self._initialized:
self._prev_prev_rsi = rv
self._prev_rsi = rv
self._initialized = True
return
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_prev_rsi = self._prev_rsi
self._prev_rsi = rv
return
buy_signal = self._prev_prev_rsi > self._prev_rsi and rv >= self._prev_rsi and self._prev_rsi < 35.0
sell_signal = self._prev_prev_rsi < self._prev_rsi and rv <= self._prev_rsi and self._prev_rsi > 65.0
if buy_signal and self.Position <= 0:
self.BuyMarket()
elif sell_signal and self.Position >= 0:
self.SellMarket()
self._prev_prev_rsi = self._prev_rsi
self._prev_rsi = rv
def CreateClone(self):
return xrsid_de_marker_histogram_strategy()