Ver en GitHub

Estrategia AltrTrend Signal v2.2

Esta estrategia es un porte de StockSharp del asesor experto de MetaTrader Exp_AltrTrend_Signal_v2_2. Recrea la lógica del canal adaptativo del indicador AltrTrend Signal original y ejecuta operaciones en barras retrasadas tal como la versión MQL5. El valor ADX contrae o amplía el canal de modo que las rupturas solo se activan cuando la fuerza de la tendencia las respalda.

Cómo funciona

  1. Se calcula un canal dinámico en cada vela completada del marco temporal configurado. El ancho del canal se define por el máximo y mínimo del precio dentro de un lookback que se expande o contrae según el valor ADX anterior (KPeriod / ADX).
  2. Los límites internos (smin, smax) se acercan al centro en KPercent. El precio debe cerrar fuera de estos límites internos para establecer un estado de tendencia direccional.
  3. Cuando la tendencia pasa de bajista a alcista y el cierre está por encima del límite superior, se genera una señal de compra. Un giro bajista por debajo del límite inferior emite una señal de venta. Las señales se ejecutan en la barra definida por el retraso SignalBar, coincidiendo con el comportamiento del asesor experto original.
  4. Los niveles opcionales de stop-loss y take-profit se asignan de puntos a pasos de precio para que las salidas de protección imiten la colocación de órdenes original con valores fijos de SL/TP.

Detalles

  • Criterios de entrada:
    • Largo: La tendencia anterior era bajista o neutral, el precio cierra por encima del límite superior contraído y las entradas largas están habilitadas. Las posiciones cortas pueden cerrarse automáticamente si está permitido.
    • Corto: La tendencia anterior era alcista o neutral, el precio cierra por debajo del límite inferior contraído y las entradas cortas están habilitadas. Las posiciones largas pueden cerrarse automáticamente si está permitido.
  • Criterios de salida:
    • Señal de ruptura opuesta cuando las salidas están permitidas para la dirección actual.
    • Distancias de stop-loss o take-profit expresadas en pasos de precio.
  • Largo/Corto: Dirección dual con interruptores independientes de habilitación/deshabilitación para entradas y salidas.
  • Gestión de riesgos:
    • StopLossPoints y TakeProfitPoints replican el módulo MM original aplicando salidas basadas en distancia después de que se ejecutan las órdenes de mercado.
  • Configuración del indicador:
    • KPercent controla cuánto se contraen los bordes del canal hacia el rango medio.
    • KStop mantiene el valor de proyección de flecha original para gráficos y logging.
    • KPeriod es el lookback base antes de la modulación ADX.
    • AdxPeriod establece la longitud del Índice Direccional Promedio que adapta el ancho del canal.
    • SignalBar retrasa la ejecución de órdenes por el número especificado de velas completadas.
  • Mercados recomendados:
    • Funciona mejor en instrumentos con fases de swing claras donde la fuerza de la tendencia varía con el tiempo (pares de forex principales, oro y futuros de índices). El marco temporal predeterminado es H1 como en la plantilla MQL5.

Parámetros

Parámetro Descripción
CandleType Marco temporal usado para construir el canal adaptativo.
KPercent Porcentaje que acerca los límites internos del canal hacia adentro.
KStop Multiplicador para los precios de flecha proyectados (mantenido por compatibilidad).
KPeriod Número base de velas examinadas antes del ajuste ADX.
AdxPeriod Período del Índice Direccional Promedio que impulsa el ancho del canal.
SignalBar Número de velas completadas que se esperan antes de ejecutar una señal.
AllowBuyEntries / AllowSellEntries Habilitar o deshabilitar la apertura de posiciones en cada dirección.
AllowBuyExits / AllowSellExits Permitir el cierre automático de posiciones en señales opuestas.
StopLossPoints Distancia del stop-loss medida en pasos de precio (0 deshabilita).
TakeProfitPoints Distancia del take-profit medida en pasos de precio (0 deshabilita).

Este porte mantiene los interruptores discrecionales y los parámetros de riesgo del asesor experto original, facilitando la reproducción del mismo comportamiento dentro de StockSharp Designer, Shell o Runner.

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>
/// AltrTrend signal strategy using EMA crossover for alternating trend detection.
/// </summary>
public class AltrTrendSignalStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;

	private decimal? _prevFast;
	private decimal? _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 AltrTrendSignalStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe", "General");

		_fastPeriod = Param(nameof(FastPeriod), 7)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast EMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow EMA period", "Indicators");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(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 ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { 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 fastVal, decimal slowVal)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!IsFormedAndOnlineAndAllowTrading())
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			return;
		}

		if (_prevFast == null || _prevSlow == null)
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			return;
		}

		var prevAbove = _prevFast.Value > _prevSlow.Value;
		var currAbove = fastVal > slowVal;

		_prevFast = fastVal;
		_prevSlow = slowVal;

		if (!prevAbove && currAbove)
		{
			if (Position < 0)
				BuyMarket();
			if (Position <= 0)
				BuyMarket();
		}
		else if (prevAbove && !currAbove)
		{
			if (Position > 0)
				SellMarket();
			if (Position >= 0)
				SellMarket();
		}
	}
}