Ver en GitHub

Estrategia EurGbp EA

Visión general

La estrategia EurGbp EA replica el asesor experto original de MetaTrader comparando el momentum MACD horario de EUR/USD y GBP/USD mientras opera en el instrumento principal configurado (normalmente EUR/GBP). El enfoque explota la fuerza relativa entre los pares principales del euro y la libra para anticipar movimientos en el cruce.

Indicadores

  • MACD (12, 26, 9) en EUR/USD (señal e histograma).
  • MACD (12, 26, 9) en GBP/USD (señal e histograma).

Ambos indicadores se evalúan en el mismo marco temporal seleccionado mediante el parámetro Candle Type (1 hora por defecto).

Lógica de negociación

  1. Suscribirse a velas del instrumento negociado más EUR/USD y GBP/USD.
  2. Calcular señal e histograma MACD para ambos pares de referencia.
  3. Condición de compra:
    • Histograma EUR/USD < histograma GBP/USD, y
    • Señal EUR/USD > señal GBP/USD,
    • Sin posición larga existente (o una corta existente que será aplanada).
  4. Condición de venta:
    • Histograma GBP/USD < histograma EUR/USD, y
    • Señal GBP/USD > señal EUR/USD,
    • Sin posición corta existente (o una larga existente que será aplanada).
  5. Solo se permite una operación por barra en cada dirección para evitar entradas duplicadas.
  6. Las órdenes de stop-loss y take-profit se adjuntan inmediatamente después de la entrada usando las distancias configuradas en puntos.

Parámetros

Nombre Descripción Predeterminado
Candle Type Marco temporal para todas las suscripciones de velas. 1 hora
EURUSD Security Instrumento que proporciona velas EUR/USD. Debe configurarse
GBPUSD Security Instrumento que proporciona velas GBP/USD. Debe configurarse
Volume Volumen de orden (lotes). 0.01
Stop Loss Stop protector en pasos de precio. 75
Take Profit Objetivo de beneficio en pasos de precio. 46

Gestión de riesgo

  • Stop Loss y Take Profit se miden en pasos de precio del instrumento negociado. Asegúrese de que el instrumento tenga un valor PriceStep válido.
  • La protección se inicia automáticamente cuando se lanza la estrategia (StartProtection).
  • Si cualquiera de las distancias es cero, se omite la orden protectora correspondiente.

Notas de uso

  • Asigne el instrumento principal de negociación a la instancia de estrategia antes de iniciar (por ejemplo, EUR/GBP).
  • Configure EURUSD Security y GBPUSD Security para que referencien fuentes de datos disponibles en su conexión.
  • La estrategia requiere datos sincronizados para los tres instrumentos en el marco temporal elegido para generar señales de forma fiable.
  • Solo se usan órdenes de mercado. Las posiciones opuestas existentes se cierran enviando el volumen inverso.

Notas de conversión

  • Las entradas originales _Lots, _SL, _TP, _MagicNumber, _Comment, _OnlyOneOpenedPos y _AutoDigits se asignan a parámetros StockSharp o comportamiento integrado.
  • Las rutinas auxiliares de cierre de órdenes de la versión MQL se reemplazan por la gestión de órdenes protectoras de alto nivel de StockSharp.
  • El manejo de errores y los bucles de reintento del código MQL se omiten porque el modelo de ejecución de StockSharp ya gestiona estados de órdenes y reintentos.
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 EurGbpEaStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private ExponentialMovingAverage _fast;
	private ExponentialMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _cooldown;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
	public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }

	public EurGbpEaStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
		_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
		_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_fast = null; _slow = null;
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_fast = new ExponentialMovingAverage { Length = FastPeriod };
		_slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
		subscription.Bind(_fast, _slow, ProcessCandle);
		subscription.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
		if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }

		var close = candle.ClosePrice;
		var step = Security?.PriceStep ?? 1m;

		if (Position > 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}
		else if (Position < 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}

		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }

		_prevFast = fastValue; _prevSlow = slowValue;
	}
}