Auf GitHub ansehen

Strategie Bollinger Supertrend

Diese Strategie kombiniert Bollinger Bands mit dem Supertrend-Indikator, um Einstiege während starker gerichteter Bewegungen zu identifizieren. Bollinger Bands messen die Volatilitätsausdehnung, während die Supertrend-Linie den übergeordneten Trend verfolgt und als Trailing-Stop fungiert.

Tests zeigen eine durchschnittliche Jahresrendite von etwa 79%. Sie funktioniert am besten auf dem Aktienmarkt.

Ein Long-Trade wird ausgelöst, wenn der Preis über dem oberen Bollinger Band schließt und über der Supertrend-Linie bleibt, was Momentum und Trendausrichtung bestätigt. Ein Short-Trade tritt auf, wenn der Preis unter dem unteren Band schließt und unter dem Supertrend-Level bleibt. Trades werden geschlossen, sobald der Preis zurück durch den Supertrend kreuzt, was darauf hindeutet, dass das Momentum nachgelassen hat.

Da das System auf Ausbrüche jenseits der normalen Volatilität wartet, eignet es sich für Trader, die anhaltende Bewegungen statt schnelle Umkehrungen erfassen möchten. Der Supertrend-Stop passt sich dynamisch an Marktschwankungen an und hilft, das Risiko ohne manuelle Eingriffe zu managen.

Details

  • Einstiegskriterien:
    • Long: Close > upper Bollinger Band && Close > Supertrend
    • Short: Close < lower Bollinger Band && Close < Supertrend
  • Long/Short: Beide Seiten.
  • Ausstiegskriterien:
    • Long: Ausstieg, wenn der Preis unter den Supertrend fällt
    • Short: Ausstieg, wenn der Preis über den Supertrend steigt
  • Stops: Ja, über Supertrend Trailing-Stop.
  • Standardwerte:
    • BollingerPeriod = 20
    • BollingerDeviation = 2.0m
    • SupertrendPeriod = 10
    • SupertrendMultiplier = 3.0m
    • CandleType = TimeSpan.FromMinutes(15)
  • Filter:
    • Kategorie: Trend
    • Richtung: Beide
    • Indikatoren: Bollinger Bands, Supertrend
    • Stops: Ja
    • Komplexität: Mittel
    • Zeitrahmen: Intraday
    • Saisonalität: Nein
    • Neuronale Netze: Nein
    • Divergenz: Nein
    • Risikolevel: Mittel
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>
/// Strategy based on Bollinger Bands and Supertrend indicators.
/// Enters long when price breaks above upper Bollinger Band and is above Supertrend.
/// Enters short when price breaks below lower Bollinger Band and is below Supertrend.
/// Uses Supertrend for dynamic exit.
/// </summary>
public class BollingerSupertrendStrategy : Strategy
{
	private readonly StrategyParam<int> _bollingerPeriod;
	private readonly StrategyParam<decimal> _bollingerDeviation;
	private readonly StrategyParam<int> _supertrendPeriod;
	private readonly StrategyParam<decimal> _supertrendMultiplier;
	private readonly StrategyParam<int> _cooldownBars;
	private readonly StrategyParam<DataType> _candleType;
	
	private BollingerBands _bollinger;
	private AverageTrueRange _atr;
	
	private bool _isLongTrend;
	private decimal _supertrendValue;
	private decimal _lastClose;
	private int _cooldown;
	
	/// <summary>
	/// Bollinger Bands period.
	/// </summary>
	public int BollingerPeriod
	{
		get => _bollingerPeriod.Value;
		set => _bollingerPeriod.Value = value;
	}
	
	/// <summary>
	/// Bollinger Bands standard deviation multiplier.
	/// </summary>
	public decimal BollingerDeviation
	{
		get => _bollingerDeviation.Value;
		set => _bollingerDeviation.Value = value;
	}
	
	/// <summary>
	/// Supertrend ATR period.
	/// </summary>
	public int SupertrendPeriod
	{
		get => _supertrendPeriod.Value;
		set => _supertrendPeriod.Value = value;
	}
	
	/// <summary>
	/// Supertrend ATR multiplier.
	/// </summary>
	public decimal SupertrendMultiplier
	{
		get => _supertrendMultiplier.Value;
		set => _supertrendMultiplier.Value = value;
	}
	
	/// <summary>
	/// Bars to wait between trades.
	/// </summary>
	public int CooldownBars
	{
		get => _cooldownBars.Value;
		set => _cooldownBars.Value = value;
	}

	/// <summary>
	/// Candle type parameter.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}
	
