Diese Strategie überwacht den realisierten Gewinn und Verlust aller von der Strategie ausgeführten Trades. Wenn der aufgelaufene Gewinn einen benutzerdefinierten Schwellenwert überschreitet, schließt sie sofort alle offenen Positionen und storniert optional aktive Aufträge. Dasselbe Verhalten kann für Drawdowns aktiviert werden, indem ein Verlustlimit gesetzt wird.
Die Strategie analysiert keine Indikatoren oder Preisbewegungen. Stattdessen fungiert sie als Schutzschicht, die den Markt verlässt, sobald ein monetäres Ziel oder ein Stop-Niveau erreicht ist. Ein einfaches Kerzen-Abonnement wird nur für periodische Überprüfungen des aktuellen PnL-Werts verwendet.
Parameter
UseProfitToClose – Schließen durch Gewinnziel aktivieren oder deaktivieren. Standard: true.
ProfitToClose – Gewinnwert in Währungseinheiten, der einen vollständigen Ausstieg auslöst. Standard: 20.
UseLossToClose – Schließen durch Verlustlimit aktivieren oder deaktivieren. Standard: false.
LossToClose – Verlustwert in Währungseinheiten, der bei Überschreitung einen vollständigen Ausstieg auslöst. Standard: 100.
ClosePendingOrders – alle aktiven Aufträge beim Schließen von Positionen stornieren. Standard: true.
CandleType – Kerzentyp für periodische Überprüfungen. Standard: 1-Minuten-Zeitrahmen.
Handelslogik
Kerzen des ausgewählten Zeitrahmens abonnieren.
Bei jeder abgeschlossenen Kerze den aktuellen realisierten PnL berechnen.
Wenn der Gewinn größer oder gleich ProfitToClose ist, die gesamte Position schließen und optional ausstehende Aufträge stornieren.
Wenn die Verlustüberwachung aktiviert ist und der aktuelle PnL kleiner oder gleich -LossToClose ist, die gesamte Position schließen und optional ausstehende Aufträge stornieren.
Zusätzliche Hinweise
Die Strategie schließt nur die Position des zugeordneten Wertpapiers.
Ausstehende Aufträge werden mit der integrierten Methode CancelActiveOrders storniert.
Die Logik kann mit anderen Einstiegsstrategien kombiniert werden, um Gewinnmitnahmen oder Portfolioschutz zu implementieren.
Filter
Kategorie: Risikomanagement
Richtung: Beide
Indikatoren: Keine
Stops: Ja
Komplexität: Grundlegend
Zeitrahmen: Beliebig
Saisonalität: Nein
Neuronale Netze: Nein
Divergenz: Nein
Risikolevel: Mittel
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>
/// EMA crossover strategy with profit/loss exit targets.
/// </summary>
public class CloseAtProfitStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
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 CloseAtProfitStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 12)
.SetGreaterThanZero()
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 26)
.SetGreaterThanZero()
.SetDisplay("Slow EMA", "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;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
SubscribeCandles(CandleType).Bind(fast, slow, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev)
{
_prevFast = fast;
_prevSlow = slow;
_hasPrev = true;
return;
}
// Fast crosses above slow => buy
if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
// Fast crosses below slow => sell
else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevFast = fast;
_prevSlow = slow;
}
}
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 close_at_profit_strategy(Strategy):
def __init__(self):
super(close_at_profit_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 12) \
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 26) \
.SetDisplay("Slow EMA", "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._has_prev = False
@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(close_at_profit_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(close_at_profit_strategy, self).OnStarted2(time)
fast = ExponentialMovingAverage()
fast.Length = self.fast_period
slow = ExponentialMovingAverage()
slow.Length = self.slow_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast, slow, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def on_process(self, candle, fast, slow):
if candle.State != CandleStates.Finished:
return
if not self._has_prev:
self._prev_fast = fast
self._prev_slow = slow
self._has_prev = True
return
# Fast crosses above slow => buy
if self._prev_fast <= self._prev_slow and fast > slow and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Fast crosses below slow => sell
elif self._prev_fast >= self._prev_slow and fast < slow and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_fast = fast
self._prev_slow = slow
def CreateClone(self):
return close_at_profit_strategy()