Ver en GitHub

Estrategia Russian20 Momentum MA

Descripción general

La Estrategia Russian20 Momentum MA es una conversión directa del asesor experto MetaTrader 5 Russian20-hp1.mq5. El script original fue publicado por Gordago Software Corp. y se basa en un gráfico de dos horas, una media móvil simple (SMA) de 20 períodos y un indicador Momentum de 5 períodos para identificar continuaciones de tendencias a corto plazo. La implementación en StockSharp mantiene el mismo núcleo analítico mientras adapta el manejo de órdenes y la gestión del dinero a la API de estrategia de alto nivel.

Lógica de trading

  • Frecuencia de datos: Trabaja con el tipo de vela definido por el usuario (el predeterminado son velas de 2 horas, coincidiendo con el marco temporal MQL5 PERIOD_H2). La lógica se ejecuta solo cuando se cierra una vela.
  • Indicadores:
    • Media móvil simple con período configurable (predeterminado 20).
    • Indicador Momentum con período configurable (predeterminado 5). El nivel neutro de Momentum es 100, reflejando la salida predeterminada de MQL5.
  • Entrada larga: Se activa cuando se satisfacen todas las siguientes condiciones en la última vela cerrada:
    1. El precio de cierre está por encima de la SMA.
    2. El valor de Momentum es mayor que 100 (aceleración positiva).
    3. El precio de cierre es más alto que el cierre de la vela anterior, asegurando momentum ascendente en la acción del precio.
  • Entrada corta: Se activa cuando se satisfacen todas las siguientes condiciones:
    1. El precio de cierre está por debajo de la SMA.
    2. El valor de Momentum es menor que 100 (aceleración negativa).
    3. El precio de cierre es más bajo que el cierre de la vela anterior.
  • Salida larga: La estrategia liquida posiciones largas cuando Momentum cae por debajo de 100 o cuando se cruza un umbral de stop-loss o take-profit de protección.
  • Salida corta: La estrategia liquida posiciones cortas cuando Momentum sube por encima de 100 o cuando se alcanzan los umbrales de protección configurados.

Gestión de riesgos

El asesor experto MQL5 original coloca órdenes fijas de stop loss y take profit en "pips" ajustados para precios Forex de 4 y 5 dígitos. La conversión en C# reproduce este comportamiento:

  • Calculando un tamaño de pip ajustado a partir del PriceStep del instrumento. Para símbolos con tres o cinco decimales, el tamaño del pip equivale a PriceStep * 10, de lo contrario equivale a PriceStep.
  • Traduciendo las entradas del usuario para stop loss y take profit en distancias de precio absolutas.
  • Monitoreando la acción del precio en cada vela cerrada y cerrando la posición cuando el precio cruza los umbrales calculados.

Parámetros

Parámetro Valor predeterminado Descripción
CandleType Velas de 2 horas Tipo de datos utilizado para la generación de señales.
MovingAverageLength 20 Retrospectiva para el filtro SMA.
MomentumPeriod 5 Retrospectiva para el indicador Momentum.
StopLossBuyPips 50 Distancia de stop-loss largo expresada en pips. Poner 0 para deshabilitar.
TakeProfitBuyPips 50 Distancia de take-profit largo en pips. Poner 0 para deshabilitar.
StopLossSellPips 50 Distancia de stop-loss corto en pips. Poner 0 para deshabilitar.
TakeProfitSellPips 50 Distancia de take-profit corto en pips. Poner 0 para deshabilitar.

Todos los parámetros numéricos están expuestos a través de StrategyParam<T> y marcados como optimizables cuando corresponde, permitiendo backtesting y optimización con herramientas de StockSharp.

Notas de implementación

  • La estrategia utiliza la API de alto nivel SubscribeCandles().Bind(...) para transmitir datos de velas y obtener simultáneamente valores de SMA y Momentum sin gestión manual de indicadores.
  • Los niveles de Momentum se evalúan exactamente como en el script MQL5 (100 como nivel neutro). Cualquier brecha más allá de los offsets de stop-loss/take-profit activa una salida de mercado, imitando fielmente la lógica original de colocación de órdenes.
  • El cierre anterior se almacena en caché para verificar el momentum del precio sin recurrir a búsquedas en colecciones históricas, en línea con las directrices de rendimiento del proyecto.
  • Los ganchos de visualización (DrawCandles, DrawIndicator, DrawOwnTrades) están conectados por conveniencia cuando el entorno host admite gráficos.

Consejos de uso

  • El marco temporal y los parámetros predeterminados corresponden a la configuración original del autor. Ajuste el tipo de vela cuando trabaje con instrumentos que no producen barras de 2 horas.
  • Al operar activos cotizados con tamaños de tick no convencionales, revise el tamaño de pip calculado para asegurarse de que las distancias de stop-loss y take-profit sean realistas.
  • La estrategia está diseñada para una única posición abierta a la vez. Las operaciones manuales externas o las posiciones simultáneas en el mismo instrumento pueden interferir con la lógica de salida integrada.
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Russian20 Momentum MA strategy. Combines SMA filter with momentum confirmation.
/// </summary>
public class Russian20MomentumMaStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _maPeriod;
	private readonly StrategyParam<int> _momPeriod;

	private decimal? _prevMom;

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

	public int MaPeriod
	{
		get => _maPeriod.Value;
		set => _maPeriod.Value = value;
	}

	public int MomPeriod
	{
		get => _momPeriod.Value;
		set => _momPeriod.Value = value;
	}

	public Russian20MomentumMaStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe", "General");

		_maPeriod = Param(nameof(MaPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("MA Period", "SMA period for trend filter", "Indicators");

		_momPeriod = Param(nameof(MomPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Momentum Period", "Momentum lookback", "Indicators");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevMom = null;
	}

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

		_prevMom = null;

		var sma = new SimpleMovingAverage { Length = MaPeriod };
		var mom = new Momentum { Length = MomPeriod };

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

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
		{
			_prevMom = momVal;
			return;
		}

		if (_prevMom == null)
		{
			_prevMom = momVal;
			return;
		}

		var close = candle.ClosePrice;

		// Price above MA + momentum crosses above zero → buy
		if (close > maVal && _prevMom.Value <= 100m && momVal > 100m && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Price below MA + momentum crosses below zero → sell
		else if (close < maVal && _prevMom.Value >= 100m && momVal < 100m && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevMom = momVal;
	}
}