On this page
Overview
In this tutorial I build a rate of change indicator for ThinkOrSwim, starting from the built-in Rate of Change study. I turn the ROC into a range-bound oscillator: one line at its highest value on the chart, one at its lowest, and a dashed line halfway to each, so you can see when the ROC is in an extreme zone.
Then I add a green arrow when the ROC turns up in the lower zone on the same bar the built-in RSI fires its bullish breakout signal, and a red arrow for the bearish side. The video is unrehearsed, bugs and chart bubble tests included, so it doubles as a lesson in turning an idea into thinkScript for anyone who wants to make a built-in study smarter.
Key Takeaways
- Our Rate of Change indicator starts from ThinkOrSwim's built-in ROC study: the percent change between the close and the close 14 bars ago.
- It draws the highest and lowest ROC on the chart as solid red and green lines, using HighestAll and LowestAll, and the halfway point between each line and zero as a dashed line.
- The upper extreme zone is the space between the upper dashed line and the red line. The lower extreme zone is the space between the lower dashed line and the green line.
- A green up arrow plots when the ROC is in the lower zone, higher than on the previous bar, and the RSI crosses above its oversold line on the same bar. The red down arrow mirrors it in the upper zone with the RSI crossing below overbought.
- I built it on a daily Amazon chart and checked it on a 5-minute chart. Our rate of change scans turn the same code into 4 ThinkOrSwim scans.
What Is the Rate of Change Indicator?
The rate of change (ROC) indicator measures how far price has moved, in percent, over a set number of bars. The textbook formula is the close minus the close n bars ago, divided by the close n bars ago, times 100. A reading of 5 means price is 5% higher than n bars ago, and -5 means it is 5% lower.
ThinkOrSwim's built-in Rate of Change study uses 14 bars by default and writes the same formula as (price / price[length] - 1) * 100. It plots the ROC around a zero line and shades it from light red near its recent lows to yellow near its recent highs.
The ROC has no fixed upper limit. The RSI stays between 0 and 100, but a ROC reading that is extreme on one chart can be ordinary on another, so the raw number doesn't tell you whether a reading is extreme for that chart. That's the gap this indicator fills.
What Our Rate of Change Indicator Plots
Our rate of change indicator keeps the built-in ROC line and zero line. The table shows the 4 lines and 2 arrows it adds:
| Plot | Code | Look | What it marks |
|---|---|---|---|
| highestROC | HighestAll(ROC) | Solid red, weight 3 | The highest ROC on the chart |
| lowestROC | LowestAll(ROC) | Solid green, weight 3 | The lowest ROC on the chart |
| midPtHighestROC | highestROC/2 | Dashed light red, weight 1 | The start of the upper extreme zone |
| midPtLowestROC | lowestROC/2 | Dashed light green, weight 1 | The start of the lower extreme zone |
| bullSignal | ROC turns up in the lower zone and the RSI fires UpSignal | Green up arrow, weight 3 | Bullish signal |
| bearSignal | ROC turns down in the upper zone and the RSI fires DownSignal | Red down arrow, weight 3 | Bearish signal |
The Idea: An Extreme ROC Plus an RSI Breakout
The rate of change idea started on a daily chart of Amazon, with the built-in ROC in the first lower panel and the built-in RSI in the second.
The plan had 2 parts. First, turn the ROC into a range-bound oscillator by marking its high and low, then split the distance from zero to each in half and call the outer halves extreme. Second, flag the bars where the RSI gives a breakout signal while the ROC sits in an extreme zone.
I marked 4 examples on that Amazon chart before writing any code:
- Bullish. The RSI gave its breakout signal while the ROC was in the lower extreme zone, and price rallied from there.
- Bearish. The RSI gave a bearish breakout signal with the ROC in the upper extreme zone, and price pulled back a little.
- Bullish. The same setup on the lower side, followed by a small bounce.
- Bullish. During an Amazon relief rally shortly before the video, the ROC was well inside the lower extreme zone when the RSI signals came.
In plain terms, a bullish signal says the ROC is slowing down. It is moving from a negative reading toward a positive one, or at least falling less quickly, while the RSI says price is moving up out of oversold territory.
Before coding, I said up front that I had no idea whether this indicator would give an edge. The video is about the process of turning an idea into code, and I wanted it to work on any timeframe.
How to Add the Rate of Change Indicator to ThinkOrSwim
The rate of change indicator installs as one study in a lower panel:
- Download the zip from this page. Inside is one study file,
TI_ROCSTUDY.ts. - Import it as a study. Our guide on how to import a study into ThinkOrSwim walks through each click.
- Add it to a chart. It opens in a lower panel.
- To build it yourself, click the Studies icon and search for the built-in Rate of Change study. Click the scroll icon with the lock next to it, copy all of its code, then click Create, delete anything in the code field and paste. I named mine TI_ROC.
How the Rate of Change Code Works
The rate of change code adds range lines, extreme zones and signals to ThinkOrSwim's built-in ROC, one block at a time. I tested each block before moving to the next, often with a chart bubble, which is a good habit when you build your own studies.
Step 1: The Range Lines
This step’s code is free with an account. Create one or sign in.
HighestAll and LowestAll return the highest and lowest ROC across every bar loaded on the chart. They give the ROC a top and a bottom, so it reads like a range-bound oscillator.
Step 2: The Halfway Lines
This step’s code is free with an account. Create one or sign in.
Each dashed line sits halfway between zero and the highest or lowest ROC. The full formula is the highest ROC minus 0, divided by 2, so the code skips the minus zero. The space between a dashed line and its solid line is the extreme zone.
Step 3: Formatting
This step’s code is free with an account. Create one or sign in.
The outer lines are red and green at weight 3, and the halfway lines light red and light green, dashed, at weight 1. I set the colors in code so they stay the same on any platform setup.
Step 4: The Extreme Zones
This step’s code is free with an account. Create one or sign in.
extremeHigh is true when the ROC is below the red line and at or above the upper dashed line. extremeLow is the mirror image. I used greater than or equal to and less than or equal to on the dashed lines so a reading right on the line counts.
To check extremeHigh, I added a temporary yellow chart bubble that printed only when it was true, then commented it out once the bubbles matched the zone.
Step 5: The RSI Breakout Signals
This step’s code is free with an account. Create one or sign in.
The RSI part doesn't copy any RSI code. RSI() calls ThinkOrSwim's built-in RSI study, and the name after the dot picks one of its plots. UpSignal fires when the RSI crosses above its oversold line and DownSignal when it crosses below its overbought line.
To test it, I put a chart bubble on RSIUpSignal and loaded the RSI with its breakout signals set to yes. Every green RSI arrow had a bubble. The test line is still in the download, commented out:
This step’s code is free with an account. Create one or sign in.
Our Dynamic RSI indicator also calls the built-in RSI study instead of copying it, with reference RSI(RSI_Period), and builds Bollinger Bands on it.
Step 6: The ROC Turn
This step’s code is free with an account. Create one or sign in.
ROCUpSignal is true when the ROC is in the lower extreme zone and higher than on the previous bar, so it has stopped falling and started to turn. ROCDownSignal is the mirror in the upper zone. While testing, I plotted each one as arrows on its own to confirm it.
Step 7: The Final Arrows
This step’s code is free with an account. Create one or sign in.
A signal needs both conditions on the same bar. The then ROC else double.nan part puts the arrow on the ROC line. Without it the arrows sit on the zero line, which is what happened on my first try.
Rate of Change Settings
The rate of change indicator has 3 inputs. Everything else sits in the code.
| Setting | Default | What it does |
|---|---|---|
| length | 14 | How many bars back the ROC compares the close with. |
| colorNormLength | 14 | Bars used to shade the ROC line from light red to yellow. Colors only. |
| price | close | The price the ROC measures. |
| Halfway divisor (in the code) | 2 | Where the dashed lines sit between zero and the outer lines. |
| RSI settings (in the code) | Built-in defaults | RSI() with empty parentheses uses the built-in RSI's own inputs, including its overbought and oversold lines. |
Dividing by a larger number than 2 moves the dashed lines toward zero, so more bars count as extreme and more bars can produce arrows. In the video I mentioned a sensitivity factor as one way to improve the indicator.
One way to add it is to replace that 2 with an input. This edit is my suggestion and is not in the video or the download. Put the input line under the other inputs and replace the two midpoint lines:
This step’s code is free with an account. Create one or sign in.
With sensitivity at 2 the indicator plots exactly as the download does. Keep it above 1: at 1 or below, the dashed lines reach or pass the solid ones and the extreme zones disappear.
Why the Lines Depend on Your Chart's History
HighestAll and LowestAll read every bar loaded on the chart, so the range lines depend on your chart's time range. A 1-year daily chart and a 5-year daily chart of the same stock can draw different red and green lines, and so different extreme zones and arrows.
The lines also move when the ROC sets a new high or low, which can change which past bars count as extreme. Before you judge an old arrow, check the chart's time range. Because extremeHigh needs the ROC below the red line, the one bar that sets the highest ROC never counts as extreme, and the same goes for the lowest.
Our rate of change scans show the same effect in the Scan tab. A 30-minute bearish signal on Apple appeared on the chart only after I cut the chart's history from 90 days to 15 days.
What the Indicator Showed in the Video
The finished rate of change indicator plotted fewer arrows on the daily Amazon chart than my 4 planning examples. Two sets of signals showed up, both while the ROC was still in an extreme zone. My guess in the video was that in the earlier examples, the RSI signal and the ROC turn didn't line up on the same bar.
On a 5-minute chart, the arrows plotted the way I expected. I loaded the RSI alongside to confirm each green arrow came with an RSI breakout signal and a rising ROC. At the end I pointed out that you can switch to another market, such as the S&P futures, and the indicator should keep plotting the same way.
One turn the indicator missed was a bearish one that came after the extreme edge had already been crossed. To catch it, the code would need context: remember that the extreme edge was crossed, then accept a turn lower just below it. I left that for a separate tutorial.
How to Read the Rate of Change Arrows
A rate of change arrow marks momentum turning at an extreme on the same bar the RSI breaks out. A bullish arrow says the ROC has stopped falling inside the lower zone while the RSI climbs out of oversold. In the planning examples, what followed ranged from a rally to a small bounce or a slight pullback, so not every arrow leads to a big move.
Treat an arrow as a read on momentum and check it against price levels before acting. Decide where your stop goes first, and size the position so a stop-out costs a small, fixed share of your account.
For more ways to work with momentum, our Smarter MACD starts from the built-in MACD code the same way, and if a change of your own throws an error, our guide on how to fix bugs in thinkScript code can help you track it down.
Rate of Change arrows on real charts
Drawn from real daily bars with the code on this page, through Oct 20, 2026. The ROC is the percent change over 14 bars. The solid lines mark its highest and lowest value on the chart and the dashed lines are halfway to each. A green arrow needs the ROC in the lower zone and turning up on the same bar the built-in RSI crosses back above 30. The red arrow is the mirror image.
Because the zones come from the highest and lowest ROC on the chart, they move when you change the chart's range, and an arrow can appear or disappear on an old bar. Everything below uses a 1-year daily chart ending Oct 20, 2026, the arrows you would see today.
XLF, Oct 5, 2026: an arrow that worked

