Dynamic RSI

Build a more powerful version of the RSI, that shifts and adapts to changing price condition and helps to identify overbought/oversold zones.


Dynamic RSI Colored Candles currently for Volatility Box members only. The below is the Basic Dynamic RSI, discussed in the tutorial video.

Welcome to the tenth episode of “How to Thinkscript”. We are TOSIndicators.com, home of the Volatility Box, the most robust ThinkOrSwim indicator based on statistical models built for large institutions and hedge funds.

In this tutorial, we show you how to build a Dynamic RSI indicator, which you can use as a substitute to a traditional RSI.

One of our members, Keith C., sent us his version of the Dynamic RSI, along with charts, and observations of recurring patterns on each of those charts. All of these are shared in the video, and we will be using Keith's code as our base starting point.

If you’d like to skip the tutorial and start playing with the indicator right away, you can download the Dynamic RSI Indicator for free below.

Keith's Original Code:

For those of you following along the tutorial, here is Keith's original code, which we are using as our base starting point:

### Includes code written by Keith C., Mobius, and TOS Indicators 
### Last Update: 11/3/2019 
### Full Tutorial Available Here: https://www.tosindicators.com/indicators/dynamic-rsi

### Global Variables ###
declare lower;
input length = 14;
input over_Bought = 70;
input over_Sold = 30;
input price = close;
input averageType = AverageType.WILDERS;
input showBreakoutSignals = no;
input Volatility_Band = 14; #20-40
input STDEV_Multiplier = 2;
input RSI_Period = 14; #8-25
input RSI_Price = 0; #0-6
input RSI_Price_Line = 2;

### Keith RSI, BB, DYN ###
def NetChgAvg = MovingAverage(averageType, price - price[1], length);
def TotChgAvg = MovingAverage(averageType, AbsValue(price - price[1]), length);
def ChgRatio = if TotChgAvg != 0 then NetChgAvg / TotChgAvg else 0;

def DYNRSI = reference RSI(RSI_Period);
def Price1 = if averageType == AverageType.SIMPLE then Average(DYNRSI, RSI_Price_Line) else ExpAverage(DYNRSI, RSI_Price_Line);
def SDBB = StDev(DYNRSI, Volatility_Band);

plot RSI = 50 * (ChgRatio + 1);
plot MiddleLine = 50;
plot MiddleLine1 = 70;
plot MiddleLine2 = 30;

plot DYNAverage = Average(DYNRSI, Volatility_Band);

plot UpperBollinger = DYNAverage + STDEV_Multiplier * SDBB;
plot LowerBollinger = DYNAverage - STDEV_Multiplier * SDBB;

plot OverSold = over_Sold;
plot OverBought = over_Bought;
plot UpSignal = if RSI crosses above OverSold then OverSold else Double.NaN;
plot DownSignal = if RSI crosses below OverBought then OverBought else Double.NaN;


RSI.DefineColor("OverBought", GetColor(5));
RSI.DefineColor("Normal", GetColor(9));
RSI.DefineColor("OverSold", GetColor(6));
RSI.AssignValueColor(if RSI > over_Bought then RSI.Color("OverBought") else if RSI < over_Sold then RSI.Color("OverSold") else RSI.Color("Normal"));

AddCloud(RSI, OverBought, Color.RED, Color.CURRENT);
AddCloud(OverSold, RSI, Color.GREEN, Color.CURRENT);

Relationships That We'll Focus On:

In the tutorial video, you'll notice that Keith had quite a few observations around the various lines in the original code.

For the purposes of brevity, we've chosen to focus on four key relationships for the first version of this indicator. If there is enough interest, we may have another "How to thinkScript" video dedicated to an update.

Here are the four relationships:

  • 1. RSI & Bollinger Bands
  • 2. Dynamic Averages & Overbought/Oversold
  • 3. Upper & Lower Bollinger Bands
  • 4. Trendline Support & Resistance

RSI & Bollinger Bands:

  • 1. For a bullish scenario, RSI <= Lower Bollinger Band
  • 2. For a bearish scenario, RSI >= Upper Bollinger Band
  • 3. How do we eliminate the noise from too many signals in the indicator?

The code below is for the upper study only:

plot BearSignal = if (UpperBollinger >= 55) and (RSI >=70) and (RSI>=UpperBollinger) then 1 else 0;

plot BullSignal = if (LowerBollinger <= 45) and (RSI <=30) and (RSI<=LowerBollinger) then 1 else 0;

Dynamic Average & Overbought/Oversold

  • 1. Dynamic Average crosses above Overbought
  • 2. Dynamic Average crosses below Oversold
  • 3. Focusing on not only entries, but exits as well
  • 4. Starting to look at the bubbles as a train leaving the station

Chart bubble code included below (and once again, for the upper study only):

def superOverbought = DYNAverage crosses above over_Bought;
def superOversold = DYNAverage crosses below over_Sold;
AddChartBubble(superOverbought and !superOverbought[1], close, "Enter Super Overbought", color.light_red); 
AddChartBubble(superOversold and !superOversold[1], close, "Enter Super Oversold", color.light_green);

def superOverbought1 = DYNAverage crosses below over_Bought;
def superOversold1 = DYNAverage crosses above over_Sold;

