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;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ParabolicSar, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class live_rsi_strategy(Strategy):
def __init__(self):
super(live_rsi_strategy, self).__init__()
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "Period for RSI", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._prev_rsi = 0.0
self._has_prev = False
@property
def rsi_period(self):
return self._rsi_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(live_rsi_strategy, self).OnReseted()
self._prev_rsi = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(live_rsi_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = self.rsi_period
sar = ParabolicSar()
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(rsi, sar, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def on_process(self, candle, rsi, sar):
if candle.State != CandleStates.Finished:
return
if not self._has_prev:
self._prev_rsi = rsi
self._has_prev = True
return
close = candle.ClosePrice
# RSI cross above 50 + SAR below price -> buy
if self._prev_rsi <= 50 and rsi > 50 and sar < close:
if self.Position < 0:
self.BuyMarket()
if self.Position <= 0:
self.BuyMarket()
# RSI cross below 50 + SAR above price -> sell
elif self._prev_rsi >= 50 and rsi < 50 and sar > close:
if self.Position > 0:
self.SellMarket()
if self.Position >= 0:
self.SellMarket()
self._prev_rsi = rsi
def CreateClone(self):
return live_rsi_strategy()