View on GitHub

Live RSI Strategy

Uses multiple RSI calculations (close, weighted, typical, median, open) and Parabolic SAR to detect trend reversals. Enters long when RSI values align in bullish order and price is above SAR, enters short when alignment is bearish and price is below SAR. SAR value acts as a trailing stop.

Details

  • Entry Criteria:
    • Long when RSI sequence is bullish and price is above SAR.
    • Short when RSI sequence is bearish and price is below SAR.
  • Long/Short: Both.
  • Exit Criteria:
    • Opposite trend signal or SAR trailing stop.
  • Stops: Optional fixed stop loss plus SAR-based trailing stop.
  • Default Values:
    • RSI Period = 30
    • SAR Step = 0.08
    • Stop Loss = 40
    • Check Hour = false
    • Start Hour = 17
    • End Hour = 1
    • Candle Type = 1 hour
  • Filters:
    • Category: Trend Following
    • Direction: Long & Short
    • Indicators: RSI, Parabolic SAR
    • Stops: Yes
    • Complexity: Intermediate
    • Timeframe: Intraday
    • Seasonality: Optional (time filter)
    • Neural networks: No
    • Divergence: No
    • Risk level: Medium
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 trend reversal strategy with Parabolic SAR confirmation.
/// Buys when RSI crosses above 50 and SAR is below price.
/// Sells when RSI crosses below 50 and SAR is above price.
/// </summary>
public class LiveRSIStrategy : Strategy
{
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevRsi;
	private bool _hasPrev;

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

	public LiveRSIStrategy()
	{
		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "Period for RSI", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles", "General");
	}

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

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevRsi = 0;
		_hasPrev = false;
	}

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

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var sar = new ParabolicSar();

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

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

		if (!_hasPrev)
		{
			_prevRsi = rsi;
			_hasPrev = true;
			return;
		}

		var close = candle.ClosePrice;

		// RSI cross above 50 + SAR below price -> buy
		if (_prevRsi <= 50 && rsi > 50 && sar < close)
		{
			if (Position < 0)
				BuyMarket();
			if (Position <= 0)
				BuyMarket();
		}
		// RSI cross below 50 + SAR above price -> sell
		else if (_prevRsi >= 50 && rsi < 50 && sar > close)
		{
			if (Position > 0)
				SellMarket();
			if (Position >= 0)
				SellMarket();
		}

		_prevRsi = rsi;
	}
}