Ver en GitHub

Glam Trader (Confirmación de múltiples períodos de tiempo)

Descripción general

La estrategia replica el asesor experto original MetaTrader "GLAM Trader" combinando información de tres períodos de tiempo:

  • Un EMA(3) rápido en el gráfico de 15 minutos captura el sesgo de tendencia a corto plazo.
  • Un filtro de Laguerre con gamma 0,7 aplicado a velas de 5 minutos mide si el precio cotiza por encima o por debajo de su trayectoria suavizada.
  • El Awesome Oscillator en las velas horarias proporciona una verificación de impulso alineada con la definición de Bill Williams'.

Sólo cuando los tres componentes están de acuerdo la estrategia abre una operación, con el objetivo de filtrar el ruido que aparecería cuando cualquier período de tiempo se evalúa de forma aislada.

Lógica de trading

  1. Preparación de datos
    • Las velas de 15 minutos alimentan un ExponentialMovingAverage con una longitud EmaPeriod (predeterminado 3).
    • Las velas de 5 minutos alimentan un LaguerreFilter con suavizado LaguerreGamma.
    • Las velas de 60 minutos alimentan un AwesomeOscillator.
    • Para cada período de tiempo, se almacena el último cierre de vela finalizado para reproducir la comparación original entre indicador y precio.
  2. Condiciones de entrada
    • Largo: el EMA está por encima del cierre actual de 15 minutos, Laguerre está por encima del último cierre de 5 minutos y Awesome Oscillator está por encima del último cierre por hora.
    • Corto: cada uno de los tres indicadores debe situarse por debajo de su cierre correspondiente.
  3. Gestión de riesgos
    • Separe las distancias de stop-loss y take-profit (expresadas en puntos de instrumento) para operaciones largas y cortas.
    • Los trailingstops se activan una vez que el precio recorre al menos la distancia de seguimiento especificada más allá del precio de entrada. El stop se mueve en la dirección de la tendencia sin retroceder.
    • Todas las acciones de protección (take-profit, stop-loss, trailing stop) cierran la posición completa con órdenes de mercado, reflejando la implementación de MQL.

Parámetros

Nombre Descripción Predeterminado
TradeVolume Tamaño del pedido para nuevas posiciones. 0.1
PrimaryCandleType Periodo utilizado para la señal EMA y principal. velas de 15 minutos
LaguerreCandleType Plazo analizado por el filtro de Laguerre. velas de 5 minutos
AwesomeCandleType Marco de tiempo analizado por Awesome Oscillator. velas de 60 minutos
EmaPeriod EMA duración en el período de tiempo principal. 3
LaguerreGamma Parámetro gamma para el filtro de Laguerre. 0,7
LongStopLossPoints Distancia de stop-loss para operaciones largas, en puntos. 20
ShortStopLossPoints Distancia de stop-loss para operaciones cortas, en puntos. 20
LongTakeProfitPoints Distancia de obtención de beneficios para operaciones largas, en puntos. 50
ShortTakeProfitPoints Distancia de obtención de beneficios para operaciones cortas, en puntos. 50
LongTrailingPoints Distancia de seguimiento para operaciones largas, en puntos. 15
ShortTrailingPoints Distancia de seguimiento para operaciones cortas, en puntos. 15

Notas

  • La estrategia se suscribe a tres flujos de velas independientes y mantiene solo los valores finales más recientes, evitando los buffers de historial manuales.
  • Todos los comentarios y mensajes de registro permanecen en inglés para mayor claridad, de acuerdo con las convenciones del proyecto.
  • Ajuste los parámetros de riesgo basados en puntos de acuerdo con el PriceStep del instrumento para que los niveles de protección reflejen el tamaño del tick del corredor.
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>
/// Glam Trader strategy - EMA crossover with momentum confirmation.
/// Buys when fast EMA crosses above slow EMA and momentum is positive.
/// Sells when fast EMA crosses below slow EMA and momentum is negative.
/// </summary>
public class GlamTraderSimpleStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _momentumPeriod;
	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 int MomentumPeriod { get => _momentumPeriod.Value; set => _momentumPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public GlamTraderSimpleStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 8)
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

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

		_momentumPeriod = Param(nameof(MomentumPeriod), 14)
			.SetDisplay("Momentum Period", "Momentum lookback", "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 mom = new Momentum { Length = MomentumPeriod };

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

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

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

		// Fast crosses above slow + positive momentum = buy
		if (_prevFast <= _prevSlow && fast > slow && mom > 0 && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Fast crosses below slow + negative momentum = sell
		else if (_prevFast >= _prevSlow && fast < slow && mom < 0 && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevFast = fast;
		_prevSlow = slow;
	}
}