Ver no GitHub

Estratégia de IMF AH HM

Resumo

A estratégia AH HM MFI negocia padrões de velas de martelo e homem enforcado que são confirmados pelo Money Flow Index (MFI). Quando um martelo de alta aparece numa tendência descendente de curto prazo e a IMF permanece abaixo de um limite de sobrevenda, a estratégia abre uma posição longa. Quando um homem pendente de baixa se forma em uma tendência de alta enquanto a IMF está acima do limite de sobrecompra, ele abre uma posição curta. As saídas de proteção são acionadas quando a IMF ultrapassa limites superiores ou inferiores predefinidos.

Lógica principal

  1. Assine as velas de período de tempo configuradas e calcule dois indicadores:
    • Índice de Fluxo de Dinheiro com período configurável (padrão: 47).
    • Média Móvel Simples dos preços de fechamento para aproximar o filtro de tendência da estratégia MQL original (comprimento padrão: 5).
  2. Detecte padrões de martelo e homem enforcado:
    • Corpo da vela localizado no terço superior da faixa.
    • Sombra inferior longa em relação ao corpo real.
    • Gap na direção da tendência em comparação com a vela anterior.
    • Confirmação da tendência usando o ponto médio da vela anterior versus a média móvel.
  3. Confirme as entradas com limites de IMF:
    • Insira longo se um martelo for detectado e o MFI estiver no nível de sobrevenda configurado ou abaixo dele (padrão: 40).
    • Digite short se um homem enforcado for detectado e a MFI estiver no nível de sobrecompra configurado ou acima dele (padrão: 60).
  4. Gerenciar saídas usando cruzamentos de IMF:
    • Fechar posições curtas quando a IMF cruzar para cima acima dos níveis de saída inferior ou superior (padrões: 30 e 70).
    • Fechar posições longas quando a IMF cruzar para cima acima do nível de saída superior ou para baixo abaixo do nível de saída inferior.
  5. Inicie o módulo integrado de proteção contra riscos para lidar com paradas de emergência.

Parâmetros

Nome Descrição Padrão
CandleType Tipo de dados de vela e período de tempo usado para detecção de padrão. Período de 30 minutos
MfiPeriod Período retrospectivo para o cálculo da IFM. 47
MaPeriod Comprimento do SMA aplicado aos preços de fechamento para confirmação da tendência. 5
HammerEntryThreshold Valor máximo de MFI permitido antes de entrar em um sinal de martelo. 40
HangingEntryThreshold Valor MFI mínimo exigido antes de entrar em um sinal de homem suspenso. 60
MfiUpperExitLevel Limite superior das IFM; cruzar acima dele fecha qualquer posição aberta. 70
MfiLowerExitLevel Limite inferior das IMFs; cruzar abaixo fecha posições longas, enquanto cruzar acima fecha posições curtas. 30

Notas

  • A estratégia avalia apenas velas finalizadas para evitar agir com base em informações incompletas.
  • A detecção do martelo e do homem enforcado é conservadora: são necessárias uma longa sombra inferior e um corpo localizado próximo à altura da vela.
  • A média móvel substitui o filtro MetaTrader 5 CloseAvg do consultor especialista original, garantindo que as entradas estejam alinhadas com a tendência mais ampla.
namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// Hammer/Hanging Man + MFI strategy.
/// Buys on hammer with low MFI (oversold), sells on hanging man with high MFI (overbought).
/// </summary>
public class AhHmMfiStrategy : 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 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 AhHmMfiStrategy()
	{
		_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), 35m)
			.SetDisplay("MFI Low", "MFI oversold threshold for buy", "Signals");
		_mfiHigh = Param(nameof(MfiHigh), 65m)
			.SetDisplay("MFI High", "MFI overbought threshold for sell", "Signals");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 8)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

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

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_candlesSinceTrade = SignalCooldownCandles;
		var rsi = new RelativeStrengthIndex { Length = MfiPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(rsi, ProcessCandle).Start();
	}

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

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		var body = Math.Abs(candle.ClosePrice - candle.OpenPrice);
		var range = candle.HighPrice - candle.LowPrice;
		if (range <= 0 || body <= 0) return;

		var upperShadow = candle.HighPrice - Math.Max(candle.OpenPrice, candle.ClosePrice);
		var lowerShadow = Math.Min(candle.OpenPrice, candle.ClosePrice) - candle.LowPrice;

		var isHammer = lowerShadow > body * 2.5m && upperShadow < body * 0.5m;
		var isHangingMan = upperShadow > body * 2.5m && lowerShadow < body * 0.5m;

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