Ver en GitHub

MACD Estrategia de cruce de señales

Descripción general

Este ejemplo convierte el MetaTrader 4 asesor experto original MACD_v1.mq4 en una estrategia de alto nivel StockSharp. El algoritmo rastrea los cruces de convergencia y divergencia del promedio móvil (MACD) y opera en la dirección de la nueva tendencia. Las salidas protectoras opcionales replican el comportamiento del asesor original: un stop-loss, una toma de ganancias distante y un objetivo de ganancias parcial que liquida la mitad de la posición actual.

Lógica de trading

  1. Fuente de datos: la estrategia se suscribe a la serie de velas configuradas (velas de 5 minutos de forma predeterminada) y vincula un indicador MovingAverageConvergenceDivergenceSignal.
  2. Condiciones de entrada:
    • Ingrese long cuando la línea MACD cruce por encima de la línea de señal. Si una posición corta está activa, se cierra antes de abrir la larga.
    • Ingrese short cuando la línea MACD cruce por debajo de la línea de señal. Si existe una posición larga, se cierra primero.
  3. Condiciones de salida:
    • El cruce opuesto MACD cierra la posición actual y abre una nueva posición en la dirección opuesta.
    • Una toma de ganancias y un stop-loss configurables administrados por StartProtection reflejan los parámetros originales de TP/SL (medidos en puntos del instrumento).
    • Un objetivo de beneficio parcial cierra la mitad de la posición abierta una vez que el precio avanza una cantidad específica desde el nivel de entrada. La salida parcial se activa sólo una vez por posición.

Parámetros

Nombre Predeterminado Descripción
Período rápido 23 Longitud rápida de EMA para el cálculo MACD (refleja el parámetro MQL a = 2300).
Período lento 40 Longitud lenta de EMA para el cálculo MACD (b = 4000 en la fuente).
Período de señal 8 Longitud de la línea de señal (c = 800 en la fuente).
Obtener ganancias 500 Distancia en puntos de precio para la orden protectora de toma de ganancias. Establezca en 0 para desactivar.
Detener pérdidas 80 Distancia en puntos de precio para la orden protectora de stop-loss. Establezca en 0 para desactivar.
Beneficio parcial 70 Distancia en puntos de precio para cerrar la mitad de la posición abierta. Establezca en 0 para deshabilitar las salidas parciales.
Tipo de vela marco de tiempo de 5 minutos Serie de velas utilizadas para los cálculos de indicadores.

Notas

  • Los parámetros del indicador se escalaron a longitudes típicas de MACD (23/40/8) porque el script MQL los expresaba como centésimas (2300/4000/800).
  • La estrategia restaura automáticamente la bandera de salida parcial cada vez que se acumula una nueva posición.
  • Los ayudantes de dibujo de gráficos resaltan velas, valores MACD y las operaciones de la estrategia cuando hay un panel de gráfico disponible.
  • El manejo de volúmenes se basa en la propiedad de la estrategia base Volume. Ajústelo antes de comenzar la estrategia para que coincida con el tamaño de su instrumento.
using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

public class MacdSignalCrossoverStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _signalPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private bool _prevMacdAboveSignal;
	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 SignalPeriod
	{
		get => _signalPeriod.Value;
		set => _signalPeriod.Value = value;
	}

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public MacdSignalCrossoverStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 23);
		_slowPeriod = Param(nameof(SlowPeriod), 40);
		_signalPeriod = Param(nameof(SignalPeriod), 8);
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame());
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevMacdAboveSignal = false;
		_hasPrev = false;
	}

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

		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;

		var macdTyped = macdValue as MovingAverageConvergenceDivergenceSignalValue;
		if (macdTyped == null)
			return;

		var macdLine = macdTyped.Macd;
		var signalLine = macdTyped.Signal;

		if (macdLine == null || signalLine == null)
			return;

		var isMacdAboveSignal = macdLine.Value > signalLine.Value;

		if (!_hasPrev)
		{
			_hasPrev = true;
			_prevMacdAboveSignal = isMacdAboveSignal;
			return;
		}

		var crossedAbove = isMacdAboveSignal && !_prevMacdAboveSignal;
		var crossedBelow = !isMacdAboveSignal && _prevMacdAboveSignal;

		if (crossedAbove)
		{
			if (Position < 0)
				BuyMarket();
			if (Position <= 0)
				BuyMarket();
		}
		else if (crossedBelow)
		{
			if (Position > 0)
				SellMarket();
			if (Position >= 0)
				SellMarket();
		}

		_prevMacdAboveSignal = isMacdAboveSignal;
	}
}