Ver en GitHub

Estrategia RSI Sign

Esta estrategia convierte el asesor experto original iRSISign de MQL5 en la API de alto nivel de StockSharp. Combina el Índice de Fuerza Relativa (RSI) con el Rango Verdadero Promedio (ATR) para generar señales de entrada y salida.

El sistema escucha velas finalizadas de un marco temporal definido por el usuario. Cuando el RSI cruza por encima del umbral inferior, señala una posible reversión alcista y abre una posición larga o cierra un corto existente. Por el contrario, cuando el RSI cae por debajo del umbral superior, entra en una posición corta o cierra un largo activo. El ATR se calcula pero se usa solo como contexto adicional, reflejando el indicador original que mostraba flechas de señal desplazadas por ATR.

Detalles

  • Criterios de entrada:
    • Largo: El valor anterior del RSI estaba por debajo de DownLevel y el RSI actual cruza por encima.
    • Corto: El valor anterior del RSI estaba por encima de UpLevel y el RSI actual cruza por debajo.
  • Largo/Corto: Ambas direcciones están permitidas y pueden habilitarse de forma independiente.
  • Criterios de salida:
    • La señal opuesta cierra la posición actual si el indicador de cierre correspondiente está habilitado.
  • Stops: No implementados. La gestión del riesgo puede añadirse externamente si es necesario.
  • Valores predeterminados:
    • RsiPeriod = 14
    • AtrPeriod = 14
    • UpLevel = 70
    • DownLevel = 30
    • CandleType = velas de 1 hora
  • Filtros:
    • Categoría: Momentum
    • Dirección: Ambos
    • Indicadores: RSI, ATR
    • Stops: No
    • Complejidad: Básico
    • Marco temporal: Flexible
    • Estacionalidad: No
    • Redes neuronales: No
    • Divergencia: No
    • Nivel de riesgo: Medio

Parámetros

Nombre Descripción
RsiPeriod Longitud del RSI.
AtrPeriod Longitud del ATR.
UpLevel Umbral superior del RSI que genera señales de venta.
DownLevel Umbral inferior del RSI que genera señales de compra.
CandleType Marco temporal de velas usado para los cálculos.
BuyOpen Habilitar apertura de posiciones largas.
SellOpen Habilitar apertura de posiciones cortas.
BuyClose Permitir cierre de largos existentes con señal opuesta.
SellClose Permitir cierre de cortos existentes con señal opuesta.

La estrategia está pensada como ejemplo educativo que demuestra cómo traducir la lógica simple de MQL5 al marco de estrategias de alto nivel de StockSharp.

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;

/// <summary>
/// RSI based signal strategy.
/// Opens long when RSI crosses above the down level.
/// Opens short when RSI crosses below the up level.
/// </summary>
public class RsiSignStrategy : Strategy
{
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _upLevel;
	private readonly StrategyParam<decimal> _downLevel;
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _previousRsi;

	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public decimal UpLevel { get => _upLevel.Value; set => _upLevel.Value = value; }
	public decimal DownLevel { get => _downLevel.Value; set => _downLevel.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public RsiSignStrategy()
	{
		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "Length of RSI indicator", "Indicator");

		_upLevel = Param(nameof(UpLevel), 70m)
			.SetDisplay("RSI Upper Level", "Sell when RSI falls below this value", "Indicator");

		_downLevel = Param(nameof(DownLevel), 30m)
			.SetDisplay("RSI Lower Level", "Buy when RSI rises above this value", "Indicator");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe used for indicator calculations", "General");
	}

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

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

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

		_previousRsi = null;

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

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

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		var prevRsi = _previousRsi;
		_previousRsi = rsiValue;

		if (prevRsi is null)
			return;

		// RSI crosses above lower level -> buy signal
		if (prevRsi <= DownLevel && rsiValue > DownLevel && Position <= 0)
			BuyMarket();
		// RSI crosses below upper level -> sell signal
		else if (prevRsi >= UpLevel && rsiValue < UpLevel && Position >= 0)
			SellMarket();
	}
}