Auf GitHub ansehen

BADX ADX Bollinger-Strategie

Übersicht

Diese Strategie reproduziert den MetaTrader-BADX-Expertenberater unter Verwendung der StockSharp High-Level-API. Sie kombiniert den Average Directional Index (ADX) mit Bollinger Bands, um Range-Bedingungen zu handeln: Wenn der ADX unter einen konfigurierbaren Schwellenwert fällt und der Preis das äußere Band berührt, faded die Strategie die Bewegung in Erwartung einer Mean Reversion. Alle Schutzorders, einschließlich Stop-Loss, Take-Profit und optionalem Trailing-Stop, werden automatisch durch StartProtection verwaltet.

Funktionsweise

  1. Abonniert die konfigurierte Kerzenserie und fügt sowohl einen AverageDirectionalIndex als auch einen BollingerBands-Indikator über High-Level-Bindings ein.
  2. Für jede abgeschlossene Kerze erhält der Callback den ADX-Wert sowie die obere und untere Bollinger-Hülle.
  3. Wenn der ADX unter AdxLevel liegt, gilt der Markt als trendlos:
    • Wenn der Schlusskurs unterhalb des unteren Bandes liegt und keine offene Position vorhanden ist, kauft die Strategie zum Marktpreis.
    • Wenn der Schlusskurs oberhalb des oberen Bandes liegt und keine offene Position vorhanden ist, verkauft die Strategie zum Marktpreis.
  4. Das Risikomanagement wandelt Pip-Abstände in absolute Preis-Offsets um. Stop-Loss, Take-Profit und Trailing-Parameter (falls aktiviert) werden unmittelbar nach Einstiegen über den Schutzmanager angewendet.
  5. Es kann immer nur eine Position aktiv sein. Ausstiege erfolgen durch Schutzorders oder Trailing-Stop-Anpassungen.

Parameter

  • CandleType (DataType): Zeitrahmen für Indikatorberechnungen. Standard: 15-Minuten-Kerzen.
  • AdxPeriod (int): Mittelungsperiode für den ADX-Indikator. Standard: 30.
  • AdxLevel (decimal): Maximaler ADX-Wert, der noch als Ranging-Markt gilt. Standard: 20.
  • BollingerPeriod (int): Periode für den gleitenden Durchschnitt der Bollinger Bands. Standard: 10.
  • BollingerDeviation (decimal): Standardabweichungs-Multiplikator für die Bollinger Bands. Standard: 1.5.
  • StopLossPips (decimal): Stop-Loss-Abstand in Pips. Standard: 50.
  • TakeProfitPips (decimal): Take-Profit-Abstand in Pips. Standard: 50.
  • TrailingStopPips (decimal): Trailing-Stop-Abstand in Pips. Standard: 5.
  • TrailingStepPips (decimal): Minimale Preisverbesserung in Pips, bevor der Trailing-Stop angepasst wird. Standard: 5.

Verwendung

  1. Die Strategie einem Wertpapier zuordnen und die Parameter nach Wunsch konfigurieren.
  2. Strategie starten. Sie abonniert automatisch den benötigten Kerzenstrom, baut die Indikatoren auf und richtet Schutzorders ein.
  3. Trades im Chart-Bereich überwachen: Kerzen, die Bollinger Bands und ausgeführte Orders werden visualisiert, wenn die Plattform Charting unterstützt.
  4. Risikoparameter (Stop-Loss, Take-Profit, Trailing-Abstände) an die Instrument-Volatilität oder persönliche Präferenzen anpassen.

Hinweise

  • Nur abgeschlossene Kerzen werden verarbeitet, um vorzeitige Einstiege zu vermeiden.
  • Die Pip-Größe wird aus dem PriceStep des Instruments abgeleitet; wenn das Instrument 3 oder 5 Dezimalstellen verwendet, wird der Pip um den Faktor zehn angepasst, was den ursprünglichen Expertenberater nachahmt.
  • Die Strategie hält Volume standardmäßig auf 1. Die Volume-Eigenschaft der Basisklasse anpassen, um die bevorzugte Handelsgröße zu erreichen.
  • Alle Inline-Kommentare im Quellcode sind gemäß den Repository-Richtlinien auf Englisch verfasst.
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>
/// BADX ADX Bollinger strategy using EMA crossover.
/// Buys when fast EMA crosses above slow EMA, sells on reverse.
/// </summary>
public class BadxAdxBollingerStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private ExponentialMovingAverage _fast;
	private ExponentialMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _cooldown;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
	public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }

	public BadxAdxBollingerStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
		_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
		_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_fast = null; _slow = null;
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_fast = new ExponentialMovingAverage { Length = FastPeriod };
		_slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
		subscription.Bind(_fast, _slow, ProcessCandle);
		subscription.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
		if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }

		var close = candle.ClosePrice;
		var step = Security?.PriceStep ?? 1m;

		if (Position > 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}
		else if (Position < 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}

		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }

		_prevFast = fastValue; _prevSlow = slowValue;
	}
}