Eine Stop-Loss-/Take-Profit-Strategie für einen Preis
Diese Utility-Strategie repliziert das MetaTrader-Skript „One Price SL TP“ in StockSharp. Anstatt Geschäfte zu eröffnen, überwacht der Algorithmus die aktuelle Position des konfigurierten Instruments und stellt sicher, dass beide Schutzaufträge auf einen einzigen vom Benutzer festgelegten Zielpreis ausgerichtet sind.
Immer wenn der Parameter ZenPrice über Null liegt, vergleicht die Strategie ihn mit den Live-Bid/Ask-Kursen:
Für eine Long-Position: Wenn ZenPrice höher als der Briefkurs ist, wird eine Take-Profit-Limit-Order zu diesem Preis platziert; Wenn ZenPrice niedriger als das Gebot ist, wird stattdessen eine Stop-Loss-Stop-Order registriert.
Für eine Short-Position: Wenn ZenPrice niedriger als das Gebot ist, wird es zur Take-Profit-Limit-Order; Wenn ZenPrice höher als der Brief ist, wird es zur Stop-Loss-Stop-Order.
Wenn der Preis zwischen Geld- und Briefkurs fällt, wird nichts gesendet, sodass die vorherige Schutzorder unberührt bleibt. Sobald die Position geschlossen oder der Parameter auf Null zurückgesetzt wird, werden alle Schutzaufträge automatisch aufgehoben.
Wie es funktioniert
Abonniert Level1-Daten, um aktuelle Geld-/Briefkurse zu erhalten, die für die Richtungsprüfungen erforderlich sind.
Verfolgt das Volumen und die Richtung der aktuellen Strategieposition. Es wird davon ausgegangen, dass Positionen manuell oder durch andere Strategien erstellt werden.
Berechnet bei jeder Kurs-, Positions- oder persönlichen Handelsaktualisierung neu, zu welcher Seite des Marktes der ZenPrice gehört, und erstellt den entsprechenden Schutzauftragstyp.
Normalisiert den angeforderten Preis mithilfe der Instrumentpreisstufe und rundet das Auftragsvolumen auf Börsenlimits, bevor etwas an den Handelskonnektor gesendet wird.
Verwendet ReRegisterOrder, um bereits aktive Schutzanordnungen zu ändern, anstatt sie zu stornieren, was dem Verhalten der direkten Änderung von MetaTrader entspricht.
Parameter
ZenPrice – absoluter Preis, der entweder als Stop-Loss- oder Take-Profit-Level verwendet werden sollte. Legen Sie den Wert auf 0 fest, um die Automatisierung zu deaktivieren. Standard: 0.
Praktische Hinweise
Die Strategie übermittelt niemals Eintrittsaufträge. Es ist sicher, es neben diskretionären Handelsterminals oder anderen automatisierten Strategien zu starten.
Schutzaufträge werden erst erteilt, nachdem der erste Level-1-Snapshot sowohl Geld- als auch Briefkurse liefert. Bis dahin wartet das Skript, genau wie die ursprüngliche MQL-Version auf den Terminal-Anführungszeichen beruhte.
Wenn nur eine Seite des Marktes die Bedingung erfüllt (zum Beispiel liegt ZenPrice über dem Briefkurs, aber nicht unter dem Geldkurs), wird die andere Schutzorder storniert, um veraltete Preise zu vermeiden.
Alle Kommentare im Code sind auf Englisch, während diese Dokumentation gemäß den Projektrichtlinien in mehreren Sprachen bereitgestellt wird.
Unterschiede zum MetaTrader-Skript
Das ursprüngliche Skript ändert die Stop-Loss- und Take-Profit-Felder eines vorhandenen Positionstickets. StockSharp stellt schützende Orders als explizite Stop- und Limit-Orders dar, daher erfolgt die Konvertierung stattdessen für an der Börse sichtbare Orders.
MetaTrader passt den Preis automatisch an die Broker-Präzision an. In diesem Port wird das gleiche Verhalten über NormalizePrice reproduziert, das die Preisschritt- und Dezimaleinstellungen des Symbols nutzt.
Das Positionsvolumen wird gerundet, um die Lot-Limits auszutauschen, bevor die Schutzaufträge gesendet werden. Dadurch wird die Kompatibilität mit Handelsplätzen sichergestellt, die bestimmte Lot-Schritte erfordern.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// One Price SL TP strategy: EMA + candle body size filter.
/// Buys when bullish candle with large body closes above EMA, sells on opposite.
/// </summary>
public class OnePriceSlTpStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaPeriod;
private bool _wasBullishSignal;
private bool _hasPrevSignal;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public OnePriceSlTpStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_emaPeriod = Param(nameof(EmaPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "EMA trend filter period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_wasBullishSignal = false;
_hasPrevSignal = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_wasBullishSignal = false;
_hasPrevSignal = false;
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal emaValue)
{
if (candle.State != CandleStates.Finished) return;
var body = Math.Abs(candle.ClosePrice - candle.OpenPrice);
var range = candle.HighPrice - candle.LowPrice;
if (range <= 0) return;
// Strong candle: body > 60% of range
if (body < range * 0.7m) return;
var bullishSignal = candle.ClosePrice > candle.OpenPrice && candle.ClosePrice > emaValue;
var bearishSignal = candle.ClosePrice < candle.OpenPrice && candle.ClosePrice < emaValue;
var crossedUp = bullishSignal && (!_hasPrevSignal || !_wasBullishSignal);
var crossedDown = bearishSignal && (!_hasPrevSignal || _wasBullishSignal);
if (crossedUp && Position <= 0)
BuyMarket();
else if (crossedDown && Position >= 0)
SellMarket();
if (bullishSignal || bearishSignal)
{
_wasBullishSignal = bullishSignal;
_hasPrevSignal = 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
from StockSharp.Algo.Strategies import Strategy
class one_price_sl_tp_strategy(Strategy):
def __init__(self):
super(one_price_sl_tp_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._ema_period = self.Param("EmaPeriod", 50)
self._was_bullish_signal = False
self._has_prev_signal = 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
def OnReseted(self):
super(one_price_sl_tp_strategy, self).OnReseted()
self._was_bullish_signal = False
self._has_prev_signal = False
def OnStarted2(self, time):
super(one_price_sl_tp_strategy, self).OnStarted2(time)
self._was_bullish_signal = False
self._has_prev_signal = False
ema = ExponentialMovingAverage()
ema.Length = self.EmaPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema, self._process_candle).Start()
def _process_candle(self, candle, ema_value):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
open_price = float(candle.OpenPrice)
high = float(candle.HighPrice)
low = float(candle.LowPrice)
ema_val = float(ema_value)
body = abs(close - open_price)
range_val = high - low
if range_val <= 0:
return
if body < range_val * 0.7:
return
bullish_signal = close > open_price and close > ema_val
bearish_signal = close < open_price and close < ema_val
crossed_up = bullish_signal and (not self._has_prev_signal or not self._was_bullish_signal)
crossed_down = bearish_signal and (not self._has_prev_signal or self._was_bullish_signal)
if crossed_up and self.Position <= 0:
self.BuyMarket()
elif crossed_down and self.Position >= 0:
self.SellMarket()
if bullish_signal or bearish_signal:
self._was_bullish_signal = bullish_signal
self._has_prev_signal = True
def CreateClone(self):
return one_price_sl_tp_strategy()