Der RSI MA für die RSI Filling Step Strategy ist ein StockSharp-Port des MetaTrader-Expertenberaters RSI_MAonRSI_Filling Step EA.mq5. Das ursprüngliche System misst den Impuls mit einem Relative Strength Index (RSI) und glättet diesen Oszillator mit einem gleitenden Durchschnitt. Trades werden eingeleitet, wenn RSI seinen gleitenden Durchschnitt kreuzt, während beide Werte auf der gleichen Seite der mittleren 50-Marke bleiben. Bei der Konvertierung bleiben die konfigurierbaren Handelsrichtungsfilter, der optionale Sitzungstimer und die Möglichkeit, die Signale umzukehren, erhalten, während die High-Level-Indikatorbindungen von StockSharp genutzt werden.
Handelslogik
Abonnieren Sie die ausgewählte Kerzenserie und berechnen Sie zwei Indikatoren für jeden fertigen Balken: RelativeStrengthIndex mit der Länge RsiPeriod und MovingAverage (MaType, MaPeriod), angewendet auf den Stream RSI.
Warten Sie, bis die Kerze vollständig ist, bevor Sie handeln. Dabei wird die „neue Balken“-Absicherung von EA nachgebildet, sodass jeder Balken höchstens eine Handelsentscheidung hervorruft.
Ein bullisches Setup tritt auf, wenn der vorherige RSI-Wert unter seinem gleitenden Durchschnitt lag und der letzte Wert über dem Durchschnitt schließt, während beide Messwerte unter MiddleLevel bleiben (Standard 50). Ein bärisches Setup ist der gespiegelte Fall oberhalb des mittleren Niveaus.
Wenn ReverseSignals aktiviert ist, generiert die bullische Bedingung einen Short-Trade und die bärische Bedingung einen Long-Trade, was die umgekehrte Flagge von EA nachahmt.
Der Parameter Mode beschränkt den Handel auf Long-Only, Short-Only oder beide Richtungen. Zusätzliche Schutzvorrichtungen schließen optional den gegenüberliegenden Zugang und blockieren neue Einträge, wenn eine Position bereits offen ist.
Ein tägliches Zeitfenster, das mit der MetaTrader-Implementierung identisch ist, kann Signale außerhalb des konfigurierten Intervalls SessionStart → SessionEnd deaktivieren, einschließlich Sitzungen, die über Mitternacht hinausgehen.
Parameter
CandleType – von der Strategie verarbeitete Datenreihe. Der Standardwert sind einstündige Zeitrahmenkerzen.
RsiPeriod – RSI Durchschnittslänge (Standard 14).
MaPeriod – Länge des gleitenden Durchschnitts, der auf RSI angewendet wird (Standard 21).
MaType – gleitender Durchschnittstyp, der für die RSI-Glättung verwendet wird (Standard Simple).
MiddleLevel – zentrale RSI-Ebene, die von beiden Indikatoren zur Validierung von Trades verwendet wird (Standard 50).
ReverseSignals – kehrt die Interpretation der bullischen/bärischen Kreuzung um (Standard false).
Modus – Handelsrichtungsfilter (BuyOnly, SellOnly, Both).
CloseOppositePositions – ob die Gegenposition abgeflacht werden soll, bevor ein neuer Trade eingegeben wird (Standard false).
OnlyOnePosition – verhindert neue Aufträge, während eine Position bereits offen ist (Standard false).
UseTimeWindow – aktiviert den täglichen Handelssitzungsfilter (Standard false).
SessionStart / SessionEnd – Start- und Endzeiten der zulässigen Handelssitzung. Funktioniert bei Sitzungen über Nacht, wenn der Abschluss nach Mitternacht erfolgt.
Implementierungshinweise
Indikatorwerte werden über Bind bereitgestellt, wodurch die Notwendigkeit einer manuellen Pufferverwaltung entfällt, die beim ursprünglichen EA mit CopyBuffer erforderlich war.
Vorherige RSI- und gleitende Durchschnittswerte werden zwischengespeichert, um das RSI[m_bar_current+1]-Zugriffsmuster von MQL widerzuspiegeln. Das Feld _lastSignalBarTime garantiert nur einen Trade pro Balken, genau wie die Zeitstempel m_last_deal_buy_in / m_last_deal_sell_in von EA.
Das Handelsmanagement verwendet BuyMarket() und SellMarket(), um die unmittelbare Marktausführung von EA widerzuspiegeln. Das optionale Schließen des Gegenrisikos wird mit ClosePosition() abgewickelt, bevor die neue Bestellung aufgegeben wird.
Der Zeitfilter repliziert die TimeControlHourMinute-Funktion von EA, einschließlich der Nachtfensterlogik, bei der die Startzeit größer als die Endzeit ist.
Charting-Helfer zeichnen Preiskerzen mit Handelsmarkierungen und einem speziellen RSI-Panel, damit die Crossovers während Backtests visuell überprüft werden können.
Unterschiede zum Expert Advisor
Money-Management-Optionen (ENUM_LOT_OR_RISK, Trailing Stops, Freeze-Level-Checks) werden nicht reproduziert. StockSharp-Benutzer können ihre eigene Schutzlogik oder Risikomodule anhängen.
Handelsbestätigungen, magische Zahlenprüfungen und manuelle Auftragswarteschlangen von EA sind nicht erforderlich, da StockSharp Auftragslebenszyklen anders verwaltet. Die Strategie geht von der sofortigen Verfügbarkeit von Marktaufträgen aus.
Stop-Loss- und Take-Profit-Orders werden nicht automatisch angehängt. Verwenden Sie StartProtection oder externe Module, wenn dieses Verhalten erforderlich ist.
Nutzungstipps
Halten Sie MiddleLevel nahe bei 50, um dem ursprünglichen Mittelwertumkehrverhalten treu zu bleiben. Eine Abweichung von diesem Wert treibt das System in Richtung Breakout-Handel.
Aktivieren Sie OnlyOnePosition, wenn Sie strikte Übergänge von flach zu Position bevorzugen. Deaktivieren Sie es, um Pyramiding mit benutzerdefinierter Volume-Logik zu ermöglichen.
Kombinieren Sie den Zeitfilter mit den Börsenhandelszeiten, wenn Sie auf Futures oder Aktien setzen, um nächtlichen Lärm zu vermeiden.
Optimieren Sie MaPeriod, RsiPeriod und MiddleLevel gemeinsam, wenn Sie die Strategie an neue Instrumente anpassen.
Mit diesen Notizen können Sie die RSI MA on RSI Filling Step-Strategie sicher in der StockSharp-Umgebung ausführen, anpassen und erweitern.
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
/// <summary>
/// RSI crossing its own moving average with trade signals.
/// Converted from the MetaTrader expert advisor "RSI_MAonRSI_Filling Step EA.mq5".
/// </summary>
public class RsiMaOnRsiFillingStepStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _maPeriod;
private RelativeStrengthIndex _rsi;
private readonly Queue<decimal> _rsiHistory = new();
private decimal? _previousRsi;
private decimal? _previousSignal;
/// <summary>
/// Initializes a new instance of <see cref="RsiMaOnRsiFillingStepStrategy"/>.
/// </summary>
public RsiMaOnRsiFillingStepStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Timeframe used for RSI calculations.", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "Number of bars for the RSI smoothing window.", "Indicators");
_maPeriod = Param(nameof(MaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("MA Period", "Length of the moving average applied to the RSI.", "Indicators");
}
/// <summary>
/// Candle type used for calculations.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// RSI averaging period.
/// </summary>
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
/// <summary>
/// Moving average period applied to the RSI output.
/// </summary>
public int MaPeriod
{
get => _maPeriod.Value;
set => _maPeriod.Value = value;
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_previousRsi = null;
_previousSignal = null;
_rsiHistory.Clear();
_rsi = null!;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_previousRsi = null;
_previousSignal = null;
_rsiHistory.Clear();
_rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_rsi, ProcessCandle)
.Start();
var priceArea = CreateChartArea();
if (priceArea != null)
{
DrawCandles(priceArea, subscription);
DrawOwnTrades(priceArea);
}
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
{
if (candle.State != CandleStates.Finished)
return;
// Accumulate RSI values for moving average calculation
_rsiHistory.Enqueue(rsiValue);
while (_rsiHistory.Count > MaPeriod)
_rsiHistory.Dequeue();
if (!_rsi.IsFormed)
return;
// Need enough RSI values to compute the MA
if (_rsiHistory.Count < MaPeriod)
{
_previousRsi = rsiValue;
return;
}
// Calculate simple moving average of RSI
var sum = 0m;
var history = _rsiHistory.ToArray();
foreach (var v in history)
sum += v;
var signalValue = sum / MaPeriod;
if (_previousRsi is null || _previousSignal is null)
{
_previousRsi = rsiValue;
_previousSignal = signalValue;
return;
}
var crossUp = _previousRsi < _previousSignal && rsiValue > signalValue;
var crossDown = _previousRsi > _previousSignal && rsiValue < signalValue;
var volume = Volume;
if (volume <= 0)
volume = 1;
if (crossUp)
{
if (Position <= 0)
BuyMarket(volume);
}
else if (crossDown)
{
if (Position >= 0)
SellMarket(volume);
}
_previousRsi = rsiValue;
_previousSignal = signalValue;
}
}
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
from StockSharp.Algo.Strategies import Strategy
class rsi_ma_on_rsi_filling_step_strategy(Strategy):
def __init__(self):
super(rsi_ma_on_rsi_filling_step_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._rsi_period = self.Param("RsiPeriod", 14)
self._ma_period = self.Param("MaPeriod", 20)
self._rsi_history = []
self._prev_rsi = 0.0
self._prev_signal = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def RsiPeriod(self):
return self._rsi_period.Value
@RsiPeriod.setter
def RsiPeriod(self, value):
self._rsi_period.Value = value
@property
def MaPeriod(self):
return self._ma_period.Value
@MaPeriod.setter
def MaPeriod(self, value):
self._ma_period.Value = value
def OnReseted(self):
super(rsi_ma_on_rsi_filling_step_strategy, self).OnReseted()
self._rsi_history = []
self._prev_rsi = 0.0
self._prev_signal = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(rsi_ma_on_rsi_filling_step_strategy, self).OnStarted2(time)
self._rsi_history = []
self._prev_rsi = 0.0
self._prev_signal = 0.0
self._has_prev = False
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, self._process_candle).Start()
def _process_candle(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
rsi_val = float(rsi_value)
# Accumulate RSI values for moving average
self._rsi_history.append(rsi_val)
ma_len = self.MaPeriod
while len(self._rsi_history) > ma_len:
self._rsi_history.pop(0)
# Need enough RSI values to compute the MA
if len(self._rsi_history) < ma_len:
self._prev_rsi = rsi_val
return
# Calculate SMA of RSI
signal_val = sum(self._rsi_history) / ma_len
if self._has_prev:
cross_up = self._prev_rsi < self._prev_signal and rsi_val > signal_val
cross_down = self._prev_rsi > self._prev_signal and rsi_val < signal_val
if cross_up and self.Position <= 0:
self.BuyMarket()
elif cross_down and self.Position >= 0:
self.SellMarket()
self._prev_rsi = rsi_val
self._prev_signal = signal_val
self._has_prev = True
def CreateClone(self):
return rsi_ma_on_rsi_filling_step_strategy()