Auf GitHub ansehen

Morgen-/Abendstern mit MFI-Bestätigungsstrategie

Überblick

Diese Strategie repliziert die Logik des MetaTrader-Experten Expert_AMS_ES_MFI und kombiniert Multi-Candle-Umkehrmuster mit der Momentum-Bestätigung durch den Money Flow Index (MFI). Es überwacht die Morgenstern- und Abendsternformationen mit drei Kerzen im ausgewählten Zeitrahmen und filtert die Signale mithilfe von MFI-Schwellenwerten, um die Erschöpfung des aktuellen Schwungs zu bestätigen, bevor Geschäfte getätigt werden. Durch MFI-Kreuzungen erkannte Momentumumkehrungen werden auch zum Schließen offener Positionen verwendet.

Handelslogik

  • Datenquelle: Fertige Kerzen des konfigurierten Zeitrahmens und ihre zugehörigen MFI-Werte.
  • Indikatoren:
    • Money Flow Index (MFI) – Zeitraum ist konfigurierbar (Standard 49).
  • Teilnahmebedingungen:
    • Long: Erkennen Sie ein Morning Star-Muster (starke bärische Kerze, mittlere Kerze mit kleinem Körper, starke bullische Kerze, die über dem Mittelpunkt der ersten schließt) und erfordern Sie, dass der MFI der vorherigen Kerze unter dem bullischen Bestätigungsschwellenwert liegt (Standard 40).
    • Short: Erkennen Sie ein Evening Star-Muster (starke bullische Kerze, kleine mittlere Kerze mit kleinem Körper, starke bärische Kerze, die unter dem Mittelpunkt der ersten schließt) und erfordern Sie, dass der MFI der vorherigen Kerze über dem bärischen Bestätigungsschwellenwert liegt (Standard 60).
    • Beim Umtausch von Positionen schließt die Strategie zunächst das entgegengesetzte Engagement, bevor der neue Handel eröffnet wird.
  • Ausgangsregeln:
    • Langer Ausstieg: Schließen Sie die Position, wenn der MFI das obere Ausstiegsniveau überschreitet (Standard 70) oder unter das untere Ausstiegsniveau (Standard 30) fällt, was entweder ein überkauftes Momentum oder eine gescheiterte Umkehr signalisiert.
    • Short Exit: Schließen Sie die Position, wenn der MFI das untere Ausstiegsniveau (Standard 30) oder das obere Ausstiegsniveau (Standard 70) überschreitet, was ein wachsendes Aufwärtsmomentum signalisiert.
  • Auftragstyp: Marktaufträge unter Verwendung des in der StockSharp-Umgebung konfigurierten Strategievolumens.

Parameter

Name Beschreibung Standard
CandleType Zeitrahmen der zur Analyse verwendeten Kerzen. 1-Stunden-Kerzen
MfiPeriod Zeitraum des MFI-Indikators. 49
BullishMfiThreshold MFI-Niveau, das die Morning Star-Signale bestätigt. 40
BearishMfiThreshold MFI-Wert, der Evening Star-Signale bestätigt. 60
UpperExitLevel MFI-Level, das zur Erkennung überkaufter Ausstiege verwendet wird. 70
LowerExitLevel MFI-Level, das zur Erkennung überverkaufter Ausstiege verwendet wird. 30

Alle Parameter können im StockSharp Designer/Optimizer optimiert werden.

Nutzungshinweise

  1. Hängen Sie die Strategie an das gewünschte Wertpapier an und stellen Sie CandleType so ein, dass es mit dem Zeitrahmen des Diagramms des ursprünglichen MQL-Experten übereinstimmt.
  2. Konfigurieren Sie die Risikoparameter, wie z. B. das Strategievolumen oder die Broker-spezifische Ordergröße, über die StockSharp-Plattform.
  3. Aktivieren Sie die Strategie. Es abonniert automatisch Kerzen, berechnet MFI-Werte und verwaltet Positionen gemäß den oben genannten Regeln.

Herkunft

Die Strategie ist eine direkte Konvertierung des MQL5-Expertenberaters in MQL/323, wobei sein Muster und seine MFI-basierte Entscheidungslogik beibehalten und gleichzeitig an den StockSharp-High-Level-API angepasst werden.

namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// Morning/Evening Star + MFI strategy.
/// Buys on morning star with low MFI, sells on evening star with high MFI.
/// </summary>
public class MorningEveningMfiStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _mfiPeriod;
	private readonly StrategyParam<decimal> _mfiLow;
	private readonly StrategyParam<decimal> _mfiHigh;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private ICandleMessage _prevCandle;
	private ICandleMessage _prevPrevCandle;
	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 MfiLow { get => _mfiLow.Value; set => _mfiLow.Value = value; }
	public decimal MfiHigh { get => _mfiHigh.Value; set => _mfiHigh.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public MorningEveningMfiStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_mfiPeriod = Param(nameof(MfiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("MFI Period", "MFI period", "Indicators");
		_mfiLow = Param(nameof(MfiLow), 40m)
			.SetDisplay("MFI Low", "MFI oversold threshold", "Signals");
		_mfiHigh = Param(nameof(MfiHigh), 60m)
			.SetDisplay("MFI High", "MFI overbought threshold", "Signals");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevCandle = null;
		_prevPrevCandle = null;
		_candlesSinceTrade = SignalCooldownCandles;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevCandle = null;
		_prevPrevCandle = null;
		_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++;

		if (_prevCandle != null && _prevPrevCandle != null)
		{
			var prevBody = Math.Abs(_prevCandle.ClosePrice - _prevCandle.OpenPrice);
			var prevRange = _prevCandle.HighPrice - _prevCandle.LowPrice;
			var isSmallBody = prevRange > 0 && prevBody < prevRange * 0.3m;
			var firstMidpoint = (_prevPrevCandle.OpenPrice + _prevPrevCandle.ClosePrice) / 2m;

			var firstBearish = _prevPrevCandle.OpenPrice > _prevPrevCandle.ClosePrice;
			var currBullish = candle.ClosePrice > candle.OpenPrice;
			var isMorningStar = firstBearish && isSmallBody && currBullish && candle.ClosePrice > firstMidpoint;

			var firstBullish = _prevPrevCandle.ClosePrice > _prevPrevCandle.OpenPrice;
			var currBearish = candle.OpenPrice > candle.ClosePrice;
			var isEveningStar = firstBullish && isSmallBody && currBearish && candle.ClosePrice < firstMidpoint;

			if (isMorningStar && mfiValue < MfiLow && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
			else if (isEveningStar && mfiValue > MfiHigh && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
		}

		_prevPrevCandle = _prevCandle;
		_prevCandle = candle;
	}
}