Ver en GitHub

Estrategia de histograma del día de apertura MACD

Descripción general

Esta estrategia replica el experto MetaTrader "2 1000 1 0,7% 0,5 500lev st" ingresando una operación al comienzo de cada nuevo día de negociación y filtrando la dirección con la pendiente del histograma MACD. El sistema fue diseñado para velas por hora y se basa en parámetros fijos de administración de dinero convertidos a partir de la configuración original MQL.

Lógica de trading

  • La estrategia monitorea las velas cada hora y detecta la primera vela de cada nuevo día.
  • Evalúa el histograma MACD en las dos velas completadas más recientes del día anterior.
  • Si el histograma cae entre esas dos barras, el sistema abre una posición larga en la primera vela del nuevo día.
  • Si el histograma aumentó, en su lugar abre una posición corta.
  • Sólo puede haber una posición activa a la vez. Las señales opuestas cierran la operación actual antes de abrir la nueva dirección.

Gestión del riesgo

  • Distancia inicial de stop-loss: 875 puntos (convertidos a precio multiplicando por el paso del precio del instrumento).
  • Distancia de obtención de beneficios: 510 puntos.
  • Distancia del trailing stop: 2172 puntos. El stop sigue el precio más alto (largo) o más bajo (corto) alcanzado desde la entrada y anula el stop inicial cuando se vuelve más ajustado.
  • La opción de equilibrio original se deshabilitó y, por lo tanto, se omitió aquí.

Parámetros

Nombre Descripción Predeterminado
CandleType Serie de velas utilizadas por la estrategia (por hora por defecto). velas de 1 hora
MacdFastPeriod Período EMA rápida para el MACD. 58
MacdSlowPeriod Período lento de EMA para el MACD. 195
MacdSignalPeriod Período de línea de señal para el MACD. 183
StopLossPoints Distancia de stop-loss expresada en puntos del instrumento. 875
TakeProfitPoints Distancia de toma de ganancias en puntos. 510
TrailingStopPoints Distancia del trailing stop en puntos. 2172

Notas

  • La estrategia utiliza sólo velas completadas para evitar la anticipación intrabarra, reflejando la opción "Usar valor de barra anterior" del experto fuente.
  • Las salidas finales y fijas se manejan internamente, por lo que las protecciones adicionales de cartera deben permanecer deshabilitadas para evitar el doble manejo de las paradas.
  • La lógica supone que el corredor utiliza definiciones de puntos estándar (paso de precio). Ajuste los parámetros si el instrumento utiliza un tamaño de tick diferente.
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Day Opening MACD Histogram strategy: MACD histogram direction.
/// Buys when MACD histogram turns positive, sells when turns negative.
/// </summary>
public class DayOpeningMacdHistogramStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _signalPeriod;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private decimal _prevHistogram;
	private int _candlesSinceTrade;
	private bool _hasPrev;

	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 int SignalPeriod { get => _signalPeriod.Value; set => _signalPeriod.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public DayOpeningMacdHistogramStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_fastPeriod = Param(nameof(FastPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("MACD Fast", "MACD fast EMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 26)
			.SetGreaterThanZero()
			.SetDisplay("MACD Slow", "MACD slow EMA period", "Indicators");
		_signalPeriod = Param(nameof(SignalPeriod), 9)
			.SetGreaterThanZero()
			.SetDisplay("Signal Period", "MACD signal period", "Indicators");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 4)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevHistogram = 0;
		_candlesSinceTrade = SignalCooldownCandles;
		_hasPrev = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevHistogram = 0;
		_candlesSinceTrade = SignalCooldownCandles;
		_hasPrev = false;
		var macd = new MovingAverageConvergenceDivergenceSignal
		{
			Macd = { ShortMa = { Length = FastPeriod }, LongMa = { Length = SlowPeriod } },
			SignalMa = { Length = SignalPeriod }
		};
		var subscription = SubscribeCandles(CandleType);
		subscription.BindEx(macd, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!macdValue.IsFinal) return;

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		if (macdValue is not MovingAverageConvergenceDivergenceSignalValue typed) return;
		if (typed.Macd is not decimal macdMain || typed.Signal is not decimal signal) return;

		var histogram = macdMain - signal;

		if (_hasPrev)
		{
			if (_prevHistogram <= 0 && histogram > 0 && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
			else if (_prevHistogram >= 0 && histogram < 0 && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
		}

		_prevHistogram = histogram;
		_hasPrev = true;
	}
}