Ver en GitHub

Estrategia XWAMI Multi-Capa MMRec

Esta estrategia porta el asesor experto original Exp_XWAMI_NN3_MMRec.mq5 a StockSharp. Tres capas independientes (A/B/C) ejecutan el indicador de momento XWAMI en diferentes marcos temporales y combinan sus señales dentro de una única posición neteada. Cada capa emula el MagicNumber correspondiente de la versión MetaTrader, incluyendo su contador de gestión de dinero y los niveles de protección.

Lógica de trading

  • Para cada capa se calcula una serie de momento como precio - precio[iPeriod] usando el precio aplicado seleccionado. La diferencia se pasa a través de cuatro suavizadores secuenciales (métodos y longitudes configurables) para obtener las líneas "up" y "down" del indicador XWAMI.
  • Las señales se evalúan en el desplazamiento SignalBar. Cuando la barra anterior tenía up > down, los cortos de esa capa se cierran y se permite una entrada larga si la barra más reciente muestra up <= down. Cuando la barra anterior tenía up < down, los largos se cierran y se permite una entrada corta cuando up >= down.
  • Antes de abrir en una nueva dirección, la estrategia aplana todas las posiciones opuestas de otras capas para respetar el modelo de neteo de StockSharp. Esto refleja el comportamiento de cerrar una operación de magic-number opuesto en el código MQL.
  • Los niveles opcionales de stop-loss y take-profit (expresados en puntos de precio) se verifican en cada vela completada usando el máximo/mínimo de la vela. Si se alcanzan, fuerzan una salida inmediata de esa capa.

Contador de gestión de dinero

Cada capa mantiene un historial continuo de sus operaciones más recientes. Cada vez que el número de pérdidas dentro del período de retroceso configurado alcanza el LossTrigger, el tamaño de posición cambia del volumen normal al volumen reducido ("Small"). Las operaciones exitosas o conteos de pérdidas menores revierten al tamaño normal. Las direcciones de compra y venta mantienen sus propios contadores, exactamente como en el asistente MMRec original.

Parámetros

La estrategia expone el conjunto completo de parámetros del experto MQL:

  • Layer?CandleType – tipo de vela (marco temporal) usado por la capa (predeterminados: A=8h, B=4h, C=1h).
  • Layer?Period – retardo usado para construir la serie de momento.
  • Layer?Method1..4, Layer?Length1..4, Layer?Phase1..4 – configuración de suavizado para las cuatro etapas XWAMI.
  • Layer?AppliedPrice – fórmula de precio aplicado (cierre, apertura, ponderado, Demark, etc.).
  • Layer?SignalBar – desplazamiento de la barra de señal (0 = actual, 1 = última barra cerrada, predeterminado 1).
  • Layer?AllowBuy/SellOpen y Layer?AllowBuy/SellClose – permisos para entradas y salidas.
  • Layer?NormalVolume, Layer?SmallVolume – tamaño de operación en lotes (o unidades) para modos normal y reducido.
  • Layer?BuyTotalTrigger, Layer?BuyLossTrigger, Layer?SellTotalTrigger, Layer?SellLossTrigger – contadores MMRec que controlan el cambio al volumen reducido.
  • Layer?StopLossPoints, Layer?TakeProfitPoints – niveles de protección en puntos de precio (0 desactiva el nivel).

Notas

  • La versión StockSharp usa una única posición neta. Cuando dos capas discrepan, las posiciones opuestas se cierran antes de entrar en la nueva, preservando el orden previsto de señales mientras se evita el hedging.
  • La etapa Tillson T3 está implementada directamente en C# para mantener paridad con el algoritmo de suavizado original. Otros modos de suavizado se mapean a los indicadores integrados de StockSharp (SMA, EMA, SMMA/RMA, LWMA, Jurik).
  • Dado que las consultas de historial de operaciones difieren entre plataformas, la lógica MMRec rastrea operaciones completadas dentro de la estrategia y reproduce los mismos umbrales sin escanear el historial del 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;
	}
}