Auf GitHub ansehen

Strategie zum Erfassen großer Kursbewegungen

Diese Strategie geht Long, wenn der Preis über dem oberen Bollinger Band schließt und alle aktivierten Filter die Bewegung bestätigen. Sie kann auch Short gehen, wenn der Preis unter dem unteren Band schließt. Zu den Filtern gehören RSI, ADX, ATR, EMA-Trendrichtung und MACD. Es wird ein fester prozentualer Stop-Loss angewendet, Positionen werden geschlossen, wenn der Preis zum mittleren Band zurückkehrt, und ein optionaler Zwangsgewinn schließt bei ungewöhnlich großen Kerzen.

Details

  • Einstiegskriterien:
    • Long: Schlusskurs > oberes Bollinger Band und alle aktiven Filter bestanden.
    • Short: Schlusskurs < unteres Bollinger Band und alle aktiven Filter bestanden.
  • Long/Short: Beide (konfigurierbar).
  • Ausstiegskriterien:
    • Preis kreuzt das mittlere Bollinger Band.
    • Optionaler Zwangsgewinn bei großen Kerzen.
  • Stops: Fester prozentualer Stop-Loss.
  • Standardwerte: Bollinger-Länge = 40, Stop-Loss = 2%, Zwangsgewinn-Schwellenwert = 5%.
  • Filter: RSI (14), ADX (28), ATR (14), EMA (350), MACD (12,26,9).
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>
/// Big Mover Catcher strategy using Bollinger Band breakout with EMA trend filter.
/// Enters long when price breaks above upper band and fast EMA > slow EMA.
/// Enters short when price breaks below lower band and fast EMA &lt; slow EMA.
/// Exits on EMA crossover reversal.
/// </summary>
public class BigMoverCatcherStrategy : Strategy
{
	private readonly StrategyParam<int> _fastEmaPeriod;
	private readonly StrategyParam<int> _slowEmaPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFastEma;
	private decimal _prevSlowEma;

	public int FastEmaPeriod { get => _fastEmaPeriod.Value; set => _fastEmaPeriod.Value = value; }
	public int SlowEmaPeriod { get => _slowEmaPeriod.Value; set => _slowEmaPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public BigMoverCatcherStrategy()
	{
		_fastEmaPeriod = Param(nameof(FastEmaPeriod), 120)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowEmaPeriod = Param(nameof(SlowEmaPeriod), 450)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");

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

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

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

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

		var fastEma = new ExponentialMovingAverage { Length = FastEmaPeriod };
		var slowEma = new ExponentialMovingAverage { Length = SlowEmaPeriod };

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

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

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

		if (_prevFastEma == 0m || _prevSlowEma == 0m)
		{
			_prevFastEma = fastEmaValue;
			_prevSlowEma = slowEmaValue;
			return;
		}

		// Buy on golden cross
		if (_prevFastEma <= _prevSlowEma && fastEmaValue > slowEmaValue && Position <= 0)
		{
			BuyMarket();
		}
		// Sell on death cross
		else if (_prevFastEma >= _prevSlowEma && fastEmaValue < slowEmaValue && Position >= 0)
		{
			SellMarket();
		}

		_prevFastEma = fastEmaValue;
		_prevSlowEma = slowEmaValue;
	}
}