Auf GitHub ansehen

Strategie Bread and Butter 2 (ADX + AMA)

Überblick

Diese Strategie ist eine Portierung des MetaTrader 5 Expert Advisors Breadandbutter2 von Ron Thompson. Die ursprüngliche Logik wartet auf eine neue Bar, vergleicht den letzten Average Directional Index (ADX)-Wert mit dem vorherigen, und prüft, ob der Kaufman Adaptive Moving Average (KAMA, auch als AMA bekannt) steigt oder fällt. Eine Long-Position wird eröffnet, wenn die Trendstärke abnimmt und die Preisdynamik sich verbessert, während eine Short-Position eröffnet wird, wenn die Trendstärke zunimmt und die Preisdynamik sich verschlechtert. Die StockSharp-Version behält das Verhalten bei, jede entgegengesetzte Exposition zu schließen, bevor eine neue Order eröffnet wird, und wendet dieselben festen Stop-Loss- und Take-Profit-Abstände an, die im Originalskript in Pips angegeben wurden.

Indikatoren

  • Average Directional Index (ADX) – misst die Stärke des aktuellen Trends. Die Strategie betrachtet die ADX-Hauptlinie und vergleicht die letzten zwei Werte, um festzustellen, ob die Trendstärke zu- oder abnimmt.
  • Kaufman Adaptive Moving Average (KAMA/AMA) – passt sich mithilfe separater schneller und langsamer Glättungskonstanten an die Marktvolatilität an. Die Strategie vergleicht die letzten zwei Werte, um die Richtung der Preisdynamik zu bewerten.

Strategielogik

  1. Mit dem konfigurierten Kerzentyp (Standard: 1-Stunden-Bars) arbeiten und warten, bis eine Kerze vollständig geschlossen ist, bevor sie verarbeitet wird.
  2. KAMA mit der ausgewählten Länge, der schnellen Periode und der langsamen Periode berechnen.
  3. ADX mit der konfigurierten Mittelungsperiode berechnen und den Wert der Hauptlinie extrahieren.
  4. Aktuelle und vorherige Indikatorlesungen vergleichen:
    • Long-Setup – der ADX-Wert sinkt (Trendstärke nimmt ab), während KAMA steigt (Preisdynamik verbessert sich).
    • Short-Setup – der ADX-Wert steigt, während KAMA fällt.
  5. Wenn ein Signal erscheint, jede Exposition der entgegengesetzten Seite schließen und eine neue Marktorder eröffnen, damit die endgültige Position dem Basisstrategie-Volumen entspricht.
  6. Die aktive Position kontinuierlich überwachen. Wenn der Preis die konfigurierten Stop-Loss- oder Take-Profit-Niveaus berührt (in Pips ausgedrückt und gemäß der Tick-Größe des Instruments in Preiseinheiten umgerechnet), den Trade sofort beenden.

Trade-Management

  • Stop-Loss – in Pips ausgedrückt; in Preiseinheiten mit dem PriceStep des Instruments umgerechnet. Für Symbole mit 3 oder 5 Dezimalstellen ist die Pip-Größe 10-mal der Preisschritt, entsprechend der MetaTrader-Implementierung.
  • Take-Profit – ebenfalls in Pips ausgedrückt und auf dieselbe Weise wie die Stop-Loss-Distanz behandelt.
  • Die Strategie verwendet Marktorders für Einstiege und Ausstiege und dreht die Position um, wenn ein entgegengesetztes Signal auftritt.

Parameter

Name Standard Beschreibung
CandleType TimeSpan.FromHours(1).TimeFrame() Kerzentyp für alle Berechnungen.
AdxPeriod 14 Mittelungslänge der ADX-Hauptlinie.
AmaPeriod 9 Basisperiode des Kaufman Adaptive Moving Average.
AmaFastPeriod 2 Schnelle EMA-Periode innerhalb des AMA.
AmaSlowPeriod 30 Langsame EMA-Periode innerhalb des AMA.
StopLossPips 50 Abstand zum Schutz-Stop-Loss in Pips. Auf 0 setzen zum Deaktivieren.
TakeProfitPips 50 Abstand zum Gewinnziel in Pips. Auf 0 setzen zum Deaktivieren.

Verwendungshinweise

  • Sicherstellen, dass die Strategie einem Wertpapier zugeordnet ist, das einen gültigen PriceStep exponiert. Für Forex-Symbole mit Bruchpips wird die Pip-Größe automatisch berechnet.
  • Volume steuert die Basis-Ordergröße. Wenn ein Umkehrsignal erscheint, fügt der Algorithmus genügend Volumen hinzu, um jede entgegengesetzte Exposition zu schließen und eine Position gleich Volume in der neuen Richtung aufzubauen.
  • Da Stop-Loss- und Take-Profit-Ausstiege auf Kerzenhochs und -tiefs bewertet werden, approximiert das Verhalten die Pending-Order-Ausführung von MetaTrader.

Referenzen

  • Ursprüngliche MetaTrader 5-Strategie: MQL/22003/Breadandbutter2.mq5
  • StockSharp-Indikatoren: KaufmanAdaptiveMovingAverage, AverageDirectionalIndex
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>
/// Bread and Butter 2 ADX AMA strategy. Uses KAMA direction with ADX filter.
/// </summary>
public class Breadandbutter2AdxAmaStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _kamaPeriod;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private decimal? _prevKama;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int KamaPeriod { get => _kamaPeriod.Value; set => _kamaPeriod.Value = value; }
	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }

	public Breadandbutter2AdxAmaStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
		_kamaPeriod = Param(nameof(KamaPeriod), 10).SetGreaterThanZero().SetDisplay("KAMA Period", "KAMA lookback", "Indicators");
		_fastPeriod = Param(nameof(FastPeriod), 8).SetGreaterThanZero().SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 21).SetGreaterThanZero().SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevKama = null;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevKama = null;
		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!IsFormedAndOnlineAndAllowTrading()) { _prevKama = fast; return; }
		if (_prevKama == null) { _prevKama = fast; return; }
		var prevAbove = _prevKama.Value > slow;
		var currAbove = fast > slow;
		_prevKama = fast;
		if (!prevAbove && currAbove && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
		else if (prevAbove && !currAbove && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
	}
}