AddChartBubble(superOverbought1 and !superOverbought1[1], close, "Exit Super Overbought", color.red); 
AddChartBubble(superOversold1 and !superOversold1[1], close, "Exit Super Oversold", color.green);

Upper & Lower Bollinger Bands (Squeeze)

  • 1. Upper & Lower Bollinger Bands Compress To Within 10 (implying Squeeze)
  • 2. Pairing the squeeze with other indicators to determine directional bias

Upper & Lower Study Squeeze Code:

def BBDistance = if UpperBollinger - LowerBollinger <= 10 then 1 else 0;
plot squeeze = if BBDistance then close else Double.nan;

Automatic Trend Lines

For the automatic trend lines component of the indicator, we found Mobius's code here, which plots automatic trend lines for price action.

We took that version of the code, and modified the components that the indicator used to measure trendlines, replacing them with the RSI instead. Keith also changed the plot of the trend lines, to make them a bit cleaner given all the lines already on our charts.

For those of you following along in the tutorial, the modified version of the code is included below:

### Automatic Trend Line Code (courtesy of Mobius) ###
### https://usethinkscript.com/threads/auto-trend-lines-indicator-for-thinkorswim-free-download.31/ ###

input TrendLineLength1 = 150;
input TrendLineLength2 = 80;
input TrendLineLength3 = 40;

def Inertia1 = InertiaAll(RSI, TrendLineLength1);
def Inertia2 = InertiaAll(RSI, TrendLineLength2);
def Inertia3 = InertiaAll(RSI, TrendLineLength3);

def TL_Bull1 = Inertia1 - (HighestAll(AbsValue(Inertia1 - RSI)) * 0.8);
def TL_Bear1 = Inertia1 + (HighestAll(AbsValue(Inertia1 - RSI)) * 0.8);
def slope1a = TL_Bull1 > TL_Bull1[1];
def slope1b = TL_Bear1 > TL_Bear1[1];

def TL_Bull2 = Inertia2 - (HighestAll(AbsValue(Inertia2 - RSI)) * 0.8);
def TL_Bear2 = Inertia2 + (HighestAll(AbsValue(Inertia2 - RSI)) * 0.8);
def slope2a = TL_Bull2 > TL_Bull2[1];
def slope2b = TL_Bear2 > TL_Bear2[1];

def TL_Bull3 = Inertia3 - (HighestAll(AbsValue(Inertia3 - RSI)) * 0.8);
def TL_Bear3 = Inertia3 + (HighestAll(AbsValue(Inertia3 - RSI)) * 0.8);
def slope3a = TL_Bull3 > TL_Bull3[1];
def slope3b = TL_Bear3 > TL_Bear3[1];
#Long length
plot TrendLine1a = if slope1a > 0 then TL_Bull1 else TL_Bear1;
TrendLine1a.AssignValueColor(if slope1a and IsAscending(RSI, 10) then Color.WHITE else if slope1a then Color.WHITE else if !IsAscending(RSI, 10) then Color.WHITE else Color.WHITE);

plot TrendLine1b = if slope1b > 0 then TL_Bear1 else TL_Bull1;
TrendLine1b.AssignValueColor(if slope1b and IsAscending(RSI, 10) then Color.WHITE else if slope1b then Color.WHITE else if !IsAscending(RSI, 10) then Color.WHITE else Color.WHITE);
#Medium length
plot TrendLine2a = if slope2a > 0 then TL_Bull2 else TL_Bear2;
TrendLine2a.AssignValueColor(if slope2a and IsAscending(RSI, 10) then Color.LIGHT_GREEN else if slope2a then Color.LIGHT_GREEN else if !IsAscending(RSI, 10) then Color.MAGENTA else Color.MAGENTA);

plot TrendLine2b = if slope2b > 0 then TL_Bear2 else TL_Bull2;
TrendLine2b.AssignValueColor(if slope2b and IsAscending(RSI, 10) then Color.LIGHT_GREEN else if slope2b then Color.LIGHT_GREEN else if !IsAscending(RSI, 10) then Color.MAGENTA else Color.MAGENTA);
#Short length
plot TrendLine3a = if slope3a > 0 then TL_Bull3 else TL_Bear3;
TrendLine3a.AssignValueColor(if slope3a and IsAscending(RSI, 10) then Color.LIGHT_GREEN else if slope3a then Color.LIGHT_GREEN else if !IsAscending(RSI, 10) then Color.PINK else Color.PINK);

plot TrendLine3b = if slope3b > 0 then TL_Bear3 else TL_Bull3;
TrendLine3b.AssignValueColor(if slope3b and IsAscending(RSI, 10) then Color.LIGHT_GREEN else if slope3b then Color.LIGHT_GREEN else if !IsAscending(RSI, 10) then Color.PINK else Color.PINK);

Conclusion & Download

Thanks for watching the tenth episode of "How to thinkScript"... we really appreciate it!

And a special thank you to Keith C., for sharing not only your code, but your detailed observations, charts and patterns.

We've included Keith's one pager, which you can use to continue building on the indicator, and integrating more patterns, if it helps your trading.

Click the button below to download the Dynamic RSI Indicator

Table of Contents
    Add a header to begin generating the table of contents

    Trade Like a Pro, With the Pros