Auf GitHub ansehen

Ausbruch-Strategie

Diese Strategie handelt auf Basis einfacher gleitender Durchschnitte der Kerzen-Eröffnungspreise. Sie vergleicht den letzten 5-Minuten-Schlusskurs mit zwei gleitenden Durchschnitten, die auf dem Eröffnungspreis berechnet werden:

  • Schneller SMA (4 Perioden) – wird als Schwellenwert für Short-Einstiege verwendet.
  • Langsamer SMA (5 Perioden) – wird als Schwellenwert für Long-Einstiege verwendet.

Funktionsweise

  1. Bei jeder abgeschlossenen 5-Minuten-Kerze aktualisiert die Strategie zwei SMAs des Kerzen-Eröffnungspreises.
  2. Wenn keine aktive Position vorhanden ist:
    • Long einsteigen, wenn der letzte Schlusskurs unter dem langsamen SMA liegt.
    • Short einsteigen, wenn der letzte Schlusskurs über dem schnellen SMA liegt.
  3. Nach dem Einstieg setzt die Strategie feste Stop-Loss- und Take-Profit-Niveaus in Preiseinheiten.
  4. Die Position wird geschlossen, wenn Take-Profit oder Stop-Loss erreicht wird.

Die Logik verwendet die StockSharp High-Level-API und ist für Bildungszwecke gedacht.

Parameter

Name Beschreibung Standard
FastLength Periode des schnellen SMA. 4
SlowLength Periode des langsamen SMA. 5
TakeProfitLong Take-Profit-Abstand für Long-Trades in Preiseinheiten. 25
TakeProfitShort Take-Profit-Abstand für Short-Trades in Preiseinheiten. 26
StopLossLong Stop-Loss-Abstand für Long-Trades in Preiseinheiten. 25
StopLossShort Stop-Loss-Abstand für Short-Trades in Preiseinheiten. 3
CandleType Kerzentyp für die Analyse. TimeFrame(5m)

Alle Parameter können über den StockSharp-Optimierer optimiert werden.

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>
/// Simple strategy based on SMA of open prices and previous close comparison.
/// Buys when the previous close is below the slow SMA.
/// Sells short when the previous close is above the fast SMA.
/// Uses fixed take profit and stop loss levels for both directions.
/// </summary>
public class EscapeStrategy : Strategy
{
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<decimal> _takeProfitLong;
	private readonly StrategyParam<decimal> _takeProfitShort;
	private readonly StrategyParam<decimal> _stopLossLong;
	private readonly StrategyParam<decimal> _stopLossShort;
	private readonly StrategyParam<DataType> _candleType;

	private SimpleMovingAverage _fastMa;
	private SimpleMovingAverage _slowMa;
	private bool _initialized;
	private decimal _previousClose;
	private decimal _previousFast;
	private decimal _previousSlow;

	/// <summary>
	/// Length of fast SMA.
	/// </summary>
	public int FastLength
	{
		get => _fastLength.Value;
		set => _fastLength.Value = value;
	}

	/// <summary>
	/// Length of slow SMA.
	/// </summary>
	public int SlowLength
	{
		get => _slowLength.Value;
		set => _slowLength.Value = value;
	}

	/// <summary>
	/// Take profit distance for long positions in price units.
	/// </summary>
	public decimal TakeProfitLong
	{
		get => _takeProfitLong.Value;
		set => _takeProfitLong.Value = value;
	}

	/// <summary>
	/// Take profit distance for short positions in price units.
	/// </summary>
	public decimal TakeProfitShort
	{
		get => _takeProfitShort.Value;
		set => _takeProfitShort.Value = value;
	}

	/// <summary>
	/// Stop loss distance for long positions in price units.
	/// </summary>
	public decimal StopLossLong
	{
		get => _stopLossLong.Value;
		set => _stopLossLong.Value = value;
	}

	/// <summary>
	/// Stop loss distance for short positions in price units.
	/// </summary>
	public decimal StopLossShort
	{
		get => _stopLossShort.Value;
		set => _stopLossShort.Value = value;
	}

	/// <summary>
	/// Candle type to analyze.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public EscapeStrategy()
	{
		_fastLength = Param(nameof(FastLength), 4)
			.SetDisplay("Fast SMA Length", "Length of fast SMA", "Parameters")
			.SetGreaterThanZero()
			;

		_slowLength = Param(nameof(SlowLength), 5)
			.SetDisplay("Slow SMA Length", "Length of slow SMA", "Parameters")
			.SetGreaterThanZero()
			;

		_takeProfitLong = Param(nameof(TakeProfitLong), 25m)
			.SetDisplay("Take Profit Long", "Take profit for long trades", "Trading")
			.SetGreaterThanZero();

		_takeProfitShort = Param(nameof(TakeProfitShort), 26m)
			.SetDisplay("Take Profit Short", "Take profit for short trades", "Trading")
			.SetGreaterThanZero();

		_stopLossLong = Param(nameof(StopLossLong), 25m)
			.SetDisplay("Stop Loss Long", "Stop loss for long trades", "Trading")
			.SetGreaterThanZero();

		_stopLossShort = Param(nameof(StopLossShort), 3m)
			.SetDisplay("Stop Loss Short", "Stop loss for short trades", "Trading")
			.SetGreaterThanZero();

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

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

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

		_fastMa = null;
		_slowMa = null;
		_initialized = false;
		_previousClose = 0m;
		_previousFast = 0m;
		_previousSlow = 0m;
	}

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

		_fastMa = new SMA { Length = FastLength };
		_slowMa = new SMA { Length = SlowLength };

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

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

		StartProtection(
			takeProfit: new Unit(2, UnitTypes.Percent),
			stopLoss: new Unit(1, UnitTypes.Percent)
		);
	}

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

		var fast = _fastMa!.Process(new DecimalIndicatorValue(_fastMa, candle.OpenPrice, candle.OpenTime) { IsFinal = true }).ToDecimal();
		var slow = _slowMa!.Process(new DecimalIndicatorValue(_slowMa, candle.OpenPrice, candle.OpenTime) { IsFinal = true }).ToDecimal();

		if (!_initialized)
		{
			_initialized = true;
			_previousClose = candle.ClosePrice;
			_previousFast = fast;
			_previousSlow = slow;
			return;
		}

		var close = candle.ClosePrice;
		var buySignal = _previousClose >= _previousSlow && close < slow;
		var sellSignal = _previousClose <= _previousFast && close > fast;

		if (Position == 0)
		{
			if (buySignal)
				BuyMarket();
			else if (sellSignal)
				SellMarket();
		}

		_previousClose = close;
		_previousFast = fast;
		_previousSlow = slow;
	}
}