Diese Strategie ist eine direkte Konvertierung des MetaTrader 5 Expert Advisors "TP SL Trailing". Die Strategie generiert selbst keine Einstiege. Stattdessen verwaltet sie bestehende Positionen, indem sie einen Schutz-Stop-Loss und Take-Profit installiert und den Stop nachzieht, sobald der Trade profitabel wird. Die pip-basierte Konfiguration entspricht den Parametern des Originalskripts und ermöglicht es, die Logik an jedes von StockSharp unterstützte Symbol anzuhängen.
Handelslogik
Wenn eine neue Position erscheint, kann die Strategie optional einen anfänglichen Stop-Loss und Take-Profit mit den konfigurierten Pip-Abständen setzen. Dieses Verhalten wird durch das Flag Only Zero Values gesteuert, genau wie im ursprünglichen Expert Advisor.
Für Long-Positionen bewegt die Strategie den Stop-Loss aufwärts, sobald der unrealisierte Gewinn die Summe aus Trailing Stop und Trailing Step überschreitet. Der Stop wird auf aktueller Preis - Trailing Stop gesetzt, was garantiert, dass ein Mindestanteil des Gewinns gesichert ist.
Für Short-Positionen spiegelt die Strategie dieselbe Idee und bewegt den Stop abwärts, sobald der Gewinn die Trailing-Schwellen überschreitet.
Wenn sowohl Trailing Stop als auch Trailing Step null sind, lässt die Strategie den Stop-Loss unberührt.
Das Take-Profit-Level wird nie nachgezogen. Es wird nur während der anfänglichen Platzierungsphase gesetzt, wenn Only Zero Values aktiviert ist, was das MQL-Verhalten vollständig repliziert.
Parameter
Name
Beschreibung
CandleType
Zeitrahmen der Kerzen, die zur Verfolgung von Preisbewegungen verwendet werden. Ein schnellerer Zeitrahmen verbessert die Trailing-Genauigkeit.
StopLossPips
Abstand in Pips zwischen Eintrittspreis und anfänglichem Stop-Loss. Nur angewendet wenn Only Zero Values aktiviert ist.
TakeProfitPips
Abstand in Pips zwischen Eintrittspreis und anfänglichem Take-Profit. Nur angewendet wenn Only Zero Values aktiviert ist.
TrailingStopPips
Kern-Trailing-Abstand in Pips. Definiert, wie weit hinter dem aktuellen Preis der Stop nach Aktivierung bleiben soll.
TrailingStepPips
Zusätzlicher Pip-Puffer, der überschritten werden muss, bevor der Stop sich wieder bewegt. Verhindert zu häufige Stop-Updates.
OnlyZeroValues
Entspricht dem ursprünglichen EA-Flag. Wenn aktiviert, werden anfängliche Schutzorders nur für Positionen erstellt, denen derzeit kein Stop-Loss oder Take-Profit zugewiesen ist.
Konvertierungshinweise
Pip-Abstände werden in Preiseinheiten unter Verwendung des PriceStep des Wertpapiers umgerechnet. Dies hält die Logik instrument-agnostisch und spiegelt die 3/5-Stellen-Anpassung in der MQL-Version wider.
Schutzorders werden neu registriert, wenn die Trailing-Logik den Stop-Loss verschiebt. Aktive Orders einer vorherigen Position werden automatisch storniert, wenn die Positionsgröße auf null zurückkehrt.
Alle Code-Kommentare sind auf Englisch geschrieben, während diese Dokumentation absichtlich detailliert ist, um jede Entscheidung des Portierungsprozesses nachvollziehbar zu machen.
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>
/// TP SL Trailing strategy. Uses EMA with price crossover for entries.
/// </summary>
public class TpSlTrailingStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaPeriod;
private decimal? _prevClose;
private decimal? _prevEma;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public TpSlTrailingStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
_emaPeriod = Param(nameof(EmaPeriod), 20).SetGreaterThanZero().SetDisplay("EMA Period", "EMA lookback", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = null;
_prevEma = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = null; _prevEma = null;
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, ema); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal emaVal)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
if (!IsFormedAndOnlineAndAllowTrading()) { _prevClose = close; _prevEma = emaVal; return; }
if (_prevClose == null || _prevEma == null) { _prevClose = close; _prevEma = emaVal; return; }
if (_prevClose.Value < _prevEma.Value && close >= emaVal && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
else if (_prevClose.Value > _prevEma.Value && close <= emaVal && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
_prevClose = close; _prevEma = emaVal;
}
}
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
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
from indicator_extensions import *
class tp_sl_trailing_strategy(Strategy):
"""EMA price crossover for entries."""
def __init__(self):
super(tp_sl_trailing_strategy, self).__init__()
self._ema_period = self.Param("EmaPeriod", 20).SetGreaterThanZero().SetDisplay("EMA Period", "EMA lookback", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))).SetDisplay("Candle Type", "Timeframe", "General")
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, value): self._candle_type.Value = value
def OnReseted(self):
super(tp_sl_trailing_strategy, self).OnReseted()
self._prev_close = 0
self._prev_ema = 0
def OnStarted2(self, time):
super(tp_sl_trailing_strategy, self).OnStarted2(time)
self._prev_close = 0
self._prev_ema = 0
ema = ExponentialMovingAverage()
ema.Length = self._ema_period.Value
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(ema, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def OnProcess(self, candle, ema_val):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
if self._prev_close == 0 or self._prev_ema == 0:
self._prev_close = close
self._prev_ema = float(ema_val)
return
ema_f = float(ema_val)
if self._prev_close < self._prev_ema and close >= ema_f and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif self._prev_close > self._prev_ema and close <= ema_f and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_close = close
self._prev_ema = ema_f
def CreateClone(self):
return tp_sl_trailing_strategy()