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
Mustererkennung – der Körper der aktuell fertigen Kerze muss die vorherige Kerze in Handelsrichtung vollständig umschließen.
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.
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;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import MoneyFlowIndex
from StockSharp.Algo.Strategies import Strategy
class engulfing_mfi_confirmation_strategy(Strategy):
def __init__(self):
super(engulfing_mfi_confirmation_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30)))
self._mfi_period = self.Param("MfiPeriod", 14)
self._oversold = self.Param("Oversold", 30.0)
self._overbought = self.Param("Overbought", 70.0)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 6)
self._candles = []
self._prev_mfi = 0.0
self._has_prev_mfi = False
self._candles_since_trade = 6
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def MfiPeriod(self):
return self._mfi_period.Value
@MfiPeriod.setter
def MfiPeriod(self, value):
self._mfi_period.Value = value
@property
def Oversold(self):
return self._oversold.Value
@Oversold.setter
def Oversold(self, value):
self._oversold.Value = value
@property
def Overbought(self):
return self._overbought.Value
@Overbought.setter
def Overbought(self, value):
self._overbought.Value = value
@property
def SignalCooldownCandles(self):
return self._signal_cooldown_candles.Value
@SignalCooldownCandles.setter
def SignalCooldownCandles(self, value):
self._signal_cooldown_candles.Value = value
def OnReseted(self):
super(engulfing_mfi_confirmation_strategy, self).OnReseted()
self._candles.clear()
self._prev_mfi = 0.0
self._has_prev_mfi = False
self._candles_since_trade = self.SignalCooldownCandles
def OnStarted2(self, time):
super(engulfing_mfi_confirmation_strategy, self).OnStarted2(time)
self._candles.clear()
self._has_prev_mfi = False
self._candles_since_trade = self.SignalCooldownCandles
mfi = MoneyFlowIndex()
mfi.Length = self.MfiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(mfi, self._process_candle).Start()
def _process_candle(self, candle, mfi_value):
if candle.State != CandleStates.Finished:
return
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
mfi_val = float(mfi_value)
self._candles.append(candle)
if len(self._candles) > 5:
self._candles.pop(0)
if len(self._candles) >= 2:
curr = self._candles[-1]
prev = self._candles[-2]
if curr is None or prev is None:
return
bullish_engulfing = (float(prev.OpenPrice) > float(prev.ClosePrice)
and float(curr.ClosePrice) > float(curr.OpenPrice)
and float(curr.OpenPrice) <= float(prev.ClosePrice)
and float(curr.ClosePrice) >= float(prev.OpenPrice))
bearish_engulfing = (float(prev.ClosePrice) > float(prev.OpenPrice)
and float(curr.OpenPrice) > float(curr.ClosePrice)
and float(curr.OpenPrice) >= float(prev.ClosePrice)
and float(curr.ClosePrice) <= float(prev.OpenPrice))
if bullish_engulfing and mfi_val < self.Oversold and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
elif bearish_engulfing and mfi_val > self.Overbought and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
if self._has_prev_mfi:
if self.Position > 0 and self._prev_mfi >= self.Overbought and mfi_val < self.Overbought and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
elif self.Position < 0 and self._prev_mfi <= self.Oversold and mfi_val > self.Oversold and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
self._prev_mfi = mfi_val
self._has_prev_mfi = True
def CreateClone(self):
return engulfing_mfi_confirmation_strategy()