Auf GitHub ansehen

Tipu MACD EA Strategie

Überblick

Die Strategie ist ein High-Level-StockSharp-Port des Tipu MACD EA von MQL4. Es handelt ein einzelnes Symbol mithilfe von MACD-basierten Signalen und spiegelt die ursprünglichen Funktionen des Expert Advisors wider:

  • Optionaler Handelsstundenfilter mit zwei konfigurierbaren Zeitfenstern.
  • MACD-Nulllinien- und Signalleitungs-Crossover-Einträge mit einstellbaren EMA-Längen und -Verschiebung.
  • Automatisches Positionsmanagement einschließlich Take-Profit, Stop-Loss, Trailing Stop und Breakeven.
  • Volumenbegrenzung, die die Einstellung „Maximale Anzahl“ aus dem Quellcode emuliert.

Alle Operationen verwenden Marktaufträge. Schutzniveaus werden intern verfolgt und Aufträge werden geschlossen, sobald eine Kerze das Stop-Loss- oder Take-Profit-Niveau durchbricht.

Handelslogik

  1. Abonnieren Sie den konfigurierten Kerzentyp und berechnen Sie einen MovingAverageConvergenceDivergenceSignal-Indikator (MACD-Linie + Signallinie).
  2. Bewerten Sie MACD-Werte anhand der ausgewählten Verschiebung (MacdShift 0 = aktuelle Kerze, 1 = vorherige Kerze) und erstellen Sie Crossover-Signale:
    • Nulllinienübergang (optional) – kaufen, wenn MACD über Null kreuzt, verkaufen, wenn es darunter kreuzt.
    • Signallinienkreuzung (optional) – kaufen, wenn MACD die Signallinie überschreitet, verkaufen, wenn sie darunter liegt.
  3. Bevor Sie eine Position eröffnen, stellen Sie sicher, dass die aktuelle Stunde zu mindestens einem der beiden Zeitfenster gehört, wenn der Filter aktiviert ist.
  4. Wenn ein langes Signal erscheint:
    • Wenn die Absicherung deaktiviert ist und ein Short offen ist, schließen Sie ihn optional (CloseOnReverseSignal) oder überspringen Sie den neuen Trade.
    • Geben Sie eine Kauf-Market-Order für den kleineren Betrag von TradeVolume und dem verbleibenden Volumen auf, bis MaxPositionVolume erreicht ist.
    • Aktualisieren Sie den Long-Entry-Snapshot und berechnen Sie schützende Stopp-/Take-Level, falls aktiviert.
  5. Wenn ein Short-Signal erscheint, befolgen Sie die symmetrische Logik für Verkaufsaufträge.
  6. Während eine Position aktiv ist:
    • Überwachen Sie Stopps und Ziele für jede fertige Kerze und schließen Sie den Handel, wenn eines der beiden Niveaus durchbrochen wird.
    • Wenn das Trailing aktiviert ist und der Preis um TrailingPips + TrailingCushionPips steigt, verschieben Sie den Stopp, um einen Abstand von TrailingPips zum Preis beizubehalten.
    • Wenn das Breakeven-Modul aktiv ist und der Gewinn RiskFreePips übersteigt, verschieben Sie den Stop auf den Einstiegspreis.

Parameter

