Ver en GitHub

Estrategia de EA Vishal EURGBP H4

Descripción general

La Estrategia de EA Vishal EURGBP H4 replica el asesor experto original de MetaTrader que combina un filtro de entrada de cruzamiento estocástico con salidas basadas en envolventes. La lógica opera en velas H4 por defecto y usa herramientas virtuales de gestión de riesgo (stop-loss, take-profit y trailing stop opcional) definidas en pips, imitando de cerca el comportamiento de MT4.

Lógica de trading

  • Entrada – la estrategia espera un cruzamiento estocástico evaluado en las dos velas completadas más recientes. Una posición larga se abre cuando %K cruza por debajo de %D entre la barra n-2 y n-1. Una posición corta se abre en el cruzamiento opuesto. Solo puede estar activa una posición a la vez.
  • Salida – las posiciones activas se gestionan en tres capas:
    1. Ruptura de envolvente – si la siguiente barra abre más allá de la banda de envolvente anterior mientras la barra anterior abrió dentro, la posición se cierra inmediatamente.
    2. Stop-loss / take-profit virtual – los precios objetivo se calculan desde el precio de entrada usando las distancias de pip configuradas.
    3. Trailing stop opcional – cuando está habilitado y un stop-loss está definido, el nivel de stop sigue el valor más alto (para largos) o más bajo (para cortos) de la vela anterior menos/más la distancia de stop.

Parámetros

Nombre Predeterminado Descripción
Volume 0.5 Volumen de la orden en lotes para cada operación.
StopLossPips 0 Distancia hard stop-loss en pips (0 deshabilita el stop).
TakeProfitPips 22 Distancia de take-profit en pips (0 deshabilita el objetivo).
UseTrailingStop false Habilita el trailing stop virtual que sigue el extremo de la vela anterior. Requiere StopLossPips > 0.
StochasticKPeriod 6 Período de lookback para el cálculo del %K estocástico.
StochasticDPeriod 3 Período de suavizado para la línea %D.
StochasticSlowing 1 Factor de ralentización aplicado a %K.
EnvelopePeriod 32 Longitud del SMA usado como base del envolvente.
EnvelopeDeviationPercent 0.3 Desviación en porcentaje aplicada por encima/debajo del SMA para construir los envolventes.
CandleType Marco temporal H4 Serie de velas que alimenta la estrategia (por defecto son velas de cuatro horas).

Notas

  • Todos los parámetros están expuestos para optimización en StockSharp Studio.
  • Los niveles protectores se rastrean internamente y se ejecutan con órdenes de mercado cuando el rango de la vela los perfora, coincidiendo con el comportamiento del asesor experto original en eventos de nueva barra.
  • La estrategia se basa únicamente en velas terminadas, asegurando backtests deterministas y comportamiento en producción.
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 EaVishalEurgbpH4Strategy : 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 EaVishalEurgbpH4Strategy()
	{
		_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;
	}
}