Auf GitHub ansehen

Strategie zum Schließen bei Gewinn

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

  1. Kerzen des ausgewählten Zeitrahmens abonnieren.
  2. Bei jeder abgeschlossenen Kerze den aktuellen realisierten PnL berechnen.
  3. Wenn der Gewinn größer oder gleich ProfitToClose ist, die gesamte Position schließen und optional ausstehende Aufträge stornieren.
  4. 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;
	}
}