Drag SL/TP Manager-Strategie
Diese Strategie platziert automatisch Stop-Loss- und Take-Profit-Orders in einem festen Abstand vom ausgeführten Handelspreis. Sie ist nützlich, wenn manuelle Positionen unmittelbar nach dem Einstieg abgesichert werden sollen.
Parameter
- Auto Set SL (
bool): automatische Stop-Loss-Platzierung aktivieren. - SL Points (
decimal): Stop-Loss-Abstand in Preisschritten. - Auto Set TP (
bool): automatische Take-Profit-Platzierung aktivieren. - TP Points (
decimal): Take-Profit-Abstand in Preisschritten.
Verhalten
Beim Start der Strategie wird StartProtection mit den gewählten Abständen aufgerufen. Jede Position, die während der Laufzeit der Strategie eröffnet wird, erhält sofort die entsprechenden Schutzorders. Die Abstände werden in Preisschritten gemessen (Security.PriceStep).
Die Strategie selbst erzeugt keine Handelssignale; sie verwaltet lediglich Schutzorders für Positionen, die manuell oder durch andere Strategien eröffnet wurden.
Hinweise
- Entwickelt für die Nutzung mit der High-Level-API.
- Nur der abgeschlossene Kerzenstatus sollte in erweiterten Versionen Handelsaktionen auslösen.
- Die grafische Drag-Funktion aus dem ursprünglichen MQL-Skript ist nicht implementiert.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy that uses EMA crossover for entries with stop-loss and take-profit.
/// </summary>
public class DragSlTpStrategy : Strategy
{
private readonly StrategyParam<decimal> _slPoints;
private readonly StrategyParam<decimal> _tpPoints;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _isInitialized;
private decimal _entryPrice;
public decimal SlPoints { get => _slPoints.Value; set => _slPoints.Value = value; }
public decimal TpPoints { get => _tpPoints.Value; set => _tpPoints.Value = value; }
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public DragSlTpStrategy()
{
_slPoints = Param(nameof(SlPoints), 500m)
.SetGreaterThanZero()
.SetDisplay("SL Points", "Stop-loss distance", "Risk");
_tpPoints = Param(nameof(TpPoints), 1000m)
.SetGreaterThanZero()
.SetDisplay("TP Points", "Take-profit distance", "Risk");
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow EMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_isInitialized = false;
_entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fastEma = new ExponentialMovingAverage { Length = FastPeriod };
var slowEma = new ExponentialMovingAverage { Length = SlowPeriod };
SubscribeCandles(CandleType)
.Bind(fastEma, slowEma, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished) return;
if (!_isInitialized)
{
_prevFast = fast;
_prevSlow = slow;
_isInitialized = true;
return;
}
var crossUp = _prevFast <= _prevSlow && fast > slow;
var crossDown = _prevFast >= _prevSlow && fast < slow;
_prevFast = fast;
_prevSlow = slow;
if (Position == 0)
{
if (crossUp)
{
BuyMarket();
_entryPrice = candle.ClosePrice;
}
else if (crossDown)
{
SellMarket();
_entryPrice = candle.ClosePrice;
}
}
else if (Position > 0)
{
var price = candle.ClosePrice;
if (price - _entryPrice >= TpPoints || _entryPrice - price >= SlPoints || crossDown)
{
SellMarket();
if (crossDown)
{
SellMarket();
_entryPrice = candle.ClosePrice;
}
}
}
else if (Position < 0)
{
var price = candle.ClosePrice;
if (_entryPrice - price >= TpPoints || price - _entryPrice >= SlPoints || crossUp)
{
BuyMarket();
if (crossUp)
{
BuyMarket();
_entryPrice = candle.ClosePrice;
}
}
}
}
}
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 drag_sl_tp_strategy(Strategy):
def __init__(self):
super(drag_sl_tp_strategy, self).__init__()
self._sl_points = self.Param("SlPoints", 500.0) \
.SetDisplay("SL Points", "Stop-loss distance", "Risk")
self._tp_points = self.Param("TpPoints", 1000.0) \
.SetDisplay("TP Points", "Take-profit distance", "Risk")
self._fast_period = self.Param("FastPeriod", 10) \
.SetDisplay("Fast Period", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 30) \
.SetDisplay("Slow Period", "Slow EMA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._is_initialized = False
self._entry_price = 0.0
@property
def sl_points(self):
return self._sl_points.Value
@property
def tp_points(self):
return self._tp_points.Value
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(drag_sl_tp_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._is_initialized = False
self._entry_price = 0.0
def OnStarted2(self, time):
super(drag_sl_tp_strategy, self).OnStarted2(time)
fast_ema = ExponentialMovingAverage()
fast_ema.Length = self.fast_period
slow_ema = ExponentialMovingAverage()
slow_ema.Length = self.slow_period
self.SubscribeCandles(self.candle_type).Bind(fast_ema, slow_ema, self.process_candle).Start()
def process_candle(self, candle, fast, slow):
if candle.State != CandleStates.Finished:
return
fv = float(fast)
sv = float(slow)
if not self._is_initialized:
self._prev_fast = fv
self._prev_slow = sv
self._is_initialized = True
return
cross_up = self._prev_fast <= self._prev_slow and fv > sv
cross_down = self._prev_fast >= self._prev_slow and fv < sv
self._prev_fast = fv
self._prev_slow = sv
tp = float(self.tp_points)
sl = float(self.sl_points)
price = float(candle.ClosePrice)
if self.Position == 0:
if cross_up:
self.BuyMarket()
self._entry_price = price
elif cross_down:
self.SellMarket()
self._entry_price = price
elif self.Position > 0:
if price - self._entry_price >= tp or self._entry_price - price >= sl or cross_down:
self.SellMarket()
if cross_down:
self.SellMarket()
self._entry_price = price
elif self.Position < 0:
if self._entry_price - price >= tp or price - self._entry_price >= sl or cross_up:
self.BuyMarket()
if cross_up:
self.BuyMarket()
self._entry_price = price
def CreateClone(self):
return drag_sl_tp_strategy()