Die 5min RSI Qualified Strategy ist eine direkte Umsetzung des MetaTrader Expert Advisors „5min_rsi_qual_01a“. Der ursprüngliche Roboter suchte anhand eines 28-Perioden-Relative-Stärke-Index (RSI) nach Erschöpfung in Fünf-Minuten-Kerzen. Sobald der Oszillator für eine vordefinierte Anzahl von Balken in einer extremen Zone blieb, eröffnete EA eine konträre Position und fügte einen Trailing Stop hinzu, der dem Schluss der vorherigen Kerze folgte. Der StockSharp-Port behält die genaue Bestätigungslogik, Preisversätze und Einzelpositionsbeschränkung bei und verlässt sich dabei auf das High-Level-Kerzenabonnement API.
Standardmäßig arbeitet die Strategie mit Fünf-Minuten-Kerzen, der Parameter CandleType akzeptiert jedoch jeden anderen vom Instrument unterstützten Zeitrahmen. Alle Indikatorschwellenwerte und Stoppentfernungen werden weiterhin in MetaTrader „Punkten“ ausgedrückt, sodass Benutzer ihre getesteten Konfigurationen ohne weitere Anpassungen erneut anwenden können.
Handelslogik
RSI-Berechnung – Bei jeder fertigen Kerze wird ein 28-Perioden-RSI aktualisiert. Nur abgeschlossene Kerzen werden verarbeitet, um der Referenz MQL4 Close[1] zu entsprechen.
Qualifikationszähler – Zwei Zähler verfolgen, wie viele aufeinanderfolgende Kerzen der RSI über dem Überkauft-Schwellenwert (UpperThreshold) oder unter dem Überverkauft-Schwellenwert (LowerThreshold) geblieben ist. Dies spiegelt die MQL-Schleife wider, die die letzten 12 Balken überprüft hat.
Eintrittsbedingungen – Wenn keine Position offen ist und der Überkauft-Zähler QualificationLength erreicht, wird die Strategie zum Marktpreis verkauft. Wenn umgekehrt der überverkaufte Zähler den Bedarf erreicht, kauft er zum Marktpreis. Dies reproduziert das Verhalten von EA, bei dem höchstens ein Trade pro Symbol gehalten wird.
Trailing Stop – Während eine Position aktiv ist, wird das Stop-Level bei jeder abgeschlossenen Kerze neu berechnet, wobei der vorherige Schlusskurs minus/plus StopLossPoints in den absoluten Preis umgewandelt wird. Der Stop bewegt sich nur in Richtung des Handels, genau wie die OrderModify-Aufrufe im Originalcode.
Anfangsstopp – Nach jeder Füllung legt die Strategie den Anfangsstopp mit InitialStopPoints fest. Wenn der Anfangswert enger als die Nachlaufdistanz ist, wird er von der Nachlauflogik nicht gelockert, wodurch das MetaTrader-Verhalten erhalten bleibt, bei dem der Anfangsstopp näher als die Nachlaufdistanz liegen könnte.
Risikomanagement
Stoppentfernungen werden in MetaTrader Punkten definiert, um mit EA übereinzustimmen. Sie werden mithilfe des PriceStep des Instruments (oder MinStep, wenn der primäre Schritt nicht verfügbar ist) in absolute Preiserhöhungen umgewandelt.
Bei der Strategie handelt es sich niemals um Pyramidengeschäfte. Eine neue Position wird erst eröffnet, wenn die vorherige vollständig geschlossen wurde.
StartProtection() wird beim Start aufgerufen, damit die Schutzinfrastruktur von StockSharp mit den manuell verwalteten Stoppebenen synchron bleibt.
Parameter
Parameter
Beschreibung
Standard
RsiPeriod
RSI Lookback-Länge.
28
QualificationLength
Anzahl aufeinanderfolgender Kerzen, bei denen RSI im Extrembereich bleiben muss, bevor ein Signal bestätigt wird.
12
UpperThreshold
RSI-Level, das ein rückläufiges Setup qualifiziert.
55
LowerThreshold
RSI-Level, das ein bullisches Setup qualifiziert.
45
StopLossPoints
Trailing-Stop-Distanz in MetaTrader Punkten. Für jede Kerze in den absoluten Preis umgerechnet. Auf 0 setzen, um das Nachstellen zu deaktivieren.
21
InitialStopPoints
Der anfängliche Schutzstoppabstand in MetaTrader Punkten wird unmittelbar nach der Einfahrt angewendet. Auf 0 einstellen, um den ersten Stopp zu überspringen.
11
CandleType
Kerzentyp, der zur Signalauswertung verwendet wird (standardmäßig 5 Minuten).
5-minute time frame
Nutzungsrichtlinien
Stellen Sie sicher, dass der Preisschritt des Instruments mit der Punktgröße übereinstimmt, die während der MetaTrader-Optimierung verwendet wurde. Bei fünfstelligen FX-Symbolen entspricht ein Punkt 0,00010 (einem Pip), sodass die Standardabstände die 11/21-Punkt-Offsets von EA reproduzieren.
Da die Methode konträr ist, sind Signale in Ranging-Märkten zuverlässiger. Erwägen Sie eine Erweiterung der Schwellenwerte oder eine Erhöhung von QualificationLength für Trend-Assets.
Die Strategie verwendet die Eigenschaft der Basisklasse Volume für die Auftragsgröße. Konfigurieren Sie es in der Benutzeroberfläche oder per Code, bevor Sie mit der Strategie beginnen.
Dank der Flags SetCanOptimize() kann eine Optimierung der RSI-Schwellenwerte, der Qualifikationslänge und der Stoppdistanzen durchgeführt werden.
Konvertierungshinweise
Die Kerzenbehandlung, die RSI-Berechnung und die Ein-Positions-Beschränkung spiegeln die MetaTrader-Implementierung wider. Es wurden keine zusätzlichen Filter eingeführt.
Der Trailing Stop aktualisiert das Stop-Level mit dem Schlusskurs der vorherigen Kerze, genau wie die MQL4 Close[1]-Logik, und stellt sicher, dass beide Versionen bei einer Umkehr zum gleichen Preis aussteigen.
Fehlerprüfungen aus dem MQL4-Skript (Balkenanzahl, freie Marge) werden absichtlich weggelassen, da StockSharp die Datenbereitschaft und Portfolioverfügbarkeit intern verwaltet.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// 5-minute RSI qualified strategy.
/// Counts consecutive candles in RSI extreme zones.
/// Buys after sustained oversold, sells after sustained overbought.
/// </summary>
public class FiveMinRsiQualifiedStrategy : Strategy
{
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _qualificationLength;
private readonly StrategyParam<decimal> _upperThreshold;
private readonly StrategyParam<decimal> _lowerThreshold;
private readonly StrategyParam<DataType> _candleType;
private int _overboughtCount;
private int _oversoldCount;
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public int QualificationLength { get => _qualificationLength.Value; set => _qualificationLength.Value = value; }
public decimal UpperThreshold { get => _upperThreshold.Value; set => _upperThreshold.Value = value; }
public decimal LowerThreshold { get => _lowerThreshold.Value; set => _lowerThreshold.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public FiveMinRsiQualifiedStrategy()
{
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetDisplay("RSI Period", "RSI lookback", "Indicators");
_qualificationLength = Param(nameof(QualificationLength), 3)
.SetDisplay("Qual Length", "Consecutive candles in extreme zone", "Indicators");
_upperThreshold = Param(nameof(UpperThreshold), 65m)
.SetDisplay("Upper", "RSI overbought threshold", "Indicators");
_lowerThreshold = Param(nameof(LowerThreshold), 35m)
.SetDisplay("Lower", "RSI oversold threshold", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_overboughtCount = 0;
_oversoldCount = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_overboughtCount = 0;
_oversoldCount = 0;
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(rsi, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
{
if (candle.State != CandleStates.Finished)
return;
// Track consecutive overbought candles
if (rsiValue >= UpperThreshold)
_overboughtCount++;
else
_overboughtCount = 0;
// Track consecutive oversold candles
if (rsiValue <= LowerThreshold)
_oversoldCount++;
else
_oversoldCount = 0;
// After qualified oversold period, buy (contrarian)
if (_oversoldCount >= QualificationLength && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
_oversoldCount = 0;
}
// After qualified overbought period, sell (contrarian)
else if (_overboughtCount >= QualificationLength && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
_overboughtCount = 0;
}
}
}