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
Datenfeed. Die Strategie abonniert Kurse der Stufe 1, um die besten Geld-/Briefkurse zu erhalten, die die Order- und Trailing-Stop-Aktualisierungen vorantreiben.
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.
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.
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.
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
Weisen Sie vor Beginn der Strategie das gewünschte Wertpapier und Portfolio zu.
Passen Sie die vier öffentlichen Parameter an, um sie an das gehandelte Instrument anzupassen (Volumen, Stop-Loss, Take-Profit und Trailing-Distanz).
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;
}
}
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 ExponentialMovingAverage, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class sample_trailingstop_mt5_strategy(Strategy):
def __init__(self):
super(sample_trailingstop_mt5_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._ema_period = self.Param("EmaPeriod", 50)
self._rsi_period = self.Param("RsiPeriod", 21)
self._prev_close = 0.0
self._prev_ema = 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 EmaPeriod(self):
return self._ema_period.Value
@EmaPeriod.setter
def EmaPeriod(self, value):
self._ema_period.Value = value
@property
def RsiPeriod(self):
return self._rsi_period.Value
@RsiPeriod.setter
def RsiPeriod(self, value):
self._rsi_period.Value = value
def OnReseted(self):
super(sample_trailingstop_mt5_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_ema = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(sample_trailingstop_mt5_strategy, self).OnStarted2(time)
self._prev_close = 0.0
self._prev_ema = 0.0
self._has_prev = False
ema = ExponentialMovingAverage()
ema.Length = self.EmaPeriod
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema, rsi, self._process_candle).Start()
def _process_candle(self, candle, ema_value, rsi_value):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
ema_val = float(ema_value)
rsi_val = float(rsi_value)
if self._has_prev:
if self._prev_close <= self._prev_ema and close > ema_val and rsi_val > 55 and self.Position <= 0:
self.BuyMarket()
elif self._prev_close >= self._prev_ema and close < ema_val and rsi_val < 45 and self.Position >= 0:
self.SellMarket()
self._prev_close = close
self._prev_ema = ema_val
self._has_prev = True
def CreateClone(self):
return sample_trailingstop_mt5_strategy()