Ver en GitHub

Estrategia Expert MACD EURUSD 1 Hora

Descripción general

Esta estrategia es una traducción en C# del asesor experto de MetaTrader 5 Expert MACD EURUSD 1 Hour. Opera en velas de una hora usando el indicador MACD con períodos corto, largo y de señal de 5 / 15 / 3. La estrategia busca un fuerte cambio de momentum donde la línea principal del MACD cruza por encima o por debajo del nivel cero mientras la línea de señal confirma el movimiento. Se usa un trailing stop para proteger las posiciones abiertas, y las operaciones se cierran cuando la pendiente del MACD se vuelve contra la posición actual.

Parámetros

  • FastLength – período de la EMA rápida para MACD (predeterminado: 5).
  • SlowLength – período de la EMA lenta para MACD (predeterminado: 15).
  • SignalLength – período de la línea de señal para MACD (predeterminado: 3).
  • TrailingPoints – distancia del trailing stop en puntos de precio (predeterminado: 25).
  • CandleType – marco temporal de las velas (predeterminado: 1 hora).
  • La propiedad Volume de la estrategia controla el tamaño de la orden.

Lógica de negociación

Entrada larga

  1. Valores de la línea de señal: mac8 > mac7 > mac6 y mac6 < mac5 (línea de señal subiendo).
  2. Valores de la línea principal: mac4 > mac3 < mac2 < mac1 (línea principal subiendo tras una caída).
  3. mac2 < -0.00020, mac4 < 0 y mac1 > 0.00020 – línea principal cruza por encima de cero.
  4. Si todas las condiciones se cumplen y no hay posición larga abierta, comprar a mercado.

Entrada corta

  1. Valores de la línea de señal: mac8 < mac7 < mac6 y mac6 > mac5 (línea de señal bajando).
  2. Valores de la línea principal: mac4 < mac3 > mac2 > mac1 (línea principal bajando tras un pico).
  3. mac2 > 0.00020, mac4 > 0 y mac1 < -0.00035 – línea principal cruza por debajo de cero.
  4. Si todas las condiciones se cumplen y no hay posición corta abierta, vender a mercado.

Reglas de salida

  • Cerrar un largo cuando el valor principal actual está por debajo del anterior.
  • Cerrar un corto cuando el valor principal actual está por encima del anterior.
  • El trailing stop se actualiza en cada vela y sale si el precio cruza el nivel del stop.

Notas

Este ejemplo demuestra el uso de la API de alto nivel de StockSharp con vinculación de indicadores y gestión manual del trailing stop. Está destinado a fines educativos y no incluye gestión de dinero más allá del parámetro fijo Volume.

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>
/// MACD based strategy converted from MetaTrader 5 Expert Advisor.
/// Uses MACD indicator with custom pattern checks on recent values and optional trailing stop.
/// </summary>
public class ExpertMacdEurusd1HourStrategy : Strategy
{
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<int> _signalLength;
	private readonly StrategyParam<decimal> _trailingPoints;
	private readonly StrategyParam<DataType> _candleType;
	private ExponentialMovingAverage _fastEma;
	private ExponentialMovingAverage _slowEma;
	private ExponentialMovingAverage _signalEma;

	private decimal _main0, _main1;
	private decimal _signal0, _signal1;
	private int _counter;

	/// <summary>
	/// Fast EMA length for MACD.
	/// </summary>
	public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }

	/// <summary>
	/// Slow EMA length for MACD.
	/// </summary>
	public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }

	/// <summary>
	/// Signal line length for MACD.
	/// </summary>
	public int SignalLength { get => _signalLength.Value; set => _signalLength.Value = value; }

	/// <summary>
	/// Trailing stop distance in price points.
	/// </summary>
	public decimal TrailingPoints { get => _trailingPoints.Value; set => _trailingPoints.Value = value; }

	/// <summary>
	/// Candle type for analysis.
	/// </summary>
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	/// <summary>
	/// Initialize strategy with default parameters.
	/// </summary>
	public ExpertMacdEurusd1HourStrategy()
	{
		_fastLength = Param(nameof(FastLength), 12)
			.SetDisplay("Fast Length", "Fast EMA length for MACD", "Parameters")
			;

		_slowLength = Param(nameof(SlowLength), 26)
			.SetDisplay("Slow Length", "Slow EMA length for MACD", "Parameters")
			;

		_signalLength = Param(nameof(SignalLength), 9)
			.SetDisplay("Signal Length", "Signal length for MACD", "Parameters")
			;

		_trailingPoints = Param(nameof(TrailingPoints), 25m)
			.SetDisplay("Trailing Points", "Trailing stop distance in points", "Risk");

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

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_main0 = _main1 = 0m;
		_signal0 = _signal1 = 0m;
		_counter = 0;
		_fastEma = null;
		_slowEma = null;
		_signalEma = null;
	}

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

		_fastEma = new ExponentialMovingAverage { Length = FastLength };
		_slowEma = new ExponentialMovingAverage { Length = SlowLength };
		_signalEma = new ExponentialMovingAverage { Length = SignalLength };

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

		StartProtection(
			new Unit(2000m, UnitTypes.Absolute),
			new Unit(1000m, UnitTypes.Absolute));

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawOwnTrades(area);
		}
	}

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

		var fast = _fastEma.Process(candle.ClosePrice, candle.CloseTime, true).ToDecimal();
		var slow = _slowEma.Process(candle.ClosePrice, candle.CloseTime, true).ToDecimal();
		if (!_fastEma.IsFormed || !_slowEma.IsFormed)
			return;

		var main = fast - slow;
		var signal = _signalEma.Process(main, candle.CloseTime, true).ToDecimal();
		if (!_signalEma.IsFormed)
			return;

		// shift stored values
		_main1 = _main0;
		_main0 = main;

		_signal1 = _signal0;
		_signal0 = signal;

		if (_counter < 3)
		{
			_counter++;
			return;
		}

		var buySignal = _main1 <= _signal1 && _main0 > _signal0 && _main0 < 0m;
		var sellSignal = _main1 >= _signal1 && _main0 < _signal0 && _main0 > 0m;

		if (buySignal && Position <= 0)
			BuyMarket();
		else if (sellSignal && Position >= 0)
			SellMarket();
	}
}