Auf GitHub ansehen

Strategie zum Schließen nach Kapital-Prozentsatz

Diese Risikomanagement-Strategie überwacht das Portfolio-Kapital und schließt jede offene Position, wenn das Kapital über das aktuelle Guthaben multipliziert mit einem benutzerdefinierten Multiplikator steigt. Sie ist darauf ausgelegt, Gewinne zu sichern, sobald der Kontowert einen gewünschten Prozentsatz über dem Basiswert erreicht.

Die Strategie führt regelmäßige Überprüfungen mithilfe von Kerzen durch und generiert selbst keine Handelseinstiege; sie verwaltet lediglich eine bestehende Position. Nach dem Schließen wird der Referenzkontostand aktualisiert, sodass der Prozess für nachfolgende Trades wiederholt werden kann.

Details

  • Einstiegskriterien: Keine (verwaltet bestehende Position).
  • Long/Short: Beide Richtungen.
  • Ausstiegskriterien: Kapital größer als balance * EquityPercentFromBalance.
  • Stops: Nein.
  • Standardwerte:
    • EquityPercentFromBalance = 1.2m
    • CandleType = TimeSpan.FromMinutes(1)
  • Filter:
    • Kategorie: Risikomanagement
    • Richtung: Beide
    • Indikatoren: Keine
    • Stops: Nein
    • Komplexität: Grundlegend
    • Zeitrahmen: Intraday (1m)
    • Saisonalität: Nein
    • Neuronale Netze: Nein
    • Divergenz: Nein
    • Risikolevel: Niedrig
using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Closes position when equity exceeds balance by a given multiplier.
/// </summary>
public class CloseByEquityPercentStrategy : Strategy
{
	private readonly StrategyParam<decimal> _equityPercent;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _currentBalance;

	/// <summary>
	/// Equity to balance multiplier.
	/// </summary>
	public decimal EquityPercentFromBalance
	{
		get => _equityPercent.Value;
		set => _equityPercent.Value = value;
	}

	/// <summary>
	/// Candle type for periodic checks.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Initializes a new instance of <see cref="CloseByEquityPercentStrategy"/>.
	/// </summary>
	public CloseByEquityPercentStrategy()
	{
		_equityPercent = Param(nameof(EquityPercentFromBalance), 1.2m)
			.SetDisplay("Equity/Bal Multiplier", "Threshold multiplier for equity relative to balance", "Risk Management")
			
			.SetOptimize(1.1m, 2m, 0.1m);

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles for periodic checks", "General");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_currentBalance = 0m;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_currentBalance = Portfolio?.CurrentValue ?? 0m;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle)
	{
		if (candle.State != CandleStates.Finished)
			return;

		var equity = Portfolio?.CurrentValue ?? 0m;

		if (equity > _currentBalance * EquityPercentFromBalance)
		{
			if (Position > 0)
				SellMarket(Position);
			else if (Position < 0)
				BuyMarket(-Position);

			_currentBalance = equity;
			return;
		}

		// Simple entry when flat
		if (Position == 0)
		{
			_currentBalance = equity;
			if (candle.ClosePrice > candle.OpenPrice)
				BuyMarket();
			else if (candle.ClosePrice < candle.OpenPrice)
				SellMarket();
		}
	}
}