Ver en GitHub

Estrategia Moving Averages

Visión general

Esta estrategia replica el asesor experto clásico de cruce de medias móviles de MQL. Usa APIs StockSharp de alto nivel para monitorizar dos medias móviles simples calculadas desde la serie de velas seleccionada. Las señales se generan cuando la media rápida cruza la lenta, y la estrategia puede cerrar opcionalmente una posición activa cuando ocurre el cruce opuesto.

Lógica de negociación

  • Suscribirse al tipo de vela configurado y calcular SMA rápida y lenta en cada vela completada.
  • Detectar un cruce alcista cuando la SMA rápida pasa de estar por debajo a estar por encima de la SMA lenta. Si no hay posición activa, abrir un largo con el volumen especificado.
  • Detectar un cruce bajista cuando la SMA rápida pasa de estar por encima a estar por debajo de la SMA lenta. Si no hay posición activa, abrir un corto con el volumen especificado.
  • Opcionalmente cerrar de inmediato una posición existente cuando se detecta el cruce opuesto, replicando el interruptor "Close on Opposite Signal" del script original.

Gestión de riesgo

  • Aplicar stop loss y take profit fijos expresados en puntos de precio. Ambos niveles se recalculan para cada nueva entrada.
  • Mover el stop protector a break-even después de que el precio recorra la distancia de activación configurada y mantener un desplazamiento adicional como beneficio bloqueado.
  • Activar trailing stop cuando la posición gane la distancia inicial definida. El stop se desplaza usando el precio de vela más favorable y nunca se mueve contra la operación.

Parámetros

  • Fast MA Period: longitud de la SMA rápida usada para detectar cruces.
  • Slow MA Period: longitud de la SMA lenta usada para detectar cruces.
  • Trade Volume: tamaño de orden en lotes.
  • Stop Loss (points): distancia en puntos del instrumento para el stop loss inicial.
  • Take Profit (points): distancia en puntos del instrumento para el take profit inicial.
  • Break-even Trigger: distancia de beneficio que activa mover el stop a break-even.
  • Break-even Offset: puntos adicionales mantenidos como beneficio después de activar break-even.
  • Trailing Start: distancia de beneficio requerida antes de habilitar trailing stop.
  • Trailing Distance: distancia mantenida entre precio y trailing stop.
  • Close On Opposite: si cerrar una operación activa cuando aparece un cruce opuesto.
  • Candle Type: serie de velas usada para cálculos de indicadores.

Notas de uso

  • Asegúrese de que la estrategia esté conectada a un instrumento con PriceStep válido. Cuando no hay paso disponible, se usa un valor de 1.
  • La gestión de trailing y break-even opera sobre velas completadas, igual que el EA original que reacciona al cierre de barra.
  • Optimice las longitudes de medias móviles y los ajustes de riesgo para adaptar el sistema a distintos mercados o marcos temporales.
using System;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Moving Averages Crossover strategy: EMA crossover.
/// Buys when fast EMA crosses above slow EMA. Sells on cross below.
/// </summary>
public class MovingAveragesCrossoverStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;

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

	public int FastPeriod
	{
		get => _fastPeriod.Value;
		set => _fastPeriod.Value = value;
	}

	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.Value = value;
	}

	public MovingAveragesCrossoverStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");

		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 30)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
	}

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

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };

		decimal? prevFast = null;
		decimal? prevSlow = null;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, slow, (candle, fastVal, slowVal) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				if (prevFast.HasValue && prevSlow.HasValue)
				{
					var crossUp = prevFast.Value <= prevSlow.Value && fastVal > slowVal;
					var crossDown = prevFast.Value >= prevSlow.Value && fastVal < slowVal;

					if (crossUp && Position <= 0)
						BuyMarket();
					else if (crossDown && Position >= 0)
						SellMarket();
				}

				prevFast = fastVal;
				prevSlow = slowVal;
			})
			.Start();

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