Auf GitHub ansehen

SampleTrailingstop MT5-Strategie

Überblick

Die SampleTrailingstopMt5Strategy reproduziert das Verhalten des MetaTrader 5 Expertenberaters SampleTrailingstop-MT5.mq5 unter Verwendung der hohen Ebene API von StockSharp. Die Strategie verwaltet ständig gepaarte Breakout-Stop-Orders, schützt gefüllte Positionen mit speziellen Exit-Orders und wendet einen Trailing-Stop an, sobald der Handel profitabel wird. Alle Berechnungen basieren auf der Preisstufe des Instruments, sodass die Logik mit der ursprünglichen, auf „Punkten“ basierenden Implementierung übereinstimmt.

Handelslogik

  1. Datenfeed. Die Strategie abonniert Kurse der Stufe 1, um die besten Geld-/Briefkurse zu erhalten, die die Order- und Trailing-Stop-Aktualisierungen vorantreiben.
  2. Eintrittsbefehle.
    • Eine Kauf-Stopp-Order wird mit BuyStop über dem aktuellen Markt platziert. Die Bestellung wird erst aktualisiert, wenn die vorherige Instanz abgeschlossen ist.
    • Eine Verkaufsstopp-Order spiegelt den Long-Einstieg mit SellStop unter dem Marktwert wider.
    • Beide Einstiegsaufträge haben das gleiche konfigurierbare Volumen sowie die gleichen Stop-Loss- und Take-Profit-Abstände. Bestellungen erhalten außerdem eine Ablaufzeit einen Tag im Voraus, passend zur MQL-Implementierung.
  3. Positionsschutz.
    • Nach der Ausführung verfolgt die Strategie die Netto-Signed-Position und den durchschnittlichen Einstiegspreis.
    • Es werden separate Exit-Stop- und Take-Profit-Orders erstellt (SellStop/BuyStop und SellLimit/BuyLimit), sodass die Schutzniveaus an der Börse auch dann bestehen bleiben, wenn die Entry-Orders storniert werden oder ablaufen.
    • Die Ausstiegsaufträge werden fortlaufend mit der aktuellen Positionsgröße und dem aktuellsten durchschnittlichen Einstiegspreis synchronisiert.
  4. Nachgestellte Logik.
    • Wenn der variable Gewinn den konfigurierten Trailing-Abstand erreicht, wird der Schutzstopp verschärft, um diesen Abstand vom aktuellen Geld- (für Long-Positionen) bzw. Brief-Kurs (für Short-Positionen) beizubehalten.
    • Der Trailing Stop überschreitet niemals den Einstiegspreis und respektiert einen minimalen Aktualisierungsschritt, der einem Preisschritt entspricht.
  5. Positionsverfolgung. Jeder eigene Trade aktualisiert den kumulierten Positionswert und berechnet den gewichteten durchschnittlichen Einstiegspreis neu, sodass Teilfüllungen und Umkehrungen korrekt verarbeitet werden.

Parameter

Parameter Beschreibung
TradeVolume Festes Ordervolumen (Lots oder Kontrakte), das für beide Breakout-Stop-Orders verwendet wird.
TakeProfitPoints Abstand in Instrumentenpunkten zum Gewinnziel. Auf Null setzen, um den Take-Profit zu deaktivieren.
StopLossPoints Abstand in Punkten für den schützenden Stop-Loss.
TrailingStopPoints Nachlaufdistanz in Punkten, die angewendet wird, sobald die Position im Gewinn ist. Null deaktiviert das Nachziehen.

Verhaltensnotizen

  • Eintrittsaufträge werden erst erneut eingereicht, nachdem die vorherige Instanz abgeschlossen (erfüllt, storniert oder abgelaufen) ist. Dies spiegelt die CheckPendingOrder-Logik des ursprünglichen Experten wider.
  • Die Stop-Loss- und Take-Profit-Abstände werden immer mit Security.PriceStep in Preiswerte umgewandelt, um ein konsistentes Verhalten über verschiedene Instrumente hinweg sicherzustellen.
  • Wenn die Position vollständig geschlossen ist, storniert die Strategie automatisch alle verbleibenden Ausstiegsaufträge und setzt die internen Durchschnittswerte zurück.
  • Die Strategie basiert ausschließlich auf Daten der Ebene 1 und erfordert keine Kerzen oder Indikatoren, sodass die Konvertierung nahe an der MQL-Vorlage bleibt.

Nutzung

  1. Weisen Sie vor Beginn der Strategie das gewünschte Wertpapier und Portfolio zu.
  2. Passen Sie die vier öffentlichen Parameter an, um sie an das gehandelte Instrument anzupassen (Volumen, Stop-Loss, Take-Profit und Trailing-Distanz).
  3. Starten Sie die Strategie. Es wird Breakout-Aufträge und Positionsschutz autonom in Echtzeit verwalten.
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Sample Trailingstop MT5 strategy: EMA + RSI confirmation.
/// Buys when close above EMA and RSI above 50, sells when close below EMA and RSI below 50.
/// </summary>
public class SampleTrailingstopMt5Strategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _rsiPeriod;

	private decimal _prevClose;
	private decimal _prevEma;
	private bool _hasPrev;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }

	public SampleTrailingstopMt5Strategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_emaPeriod = Param(nameof(EmaPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA period", "Indicators");
		_rsiPeriod = Param(nameof(RsiPeriod), 21)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI period", "Indicators");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevClose = 0;
		_prevEma = 0;
		_hasPrev = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevClose = 0;
		_prevEma = 0;
		_hasPrev = false;
		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(ema, rsi, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal emaValue, decimal rsiValue)
	{
		if (candle.State != CandleStates.Finished) return;

		if (_hasPrev)
		{
			if (_prevClose <= _prevEma && candle.ClosePrice > emaValue && rsiValue > 55 && Position <= 0)
				BuyMarket();
			else if (_prevClose >= _prevEma && candle.ClosePrice < emaValue && rsiValue < 45 && Position >= 0)
				SellMarket();
		}

		_prevClose = candle.ClosePrice;
		_prevEma = emaValue;
		_hasPrev = true;
	}
}