Ver en GitHub

Estrategia ADX Smoothed Cross

Resumen

La estrategia opera basándose en un índice de dirección promedio (ADX) de doble suavizado. Compara las líneas +DI y -DI suavizadas para detectar cambios de tendencia. Cuando la línea +DI suavizada cruza por encima de la línea -DI suavizada, la estrategia entra en una posición larga. Cuando la línea +DI suavizada cruza por debajo de la línea -DI suavizada, abre una posición corta.

Cómo Funciona

  • Utiliza un indicador ADX con período configurable.
  • Aplica dos pasadas de suavizado exponencial controladas por los parámetros Alpha1 y Alpha2.
  • Una señal larga ocurre cuando el +DI suavizado anterior estaba por debajo del -DI suavizado y el +DI suavizado actual está por encima.
  • Una señal corta ocurre en el cruce opuesto.
  • Parámetros opcionales permiten deshabilitar operaciones largas o cortas y controlar si las posiciones existentes pueden cerrarse cuando aparece una señal opuesta.
  • La gestión de riesgo incorporada establece niveles de stop-loss y take-profit en puntos.

Parámetros

Nombre Descripción
AdxPeriod Período para el cálculo del ADX.
Alpha1 Primer coeficiente de suavizado (0-1).
Alpha2 Segundo coeficiente de suavizado (0-1).
StopLoss Stop-loss en puntos.
TakeProfit Take-profit en puntos.
AllowBuy Habilitar entradas largas.
AllowSell Habilitar entradas cortas.
AllowCloseBuy Permitir cerrar posiciones largas en señales de venta.
AllowCloseSell Permitir cerrar posiciones cortas en señales de compra.
CandleType Marco temporal utilizado para el indicador.

Notas

  • Solo se procesan velas finalizadas.
  • La estrategia usa la API de alto nivel con vinculación de indicadores.
  • El stop-loss y el take-profit se gestionan mediante StartProtection.
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;

/// <summary>
/// Smoothed EMA crossover strategy (ADX-inspired directional cross concept).
/// Buys when fast EMA crosses above slow EMA, sells when below.
/// </summary>
public class AdxSmoothedCrossStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _prevFast;
	private decimal? _prevSlow;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public AdxSmoothedCrossStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast EMA period", "Indicator");

		_slowPeriod = Param(nameof(SlowPeriod), 25)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow EMA period", "Indicator");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "General");
	}

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

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

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

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

		SubscribeCandles(CandleType)
			.Bind(fast, slow, ProcessCandle)
			.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (_prevFast is null || _prevSlow is null)
		{
			_prevFast = fastValue;
			_prevSlow = slowValue;
			return;
		}

		var crossUp = _prevFast <= _prevSlow && fastValue > slowValue;
		var crossDown = _prevFast >= _prevSlow && fastValue < slowValue;

		if (crossUp && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (crossDown && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevFast = fastValue;
		_prevSlow = slowValue;
	}
}