Ver no GitHub

Morning/Evening Star com estratégia de confirmação de IMF

Visão geral

Esta estratégia replica a lógica do especialista MetaTrader Expert_AMS_ES_MFI, combinando padrões de reversão de múltiplas velas com confirmação de impulso do Money Flow Index (MFI). Ele monitora as formações de três velas Morning Star e Evening Star no período de tempo selecionado e filtra os sinais usando limites de MFI para confirmar o esgotamento da oscilação atual antes de entrar nas negociações. As reversões de momentum detectadas pelos cruzamentos das IMFs também são usadas para fechar posições abertas.

Lógica de negociação

  • Fonte de dados: Candles finalizadas do timeframe configurado e seus valores MFI associados.
  • Indicadores:
    • Índice de fluxo de dinheiro (MFI) – o período é configurável (padrão 49).
  • Regras de inscrição:
    • Longo: detecta um padrão Morning Star (vela forte de baixa, vela intermediária de corpo pequeno, vela forte de alta fechando acima do ponto médio da primeira) e exige que o MFI da vela anterior esteja abaixo do limite de confirmação de alta (padrão 40).
    • Venda: detecta um padrão Evening Star (vela forte de alta, vela intermediária de corpo pequeno, vela forte de baixa fechando abaixo do ponto médio da primeira) e exige que o MFI da vela anterior esteja acima do limite de confirmação de baixa (padrão 60).
    • Ao inverter posições, a estratégia primeiro fecha a exposição oposta antes de abrir a nova negociação.
  • Regras de saída:
    • Saída Longa: Feche a posição quando a IMF cruzar acima do nível de saída superior (padrão 70) ou cair abaixo do nível de saída inferior (padrão 30), sinalizando impulso de sobrecompra ou uma reversão falhada.
    • Saída Curta: Fecha a posição quando a IMF cruza acima do nível de saída inferior (padrão 30) ou acima do nível de saída superior (padrão 70), sinalizando crescente impulso de alta.
  • Tipo de Ordem: Ordens de mercado utilizando o volume da estratégia configurado no ambiente StockSharp.

Parâmetros

Nome Descrição Padrão
CandleType Prazo das velas utilizadas para análise. Velas de 1 hora
MfiPeriod Período do indicador IMF. 49
BullishMfiThreshold Nível MFI que confirma os sinais da Morning Star. 40
BearishMfiThreshold Nível MFI que confirma os sinais do Evening Star. 60
UpperExitLevel Nível MFI usado para detecção de saída de sobrecompra. 70
LowerExitLevel Nível MFI usado para detecção de saída de sobrevenda. 30

Todos os parâmetros podem ser otimizados dentro do StockSharp Designer/Optimizer.

Notas de uso

  1. Anexe a estratégia à segurança desejada e defina o CandleType para corresponder ao período do gráfico do especialista MQL original.
  2. Configure os parâmetros de risco, como volume da estratégia ou tamanho do pedido específico da corretora, por meio da plataforma StockSharp.
  3. Habilite a estratégia. Ele assinará automaticamente velas, calculará valores de IMF e gerenciará posições de acordo com as regras acima.

Origem

A estratégia é uma conversão direta do consultor especialista MQL5 localizado em MQL/323, preservando seu padrão e lógica de decisão baseada em MFI enquanto o adapta ao StockSharp API de alto nível.

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;
	}
}