Supertrend RSI Divergence
The Supertrend RSI Divergence strategy is built around that uses Supertrend indicator along with RSI divergence to identify trading opportunities.
Testing indicates an average annual return of about 67%. It performs best in the stocks market.
Signals trigger when Divergence confirms divergence setups on intraday (15m) data. This makes the method suitable for active traders.
Stops rely on ATR multiples and factors like SupertrendPeriod, SupertrendMultiplier. Adjust these defaults to balance risk and reward.
Details
- Entry Criteria: see implementation for indicator conditions.
- Long/Short: Both directions.
- Exit Criteria: opposite signal or stop logic.
- Stops: Yes, using indicator-based calculations.
- Default Values:
SupertrendPeriod = 10SupertrendMultiplier = 3.0mRsiPeriod = 14CandleType = TimeSpan.FromMinutes(15).TimeFrame()
- Filters:
- Category: Trend following
- Direction: Both
- Indicators: Divergence
- Stops: Yes
- Complexity: Intermediate
- Timeframe: Intraday (15m)
- Seasonality: No
- Neural Networks: No
- Divergence: Yes
- Risk Level: Medium
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy that uses Supertrend indicator along with RSI divergence to identify trading opportunities.
/// </summary>
public class SupertrendRsiDivergenceStrategy : Strategy
{
private readonly StrategyParam<int> _supertrendPeriod;
private readonly StrategyParam<decimal> _supertrendMultiplier;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<DataType> _candleType;
private SuperTrend _supertrend;
private RelativeStrengthIndex _rsi;
// Data for divergence detection
private readonly SynchronizedList<decimal> _prices = [];
private readonly SynchronizedList<decimal> _rsiValues = [];
// Supertrend state tracking
private decimal _supertrendValue;
private TrendDirections _trendDirection = TrendDirections.None;
/// <summary>
/// Supertrend period.
/// </summary>
public int SupertrendPeriod
{
get => _supertrendPeriod.Value;
set => _supertrendPeriod.Value = value;
}
/// <summary>
/// Supertrend multiplier.
/// </summary>
public decimal SupertrendMultiplier
{
get => _supertrendMultiplier.Value;
set => _supertrendMultiplier.Value = value;
}
/// <summary>
/// RSI period.
/// </summary>
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
/// <summary>
/// Candle type to use for the strategy.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="SupertrendRsiDivergenceStrategy"/>.
/// </summary>
public SupertrendRsiDivergenceStrategy()
{
_supertrendPeriod = Param(nameof(SupertrendPeriod), 10)
.SetDisplay("Supertrend Period", "Supertrend ATR period", "Supertrend")
.SetOptimize(5, 20, 1);
_supertrendMultiplier = Param(nameof(SupertrendMultiplier), 3.0m)
.SetDisplay("Supertrend Multiplier", "Supertrend ATR multiplier", "Supertrend")
.SetOptimize(2.0m, 5.0m, 0.5m);
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetDisplay("RSI Period", "RSI period for divergence detection", "RSI")
.SetOptimize(8, 20, 2);
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prices.Clear();
_rsiValues.Clear();
_trendDirection = TrendDirections.None;
_supertrendValue = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_supertrend = new SuperTrend
{
Length = SupertrendPeriod,
Multiplier = SupertrendMultiplier
};
_rsi = new RelativeStrengthIndex
{
Length = RsiPeriod
};
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_supertrend, _rsi, ProcessCandle)
.Start();
StartProtection(
takeProfit: new Unit(2, UnitTypes.Percent),
stopLoss: new Unit(1, UnitTypes.Percent));
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _supertrend);
DrawIndicator(area, _rsi);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal supertrendValue, decimal rsiValue)
{
// Skip unfinished candles
if (candle.State != CandleStates.Finished)
return;
// Extract values from indicators
_supertrendValue = supertrendValue;
decimal rsi = rsiValue;
// Store values for divergence calculation
_prices.Add(candle.ClosePrice);
_rsiValues.Add(rsi);
// Keep reasonable history
while (_prices.Count > 50)
{
_prices.RemoveAt(0);
_rsiValues.RemoveAt(0);
}
// Determine Supertrend trend direction
TrendDirections previousDirection = _trendDirection;
if (candle.ClosePrice > _supertrendValue)
_trendDirection = TrendDirections.Up;
else if (candle.ClosePrice < _supertrendValue)
_trendDirection = TrendDirections.Down;
// Check for trend direction change
bool trendDirectionChanged = previousDirection != TrendDirections.None && previousDirection != _trendDirection;
// Check for divergence
bool bullishDivergence = CheckBullishDivergence();
bool bearishDivergence = CheckBearishDivergence();
if (Position != 0)
return;
// Bullish setup - price above Supertrend with RSI not overbought
if (candle.ClosePrice > _supertrendValue && rsi < 60m)
BuyMarket();
// Bearish setup - price below Supertrend with RSI not oversold
else if (candle.ClosePrice < _supertrendValue && rsi > 40m)
SellMarket();
}
private bool CheckBullishDivergence()
{
// Need at least a few candles for divergence check
if (_prices.Count < 5 || _rsiValues.Count < 5)
return false;
// Check for bullish divergence: price making lower lows while RSI making higher lows
// Look at the last 5 candles for a simple check
decimal currentPrice = _prices[_prices.Count - 1];
decimal previousPrice = _prices[_prices.Count - 2];
decimal currentRsi = _rsiValues[_rsiValues.Count - 1];
decimal previousRsi = _rsiValues[_rsiValues.Count - 2];
// Bullish divergence: price lower but RSI higher
bool divergence = currentPrice < previousPrice && currentRsi > previousRsi;
if (divergence)
{
LogInfo($"Bullish Divergence Detected: Price {previousPrice:F2}->{currentPrice:F2}, RSI {previousRsi:F2}->{currentRsi:F2}");
}
return divergence;
}
private bool CheckBearishDivergence()
{
// Need at least a few candles for divergence check
if (_prices.Count < 5 || _rsiValues.Count < 5)
return false;
// Check for bearish divergence: price making higher highs while RSI making lower highs
// Look at the last 5 candles for a simple check
decimal currentPrice = _prices[_prices.Count - 1];
decimal previousPrice = _prices[_prices.Count - 2];
decimal currentRsi = _rsiValues[_rsiValues.Count - 1];
decimal previousRsi = _rsiValues[_rsiValues.Count - 2];
// Bearish divergence: price higher but RSI lower
bool divergence = currentPrice > previousPrice && currentRsi < previousRsi;
if (divergence)
{
LogInfo($"Bearish Divergence Detected: Price {previousPrice:F2}->{currentPrice:F2}, RSI {previousRsi:F2}->{currentRsi:F2}");
}
return divergence;
}
// Trend direction enum for tracking Supertrend state
private enum TrendDirections
{
None,
Up,
Down
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math, Decimal
from StockSharp.Messages import DataType, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Indicators import SuperTrend, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class supertrend_rsi_divergence_strategy(Strategy):
"""
Strategy that uses Supertrend indicator along with RSI divergence to identify trading opportunities.
"""
def __init__(self):
super(supertrend_rsi_divergence_strategy, self).__init__()
self._supertrend_period = self.Param("SupertrendPeriod", 10) \
.SetDisplay("Supertrend Period", "Supertrend ATR period", "Supertrend")
self._supertrend_multiplier = self.Param("SupertrendMultiplier", 3.0) \
.SetDisplay("Supertrend Multiplier", "Supertrend ATR multiplier", "Supertrend")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI period for divergence detection", "RSI")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._prices = []
self._rsi_values = []
self._supertrend_val = 0.0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(supertrend_rsi_divergence_strategy, self).OnReseted()
self._prices = []
self._rsi_values = []
self._supertrend_val = 0.0
def OnStarted2(self, time):
super(supertrend_rsi_divergence_strategy, self).OnStarted2(time)
supertrend = SuperTrend()
supertrend.Length = int(self._supertrend_period.Value)
supertrend.Multiplier = Decimal(self._supertrend_multiplier.Value)
rsi = RelativeStrengthIndex()
rsi.Length = int(self._rsi_period.Value)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(supertrend, rsi, self._process_candle).Start()
self.StartProtection(
Unit(2, UnitTypes.Percent),
Unit(1, UnitTypes.Percent)
)
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, supertrend)
self.DrawIndicator(area, rsi)
self.DrawOwnTrades(area)
def _process_candle(self, candle, supertrend_value, rsi_value):
if candle.State != CandleStates.Finished:
return
self._supertrend_val = float(supertrend_value)
rsi = float(rsi_value)
close_price = float(candle.ClosePrice)
self._prices.append(close_price)
self._rsi_values.append(rsi)
while len(self._prices) > 50:
self._prices.pop(0)
self._rsi_values.pop(0)
if self.Position != 0:
return
if close_price > self._supertrend_val and rsi < 60.0:
self.BuyMarket()
elif close_price < self._supertrend_val and rsi > 40.0:
self.SellMarket()
def CreateClone(self):
return supertrend_rsi_divergence_strategy()