	/// <summary>
	/// Constructor.
	/// </summary>
	public BollingerSupertrendStrategy()
	{
		_bollingerPeriod = Param(nameof(BollingerPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("Bollinger Period", "Period for Bollinger Bands calculation", "Indicators")
			
			.SetOptimize(10, 30, 5);
			
		_bollingerDeviation = Param(nameof(BollingerDeviation), 2.0m)
			.SetGreaterThanZero()
			.SetDisplay("Bollinger Deviation", "Standard deviation multiplier for Bollinger Bands", "Indicators")
			
			.SetOptimize(1.5m, 3.0m, 0.5m);
			
		_supertrendPeriod = Param(nameof(SupertrendPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Supertrend Period", "ATR period for Supertrend calculation", "Indicators")
			
			.SetOptimize(7, 14, 1);
			
		_supertrendMultiplier = Param(nameof(SupertrendMultiplier), 3.0m)
			.SetGreaterThanZero()
			.SetDisplay("Supertrend Multiplier", "ATR multiplier for Supertrend calculation", "Indicators")
			
			.SetOptimize(2.0m, 4.0m, 0.5m);

		_cooldownBars = Param(nameof(CooldownBars), 60)
			.SetRange(1, 200)
			.SetDisplay("Cooldown Bars", "Bars between trades", "General");
			
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).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();

		_bollinger = null;
		_atr = null;
		_isLongTrend = default;
		_supertrendValue = default;
		_lastClose = default;
		_cooldown = 0;
	}

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

// Initialize indicators
		_bollinger = new BollingerBands
	{
Length = BollingerPeriod,
Width = BollingerDeviation
	};
		
		_atr = new AverageTrueRange
		{
			Length = SupertrendPeriod
		};
		
		// Create candles subscription
		var subscription = SubscribeCandles(CandleType);
		
		// Bind Bollinger indicator to candle subscription
		subscription
			.BindEx(_bollinger, _atr, ProcessCandle)
			.Start();
		
		// Setup chart if available
		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, _bollinger);
			DrawOwnTrades(area);
		}
	}
	
	private void ProcessCandle(ICandleMessage candle, IIndicatorValue bollingerValue, IIndicatorValue atrValue)
	{
		// Skip unfinished candles
		if (candle.State != CandleStates.Finished)
			return;
			
		// Extract Bollinger Band values
		var bb = (BollingerBandsValue)bollingerValue;
		if (bb.MovingAverage is not decimal middleBand)
			return;
		if (bb.UpBand is not decimal upperBand)
			return;
		if (bb.LowBand is not decimal lowerBand)
			return;

		// Calculate Supertrend
		// Note: This is a simplified Supertrend implementation
		decimal atrValue2 = atrValue.ToDecimal() * SupertrendMultiplier;
		decimal upperBand2 = (candle.HighPrice + candle.LowPrice) / 2 + atrValue2;
		decimal lowerBand2 = (candle.HighPrice + candle.LowPrice) / 2 - atrValue2;
		
		// Determine Supertrend value and direction
		if (_lastClose == 0)
		{
			// First candle initialization
			_supertrendValue = candle.ClosePrice > (candle.HighPrice + candle.LowPrice) / 2 ? 
				lowerBand2 : upperBand2;
			_isLongTrend = candle.ClosePrice > _supertrendValue;
		}
		else
		{
			// Calculate Supertrend
			if (_isLongTrend)
			{
				// Previous trend was up
				if (candle.ClosePrice < _supertrendValue)
				{
					// Trend changes to down
					_isLongTrend = false;
					_supertrendValue = upperBand2;
				}
				else
				{
					// Trend remains up, adjust supertrend value
					_supertrendValue = Math.Max(lowerBand2, _supertrendValue);
				}
			}
			else
			{
				// Previous trend was down
				if (candle.ClosePrice > _supertrendValue)
				{
					// Trend changes to up
					_isLongTrend = true;
					_supertrendValue = lowerBand2;
				}
				else
				{
					// Trend remains down, adjust supertrend value
					_supertrendValue = Math.Min(upperBand2, _supertrendValue);
				}
			}
		}
		
		_lastClose = candle.ClosePrice;
		
		// Trading logic
		bool isPriceAboveSupertrend = candle.ClosePrice > _supertrendValue;
		bool isPriceAboveUpperBand = candle.ClosePrice > upperBand;
		bool isPriceBelowLowerBand = candle.ClosePrice < lowerBand;
		if (_cooldown > 0)
			_cooldown--;
		
		// Long signal: Price breaks above upper Bollinger Band and is above Supertrend
		if (_cooldown == 0 && isPriceAboveUpperBand && isPriceAboveSupertrend)
		{
			if (Position <= 0)
			{
				BuyMarket();
				_cooldown = CooldownBars;
			}
		}
		// Short signal: Price breaks below lower Bollinger Band and is below Supertrend
		else if (_cooldown == 0 && isPriceBelowLowerBand && !isPriceAboveSupertrend)
		{
			if (Position >= 0)
			{
				SellMarket();
				_cooldown = CooldownBars;
			}
		}
		// Exit signals based on Supertrend
		else if ((Position > 0 && !isPriceAboveSupertrend) || 
				(Position < 0 && isPriceAboveSupertrend))
		{
			if (Position > 0)
			{
				SellMarket();
				_cooldown = CooldownBars;
			}
			else if (Position < 0)
			{
				BuyMarket();
				_cooldown = CooldownBars;
			}
		}
	}
}