Auf GitHub ansehen

MACD Stochastic 2-Strategie

Diese Strategie reproduziert die MetaTrader-Expertenlogik "MACD Stochastic 2" mit der High-Level-API von StockSharp. Sie kombiniert einen Drei-Bar-MACD-Swing-Filter mit einem Stochastik-Oszillator, um Momentum-Umkehrungen nahe überverkauften und überkauften Bereichen zu identifizieren. Das Risiko wird durch richtungsspezifische Stops, Take-Profits und einen optionalen Trailing Stop in Pip-Einheiten kontrolliert.

Überblick

  • Funktioniert auf jedem Instrument und Zeitrahmen, der über den Parameter CandleType angegeben wird.
  • Verwendet die MACD-Hauptlinie zur Bestätigung lokaler Tiefs/Hochs, während MACD-Histogramm und Signallinie für die Visualisierung verfügbar bleiben.
  • Bestätigt Einstiege mit einer Stochastik-%K-Messung unter 20 für Longs und über 80 für Shorts.
  • Adaptiert die MetaTrader-Pip-Berechnung, indem die Pip-Größe aus dem Kursschritt des Instruments abgeleitet und mit 10 multipliziert wird, wenn das Symbol 3 oder 5 Dezimalstellen hat.

Handelslogik

Long-Einstieg

  1. MACD-Hauptlinienwerte der aktuellen und der beiden vorherigen abgeschlossenen Kerzen liegen alle unter null.
  2. Der aktuelle MACD-Wert ist größer als der vorherige, während der vorherige kleiner als der Wert vor zwei Bars ist (lokales Tief).
  3. Stochastik-%K liegt unter 20 (überverkauft).
  4. Es ist keine bestehende Long-Position offen (Position <= 0). Jede Short-Position wird vor dem Eingehen des neuen Longs glattgestellt.

Short-Einstieg

  1. MACD-Hauptlinienwerte der aktuellen und der beiden vorherigen abgeschlossenen Kerzen liegen alle über null.
  2. Der aktuelle MACD-Wert ist kleiner als der vorherige, während der vorherige größer als der Wert vor zwei Bars ist (lokales Hoch).
  3. Stochastik-%K liegt über 80 (überkauft).
  4. Es ist keine bestehende Short-Position offen (Position >= 0). Jede Long-Position wird vor dem Eingehen des neuen Shorts geschlossen.

Risikomanagement & Ausstiege

  • Harter Stop / Take Profit: Jede Richtung hat unabhängige Pip-basierte Stop-Loss- und Take-Profit-Abstände. Pips werden anhand der berechneten Pip-Größe in absolute Preisoffsets umgerechnet.
  • Trailing Stop: Wenn aktiviert, tritt der Trailing Stop in Kraft, nachdem der Preis über die Trailing-Distanz hinausgeht. Der Stop wird nur angehoben/gesenkt, wenn die Bewegung den konfigurierten Trailing-Schritt überschreitet, um übermäßige Order-Fluktuationen zu vermeiden.
  • Gegenläufige Signale: Beim Eingehen eines entgegengesetzten Signals wird zuerst die bestehende Position glattgestellt, dann die neue mit dem konfigurierten Handelsvolumen eröffnet.

Parameter

Parameter Standard Beschreibung
TradeVolume 1 Order-Volumen, das mit jedem neuen Trade gesendet wird.
StopLossBuyPips 50 Pip-Abstand für Long-Stop-Loss. Auf 0 setzen zum Deaktivieren.
StopLossSellPips 50 Pip-Abstand für Short-Stop-Loss. Auf 0 setzen zum Deaktivieren.
TakeProfitBuyPips 50 Pip-Abstand für Long-Take-Profit. Auf 0 setzen zum Deaktivieren.
TakeProfitSellPips 50 Pip-Abstand für Short-Take-Profit. Auf 0 setzen zum Deaktivieren.
TrailingStopPips 0 Trailing-Stop-Abstand in Pips. 0 deaktiviert Trailing.
TrailingStepPips 5 Minimaler Pip-Gewinn vor der Aktualisierung des Trailing Stops. Muss bei aktiviertem Trailing positiv bleiben.
MacdFastPeriod 12 Schnelle EMA-Länge für MACD.
MacdSlowPeriod 26 Langsame EMA-Länge für MACD.
MacdSignalPeriod 9 Signal-Glättungslänge für MACD.
StochasticKPeriod 5 Lookback-Periode für Stochastik-%K.
StochasticDPeriod 3 Glättungsperiode für Stochastik-%D.
StochasticSlowing 3 Zusätzliche Glättung, die auf Stochastik-%K angewendet wird.
CandleType 1h Zeitrahmen Kerzentyp (Zeitrahmen), der für Indikatorberechnungen verwendet wird.

Hinweise

  • Die Pip-Größenberechnung spiegelt den ursprünglichen MetaTrader-Experten wider: pip = PriceStep und wird mit 10 multipliziert, wenn das Instrument mit 3 oder 5 Dezimalstellen notiert wird.
  • Stochastik-Schwellenwerte (20/80) bleiben wie im Originalskript als Konstanten. Passen Sie diese direkt im Code an, wenn benutzerdefinierte Niveaus benötigt werden.
  • Die Strategie operiert nur auf vollständig abgeschlossenen Kerzen und gewährleistet so Konsistenz mit der Bar-Close-Ausführung von MetaTrader.

