Ver no GitHub

Estratégia XWAMI Multicamada MMRec

Esta estratégia porta o assessor especializado original Exp_XWAMI_NN3_MMRec.mq5 para o StockSharp. Três camadas independentes (A/B/C) executam o indicador de momentum XWAMI em diferentes períodos e combinam seus sinais dentro de uma única posição líquida. Cada camada emula o MagicNumber correspondente da versão MetaTrader, incluindo seu contador de gestão de dinheiro e níveis de proteção.

Lógica de trading

  • Para cada camada, uma série de momentum é calculada como preço - preço[iPeriod] usando o preço aplicado selecionado. A diferença é passada por quatro suavizadores sequenciais (métodos e comprimentos configuráveis) para obter as linhas "up" e "down" do indicador XWAMI.
  • Os sinais são avaliados no deslocamento SignalBar. Quando a barra anterior tinha up > down, os vendidos dessa camada são fechados e uma entrada comprada é permitida se a barra mais recente mostrar up <= down. Quando a barra anterior tinha up < down, os comprados são fechados e uma entrada vendida é permitida quando up >= down.
  • Antes de abrir em uma nova direção, a estratégia fecha todas as posições opostas de outras camadas para respeitar o modelo de netagem do StockSharp. Isso espelha o comportamento de fechar uma operação de magic-number oposto no código MQL.
  • Níveis opcionais de stop-loss e take-profit (expressos em pontos de preço) são verificados em cada vela completada usando o máximo/mínimo da vela. Se atingidos, forçam uma saída imediata para essa camada.

Contador de gestão de dinheiro

Cada camada mantém um histórico contínuo de suas operações mais recentes. Sempre que o número de perdas dentro do período de retrocesso configurado atinge o LossTrigger, o tamanho da posição muda do volume normal para o volume reduzido ("Small"). Operações bem-sucedidas ou contagens de perdas menores revertem para o tamanho normal. As direções de compra e venda mantêm seus próprios contadores, exatamente como no auxiliar MMRec original.

Parâmetros

A estratégia expõe o conjunto completo de parâmetros do especialista MQL:

  • Layer?CandleType – tipo de vela (período) usado pela camada (padrões: A=8h, B=4h, C=1h).
  • Layer?Period – atraso usado para construir a série de momentum.
  • Layer?Method1..4, Layer?Length1..4, Layer?Phase1..4 – configuração de suavização para as quatro etapas XWAMI.
  • Layer?AppliedPrice – fórmula de preço aplicado (fechamento, abertura, ponderado, Demark, etc.).
  • Layer?SignalBar – deslocamento da barra de sinal (0 = atual, 1 = última barra fechada, padrão 1).
  • Layer?AllowBuy/SellOpen e Layer?AllowBuy/SellClose – permissões para entradas e saídas.
  • Layer?NormalVolume, Layer?SmallVolume – tamanho de operação em lotes (ou unidades) para modos normal e reduzido.
  • Layer?BuyTotalTrigger, Layer?BuyLossTrigger, Layer?SellTotalTrigger, Layer?SellLossTrigger – contadores MMRec que controlam a mudança para o volume reduzido.
  • Layer?StopLossPoints, Layer?TakeProfitPoints – níveis de proteção em pontos de preço (0 desativa o nível).

Notas

  • A versão StockSharp usa uma única posição líquida. Quando duas camadas discordam, as posições opostas são fechadas antes de entrar na nova, preservando a ordem pretendida de sinais enquanto evita hedging.
  • A etapa Tillson T3 é implementada diretamente em C# para manter paridade com o algoritmo de suavização original. Outros modos de suavização são mapeados para os indicadores integrados do StockSharp (SMA, EMA, SMMA/RMA, LWMA, Jurik).
  • Como as consultas de histórico de operações diferem entre plataformas, a lógica MMRec rastreia operações concluídas dentro da estratégia e reproduz os mesmos limiares sem escanear o histórico do terminal.
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// XWAMI multi-layer strategy using triple WMA for trend alignment.
/// </summary>
public class XwamiMultiLayerMmrecStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _midPeriod;
	private readonly StrategyParam<int> _slowPeriod;

	private decimal? _prevFast;
	private decimal? _prevMid;

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

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

	public int MidPeriod
	{
		get => _midPeriod.Value;
		set => _midPeriod.Value = value;
	}

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

	public XwamiMultiLayerMmrecStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe", "General");

		_fastPeriod = Param(nameof(FastPeriod), 8)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast WMA", "Indicators");

		_midPeriod = Param(nameof(MidPeriod), 21)
			.SetGreaterThanZero()
			.SetDisplay("Mid Period", "Medium WMA", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow WMA", "Indicators");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = null;
		_prevMid = null;
	}

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

		_prevFast = null;
		_prevMid = null;

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var mid = new ExponentialMovingAverage { Length = MidPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, mid, slow, ProcessCandle)
			.Start();

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
		{
			_prevFast = fastVal;
			_prevMid = midVal;
			return;
		}

		if (_prevFast == null || _prevMid == null)
		{
			_prevFast = fastVal;
			_prevMid = midVal;
			return;
		}

		// Fast crosses above mid with trend alignment (fast > slow)
		if (_prevFast.Value <= _prevMid.Value && fastVal > midVal && fastVal > slowVal)
		{
			if (Position < 0)
				BuyMarket();
			if (Position <= 0)
				BuyMarket();
		}
		// Fast crosses below mid with trend alignment (fast < slow)
		else if (_prevFast.Value >= _prevMid.Value && fastVal < midVal && fastVal < slowVal)
		{
			if (Position > 0)
				SellMarket();
			if (Position >= 0)
				SellMarket();
		}

		_prevFast = fastVal;
		_prevMid = midVal;
	}
}