Auf GitHub ansehen

Bollinger Band-Strategie für ausstehende Stopps

Überblick

Dieses Beispiel wandelt den ursprünglichen Expertenberater MQL „Bb_0_1“ in den hochrangigen StockSharp API um. Die Strategie überwacht ein Kerzenabonnement und verwendet Bollinger-Bänder, um den aktuellen Preis zu klammern. Wenn der Markt zwischen dem oberen und dem unteren Band liegt, platziert der Algorithmus dreischichtige Kauf-Stopp-Orders über dem Preis und dreischichtige Verkaufs-Stopp-Orders unter dem Preis. Jede Ebene ist mit individuellen Take-Profit-Abständen konfiguriert und nutzt dabei die gleiche Stopp-Referenz, die vom gegenüberliegenden Band übernommen wird.

Handelslogik

  • Abonnieren Sie den konfigurierten Zeitrahmen und berechnen Sie Bollinger Bänder mit dem gewünschten Zeitraum und der gewünschten Abweichung.
  • Geben Sie innerhalb des Handelsfensters (StartHour < Stunde < EndHour) und während der Preis zwischen den Bändern bleibt, ausstehende Aufträge auf:
    • Drei Kaufstopps auf dem aktuellen oberen Bandniveau mit um FirstTakeProfit, SecondTakeProfit und ThirdTakeProfit Preisschritten über dem Einstiegspunkt verschobenen Take-Profits.
    • Drei Verkaufsstopps auf dem aktuellen unteren Bandniveau mit gespiegelten Take-Profits unterhalb des Einstiegs.
    • Alle Einträge übernehmen das entgegengesetzte Band als anfänglichen Schutzstopp.
  • Ausstehende Aufträge werden automatisch neu registriert, wenn sich die Bänder dem Preis nähern, sodass die Aufträge den Indikatorumschlägen folgen.
  • Sobald eine Stop-Order ausgeführt wird, registriert die Strategie explizite Stop-Loss- und Take-Profit-Orders für das ausgeführte Volumen.
  • Der Trailing-Schutz ist optional: UseBandTrailingStop wählt das entgegengesetzte Band für das Trailing aus, andernfalls wird das mittlere Band (EMA) verwendet. Stopps fallen nur dann nach, wenn der Schlusskurs über den Einstiegspreis hinausgeht und der Indikatorwert ein besseres Niveau bietet.

Parameter

Name Beschreibung
CandleType Zeitrahmen, der für die Bollinger-Bandberechnungen verwendet wird.
BandPeriod Anzahl der von den Bands verwendeten Kerzen.
BandDeviation Standardabweichungsmultiplikator für die Bänder.
Volume Volumen jeder ausstehenden Ebene.
StartHour / EndHour Stündliches Handelsfenster (exklusive Grenzen).
FirstTakeProfit, SecondTakeProfit, ThirdTakeProfit Take-Profit-Abstände, ausgedrückt in Preisschritten für jede Ebene.
UseBandTrailingStop Wählen Sie die nachgestellte Referenz aus: gegenüberliegendes Band (true) oder Bollinger Mittellinie (false).

Hinweise zur Implementierung

  • Das Bestellvolumen spiegelt den ursprünglichen Expert Advisor wider, indem eine statische Größe (Volume) verwendet wird. Die risikobasierte Positionsgrößenbestimmung aus dem Code MQL ist nicht implementiert, da die Beispielumgebung StockSharp keinen Kontoverlauf bereitstellt.
  • Indikatorverschiebungsparameter aus dem MQL-Skript werden nicht angezeigt, da die hohe Ebene API bereits ausgerichtete Werte für die aktuelle Kerze liefert.
  • Schutzaufträge sind normale Stop- und Limit-Aufträge, die immer dann aktualisiert werden, wenn die bandbasierten Trailing-Bedingungen das Stop-Level verbessern.
using System;
using System.Collections.Generic;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Bollinger Band breakout strategy.
/// Buys when price closes above upper band, sells when price closes below lower band.
/// Exits at middle band.
/// </summary>
public class BollingerBandPendingStopsStrategy : Strategy
{
	private readonly StrategyParam<int> _bandPeriod;
	private readonly StrategyParam<decimal> _bandWidth;
	private readonly StrategyParam<DataType> _candleType;

	public int BandPeriod { get => _bandPeriod.Value; set => _bandPeriod.Value = value; }
	public decimal BandWidth { get => _bandWidth.Value; set => _bandWidth.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public BollingerBandPendingStopsStrategy()
	{
		_bandPeriod = Param(nameof(BandPeriod), 20)
			.SetDisplay("Band Period", "Bollinger bands period", "Indicators");

		_bandWidth = Param(nameof(BandWidth), 1m)
			.SetDisplay("Band Width", "Bollinger bands deviation", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); }

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

		var bb = new BollingerBands { Length = BandPeriod, Width = BandWidth };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(bb, ProcessCandle)
			.Start();
	}

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

		if (!value.IsFinal || value.IsEmpty)
			return;

		var bbVal = value.IsEmpty ? null : value as BollingerBandsValue;
		if (bbVal == null)
			return;

		var upper = bbVal.UpBand;
		var lower = bbVal.LowBand;
		var middle = bbVal.MovingAverage;

		if (upper == null || lower == null || middle == null)
			return;

		var close = candle.ClosePrice;

		// Breakout above upper band - buy
		if (close > upper.Value && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Breakout below lower band - sell
		else if (close < lower.Value && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
		// Exit at middle band
		else if (Position > 0 && close < middle.Value)
		{
			SellMarket();
		}
		else if (Position < 0 && close > middle.Value)
		{
			BuyMarket();
		}
	}
}