Ver no GitHub

Estratégia Head and Shoulders

Visão geral

A Estratégia Head and Shoulders é um port direto do expert advisor "HEAD AND SHOULDERS" do MetaTrader (MQL ID 26066). O robô original combina reconhecimento do padrão ombro-cabeça-ombro com filtros de momentum, média móvel e MACD, além de gerenciar posições com trailing stops, proteção de patrimônio e regras de break-even. Esta implementação StockSharp foca na lógica discricionária do mecanismo de entrada e saída usando a API de alto nível, fornecendo bindings limpos para indicadores e gestão automatizada de risco via StartProtection.

Lógica de negociação

  1. Detecção de padrão
    • Usa uma janela fractal de cinco barras para aproximar swing highs e lows, espelhando o reconhecimento de padrões baseado em fractais do EA de origem.
    • Confirma um ombro-cabeça-ombro baixista quando três máximas fractais sequenciais aparecem e a máxima central (a cabeça) excede os dois ombros por um limiar de dominância configurável.
    • Confirma um ombro-cabeça-ombro invertido quando três mínimas fractais sequenciais se formam e a mínima central fica suficientemente abaixo dos dois ombros.
    • A linha de pescoço é calculada a partir das mínimas fractais mais recentes (padrão baixista) ou máximas (padrão altista) localizadas entre os ombros e a cabeça.
  2. Filtros de momentum e tendência
    • Médias móveis simples rápida e lenta devem se alinhar com a direção esperada da tendência.
    • Momentum absoluto (diferença entre valor atual e período de retrospectiva) deve exceder um limiar e apontar na mesma direção da operação.
    • O valor MACD precisa concordar com a direção do rompimento para evitar sinais contra a tendência.
  3. Execução do rompimento
    • Compras disparam quando o preço de fechamento rompe acima da linha de pescoço altista enquanto todos os filtros concordam.
    • Vendas disparam quando o fechamento rompe abaixo da linha de pescoço baixista sob filtros baixistas alinhados.
  4. Gestão de posição
    • Posições saem se a linha de pescoço for violada na direção oposta ou se médias móveis e MACD perderem alinhamento.
    • Ordens protetoras opcionais são configuradas pelo helper integrado StartProtection, usando parâmetros de stop-loss, take-profit e trailing-stop expressos em passos de preço.

Parâmetros

Parâmetro Padrão Descrição
CandleType Timeframe 1H Série principal de candles para detecção do padrão.
OrderVolume 1 Tamanho base da ordem.
FastMaLength / SlowMaLength 6 / 85 Comprimentos dos filtros de tendência de média móvel.
MomentumPeriod 14 Período de retrospectiva do indicador de momentum.
MomentumThreshold 0.3 Momentum absoluto mínimo exigido para confirmação.
MacdFastLength, MacdSlowLength, MacdSignalLength 12, 26, 9 Configuração MACD.
ShoulderTolerancePercent 5 Desvio máximo permitido entre ombro esquerdo e direito.
HeadDominancePercent 2 Quantidade mínima que a cabeça deve exceder cada ombro.
StopLossSteps, TakeProfitSteps, TrailingStopSteps 100, 200, 0 Tamanhos de ordens protetoras em passos de preço (zero desativa um componente).

Todos os parâmetros criados com Param() expõem metadados para exibição na UI e podem ser otimizados pelo otimizador StockSharp.

Diferenças em relação ao expert original

  • Remove stop de patrimônio, trailing e rotinas de modificação de ordens específicas do MetaTrader em favor dos mecanismos integrados de proteção de carteira do StockSharp.
  • Foca puramente em ordens a mercado e chamadas de API de alto nível (BuyMarket / SellMarket).
  • Simplifica recursos auxiliares como alertas, notificações push e desenho de objetos gráficos; a versão StockSharp registra detecções com LogInfo.
  • O reconhecimento de padrões mantém o espírito da lógica fractal original, mas é reescrito para evitar acesso direto a arrays de dados e manipulação de tickets de ordens.

Notas de uso

  • Como a estratégia depende de candles concluídos, garanta que as assinaturas de dados entreguem barras finalizadas (CandleStates.Finished).
  • A proteção trailing usa passos de preço; verifique se Security.PriceStep reflete o tamanho de tick do instrumento antes de habilitar trailing stops.
  • O detector de padrões armazena apenas fractais recentes para evitar coleções ilimitadas, tornando-o adequado para longas sessões ao vivo.
  • Para camadas adicionais de confirmação (por exemplo, MACD de timeframe superior como no EA original), estenda a estratégia com assinaturas extras usando a mesma abordagem de binding mostrada nesta implementação.

Referências

using System;

using Ecng.Common;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Head and Shoulders strategy: EMA crossover + RSI confirmation.
/// Buys when fast EMA crosses above slow EMA and RSI &lt; 55.
/// Sells when fast EMA crosses below slow EMA and RSI &gt; 45.
/// </summary>
public class HeadAndShouldersStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _rsiPeriod;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int FastPeriod
	{
		get => _fastPeriod.Value;
		set => _fastPeriod.Value = value;
	}

	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.Value = value;
	}

	public int RsiPeriod
	{
		get => _rsiPeriod.Value;
		set => _rsiPeriod.Value = value;
	}

	public HeadAndShouldersStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");

		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 21)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");

		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI period", "Indicators");
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

		decimal? prevFast = null;
		decimal? prevSlow = null;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, slow, rsi, (candle, fastVal, slowVal, rsiVal) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				if (prevFast.HasValue && prevSlow.HasValue)
				{
					var crossUp = prevFast.Value <= prevSlow.Value && fastVal > slowVal;
					var crossDown = prevFast.Value >= prevSlow.Value && fastVal < slowVal;

					if (crossUp && rsiVal < 55m && Position <= 0)
						BuyMarket();
					else if (crossDown && rsiVal > 45m && Position >= 0)
						SellMarket();
				}

				prevFast = fastVal;
				prevSlow = slowVal;
			})
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, fast);
			DrawIndicator(area, slow);
			DrawOwnTrades(area);
		}
	}
}