Auf GitHub ansehen

MTF RSI SAR Strategy

This strategy combines Relative Strength Index (RSI) readings across four timeframes, Parabolic SAR, and Bollinger Bands to capture trend continuation after short pullbacks. Signals are generated on 5‑minute candles while higher timeframes act as confirmation filters.

Concept

  1. RSI filter – 5, 15, 30 and 60 minute RSI values must all be above 50 for long entries or below 50 for short entries. This multi‑timeframe confirmation aims to align trades with the broader trend.
  2. Parabolic SAR filter – Parabolic SAR values on 5, 15 and 30 minute charts must be below the current candle for longs or above for shorts. This ensures that price is trending in the desired direction.
  3. Bollinger Band trigger – On the 5‑minute chart the candle close must break the upper band for longs or the lower band for shorts. Bollinger Bands provide an overbought/oversold trigger.
  4. Entry and exit – A long position is opened when all active filters point up. A short position is opened when all active filters point down. The opposite signal closes an open position.

Any of the three filters can be individually disabled via parameters, allowing the strategy to operate with RSI only, Bollinger Bands only, SAR only, or any combination of the above.

Parameters

  • UseRsi – enable RSI filter (default: true).
  • UseBollinger – enable Bollinger Band trigger (default: true).
  • UseSar – enable Parabolic SAR filter (default: true).
  • RsiPeriod – RSI calculation period (default: 14).
  • BollingerPeriod – number of bars for Bollinger Bands (default: 20).
  • BollingerWidth – width (standard deviation multiplier) for Bollinger Bands (default: 2).
  • SarStep – acceleration factor for Parabolic SAR (default: 0.02).
  • SarMax – maximum acceleration factor for Parabolic SAR (default: 0.2).
  • CandleType – base candle timeframe, 5 minutes by default.

Trading Rules

  • Long: all enabled filters provide bullish signals.
  • Short: all enabled filters provide bearish signals.
  • Exit: opposite signal closes the position.

Notes

  • Strategy operates on one security with four candle subscriptions: 5, 15, 30 and 60 minute timeframes.
  • Designed as an educational example of multi‑timeframe confirmation using StockSharp's high‑level API.
  • There are no fixed stop‑loss or profit targets; risk management should be added externally if required.
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 and Parabolic SAR strategy.
/// Buys when RSI below oversold and SAR below price; sells on opposite.
/// </summary>
public class MtfRsiSarStrategy : Strategy
{
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _rsiOversold;
	private readonly StrategyParam<decimal> _rsiOverbought;
	private readonly StrategyParam<DataType> _candleType;

	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public decimal RsiOversold { get => _rsiOversold.Value; set => _rsiOversold.Value = value; }
	public decimal RsiOverbought { get => _rsiOverbought.Value; set => _rsiOverbought.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

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

		_rsiOversold = Param(nameof(RsiOversold), 35m)
			.SetDisplay("RSI Oversold", "RSI oversold level", "Indicators");

		_rsiOverbought = Param(nameof(RsiOverbought), 65m)
			.SetDisplay("RSI Overbought", "RSI overbought level", "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 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;

		var close = candle.ClosePrice;

		// Buy: RSI oversold + SAR below price
		if (rsi < RsiOversold && sar < close)
		{
			if (Position < 0)
				BuyMarket();
			if (Position <= 0)
				BuyMarket();
		}
		// Sell: RSI overbought + SAR above price
		else if (rsi > RsiOverbought && sar > close)
		{
			if (Position > 0)
				SellMarket();
			if (Position >= 0)
				SellMarket();
		}
		// Exit long when RSI overbought
		else if (Position > 0 && rsi > RsiOverbought)
		{
			SellMarket();
		}
		// Exit short when RSI oversold
		else if (Position < 0 && rsi < RsiOversold)
		{
			BuyMarket();
		}
	}
}