Introduction
In this tutorial, I’ll show you how to build a Dynamic RSI Indicator using thinkScript code for the ThinkOrSwim (TOS) trading platform. We’ll leverage code snippets, and our own logic, to create a powerful RSI indicator that adapts to market volatility.
- RSI with Bollinger Bands for dynamic overbought/oversold levels
- Automatic trend line detection for objective support and resistance
- Squeeze detection for compression and breakout identification
- Dynamic yellow average line for trend confirmation
- Upper and lower study configuration for comprehensive analysis
The Dynamic RSI indicator combines Bollinger Bands, trend lines, and various RSI metrics. The Bollinger Bands on the RSI chart help gauge overbought and oversold conditions, while trend lines provide support and resistance levels for potential trading signals.
I’ll take you through, step-by-step, how to build the Dynamic RSI indicator for ThinkOrSwim below.
The Complete Guide to Building a Dynamic RSI Indicator in ThinkOrSwim
The Relative Strength Index (RSI) is one of the most widely used technical indicators, but in its standard form, it often generates too many false signals and lacks the nuanced analysis needed for today’s complex markets. The Dynamic RSI indicator changes that by layering additional analytical components that transform the basic RSI into a sophisticated trading system capable of identifying institutional activity and market reversals with remarkable precision.
This tutorial takes you through the complete process of building Keith’s Dynamic RSI indicator, a system that has been refined through thousands of hours of real trading and market observation. Unlike static indicators that use fixed parameters, this Dynamic RSI adapts to market conditions, providing more reliable signals and reducing false breakouts that plague traditional RSI analysis.
Understanding the Core Components
The Dynamic RSI system consists of five integrated components that work together to create a comprehensive trading tool. Each component serves a specific purpose and contributes unique information to your trading decisions.
The foundation starts with the traditional RSI calculation, but we enhance it with a dynamic yellow average line that provides smoother trend identification. This yellow line acts as a filter, helping distinguish between temporary price fluctuations and meaningful trend changes. When this dynamic average crosses above or below traditional overbought and oversold levels, it signals that institutional money is actively moving the market.
Bollinger Bands applied to the RSI create adaptive overbought and oversold zones that adjust to market volatility. Unlike fixed RSI levels at 70 and 30, these Bollinger Bands expand during volatile periods and contract during quiet markets, providing more accurate reversal signals. When the RSI breaks outside these bands, it indicates extreme conditions that often precede significant price movements.
Automatic trend line detection removes the subjectivity from traditional trend line analysis. Using Mobius’s proven algorithm, the indicator automatically draws trend lines on the RSI, identifying support and resistance levels that would be impossible to spot manually in real-time. These trend lines provide objective entry and exit points based on mathematical calculations rather than subjective interpretation.
Squeeze detection monitors the compression between the upper and lower Bollinger Bands on the RSI. When these bands compress, it indicates a period of low volatility that often precedes explosive price movements. The squeeze dots provide early warning of impending breakouts, allowing you to position before the crowd recognizes the setup.
Signal Generation and Filtering Logic
The Dynamic RSI generates multiple types of signals, each serving different trading objectives. Understanding how to interpret and combine these signals is crucial for successful implementation.
Bollinger Band breakthrough signals occur when the RSI breaks above the upper band or below the lower band. These signals indicate extreme momentum conditions that often lead to price reversals. For bullish signals, the system requires the RSI to fall below the lower Bollinger Band while ensuring the lower band itself is below the 45 level and the RSI is in oversold territory below 30. This multi-condition approach significantly reduces false signals.
Bearish signals require the RSI to break above the upper Bollinger Band while the upper band is above 55 and the RSI is in overbought territory above 70. These additional filters ensure that signals only generate during meaningful extreme conditions rather than temporary fluctuations.
Dynamic average crossover signals provide trend confirmation and reversal warnings. When the yellow dynamic average crosses above the overbought level (70), it indicates the market is entering a potentially unstable bullish phase. The system also tracks when the dynamic average exits these extreme zones, providing valuable information about trend sustainability.
Step-by-Step Coding Tutorial
Now let’s walk through the complete process of building this Dynamic RSI indicator from the ground up. By building it step-by-step, you’ll understand exactly how the indicator functions and be able to customize it for your specific needs.
Step 1: Setting Up Global Variables and Input Parameters
We start by declaring this as a lower study and setting up all the input parameters that control the indicator’s behavior:
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;
input STDEV_Multiplier = 2;
input RSI_Period = 14;
input RSI_Price_Line = 2;
The declare lower statement tells ThinkOrSwim to display this indicator in the lower study area. The input variables provide flexibility for different trading styles – day traders might use shorter periods while swing traders prefer longer settings.
Step 2: Building the Core RSI Calculations
Next, we calculate the RSI using a more flexible approach that allows different moving average types:
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);
These calculations create the foundation for our dynamic RSI. The DYNRSI references the standard RSI calculation, while SDBB calculates the standard deviation for our Bollinger Bands.
Step 3: Plotting RSI and Reference Levels
Now we plot the actual RSI line along with reference levels and the crucial dynamic yellow average line:
plot RSI = 50 * (ChgRatio + 1);
plot MiddleLine = 50;
plot MiddleLine1 = 70;
plot MiddleLine2 = 30;
plot DYNAverage = Average(DYNRSI, Volatility_Band);
DYNAverage.SetDefaultColor(Color.YELLOW);
DYNAverage.SetLineWeight(2);
The yellow dynamic average line is crucial – it smooths out RSI noise and provides more reliable trend signals than the raw RSI line.
Step 4: Creating Dynamic Bollinger Bands
The Bollinger Bands create adaptive overbought and oversold zones that adjust to market volatility:
plot UpperBollinger = DYNAverage + STDEV_Multiplier * SDBB;
UpperBollinger.SetDefaultColor(Color.RED);
plot LowerBollinger = DYNAverage - STDEV_Multiplier * SDBB;
LowerBollinger.SetDefaultColor(Color.GREEN);
These bands use the dynamic average as the middle line rather than a simple moving average. When the RSI breaks outside these bands, it indicates extreme conditions.
Step 5: Adding Signal Generation Logic
We add breakthrough signal logic with multiple filters to reduce false positives:
plot BullSignal = if RSI <= LowerBollinger and
LowerBollinger <= 45 and
RSI = UpperBollinger and
UpperBollinger >= 55 and
RSI >= 70
then 1 else 0;
BullSignal.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
BearSignal.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
The bull signal requires the RSI to break below the lower Bollinger Band while ensuring we’re in truly oversold conditions. These multiple filters dramatically reduce false signals.
Step 6: Implementing Dynamic Average Entry/Exit Tracking
One of Keith’s key insights was tracking when the dynamic average enters and exits extreme zones:
def SuperOverbought = DYNAverage crosses above over_Bought;
def SuperOversold = DYNAverage crosses below over_Sold;
def SuperOverboughtExit = DYNAverage crosses below over_Bought;
def SuperOversoldExit = DYNAverage crosses above over_Sold;
AddChartBubble(SuperOverbought and !SuperOverbought[1], close, "Enter Super OB", Color.LIGHT_RED);
AddChartBubble(SuperOversold and !SuperOversold[1], close, "Enter Super OS", Color.LIGHT_GREEN);
AddChartBubble(SuperOverboughtExit and !SuperOverboughtExit[1], close, "Exit Super OB", Color.RED);
AddChartBubble(SuperOversoldExit and !SuperOversoldExit[1], close, "Exit Super OS", Color.GREEN);
These chart bubbles provide context about market momentum and potential trend changes, with color coding to help you quickly identify signal types.
Step 7: Adding Squeeze Detection
The squeeze detection monitors when the Bollinger Bands compress, indicating low volatility that often precedes explosive moves:
def BBDistance = if UpperBollinger - LowerBollinger <= 10 then 1 else 0;
plot squeeze = if BBDistance then 50 else Double.NaN;
squeeze.SetPaintingStrategy(PaintingStrategy.POINTS);
squeeze.SetLineWeight(4);
squeeze.SetDefaultColor(Color.RED);
When the distance between the Bollinger Bands falls below 10 points, red dots appear warning of impending volatility expansion.
Step 8: Incorporating Automatic Trend Lines
The automatic trend line system uses Mobius's proven inertia-based algorithm:
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_Bull2 = Inertia2 - (HighestAll(AbsValue(Inertia2 - RSI)) * 0.8);
def TL_Bear2 = Inertia2 + (HighestAll(AbsValue(Inertia2 - RSI)) * 0.8);
plot TrendLine2a = TL_Bull2;
plot TrendLine2b = TL_Bear2;
This creates multiple trend lines with different sensitivities. We focus on the medium-length trend lines as they provide the best balance between reliability and signal frequency.
Step 9: Adding Trend Line Signal Detection
Finally, we add logic to detect when the RSI bounces off or breaks through the trend lines:
def trendLineSignalLong = if RSI >= TrendLine2b and RSI[1] < TrendLine2b then 1 else 0;
def trendLineSignalShort = if RSI TrendLine2a then 1 else 0;
AddChartBubble(trendLineSignalLong and !trendLineSignalLong[1], TrendLine2b, "Long", Color.LIGHT_GREEN);
AddChartBubble(trendLineSignalShort and !trendLineSignalShort[1], TrendLine2a, "Short", Color.LIGHT_RED);
These chart bubbles appear when the RSI touches the trend lines, providing clear entry signals for trend line bounces.
Step 10: Creating the Upper Study Version
For the upper study that appears on your price chart, we simplify the display to show only the most critical signals:
declare upper;
# Copy the same calculation logic here but change plots to definitions
plot BullishArrow = if (RSI breakthrough conditions met) then close else Double.NaN;
plot BearishArrow = if (RSI breakthrough conditions met) then close else Double.NaN;
plot SqueezeUpper = if BBDistance then close else Double.NaN;
BullishArrow.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
BearishArrow.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
SqueezeUpper.SetPaintingStrategy(PaintingStrategy.POINTS);
The upper study focuses on actionable signals without cluttering your price chart. Arrows appear when breakthrough conditions are met, and squeeze dots warn of volatility compression.
Customization and Integration
Once you have the basic indicator built, you can customize it for your specific trading style. For day trading, consider reducing the RSI period to 8-10 and using shorter Bollinger Band periods. Swing traders typically prefer longer periods that filter out noise.
The Dynamic RSI works exceptionally well as a confirmation tool with other trading systems. When combined with volatility-based systems like the Volatility Box, Dynamic RSI signals help validate trading opportunities and improve entry timing. Keith's research suggests that 4-minute charts provide an optimal balance between signal frequency and accuracy for day trading.
The Dynamic RSI represents a significant evolution beyond traditional RSI analysis. By combining multiple analytical layers, it creates a comprehensive trading system that adapts to changing market conditions. Start by implementing the basic version and familiarize yourself with the signals it generates before experimenting with customization options to optimize it for your trading style.
### 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;
// ... 171 more lines ...Here are some resources that you may find useful: