Ver en GitHub

Estrategia de Velas MACD

Esta estrategia reproduce el experto de MetaTrader "Exp_MACDCandle". Convierte la salida de color de un indicador de velas basado en MACD en señales de trading utilizando la API de alto nivel de StockSharp.

Concepto

El indicador MACD Candle construye velas sintéticas a partir de los valores MACD calculados sobre los precios de apertura y cierre. Si el MACD calculado sobre el cierre está por encima del MACD calculado sobre la apertura, la vela se considera alcista (color 2). Lo contrario genera una vela bajista (color 0). Un color neutro (1) aparece cuando ambos valores son iguales.

La estrategia abre posiciones largas cuando aparece una vela alcista después de una no alcista, y abre posiciones cortas cuando una vela bajista sigue a una no bajista. Las posiciones existentes se revierten en la nueva dirección.

Parámetros

  • FastLength – período de la EMA rápida para MACD (predeterminado 12).
  • SlowLength – período de la EMA lenta para MACD (predeterminado 26).
  • SignalLength – período de la línea de señal para MACD (predeterminado 9).
  • CandleType – tipo de vela utilizado para los cálculos, predeterminado TimeFrameCandle con un período de cuatro horas.

Todos los parámetros son configurables y soportan optimización.

Reglas de Entrada y Salida

  • Entrada larga: el MACD sobre el cierre sube por encima del MACD sobre la apertura mientras la vela anterior no era alcista.
  • Entrada corta: el MACD sobre la apertura sube por encima del MACD sobre el cierre mientras la vela anterior no era bajista.
  • Salida: la estrategia cierra la posición actual cuando ocurre una señal opuesta; no se aplica stop‑loss ni take‑profit explícito.

Notas

  • La estrategia utiliza órdenes de mercado (BuyMarket y SellMarket).
  • Las señales se evalúan únicamente en velas terminadas para evitar el ruido.
  • El ejemplo está destinado a fines educativos y no incluye gestión de riesgos.
using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Strategy based on the MACD Candle indicator.
/// Compares MACD computed on opens vs closes.
/// </summary>
public class MacdCandleStrategy : Strategy
{
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<int> _signalLength;
	private readonly StrategyParam<DataType> _candleType;

	private MovingAverageConvergenceDivergenceSignal _macdOpen;
	private MovingAverageConvergenceDivergenceSignal _macdClose;
	private decimal? _previousColor;

	public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
	public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
	public int SignalLength { get => _signalLength.Value; set => _signalLength.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public MacdCandleStrategy()
	{
		_fastLength = Param(nameof(FastLength), 12)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicator")
			.SetOptimize(8, 16, 2);

		_slowLength = Param(nameof(SlowLength), 26)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicator")
			.SetOptimize(20, 40, 2);

		_signalLength = Param(nameof(SignalLength), 9)
			.SetGreaterThanZero()
			.SetDisplay("Signal", "Signal period", "Indicator")
			.SetOptimize(5, 15, 1);

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

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_previousColor = null;
		_macdOpen = default;
		_macdClose = default;
	}

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

		_macdOpen = new MovingAverageConvergenceDivergenceSignal
		{
			Macd =
			{
				ShortMa = { Length = FastLength },
				LongMa = { Length = SlowLength },
			},
			SignalMa = { Length = SignalLength }
		};

		_macdClose = new MovingAverageConvergenceDivergenceSignal
		{
			Macd =
			{
				ShortMa = { Length = FastLength },
				LongMa = { Length = SlowLength },
			},
			SignalMa = { Length = SignalLength }
		};

		Indicators.Add(_macdOpen);
		Indicators.Add(_macdClose);

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

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

		var openInput = new DecimalIndicatorValue(_macdOpen, candle.OpenPrice, candle.OpenTime) { IsFinal = true };
		var closeInput = new DecimalIndicatorValue(_macdClose, candle.ClosePrice, candle.OpenTime) { IsFinal = true };

		var openValue = _macdOpen.Process(openInput);
		var closeValue = _macdClose.Process(closeInput);

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		var openMacd = ((IMovingAverageConvergenceDivergenceSignalValue)openValue).Macd;
		var closeMacd = ((IMovingAverageConvergenceDivergenceSignalValue)closeValue).Macd;

		if (openMacd == null || closeMacd == null)
			return;

		var color = openMacd < closeMacd ? 2m : openMacd > closeMacd ? 0m : 1m;

		if (_previousColor is null)
		{
			_previousColor = color;
			return;
		}

		if (color == 2m && _previousColor < 2m)
		{
			if (Position < 0)
				BuyMarket();
			if (Position <= 0)
				BuyMarket();
		}
		else if (color == 0m && _previousColor > 0m)
		{
			if (Position > 0)
				SellMarket();
			if (Position >= 0)
				SellMarket();
		}

		_previousColor = color;
	}
}