Verwendung

  1. Konfigurieren Sie das gewünschte Instrument, CandleType und das Volumen vor dem Start der Strategie.
  2. Passen Sie Stop-, Take-Profit- und Trailing-Parameter an die Volatilität des Instruments an.
  3. Optimieren Sie optional MACD- und Stochastik-Längen mit dem Optimizer von StockSharp dank der exponierten Parameter.
  4. Überwachen Sie die Chart-Objekte (Kerzen, MACD, Stochastik, eigene Trades), die automatisch hinzugefügt werden, wenn ein Chart-Bereich verfügbar ist.
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>
/// MACD and stochastic based swing strategy.
/// Buys when MACD turns up in negative zone + stochastic is oversold.
/// Sells when MACD turns down in positive zone + stochastic is overbought.
/// </summary>
public class MacdStochastic2Strategy : Strategy
{
	private readonly StrategyParam<decimal> _oversoldThreshold;
	private readonly StrategyParam<decimal> _overboughtThreshold;
	private readonly StrategyParam<int> _macdFastPeriod;
	private readonly StrategyParam<int> _macdSlowPeriod;
	private readonly StrategyParam<int> _stochasticKPeriod;
	private readonly StrategyParam<int> _stochasticDPeriod;
	private readonly StrategyParam<decimal> _stopLoss;
	private readonly StrategyParam<decimal> _takeProfit;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _macdPrev1;
	private decimal _macdPrev2;
	private int _macdCount;

	public decimal OversoldThreshold { get => _oversoldThreshold.Value; set => _oversoldThreshold.Value = value; }
	public decimal OverboughtThreshold { get => _overboughtThreshold.Value; set => _overboughtThreshold.Value = value; }
	public int MacdFastPeriod { get => _macdFastPeriod.Value; set => _macdFastPeriod.Value = value; }
	public int MacdSlowPeriod { get => _macdSlowPeriod.Value; set => _macdSlowPeriod.Value = value; }
	public int StochasticKPeriod { get => _stochasticKPeriod.Value; set => _stochasticKPeriod.Value = value; }
	public int StochasticDPeriod { get => _stochasticDPeriod.Value; set => _stochasticDPeriod.Value = value; }
	public decimal StopLoss { get => _stopLoss.Value; set => _stopLoss.Value = value; }
	public decimal TakeProfit { get => _takeProfit.Value; set => _takeProfit.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public MacdStochastic2Strategy()
	{
		_oversoldThreshold = Param(nameof(OversoldThreshold), 20m)
			.SetDisplay("Oversold", "Stochastic oversold threshold", "Stochastic");

		_overboughtThreshold = Param(nameof(OverboughtThreshold), 80m)
			.SetDisplay("Overbought", "Stochastic overbought threshold", "Stochastic");

		_macdFastPeriod = Param(nameof(MacdFastPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("MACD Fast", "Fast EMA length for MACD", "MACD");

		_macdSlowPeriod = Param(nameof(MacdSlowPeriod), 26)
			.SetGreaterThanZero()
			.SetDisplay("MACD Slow", "Slow EMA length for MACD", "MACD");

		_stochasticKPeriod = Param(nameof(StochasticKPeriod), 5)
			.SetGreaterThanZero()
			.SetDisplay("Stochastic K", "Lookback for %K", "Stochastic");

		_stochasticDPeriod = Param(nameof(StochasticDPeriod), 3)
			.SetGreaterThanZero()
			.SetDisplay("Stochastic D", "Smoothing for %D", "Stochastic");

		_stopLoss = Param(nameof(StopLoss), 1000m)
			.SetGreaterThanZero()
			.SetDisplay("Stop Loss", "Stop loss in price units", "Risk");

		_takeProfit = Param(nameof(TakeProfit), 2000m)
			.SetGreaterThanZero()
			.SetDisplay("Take Profit", "Take profit in price units", "Risk");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle type for calculations", "General");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_macdPrev1 = 0m;
		_macdPrev2 = 0m;
		_macdCount = 0;
	}

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

		var macd = new MovingAverageConvergenceDivergence(
			new ExponentialMovingAverage { Length = MacdSlowPeriod },
			new ExponentialMovingAverage { Length = MacdFastPeriod });

		var rsi = new RelativeStrengthIndex { Length = StochasticKPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(rsi, (candle, rsiValue) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				// Process MACD manually
				var macdResult = macd.Process(candle.ClosePrice, candle.CloseTime, true);
				if (!macd.IsFormed)
					return;

				var macdValue = macdResult.ToDecimal();

				_macdCount++;
				if (_macdCount < 3)
				{
					_macdPrev2 = _macdPrev1;
					_macdPrev1 = macdValue;
					return;
				}

				var macd0 = macdValue;
				var macd1 = _macdPrev1;
				var macd2 = _macdPrev2;

				// Buy: MACD in negative zone turning up + stochastic oversold
				var longSignal = macd0 < 0m && macd1 < 0m && macd2 < 0m &&
					macd0 > macd1 && macd1 < macd2 &&
					rsiValue < OversoldThreshold;

				// Sell: MACD in positive zone turning down + stochastic overbought
				var shortSignal = macd0 > 0m && macd1 > 0m && macd2 > 0m &&
					macd0 < macd1 && macd1 > macd2 &&
					rsiValue > OverboughtThreshold;

				if (longSignal && Position <= 0)
					BuyMarket();
				else if (shortSignal && Position >= 0)
					SellMarket();

				_macdPrev2 = _macdPrev1;
				_macdPrev1 = macdValue;
			})
			.Start();

		StartProtection(
			new Unit(TakeProfit, UnitTypes.Absolute),
			new Unit(StopLoss, UnitTypes.Absolute));

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, rsi);
			DrawOwnTrades(area);
		}
	}
}