Diese Strategie repliziert das Verhalten des MetaTrader-Experten Dual StopLoss.mq4. Es fungiert als Risikomanagementebene: Es überwacht die schützenden Stop-Loss-Aufträge, die mit offenen Positionen verbunden sind, und schließt diese Positionen einige Punkte, bevor der Stop ausgelöst wird. Der frühe Ausstieg soll einen negativen Slippage bei stark volatilen Bewegungen vermeiden und gleichzeitig die anfängliche Stop-Platzierung des Händlers respektieren.
Wie es funktioniert
Die Strategie abonniert Level1-Daten, um den aktuell besten Geld-/Briefkurs und den vom Broker veröffentlichten StopLevel-Abstand (oder einen gleichwertigen Abstand) zu verfolgen.
Jedes Mal, wenn neue Preise eintreffen oder sich Aufträge/Geschäfte ändern, wird nach der nächstgelegenen aktiven Stop-Order gesucht, die zum verwalteten Wertpapier gehört.
Der Abstand zwischen dem Marktpreis und diesem Schutzstopp wird mit einem konfigurierbaren Schwellenwert verglichen:
pointValue stimmt mit MetaTraders Point überein (0,0001 für die meisten FX-Paare, automatisch aus den Sicherheitseinstellungen erkannt).
stopLevelDistance stammt aus Level1-Feldern (StopLevel, MinStopPrice, StopPrice oder StopDistance), sofern verfügbar, andernfalls Null.
Wenn die verbleibende Distanz kleiner oder gleich dem Schwellenwert ist, wird die Position sofort mit einer Marktorder geschlossen.
Die Logik umfasst sowohl Long- als auch Short-Positionen. Bei Long-Positionen wird das beste Gebot mit dem Sell-Stop-Preis verglichen; Bei Short-Positionen wird der beste Ask-Preis mit dem Buy-Stop-Preis verglichen. Es werden nur Stop- und Stop-Limit-Orders im aktiven Zustand berücksichtigt.
Parameter
Parameter
Beschreibung
WhenToClosePoints
Entfernung (in MetaTrader Punkten) von der Stoppebene, die den vorzeitigen Ausstieg auslösen soll. Standard: 10. Auf Null gesetzt, um sich nur auf die minimale Stop-Level-Distanz des Brokers zu verlassen.
Hinweise und Einschränkungen
Die Strategie eröffnet keine Positionen allein; Es verwaltet nur Positionen, die bereits vorhanden sind und über schützende Stop-Orders verfügen.
Stellen Sie sicher, dass der zugrunde liegende Connector/Broker Stop-Level-Werte über Level1-Daten bereitstellt, wenn Sie vom Broker vorgegebene Mindestabstände berücksichtigen möchten. Fehlen diese Informationen, funktioniert die Strategie trotzdem nur mit der konfigurierten Punktentfernung.
Der StartProtection()-Anruf aktiviert die integrierten Sicherheitsvorrichtungen von StockSharp, sodass Notausgänge aktiv bleiben, sobald die Strategie gestartet wurde.
Stopps werden aus der Orders-Sammlung der Strategie erkannt. Stellen Sie sicher, dass Schutzstopps über dieselbe Strategieinstanz registriert werden, damit sie in dieser Liste erscheinen.
Wenn mehrere Stop-Orders für die gleiche Richtung vorhanden sind, wird diejenige verwendet, die dem Markt am nächsten liegt.
Anwendungstipps
Hängen Sie die Strategie an ein Portfolio/Wertpapier an, bei dem Positionen manuell oder durch ein anderes System eröffnet werden, aber Schutzstopps im gleichen Strategiekontext platziert werden.
Konfigurieren Sie WhenToClosePoints entsprechend der Menge an Polsterung, die Sie vor dem Stopp benötigen. Dieser Wert wird genau wie in MetaTrader interpretiert (Punkte, keine Preiseinheiten).
Starten Sie die Strategie und überwachen Sie das Protokoll. Wenn sich der Marktpreis dem Stop nähert, erteilt die Strategie einen Marktauftrag, um die Position proaktiv zu schließen.
Kombinieren Sie dieses Modul mit anderen Einstiegs- oder Positionsgrößenstrategien, um einen vollständigen Handelsworkflow zu erstellen.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Dual Stoploss strategy: dual SMA crossover with confirmation.
/// Buys when fast SMA crosses above mid SMA and mid is above slow, sells on opposite.
/// </summary>
public class DualStoplossStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _midPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal _prevFast;
private decimal _prevMid;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int MidPeriod { get => _midPeriod.Value; set => _midPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public DualStoplossStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 3)
.SetGreaterThanZero()
.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");
_midPeriod = Param(nameof(MidPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Mid SMA", "Mid SMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevMid = 0;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fast = new SimpleMovingAverage { Length = FastPeriod };
var mid = new SimpleMovingAverage { Length = MidPeriod };
var slow = new SimpleMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, mid, slow, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal midValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (_hasPrev)
{
if (_prevFast <= _prevMid && fastValue > midValue && midValue > slowValue && Position <= 0)
BuyMarket();
else if (_prevFast >= _prevMid && fastValue < midValue && midValue < slowValue && Position >= 0)
SellMarket();
}
else
{
if (fastValue > midValue && midValue > slowValue && Position <= 0)
BuyMarket();
else if (fastValue < midValue && midValue < slowValue && Position >= 0)
SellMarket();
}
_prevFast = fastValue;
_prevMid = midValue;
_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 SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class dual_stoploss_strategy(Strategy):
"""
Dual Stoploss strategy: triple SMA crossover with confirmation.
Buys when fast SMA crosses above mid SMA and mid is above slow.
Sells on opposite crossover.
"""
def __init__(self):
super(dual_stoploss_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._fast_period = self.Param("FastPeriod", 3) \
.SetDisplay("Fast SMA", "Fast SMA period", "Indicators")
self._mid_period = self.Param("MidPeriod", 10) \
.SetDisplay("Mid SMA", "Mid SMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 30) \
.SetDisplay("Slow SMA", "Slow SMA period", "Indicators")
self._prev_fast = 0.0
self._prev_mid = 0.0
self._has_prev = False
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(dual_stoploss_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_mid = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(dual_stoploss_strategy, self).OnStarted2(time)
self._has_prev = False
fast = SimpleMovingAverage()
fast.Length = self._fast_period.Value
mid = SimpleMovingAverage()
mid.Length = self._mid_period.Value
slow = SimpleMovingAverage()
slow.Length = self._slow_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast, mid, slow, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, mid)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def _process_candle(self, candle, fast_val, mid_val, slow_val):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_val)
mid_val = float(mid_val)
slow_val = float(slow_val)
if self._has_prev:
if self._prev_fast <= self._prev_mid and fast_val > mid_val and mid_val > slow_val and self.Position <= 0:
self.BuyMarket()
elif self._prev_fast >= self._prev_mid and fast_val < mid_val and mid_val < slow_val and self.Position >= 0:
self.SellMarket()
else:
if fast_val > mid_val and mid_val > slow_val and self.Position <= 0:
self.BuyMarket()
elif fast_val < mid_val and mid_val < slow_val and self.Position >= 0:
self.SellMarket()
self._prev_fast = fast_val
self._prev_mid = mid_val
self._has_prev = True
def CreateClone(self):
return dual_stoploss_strategy()