Ver no GitHub

RSI Sign Strategy

This strategy converts the original iRSISign expert advisor from MQL5 into the StockSharp high level API. It combines the Relative Strength Index (RSI) with the Average True Range (ATR) to generate entry and exit signals.

The system listens to finished candles of a user defined timeframe. When the RSI crosses above the lower threshold it signals a potential bullish reversal and opens a long position or closes an existing short. Conversely, when RSI falls below the upper threshold it enters a short position or closes an active long. ATR is calculated but used only for additional context, mirroring the original indicator that displayed signal arrows offset by ATR.

Details

  • Entry Criteria:
    • Long: Previous RSI value was below DownLevel and current RSI crosses above it.
    • Short: Previous RSI value was above UpLevel and current RSI crosses below it.
  • Long/Short: Both directions are allowed and can be independently enabled.
  • Exit Criteria:
    • Opposite signal closes the current position if the corresponding close flag is enabled.
  • Stops: Not implemented. Risk management can be added externally if needed.
  • Default Values:
    • RsiPeriod = 14
    • AtrPeriod = 14
    • UpLevel = 70
    • DownLevel = 30
    • CandleType = 1 hour candles
  • Filters:
    • Category: Momentum
    • Direction: Both
    • Indicators: RSI, ATR
    • Stops: No
    • Complexity: Basic
    • Timeframe: Flexible
    • Seasonality: No
    • Neural networks: No
    • Divergence: No
    • Risk level: Medium

Parameters

Name Description
RsiPeriod RSI length.
AtrPeriod ATR length.
UpLevel RSI upper threshold generating sell signals.
DownLevel RSI lower threshold generating buy signals.
CandleType Candle timeframe used for calculations.
BuyOpen Enable opening of long positions.
SellOpen Enable opening of short positions.
BuyClose Allow closing of existing longs on opposite signal.
SellClose Allow closing of existing shorts on opposite signal.

The strategy is intended as an educational example demonstrating how to translate simple MQL5 logic into StockSharp's high level strategy framework.

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();
	}
}