Auf GitHub ansehen

Modifizierte Bollinger-Bands-Strategie

Strategie, die Bollinger-Bands-Ausbrüche mit einem optionalen EMA-Trendfilter handelt. Geht long, wenn der Preis über das obere Band kreuzt, und short, wenn er unter das untere Band kreuzt.

Der Stop Loss wird beim jüngsten Hoch oder Tief platziert, und das Take Profit ist ein Vielfaches des Risikos.

Details

  • Einstiegskriterien:
    • Long: Preis kreuzt über das obere Bollinger Band
    • Short: Preis kreuzt unter das untere Bollinger Band
  • Long/Short: Beide
  • Ausstiegskriterien:
    • Long: Stop beim jüngsten Tief, Ziel bei Risiko * Faktor
    • Short: Stop beim jüngsten Hoch, Ziel bei Risiko * Faktor
  • Stops: Höchst-/Tiefstwert der letzten N Kerzen
  • Standardwerte:
    • BollingerLength = 20
    • BollingerDeviation = 0.38m
    • EmaLength = 80
    • HighestLength = 7
    • LowestLength = 7
    • TargetFactor = 1.6m
    • EmaTrend = true
    • CrossoverCheck = false
    • CrossunderCheck = false
    • CandleType = TimeSpan.FromMinutes(5).TimeFrame()
  • Filter:
    • Kategorie: Trend
    • Richtung: Beide
    • Indikatoren: Bollinger Bands, EMA, Highest, Lowest
    • Stops: Ja
    • Komplexität: Anfänger
    • Zeitrahmen: Mittelfristig
    • Saisonalität: Nein
    • Neuronale Netze: Nein
    • Divergenz: Nein
    • Risikolevel: Mittel
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>
/// BollingerBandsModifiedStrategy using EMA crossover for trend timing.
/// Enters long on golden cross, short on death cross.
/// </summary>
public class BollingerBandsModifiedStrategy : 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 BollingerBandsModifiedStrategy()
	{
		_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", "Type of candles to use", "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;
		}

		if (_prevFastEma <= _prevSlowEma && fastEmaValue > slowEmaValue && Position <= 0)
		{
			BuyMarket();
		}
		else if (_prevFastEma >= _prevSlowEma && fastEmaValue < slowEmaValue && Position >= 0)
		{
			SellMarket();
		}

		_prevFastEma = fastEmaValue;
		_prevSlowEma = slowEmaValue;
	}
}