Auf GitHub ansehen

Verschlingende MFI-Bestätigungsstrategie

Diese Strategie repliziert den MetaTrader-Experten „Expert_ABE_BE_MFI“, indem sie japanische Candlestick-Engulfing-Muster mit der Bestätigung durch den Money Flow Index (MFI)-Oszillator kombiniert. Eine Long-Position wird eröffnet, wenn eine bullische Engulfing-Kerze erscheint, während der Geldfluss in einer überverkauften Zone bleibt. Eine Short-Position wird eröffnet, wenn sich unter überkauften Geldflussbedingungen eine bärische Engulfing-Kerze bildet. Positionen werden geschlossen, wenn MFI dynamische Ausstiegsschwellen überschreitet, was eine Momentumumkehr signalisiert.

Kernidee

  1. Mustererkennung – der Körper der aktuell fertigen Kerze muss die vorherige Kerze in Handelsrichtung vollständig umschließen.
  2. Volumenbestätigung – der MFI-Indikator (Länge konfigurierbar, Standard 37) muss bei Long-Einstiegen unter dem überverkauften Niveau (40) oder bei Short-Einstiegen über dem überkauften Niveau (60) liegen.
  3. Momentum-Ausgänge – offene Positionen werden geschlossen, wenn MFI wichtige Umkehrniveaus (30 und 70) in die entgegengesetzte Richtung überschreitet, was die ursprüngliche Abstimmungslogik des MQL-Experten nachahmt.

Indikatoren

  • Money Flow Index (MFI) – berechnet das volumenbereinigte Momentum. Die Strategie speichert die letzten beiden MFI-Messwerte, um Bahnübergänge zu erkennen.
  • Candlestick-Körperanalyse – es ist kein zusätzlicher Indikator registriert; Die Engulfing-Erkennung verwendet die letzten beiden abgeschlossenen Kerzen.

Handelsregeln

Langer Eintrag

  • Die vorherige Kerze ist bärisch und die aktuelle Kerze ist bullisch.
  • Der aktuelle Kerzenkörper öffnet sich unterhalb oder gleich dem vorherigen Schlusskurs und schließt oberhalb oder gleich dem vorherigen Eröffnungskurs (striktes Engulfing).
  • Der neueste MFI-Wert liegt unter dem konfigurierbaren OversoldLevel (Standard 40).

Kurzer Eintrag

  • Die vorherige Kerze ist bullisch und die aktuelle Kerze ist bärisch.
  • Der aktuelle Kerzenkörper öffnet sich über oder gleich dem vorherigen Schlusskurs und schließt unter oder gleich dem vorherigen Eröffnungskurs.
  • Der neueste MFI-Wert liegt über dem konfigurierbaren OverboughtLevel (Standard 60).

Ausstiegsbedingungen

  • Short schließen, wenn MFI von unten über ExitLongLevel (30) oder ExitShortLevel (70) kreuzt.
  • Long schließen, wenn der MFI von oben unter ExitShortLevel (70) oder ExitLongLevel (30) fällt.

Diese Ausstiegsschwellen stellen die doppelte Abstimmungslogik des ursprünglichen Experten wieder her und stellen sicher, dass längere Bewegungen des Geldflusses eine rechtzeitige Liquidation von Positionen auslösen.

Handelsmanagement

  • Für Ein- und Ausstiege werden Marktaufträge (BuyMarket / SellMarket) verwendet.
  • Es wird kein expliziter Stop-Loss oder Take-Profit verwendet; Das Risikomanagement stützt sich auf die MFI-Umkehrsignale.

Parameter

Name Beschreibung Standard Bereich / Hinweise
CandleType Für die Analyse verwendeter Kerzenzeitrahmen. 1 Minute Jeder unterstützte Kerzentyp.
MfiPeriod Länge des Geldflussindex. 37 Muss > 0 sein; Entspricht der ursprünglichen EA-Standardeinstellung.
OversoldLevel MFI-Niveau, das bullische Engulfing-Setups bestätigt. 40 Aktivieren Sie bei Bedarf die Optimierung.
OverboughtLevel MFI-Niveau, das rückläufige Engulfing-Setups bestätigt. 60 Aktivieren Sie bei Bedarf die Optimierung.
ExitLongLevel Untere MFI-Grenze zur Erkennung von Umkehrungen. 30 Wird sowohl für lange Exits als auch für kurze Bestätigungen verwendet.
ExitShortLevel Obere MFI-Grenze zur Erkennung von Umkehrungen. 70 Wird sowohl für kurze Exits als auch für lange Bestätigungen verwendet.

