Stochastic RSI: formula, K/D and Pine Script
The RSI stochastic indicator measures where RSI sits within its own recent range. Compute RSI first, normalize that series, then smooth the result into K and D. It is different from applying Stochastic to price. Use the worked table and copyable code to check each stage, including scale, missing values, and startup bars.
Example defaults: RSI 14 · Stochastic 14 · K 3 · D 3 · Close source
Two windows, followed by two smoothing steps
TradingView defines Stoch RSI as RSI relative to its own high-low range. RSI length controls the upstream momentum calculation. Stochastic length controls the rolling minimum and maximum of that RSI series.
L = lowest R over N bars; H = highest R over N bars
raw = (R − L) / (H − L)
K = SMA(raw, K length)
D = SMA(K, D length)
The stochastic window includes the current RSI reading. Multiplying raw, K, and D by 100 changes only their display scale. The reference levels 0.2 / 0.8 become 20 / 80; a comparison against 80 on a 0-1 series cannot work.
Normalization and smoothing do different jobs. A small RSI change can occupy a large fraction of a narrow RSI range. Averaging then spreads that movement across several observations. More smoothing does not make the response faster.
Worked example: RSI can fall while Stoch RSI rises
This hypothetical input is a sequence of already-computed RSI readings, not market data or a backtest: 40, 50, 60, 55, 45, 50, 55. Set the stochastic window to 3 and both smoothing lengths to 2. The shorter lengths make every calculation visible.
| Bar | RSI | 3-bar low / high | Raw × 100 | K × 100 | D × 100 |
|---|---|---|---|---|---|
| 1 | 40 | Incomplete | na | na | na |
| 2 | 50 | Incomplete | na | na | na |
| 3 | 60 | 40 / 60 | 100 | na | na |
| 4 | 55 | 50 / 60 | 50 | 75 | na |
| 5 | 45 | 45 / 60 | 0 | 25 | 50 |
| 6 | 50 | 45 / 55 | 50 | 25 | 25 |
| 7 | 55 | 45 / 55 | 100 | 75 | 50 |
At bar 5, raw = (45 − 45) / (60 − 45) = 0. K averages raw values 50 and 0 to give 25; D averages K values 75 and 25 to give 50. Raw reaches zero while both smoothed lines remain above zero.
Now consider a separate 3-bar window: RSI values 70, 40, 50 give raw = 33.33 on the 0-100 scale. Let the next RSI be 49. The new window 40, 50, 49 gives raw = 90. RSI fell from 50 to 49, yet raw rose because the old high of 70 left the window. Neither calculation predicts what price does next.
Pine Script with explicit missing-value rules
Paste this into TradingView Pine Editor and add it to the chart. It retains K/D plots and reference bands, adds raw values to the Data Window, and lets you switch scales. This is a calculation example, not a strategy.
//@version=6
indicator("Stochastic RSI - explicit windows", overlay = false, precision = 2, max_bars_back = 500)
rsiLength = input.int(14, "RSI length", minval = 1, maxval = 500)
stochLength = input.int(14, "Stochastic length", minval = 2, maxval = 500)
kLength = input.int(3, "K smoothing", minval = 1, maxval = 500)
dLength = input.int(3, "D smoothing", minval = 1, maxval = 500)
source = input.source(close, "RSI source")
unitScale = input.bool(false, "Use 0-1 scale")
// Require consecutive valid observations; do not skip missing bars.
strictAverage(float values, int length) =>
float total = 0.0
bool valid = true
for i = 0 to length - 1
if na(values[i])
valid := false
else
total += values[i]
valid ? total / length : na
rsi = ta.rsi(source, rsiLength)
var int validRsiBars = 0
validRsiBars := na(rsi) ? 0 : validRsiBars + 1
lowestRsi = ta.lowest(rsi, stochLength)
highestRsi = ta.highest(rsi, stochLength)
rsiRange = highestRsi - lowestRsi
ready = validRsiBars >= stochLength
raw = ready and rsiRange > 0 ? (rsi - lowestRsi) / rsiRange : na
kUnit = strictAverage(raw, kLength)
dUnit = strictAverage(kUnit, dLength)
scale = unitScale ? 1.0 : 100.0
plot(kUnit * scale, "K", color.blue, 2, style = plot.style_linebr)
plot(dUnit * scale, "D", color.orange, 2, style = plot.style_linebr)
plot(raw * scale, "Raw Stoch RSI", display = display.data_window)
upper = hline(unitScale ? 0.8 : 80.0, "Upper reference", color.gray)
hline(unitScale ? 0.5 : 50.0, "Midpoint", color.new(color.gray, 50))
lower = hline(unitScale ? 0.2 : 20.0, "Lower reference", color.gray)
fill(upper, lower, color.new(color.blue, 92))Blue is K; orange is D. The shaded band runs from 20 to 80, or 0.2 to 0.8. Gaps are intentional: no value is drawn while the RSI range is zero or a required window is incomplete. This explicit policy can differ from an implementation that uses partial windows or skips missing values.
Parameters and the first valid bar
| Input | Default | What changes |
|---|---|---|
| RSI length | 14 | The upstream RSI calculation, before normalization. |
| Stochastic length | 14 | Which RSI extrema define the current range. Minimum 2 in this example. |
| K smoothing | 3 | Consecutive raw values averaged into K. Set 1 to inspect raw. |
| D smoothing | 3 | Consecutive K values averaged into D. Set 1 to make D equal K. |
| RSI source | Close | The series supplied to ta.rsi. Keep it identical when comparing scripts. |
| Use 0-1 scale | False | Switches all displayed values and reference levels together. |
Count from the first valid RSI observation. With N = 14, raw first becomes eligible on RSI observation 14, K on observation 16, and D on observation 18, provided the RSI range remains positive. The first valid RSI itself needs earlier price history; 18 RSI observations do not mean 18 price bars from an empty chart.
The general D requirement is N + K length + D length − 2 valid RSI observations when there are no gaps. The code requires consecutive valid raw and K windows. A zero-range raw value invalidates K until that gap leaves its averaging window, and the K gap propagates into D.
If the RSI window is [50, 50, 50], H − L is zero. The code returns na, not zero or the midpoint. With RSI [49.9, 50, 50.1], the raw reading is 100 despite a total RSI spread of only 0.2. A relative extreme says little about the absolute size of a price move.
How to read Stochastic RSI without turning a level into a forecast
| Observation | What the calculation establishes | What still needs testing |
|---|---|---|
| Raw = 100 | Current RSI equals its window high when the range is positive. | Whether price continues or reverses. |
| K crosses D | The average of raw readings changes position relative to its own average. | Any entry, exit, or confirmation rule. |
| K stays above 80 | Recent normalized RSI readings remain near their range highs. | Whether a short position has any advantage. |
| A live cross disappears | The current candle changed before it closed. | Use a defined bar-close decision rule when testing. |
Pine indicators recalculate on realtime updates. The code displays the live candle. Compare closed bars first; if you later add alerts, specify whether they require bar confirmation.
RSI, price Stochastic, and Stoch RSI share bounded displays but use different inputs. RSI processes gains and losses; Stochastic compares price to its price range. Stoch RSI applies range normalization to RSI. Matching 14-bar settings does not make these formulas interchangeable.
Educational calculation only, not investment advice. A strategy needs separate rules for order timing, exits, position sizing, costs, and missing observations. No profit or signal-accuracy claim is made here.
Turn the calculation into a specification for Pineify
The Pineify Pine Script AI Coding Agent can help write a custom script from a description. Give it the calculation contract before asking for alerts or strategy orders.
- Set the chart source and RSI/stochastic/K/D lengths explicitly.
- Specify the output scale and the zero-range policy: return na and require consecutive valid smoothing windows.
- Compare raw, K, and D against the table and inspect the first valid observations.
- Define a closed-bar event, such as K crossing D, separately from an order rule.
- Add exits, sizing, commission, and slippage before evaluating a strategy; keep a separate period for evaluation.
Stochastic RSI questions
Sources and related indicators
Official references checked October 17, 2026. The worked RSI sequences and strict window policy are examples created for this page.