Name Beschreibung
CandleType Kerzenreihe, die für MACD-Berechnungen verwendet wird.
TradeVolume Volumen jedes Markteintritts (Lots).
MaxPositionVolume Maximal zulässige kumulative lange oder kurze Exposition.
UseTimeFilter Aktiviert den Dual-Window-Handelsstundenfilter.
Zone1StartHour, Zone1EndHour Start-/Endzeiten für das erste Handelsfenster (einschließlich Börsenzeit).
Zone2StartHour, Zone2EndHour Start-/Endzeiten für das zweite Handelsfenster.
FastPeriod, SlowPeriod, SignalPeriod MACD schnelle EMA, langsame EMA und Signallängen von SMA.
MacdShift 0 = den aktuellen Balken auswerten, 1 = den vorherigen Balken auswerten (entsprechend dem MQL iShift).
UseZeroCross Ermöglicht MACD Nulllinien-Kreuzeingaben.
UseSignalCross Ermöglicht MACD vs. Signalleitungskreuzeinträge.
AllowHedging Ermöglicht den Aufbau sowohl langer als auch kurzer Belichtungen, ohne zuerst die gegenüberliegende Seite zu schließen.
CloseOnReverseSignal Schließt die Gegenposition, wenn ein neues Signal erscheint (wird verwendet, wenn die Absicherung deaktiviert ist).
UseTakeProfit, TakeProfitPips Aktiviert und konfiguriert die Take-Profit-Distanz (Pips).
UseStopLoss, StopLossPips Aktiviert und konfiguriert den Stop-Loss-Abstand (Pips).
UseTrailingStop, TrailingPips, TrailingCushionPips Ermöglicht die Nachlaufverwaltung, legt den Nachlaufabstand und das Polster (Pips) fest.
UseRiskFree, RiskFreePips Verschiebt den Stop auf die Gewinnschwelle, sobald der Gewinn die angegebenen Pips überschreitet.

Nutzungshinweise

  • Konfigurieren Sie den Kerzentyp so, dass er dem in MetaTrader verwendeten Zeitrahmen entspricht (standardmäßige 15-Minuten-Balken).
  • Die Pip-Größe wird von Security.PriceStep abgeleitet. Fehlen dem Instrument diese Metadaten, wird der Standardwert 0,0001 verwendet.
  • Die Strategie geht von der sofortigen Ausführung von Marktaufträgen aus. Stellen Sie beim Betrieb unter Spannung ggf. eine ordnungsgemäße Handhabung des Schlupfs sicher.
  • Wenn sowohl Nulllinien- als auch Signallinieneinträge deaktiviert sind, bleibt die Strategie im Leerlauf.
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Tipu MACD EA strategy: MACD signal line crossover.
/// Buys when MACD crosses above signal, sells when crosses below.
/// </summary>
public class TipuMacdEaStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _signalPeriod;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private decimal _prevMacd;
	private decimal _prevSignal;
	private int _candlesSinceTrade;
	private bool _hasPrev;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int SignalPeriod { get => _signalPeriod.Value; set => _signalPeriod.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public TipuMacdEaStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_fastPeriod = Param(nameof(FastPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("MACD Fast", "MACD fast EMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 26)
			.SetGreaterThanZero()
			.SetDisplay("MACD Slow", "MACD slow EMA period", "Indicators");
		_signalPeriod = Param(nameof(SignalPeriod), 9)
			.SetGreaterThanZero()
			.SetDisplay("Signal Period", "MACD signal period", "Indicators");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 4)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevMacd = 0;
		_prevSignal = 0;
		_candlesSinceTrade = SignalCooldownCandles;
		_hasPrev = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevMacd = 0;
		_prevSignal = 0;
		_candlesSinceTrade = SignalCooldownCandles;
		_hasPrev = false;
		var macd = new MovingAverageConvergenceDivergenceSignal
		{
			Macd = { ShortMa = { Length = FastPeriod }, LongMa = { Length = SlowPeriod } },
			SignalMa = { Length = SignalPeriod }
		};
		var subscription = SubscribeCandles(CandleType);
		subscription.BindEx(macd, ProcessCandle).Start();
	}

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

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		if (macdValue is not MovingAverageConvergenceDivergenceSignalValue typed) return;
		if (typed.Macd is not decimal macdMain || typed.Signal is not decimal signal) return;

		if (_hasPrev)
		{
			if (_prevMacd <= _prevSignal && macdMain > signal && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
			else if (_prevMacd >= _prevSignal && macdMain < signal && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
		}

		_prevMacd = macdMain;
		_prevSignal = signal;
		_hasPrev = true;
	}
}