Hinweise zur Konvertierung

  • Der ursprüngliche MQL-Experte sammelte „Stimmen“ aus Engulfing-Mustern und MFI-Filtern. Die C#-Strategie reproduziert denselben Entscheidungsfluss, indem sie die Abstimmungsregeln direkt in diskrete Eintritts- und Austrittsbedingungen umwandelt.
  • Money-Management- und Trailing-Module aus der MQL-Version werden weggelassen; Die Positionsgröße von StockSharp wird durch das Strategievolumen gesteuert.
  • Alle Indikatorbindungen nutzen nach Bedarf die übergeordnete API (SubscribeCandles().Bind(...)).

Nutzungstipps

  • Optimieren Sie MfiPeriod, OversoldLevel und OverboughtLevel, um die Strategie an bestimmte Märkte anzupassen.
  • Kombinieren Sie es mit Risikokontrollen (Schutzstopps) über StartProtection in der Host-Anwendung, wenn zusätzliche Sicherheit erforderlich ist.
  • Stellen Sie sicher, dass ausreichend historische Daten vorhanden sind, damit der Geldflussindex vollständig gebildet ist, bevor Sie den Handel aktivieren.
namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// Engulfing MFI Confirmation strategy: Engulfing pattern with MFI filter.
/// Bullish engulfing + oversold MFI for long, bearish engulfing + overbought MFI for short.
/// </summary>
public class EngulfingMfiConfirmationStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _mfiPeriod;
	private readonly StrategyParam<decimal> _oversold;
	private readonly StrategyParam<decimal> _overbought;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private readonly List<ICandleMessage> _candles = new();
	private decimal _prevMfi;
	private bool _hasPrevMfi;
	private int _candlesSinceTrade;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int MfiPeriod { get => _mfiPeriod.Value; set => _mfiPeriod.Value = value; }
	public decimal Oversold { get => _oversold.Value; set => _oversold.Value = value; }
	public decimal Overbought { get => _overbought.Value; set => _overbought.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public EngulfingMfiConfirmationStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_mfiPeriod = Param(nameof(MfiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("MFI Period", "Money Flow Index period", "Indicators");
		_oversold = Param(nameof(Oversold), 30m)
			.SetDisplay("Oversold", "MFI oversold level", "Signals");
		_overbought = Param(nameof(Overbought), 70m)
			.SetDisplay("Overbought", "MFI overbought level", "Signals");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_candles.Clear();
		_prevMfi = 0m;
		_hasPrevMfi = false;
		_candlesSinceTrade = SignalCooldownCandles;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_candles.Clear();
		_hasPrevMfi = false;
		_candlesSinceTrade = SignalCooldownCandles;
		var mfi = new MoneyFlowIndex { Length = MfiPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(mfi, ProcessCandle).Start();
	}

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

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		_candles.Add(candle);
		if (_candles.Count > 5)
			_candles.RemoveAt(0);

		if (_candles.Count >= 2)
		{
			var curr = _candles[^1];
			var prev = _candles[^2];

			if (curr is null || prev is null)
				return;

			var bullishEngulfing = prev.OpenPrice > prev.ClosePrice
				&& curr.ClosePrice > curr.OpenPrice
				&& curr.OpenPrice <= prev.ClosePrice
				&& curr.ClosePrice >= prev.OpenPrice;

			var bearishEngulfing = prev.ClosePrice > prev.OpenPrice
				&& curr.OpenPrice > curr.ClosePrice
				&& curr.OpenPrice >= prev.ClosePrice
				&& curr.ClosePrice <= prev.OpenPrice;

			if (bullishEngulfing && mfiValue < Oversold && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
			else if (bearishEngulfing && mfiValue > Overbought && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
		}

		// Exit on MFI crossing
		if (_hasPrevMfi)
		{
			if (Position > 0 && _prevMfi >= Overbought && mfiValue < Overbought && _candlesSinceTrade >= SignalCooldownCandles)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
			else if (Position < 0 && _prevMfi <= Oversold && mfiValue > Oversold && _candlesSinceTrade >= SignalCooldownCandles)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
		}

		_prevMfi = mfiValue;
		_hasPrevMfi = true;
	}
}