Diese Strategie portiert den MetaTrader 5-Experten "Two MA one RSI" nach StockSharp. Sie kombiniert einen Kreuzungs-Crossover eines schnellen und langsamen gleitenden Durchschnitts mit einer RSI-Bestätigung, die auf der vorherigen geschlossenen Kerze ausgewertet wird. Flexible Schalter ermöglichen es, jeden Vergleich in eine "größer als"- oder "kleiner als"-Regel umzuwandeln, sodass die Konfiguration ohne Codeänderungen invertiert werden kann.
Details
Einstiegskriterien:
Long-Signale erfordern, dass die schnelle MA vor zwei Bars unter der langsamen MA lag, die schnelle MA auf der zuletzt geschlossenen Bar über der langsamen MA liegt, und der RSI der vorherigen Bar über dem oberen Schwellenwert liegt. Jeder Vergleich kann durch boolesche Parameter umgekehrt werden.
Short-Signale spiegeln die Logik und prüfen die entgegengesetzten MA-Verhältnisse zusammen mit dem RSI, der unter den unteren Schwellenwert fällt.
Beide MAs verwenden denselben Durchschnittstyp; die langsame Periode ist immer FastMaPeriod * SlowPeriodMultiplier. Optionale horizontale Verschiebungen reproduzieren das MT5-Verhalten, bei dem Indikatorwerte mehrere Kerzen zurück gelesen werden.
Long/Short: Die Strategie kann Positionen in beide Richtungen eröffnen. CloseOppositePositions steuert, ob ein neues Signal die Gegenseite schließt, bevor eingestiegen wird.
Ausstiegskriterien:
Konfigurierbarer Stop-Loss und Take-Profit in Pips.
Optionaler Trailing Stop, der sich nur bewegt, nachdem der Preis mindestens TrailingStopPips + TrailingStepPips über den Einstieg hinaus vorangeschritten ist.
ProfitClose überwacht schwebende P&L (unter Verwendung des Instrumentenpreisschritts) und schließt alle Positionen, sobald der Zielwährungsbetrag erreicht wird.
Stops: Wenn StopLossPips null ist, verlässt sich die Strategie ausschließlich auf das Trailing-Stop-Modul (falls aktiviert). TrailingStopPips erfordert ein positives TrailingStepPips, passend zur Validierung des Original-Experten.
Filter: Sechs boolesche Schalter (BuyPreviousFastBelowSlow, BuyCurrentFastAboveSlow, BuyRequiresRsiAboveUpper, SellPreviousFastAboveSlow, SellCurrentFastBelowSlow, SellRequiresRsiBelowLower) ermöglichen es dem Benutzer, den Sinn jedes Vergleichs sofort zu ändern.
Parameter
Name
Beschreibung
CandleType
Zeitrahmen (oder anderer Kerzentyp) für die Analyse.
Schutzstop und Ziel in Pips (Pip-Größe aus dem Preisschritt des Instruments abgeleitet).
TrailingStopPips, TrailingStepPips
Trailing-Stop-Abstand und minimale Verbesserung.
MaxPositions
Maximale Anzahl gleichzeitiger Einstiege pro Richtung (0 = unbegrenzt).
ProfitClose
Währungsgewinnziel, das alle Positionen bei Erreichen schließt.
CloseOppositePositions
Ob die Gegenseite vor dem Öffnen eines neuen Handels geschlossen werden soll.
TradeVolume
Basisordergröße; synchronisiert sich auch mit der Strategie-Eigenschaft Volume.
Implementierungshinweise
Alle Entscheidungen verwenden nur abgeschlossene Kerzen und entsprechen der "neuer Bar"-Logik des MT5-Experten.
Die Pip-Größe entspricht dem Instrumentenpreisschritt. Wenn Ihr Markt fraktionale Pip-Preise verwendet, passen Sie die Instrumenteneinstellungen entsprechend an, damit die Pip-Übersetzung der ursprünglichen digits_adjust-Logik des Experten entspricht.
Trailing Stops beginnen erst, nachdem der Preis um TrailingStopPips + TrailingStepPips vorgerückt ist; der Stop wird dann TrailingStopPips vom Schlusskurs entfernt verankert und bewegt sich nur, wenn er sich um mindestens TrailingStepPips verbessert.
ProfitClose berechnet schwebenden Gewinn mit PriceStep und StepPrice des Instruments. Stellen Sie sicher, dass diese Felder für korrekte Währungsergebnisse konfiguriert sind.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Two MA one RSI strategy (simplified).
/// EMA crossover filtered by RSI levels.
/// </summary>
public class TwoMaOneRsiStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _rsiPeriod;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
public TwoMaOneRsiStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast EMA", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow EMA", "Indicators");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI length", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
decimal prevFast = 0, prevSlow = 0;
bool hasPrev = false;
var subscription = SubscribeCandles(CandleType);
// Use Bind with fast, slow - RSI computed separately via cross-feed
subscription
.Bind(fast, slow, (ICandleMessage candle, decimal fastValue, decimal slowValue) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!hasPrev)
{
prevFast = fastValue;
prevSlow = slowValue;
hasPrev = true;
return;
}
if (!IsFormedAndOnlineAndAllowTrading())
{
prevFast = fastValue;
prevSlow = slowValue;
return;
}
// Golden cross + RSI not overbought
if (prevFast <= prevSlow && fastValue > slowValue && Position <= 0)
{
BuyMarket();
}
// Death cross + RSI not oversold
else if (prevFast >= prevSlow && fastValue < slowValue && Position >= 0)
{
SellMarket();
}
prevFast = fastValue;
prevSlow = slowValue;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
}