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
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).
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.
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).
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.
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;
}
}
}
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 RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class ah_hm_mfi_strategy(Strategy):
def __init__(self):
super(ah_hm_mfi_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._mfi_period = self.Param("MfiPeriod", 14)
self._mfi_low = self.Param("MfiLow", 35.0)
self._mfi_high = self.Param("MfiHigh", 65.0)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 8)
self._candles_since_trade = 8
@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 MfiLow(self):
return self._mfi_low.Value
@MfiLow.setter
def MfiLow(self, value):
self._mfi_low.Value = value
@property
def MfiHigh(self):
return self._mfi_high.Value
@MfiHigh.setter
def MfiHigh(self, value):
self._mfi_high.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(ah_hm_mfi_strategy, self).OnReseted()
self._candles_since_trade = self.SignalCooldownCandles
def OnStarted2(self, time):
super(ah_hm_mfi_strategy, self).OnStarted2(time)
self._candles_since_trade = self.SignalCooldownCandles
rsi = RelativeStrengthIndex()
rsi.Length = self.MfiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, 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)
body = abs(float(candle.ClosePrice) - float(candle.OpenPrice))
rng = float(candle.HighPrice) - float(candle.LowPrice)
if rng <= 0 or body <= 0:
return
upper_shadow = float(candle.HighPrice) - max(float(candle.OpenPrice), float(candle.ClosePrice))
lower_shadow = min(float(candle.OpenPrice), float(candle.ClosePrice)) - float(candle.LowPrice)
is_hammer = lower_shadow > body * 2.5 and upper_shadow < body * 0.5
is_hanging_man = upper_shadow > body * 2.5 and lower_shadow < body * 0.5
if is_hammer and mfi_val < self.MfiLow and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
elif is_hanging_man and mfi_val > self.MfiHigh and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
def CreateClone(self):
return ah_hm_mfi_strategy()