Auf GitHub ansehen

Disturbed-Strategie

Diese Absicherungsstrategie eröffnet gleichzeitig Long- und Short-Marktorders und verwaltet sie anhand des aktuellen Spreads. Sobald sich der Preis um einen Spread gegen eine der Seiten bewegt, wird diese Position geschlossen. Die verbleibende Position zielt dann auf einen Gewinn oder Verlust in Höhe eines konfigurierbaren Vielfachen des Spreads ab.

Details

  • Einstiegskriterien:
    • Beim Start werden gleichzeitig Kauf- und Verkaufs-Marktorders platziert.
  • Long/Short: Beide gleichzeitig.
  • Ausstiegskriterien:
    • Schließen der Seite, die einen Spread verliert.
    • Schließen der verbleibenden Seite bei gainMultiplier * spread Gewinn oder Verlust.
  • Stops: Implizit über spreadbasierte Niveaus.
  • Filter: Keine.
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>
/// Hedging-style strategy using EMA crossover with ATR-based mean reversion.
/// </summary>
public class DisturbedStrategy : Strategy
{
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _atrPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevEma;
	private bool _hasPrev;

	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public int AtrPeriod { get => _atrPeriod.Value; set => _atrPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public DisturbedStrategy()
	{
		_emaPeriod = Param(nameof(EmaPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA period", "Indicators");
		_atrPeriod = Param(nameof(AtrPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("ATR Period", "ATR 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();
		_prevEma = 0; _hasPrev = false;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var atr = new StandardDeviation { Length = AtrPeriod };

		SubscribeCandles(CandleType).Bind(ema, atr, ProcessCandle).Start();
	}

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

		if (!_hasPrev) { _prevEma = ema; _hasPrev = true; return; }

		var close = candle.ClosePrice;

		// Price crosses above EMA + ATR => buy
		if (close > ema + atr && _prevEma > 0 && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		// Price crosses below EMA - ATR => sell
		else if (close < ema - atr && _prevEma > 0 && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}
		// Exit long when price returns to EMA
		else if (Position > 0 && close <= ema)
		{
			SellMarket();
		}
		// Exit short when price returns to EMA
		else if (Position < 0 && close >= ema)
		{
			BuyMarket();
		}

		_prevEma = ema;
	}
}