Ver en GitHub

Estrategia de canales

Esta estrategia es un puerto directo del asesor experto MetaTrader 4 "Canales" incluido en la biblioteca pública de Gordago. Combina una media móvil exponencial muy rápida (EMA) con tres envolventes basadas en EMA para detectar momentos en los que el precio escapa de las zonas comprimidas. Una vez que se abre una sola posición, la estrategia se basa en órdenes de parada y paradas dinámicas opcionales para gestionar las salidas, al igual que la implementación original MQL.

Lógica comercial

  • La estrategia se suscribe a velas horarias de forma predeterminada y calcula:
    • Un EMA rápido (longitud 2) utilizando precios de cierre de velas.
    • Un segundo EMA rápido (longitud 2) utilizando precios de vela apertura, requeridos por las reglas de entrada corta del asesor experto.
    • Un EMA lento (longitud 220) en cierres que sirve como base para tres desviaciones de envolvente: ±1,0%, ±0,7% y ±0,3%.
  • Se abre una posición larga cuando el cierre EMA rápida satisface cualquiera de las seis verificaciones cruzadas históricas:
    1. Cruza hacia arriba a través de la envoltura exterior inferior del 1%.
    2. Cruza hacia arriba a través de la envolvente inferior del 0,7%.
    3. Pasa dos barras consecutivas por debajo del límite inferior del 0,3% (condición de sobreventa).
    4. Cruza hacia arriba a través del EMA lenta.
    5. Cruza hacia arriba a través de la envolvente superior del 0,3%.
    6. Cruza hacia arriba a través de la envolvente superior del 0,7%.
  • Se abre una posición corta cuando el EMA rápido basado en apertura activa cualquiera de las reglas cortas simétricas:
    1. Cruza hacia abajo a través de la envoltura superior exterior del 1%.
    2. Cruza hacia abajo a través de la envolvente superior del 0,7%.
    3. Cruza hacia abajo a través de la envolvente superior del 0,3%.
    4. Cruza hacia abajo por el EMA lenta.
    5. Cruza hacia abajo a través de la envolvente inferior del 0,3%.
    6. Cruza hacia abajo a través de la envolvente inferior del 0,7%.
  • Sólo puede existir una posición de mercado a la vez. Una nueva señal se ignora mientras una operación está activa, coincidiendo con el comportamiento del experto MetaTrader.

Gestión de riesgos

  • Se pueden configurar distancias individuales de stop-loss y take-profit para operaciones largas y cortas. Cuando se establece en cero, esas órdenes de protección se omiten, lo que replica el estado deshabilitado por defecto de la fuente original.
  • Los trailingstops opcionales refuerzan la orden de protección una vez que el precio se mueve a favor de la posición en más que la distancia de seguimiento medida en puntos.
  • Todas las órdenes de protección se cancelan automáticamente cuando la posición se aplana o la estrategia se detiene.

Parámetros

Nombre Descripción
Candle Type Plazo utilizado para el análisis de precios (predeterminado: 1 hora).
Volume Tamaño del pedido utilizado para todas las entradas.
Fast EMA / Slow EMA Períodos para las EMA rápidas y lentas.
Envelope 1%, Envelope 0.7%, Envelope 0.3% Ancho porcentual de las tres bandas envolventes.
Buy Stop-Loss, Sell Stop-Loss Distancia en puntos entre el precio de entrada y el stop-loss inicial para operaciones largas o cortas.
Buy Take-Profit, Sell Take-Profit Distancia en puntos para los niveles de toma de ganancias fijos opcionales.
Buy Trailing, Sell Trailing Distancia del trailing stop en puntos para posiciones largas o cortas.
Use Trading Hours Habilita el filtro de ventana de tiempo.
From Hour, To Hour Límites horarios inclusivos para la apertura de nuevas posiciones. La ventana cierra alrededor de la medianoche si From es mayor que To.

Notas de uso

  1. Debido a que las distancias de parada se definen en puntos, se multiplican internamente por la seguridad PriceStep. Asegúrese de que este paso coincida con el instrumento utilizado para operar.
  2. La longitud rápida EMA es intencionalmente muy corta para reflejar al experto en MT4. Aumentarlo cambiará drásticamente la frecuencia de la señal.
  3. El asesor original también permitía la inclusión en listas blancas de cuentas y alertas sonoras. Se omitieron porque son específicos de la plataforma y no afectan la lógica de los pedidos.
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>
/// Channels strategy - EMA envelope breakout.
/// Buys when price breaks above fast EMA + offset, sells when it breaks below.
/// Uses slow EMA as trend filter.
/// </summary>
public class ChannelsStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;

	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 ChannelsStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 30)
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");

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

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); _prevFast = 0m; _prevSlow = 0m; _hasPrev = false; }

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

		_hasPrev = false;

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

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

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

		if (!_hasPrev)
		{
			_prevFast = fast;
			_prevSlow = slow;
			_hasPrev = true;
			return;
		}

		var close = candle.ClosePrice;

		// Buy: price crosses above fast EMA, fast EMA above slow EMA (uptrend)
		if (close > fast && fast > slow && _prevFast <= _prevSlow && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Sell: price crosses below fast EMA, fast EMA below slow EMA (downtrend)
		else if (close < fast && fast < slow && _prevFast >= _prevSlow && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
		// Exit long when fast crosses below slow
		else if (Position > 0 && fast < slow && _prevFast >= _prevSlow)
		{
			SellMarket();
		}
		// Exit short when fast crosses above slow
		else if (Position < 0 && fast > slow && _prevFast <= _prevSlow)
		{
			BuyMarket();
		}

		_prevFast = fast;
		_prevSlow = slow;
	}
}