Auf GitHub ansehen

Einfache Trailing-Stop-Strategie

Dieses Beispiel zeigt, wie man eine offene Position mit einem Trailing Stop mithilfe der High-Level-API von StockSharp verwaltet.

Überblick

  • Eröffnet eine einzelne Long-Position nach Erhalt der ersten abgeschlossenen Kerze.
  • Aktiviert den Positionsschutz mit einem Trailing Stop.
  • Der Stop-Preis folgt dem aktuellen Preis in einem festen Abstand.

Parameter

  • TrailPoints – Abstand in Kurseinheiten, der für den Trailing Stop verwendet wird.
  • CandleType – Art der von der Strategie verarbeiteten Kerzen.

Logik

  1. Beim Start abonniert die Strategie Kerzen und aktiviert StartProtection mit Trailing.
  2. Nach der ersten abgeschlossenen Kerze kauft die Strategie zum Marktpreis.
  3. Wenn sich der Preis zugunsten der Position bewegt, wird das Stop-Level verschoben, um den durch TrailPoints definierten Abstand beizubehalten.
  4. Wenn der Preis umkehrt und den Trailing Stop erreicht, wird die Position automatisch geschlossen.

Die Strategie ist vereinfacht und soll die grundlegende Verwendung des Trailing Stops zeigen.

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>
/// Simple trailing stop strategy.
/// Uses EMA crossover for entries with a trailing stop for protection.
/// </summary>
public class SimpleTrailingStopStrategy : Strategy
{
	private readonly StrategyParam<decimal> _trailPercent;
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<DataType> _candleType;

	public decimal TrailPercent { get => _trailPercent.Value; set => _trailPercent.Value = value; }
	public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
	public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public SimpleTrailingStopStrategy()
	{
		_trailPercent = Param(nameof(TrailPercent), 2m)
			.SetDisplay("Trail %", "Trailing stop distance as percentage", "Protection");

		_fastLength = Param(nameof(FastLength), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicator");

		_slowLength = Param(nameof(SlowLength), 30)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicator");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(8).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles", "General");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
	}

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

		StartProtection(
			takeProfit: null,
			stopLoss: new Unit(TrailPercent, UnitTypes.Percent),
			isStopTrailing: true,
			useMarketOrders: true);

		var fast = new ExponentialMovingAverage { Length = FastLength };
		var slow = new ExponentialMovingAverage { Length = SlowLength };

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

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

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

		if (fastVal > slowVal && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (fastVal < slowVal && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}
	}
}