Esta estratégia reimplementa o especialista MetaTrader "AH HM CCI" em StockSharp. Observa o martelo e o castiçal do homem enforcado
padrões e requer confirmação do Commodity Channel Index (CCI) antes de entrar em uma negociação. Os filtros extras de confirmação
elimina padrões fracos e ajuda a alinhar as entradas com a mudança de impulso sinalizada por CCI.
A lógica é executada apenas em velas concluídas e usa uma média móvel simples e curta (SMA) para definir a tendência predominante. O anterior
a vela deve ser um martelo em tendência de baixa com sobrevenda CCI para comprar, ou um homem enforcado em tendência de alta com sobrecompra CCI para vender. Saídas
são gerenciados quando CCI cruza níveis de gatilho configuráveis, replicando a lógica de saída baseada em voto do especialista original.
Lógica de negociação
Filtro de tendência – O ponto médio da vela anterior deve estar abaixo (para posições compradas) ou acima (para posições vendidas) de um SMA calculado em
preços de fechamento. Isso imita a verificação de tendência da média móvel do assistente original.
Detecção de padrões – A estratégia avalia a barra anterior e verifica:
Corpo inteiramente no terço superior da faixa de velas.
Espaço entre a abertura/fechamento da vela anterior e a vela anterior.
Contexto direcional (martelo para tendência de baixa, homem enforcado para tendência de alta).
CCI confirmação – O CCI da barra anterior deve estar abaixo do limite longo ou acima do limite curto. Os valores padrão
corresponda ao modelo MetaTrader (40 para posições longas e 60 para posições curtas).
Saídas de posição – As posições existentes são fechadas quando CCI ultrapassa os limites de saída inferior ou superior. Cruzando de
abaixo fecha posições compradas; cruzar por cima fecha o short.
Parâmetros
Nome
Descrição
Padrão
CandleType
Tipo de vela e intervalo de tempo usado para reconhecimento de padrões.
TimeSpan.FromMinutes(15)
CciPeriod
Número de barras utilizadas pelo Commodity Channel Index.
11
MaPeriod
Número de barras no filtro de tendência SMA.
5
LongConfirmationThreshold
Valor máximo CCI permitido para um sinal de martelo.
40
ShortConfirmationThreshold
Valor mínimo CCI permitido para um sinal de homem suspenso.
60
ExitUpperThreshold
CCI nível que aciona saídas após uma travessia ascendente.
70
ExitLowerThreshold
Nível de saída secundário para sinais antecipados.
30
Todos os parâmetros estão disponíveis para otimização. Os limites aceitam valores negativos, para que você possa adaptar a estratégia a outras
mercados ou níveis de ruído apertando ou afrouxando os filtros.
Gerenciamento de ordens
Entradas usam ordens de mercado dimensionadas como Volume + |Position|, garantindo que as reversões sejam executadas em uma única negociação.
Saídas dependem exclusivamente dos cruzamentos CCI para ficar perto do especialista MetaTrader. Adicione chamadas StartProtection se precisar
níveis explícitos de stop-loss ou take-profit.
Dicas de uso
Aplique a estratégia em instrumentos líquidos onde as lacunas e caudas das velas são informativas.
Experimente valores mais longos de CciPeriod e MaPeriod para suavizar o ruído ao negociar prazos mais longos.
Diminuir LongConfirmationThreshold ou aumentar ShortConfirmationThreshold reduzirá o número de negociações, mas melhorará
seletividade.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Hammer/Hanging Man + CCI strategy.
/// Buys on hammer with negative CCI, sells on hanging man with positive CCI.
/// </summary>
public class HammerHangingManCciStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<decimal> _cciLevel;
private readonly StrategyParam<int> _signalCooldownCandles;
private int _candlesSinceTrade;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
public decimal CciLevel { get => _cciLevel.Value; set => _cciLevel.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public HammerHangingManCciStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("CCI Period", "CCI period", "Indicators");
_cciLevel = Param(nameof(CciLevel), 100m)
.SetDisplay("CCI Level", "CCI threshold", "Signals");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
.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 cci = new CommodityChannelIndex { Length = CciPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(cci, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal cciValue)
{
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 && cciValue < -CciLevel && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (isHangingMan && cciValue > CciLevel && 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 CommodityChannelIndex
from StockSharp.Algo.Strategies import Strategy
class hammer_hanging_man_cci_strategy(Strategy):
def __init__(self):
super(hammer_hanging_man_cci_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._cci_period = self.Param("CciPeriod", 14)
self._cci_level = self.Param("CciLevel", 100.0)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 6)
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 CciPeriod(self):
return self._cci_period.Value
@CciPeriod.setter
def CciPeriod(self, value):
self._cci_period.Value = value
@property
def CciLevel(self):
return self._cci_level.Value
@CciLevel.setter
def CciLevel(self, value):
self._cci_level.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(hammer_hanging_man_cci_strategy, self).OnReseted()
self._candles_since_trade = self.SignalCooldownCandles
def OnStarted2(self, time):
super(hammer_hanging_man_cci_strategy, self).OnStarted2(time)
self._candles_since_trade = self.SignalCooldownCandles
cci = CommodityChannelIndex()
cci.Length = self.CciPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(cci, self._process_candle).Start()
def _process_candle(self, candle, cci_value):
if candle.State != CandleStates.Finished:
return
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
cci_val = float(cci_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 cci_val < -self.CciLevel and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
elif is_hanging_man and cci_val > self.CciLevel and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
def CreateClone(self):
return hammer_hanging_man_cci_strategy()