Ver no GitHub

Estratégia Ichimoku Momentum MACD

Resumo

  • Tipo: Seguidor de tendência com confirmação de Momentum.
  • Período: Configurável (padrão de velas de 15 minutos).
  • Indicadores: Ichimoku (Tenkan/Kijun), Médias Móveis Ponderadas Lineares, Momentum, MACD.
  • Stops: Take-profit e stop-loss fixos opcionais em pontos de preço via StartProtection.

Descrição da estratégia

Esta estratégia recria o fluxo de decisão do expert do MetaTrader "Ichimoku" (pasta MQL/23469). Ela avalia a vela fechada anterior e abre novos trades no início da próxima barra quando todas as quatro confirmações concordam:

  1. Alinhamento Ichimoku – Tenkan (linha de conversão) deve estar acima de Kijun (linha base) para trades longos e abaixo para curtos.
  2. Filtro de tendência LWMA – Uma média móvel ponderada linear rápida deve permanecer acima da LWMA lenta para longos e abaixo para curtos. Ambas as médias são calculadas no mesmo período que as velas assinadas.
  3. Força do Momentum – A distância absoluta do oscilador de momentum do nível neutro 100 deve ser maior que um limite configurável em pelo menos uma das últimas três velas fechadas.
  4. Confirmação MACD – O histograma MACD deve concordar com a direção (linha MACD posicionada além da linha de sinal com o mesmo sinal).

Quando todas as quatro condições se alinham de forma altista e a estratégia não está atualmente longa, ela compra o volume configurado mais as unidades necessárias para zerar uma posição curta existente. Quando as condições mudam para baixistas, o processo é espelhado no lado da venda. Sinais opostos sempre fecham posições abertas, fornecendo uma saída determinística mesmo sem ordens protetoras.

O gerenciamento de risco é tratado através do StartProtection do StockSharp, permitindo distâncias fixas de take-profit e stop-loss expressas em pontos do instrumento. Definir qualquer parâmetro como zero desabilita a perna de proteção correspondente.

Visão geral dos parâmetros

Parâmetro Descrição
FastMaPeriod Comprimento da média móvel ponderada linear rápida usada para o filtro de tendência.
SlowMaPeriod Comprimento da média móvel ponderada linear lenta.
MomentumPeriod Período de lookback do oscilador de momentum.
MomentumThreshold Distância mínima de 100 que o momentum deve atingir em pelo menos uma das últimas três velas.
MacdFastPeriod Comprimento EMA rápido do filtro MACD.
MacdSlowPeriod Comprimento EMA lento do filtro MACD.
MacdSignalPeriod Comprimento EMA de sinal do filtro MACD.
TenkanPeriod Comprimento do Ichimoku Tenkan-sen.
KijunPeriod Comprimento do Ichimoku Kijun-sen.
SenkouSpanBPeriod Comprimento do Ichimoku Senkou Span B.
TakeProfitPoints Distância de take-profit opcional em pontos de preço (0 desabilita).
StopLossPoints Distância de stop-loss opcional em pontos de preço (0 desabilita).
CandleType Período usado para todos os cálculos de indicadores.

Notas de uso

  • A estratégia lê apenas velas concluídas e armazena os valores de indicadores da barra anterior, correspondendo à lógica shift=1 do EA do MetaTrader.
  • Ajustar MomentumThreshold ao mudar para mercados com diferente escalonamento de momentum (por exemplo, cripto vs. pares forex).
  • As ordens protetoras são gerenciadas internamente; ordens de bracket no nível da bolsa não são enviadas.
  • Os gráficos, se disponíveis, exibirão velas de preço, ambas as LWMAs, a nuvem Ichimoku e trades executados.
using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

public class IchimokuMomentumMacdStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private ExponentialMovingAverage _fast;
	private ExponentialMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _cooldown;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
	public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }

	public IchimokuMomentumMacdStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 12).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
		_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
		_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_fast = null; _slow = null;
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_fast = new ExponentialMovingAverage { Length = FastPeriod };
		_slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
		subscription.Bind(_fast, _slow, ProcessCandle);
		subscription.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
		if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }

		var close = candle.ClosePrice;
		var step = Security?.PriceStep ?? 1m;

		if (Position > 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}
		else if (Position < 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}

		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }

		_prevFast = fastValue; _prevSlow = slowValue;
	}
}