Ver en GitHub

Estrategia Exp XHullTrend Digit

Descripción general

  • Conversión del experto MQL5 Exp_XHullTrend_Digit.mq5 ubicado en MQL/22117.
  • Utiliza la API de alto nivel de StockSharp con el XHullTrendDigitIndicator personalizado que replica la lógica original de XHullTrend Digit.
  • Enfocado en el seguimiento de tendencia a medio plazo en el marco temporal configurado del indicador (8 horas por defecto).

Lógica del indicador

  1. El precio se toma de la fuente de vela seleccionada (cierre por defecto).
  2. Se calculan dos medias móviles con longitudes BaseLength y BaseLength / 2 usando el método de suavizado elegido (simple, exponencial, suavizado o ponderado).
  3. Una proyección estilo Hull 2 * shortMA - longMA se suaviza dos veces: primero por SignalLength, luego por sqrt(BaseLength).
  4. Ambas líneas resultantes se redondean al múltiplo más cercano del paso del instrumento escalado por 10^RoundingDigits para imitar el redondeo de dígitos de la versión MQL5.
  5. Cuando el redondeo produce valores iguales mientras los valores brutos difieren, la línea más rápida se desplaza un paso en la dirección de la diferencia para que el cruce siga siendo detectable.

Reglas de trading

  • Las señales se evalúan únicamente en velas cerradas.
  • SignalBar define cuántas barras atrás se usan para la detección del cruce (1 = usar la barra completada anterior contra la barra anterior a ella).
  • Entrada larga: línea rápida anterior por encima de la lenta y la línea rápida de la barra seleccionada en o por debajo de la lenta (cruce hacia arriba). Las posiciones cortas se cierran opcionalmente al mismo tiempo.
  • Entrada corta: línea rápida anterior por debajo de la lenta y la línea rápida de la barra seleccionada en o por encima de la lenta (cruce hacia abajo). Las posiciones largas se cierran simultáneamente de forma opcional.
  • Salida larga: cuando la línea rápida anterior cae por debajo de la lenta.
  • Salida corta: cuando la línea rápida anterior sube por encima de la lenta.
  • Si aparece una señal de reversión mientras se mantiene la posición opuesta, la estrategia envía la orden de cierre seguida de una orden dimensionada para voltear la posición a la nueva dirección.

Parámetros

  • OrderVolume – volumen para entradas de mercado.
  • StopLoss / TakeProfit – distancias de protección opcionales en pasos de precio (convertidas a UnitTypes.Step de StockSharp).
  • EnableBuyEntry, EnableSellEntry – permitir o bloquear nuevas posiciones en cada dirección.
  • EnableBuyExit, EnableSellExit – controlar las salidas automáticas para lados largos y cortos.
  • CandleType – marco temporal usado para cálculos del indicador (marco temporal de 8 horas por defecto).
  • BaseLength – longitud de suavizado base para el indicador (equivale a XLength en MQL5).
  • SignalLength – longitud del suavizado Hull intermedio (HLength en MQL5).
  • PriceSource – precio de vela usado para los cálculos (cierre/apertura/máximo/mínimo/típico/ponderado/mediano/promedio).
  • SmoothMethod – tipo de media móvil para todas las etapas de suavizado (simple, exponencial, suavizado, ponderado).
  • Phase – mantenido por compatibilidad; sin efecto con los tipos de suavizado soportados.
  • RoundingDigits – número de ajustes de dígitos adicionales aplicados durante el redondeo.
  • SignalBar – desplazamiento de barra para la evaluación de señales (0 = barra cerrada actual, 1 = barra anterior, etc.).

Gestión de riesgo

  • Stop loss y take profit opcionales manejados por el helper StartProtection incorporado usando distancias basadas en pasos.
  • El volumen puede ajustarse a través de OrderVolume para coincidir con el tamaño del instrumento objetivo.

Notas

  • El indicador personalizado reproduce el comportamiento de redondeo del script original; asegúrese de que Security.PriceStep esté configurado para un redondeo preciso.
  • Solo se implementan los suavizados SMA, EMA, SMMA (RMA) y LWMA porque la biblioteca estándar de StockSharp los proporciona de serie. Otros modos de suavizado exóticos de la fuente MQL5 pueden añadirse posteriormente si es necesario.
  • Funciona en cualquier instrumento que entregue velas para el marco temporal seleccionado. Ajuste los dígitos de redondeo y la longitud base al cambiar entre activos con diferentes tamaños de tick.
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

public class ExpXHullTrendDigitStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private decimal? _prevFast, _prevSlow;

	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 ExpXHullTrendDigitStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
		_fastPeriod = Param(nameof(FastPeriod), 9).SetGreaterThanZero().SetDisplay("Fast WMA", "Fast period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 25).SetGreaterThanZero().SetDisplay("Slow WMA", "Slow period", "Indicators");
	}

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

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

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevFast = null; _prevSlow = null;
		var fast = new WeightedMovingAverage { Length = FastPeriod };
		var slow = new WeightedMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!IsFormedAndOnlineAndAllowTrading()) { _prevFast = fast; _prevSlow = slow; return; }
		if (_prevFast == null || _prevSlow == null) { _prevFast = fast; _prevSlow = slow; return; }
		var prevAbove = _prevFast.Value > _prevSlow.Value;
		var currAbove = fast > slow;
		_prevFast = fast; _prevSlow = slow;
		if (!prevAbove && currAbove && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
		else if (prevAbove && !currAbove && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
	}
}