XLF closed at $53.88 on the arrow and at $55.07 ten trading days later, +2.2%.
BA, Sep 29, 2026: one that did not

BA closed at $187.72 on the arrow and at $186.55 ten trading days later, -0.6%.
By the numbers
On a chart the zones use the whole visible year, including bars after each arrow, so arrows on a chart look better than they traded. The two percentages test the arrow without hindsight: each day's zones come from the year of ROC up to that day, on every stock and ETF in our data from Aug 1, 2025 to Oct 20, 2026 (873 green arrows). This matches the Rate of Change scans, which see only the bars up to the day they run.
Full thinkScript code
Create a free account or sign in to copy all 67 lines and download the file.
Download
Download the Rate of Change indicator for ThinkOrSwim. The download is a .zip with one study file, TI_ROCSTUDY.ts: the built-in ROC with the highest, lowest and halfway lines and the RSI-confirmed bullish and bearish arrows, the same code as the Code tab on this page. If you haven't added a custom study before, here's how to import an indicator into your ThinkOrSwim platform.
Questions
What is the rate of change indicator?
The rate of change (ROC) indicator measures the percent change in price over a set number of bars: the close minus the close n bars ago, divided by the close n bars ago, times 100. ThinkOrSwim's built-in study uses 14 bars. A positive reading means price is higher than 14 bars ago, and a negative reading means it is lower.
How is this ROC indicator different from the built-in one?
It keeps the built-in ROC line and adds lines at the highest and lowest ROC on the chart, plus dashed lines halfway to each, which mark the extreme zones. It also plots a green or red arrow when the ROC turns inside an extreme zone on the same bar the built-in RSI fires its breakout signal.
How are the rate of change extreme zones calculated?
The upper zone runs from half the highest ROC on the chart up to the highest ROC. The lower zone runs from half the lowest ROC down to the lowest ROC. HighestAll and LowestAll find those values across every bar loaded on the chart, and the code divides each by 2 for the dashed lines.
What triggers a bullish arrow on the rate of change indicator?
Three things on the same bar: the ROC is in the lower extreme zone, the ROC is higher than on the previous bar, and the built-in RSI fires its UpSignal by crossing above its oversold line. The bearish arrow needs the ROC in the upper zone, lower than on the previous bar, and the RSI crossing below its overbought line.
Why do the lines move when I change the chart's time range?
The highest and lowest lines come from HighestAll and LowestAll, which read every bar on the chart. Load more or less history and the highest and lowest ROC can change, which moves the dashed lines, the extreme zones and the arrows. Compare charts that load the same time range.
Does the rate of change indicator work on intraday charts?
Yes. I built it on a daily Amazon chart, then switched to a 5-minute chart, and the arrows plotted the way I expected, lining up with the RSI's breakout signals. The code has no timeframe setting, so it reads whatever chart you put it on. At the end of the video I said it should plot the same way on other markets, such as the S&P futures.
How do I change the ROC length?
Open the study's settings and change length, which defaults to 14. It sets how many bars back the ROC compares the close with. colorNormLength, also 14, only changes the line's color shading. The RSI part uses the built-in RSI's own settings, so changing length doesn't change the RSI signals.
Can I scan for the rate of change signals?
Yes. Our rate of change scans tutorial pastes this indicator's code into a ThinkOrSwim scan filter and comes with 4 ready-made scans: bullish signal, bearish signal, lower extreme zone and upper extreme zone. A scan filter takes exactly one plot, so every other plot becomes a def.
Get each new indicator by email
One email on Sundays with the week's new tool and its code. A free account also unlocks every .txt download.
No credit card. Unsubscribe anytime.
Fair Value Gap
False Breakout Scanner
Heiken Ashi Trend



Stock Volatility Box
Futures Volatility Box
ORB Setups
Squeeze Setups
Rate of Change Scans
Relative Performance
Opening Range Breakout
P/E Ratio
Multiple Time Frame Moving Averages
Extreme TICK Counter