Volatility oscillator · Pine Script v6
Relative Volatility Index: formula and Pine Script
The Relative Volatility Index assigns rolling price standard deviation to directional branches, smooths them, and expresses the upper share on a 0-to-100 scale. This guide implements a close/EMA version with explicit initialization and a worked calculation. It is different from the Relative Vigor Index, which also uses the abbreviation RVI.
Choose the RVI version before comparing values
Donald Dorsey developed the Relative Volatility Index to describe volatility direction. The TradingView help article describes a high/low standard deviation formulation. The code here uses the close/EMA formulation found in the Pineify RVOI implementation; it is a defined teaching example, not a claim of exact parity with every built-in or community script.
Its two lengths do different jobs: 10 closes form each standard deviation window, while a 14-period EMA smooths each directional input. This is standard deviation of price levels. It is not standard deviation of returns, nor a separate standard deviation calculated only from up bars.
Version contract: close source, population standard deviation, EMA smoothing, unchanged closes assigned to the lower branch, first-valid-input seeds, zero denominator returning na, and zero plot offset.
Formula, smoothing, and boundary conditions
σ = sqrt(sum((close − mean(close, n))²) / n)
u = close > close[1] ? σ : 0
d = close > close[1] ? 0 : σ
α = 2 / (m + 1)
U = α × u + (1 − α) × U[1]
D = α × d + (1 − α) × D[1]
RVI = 100 × U / (U + D)
The EMA is a decaying accumulation of directional inputs, not a fixed rolling sum. The code seeds U and D with their first valid inputs, including zero. Both stay uninitialized until σ and the previous close are available. Invalid current inputs leave the stored EMA state unchanged and produce no RVI point.
When U + D is zero, the ratio is undefined. The script plots a gap instead of inventing a neutral 50. A constant series from the start stays undefined; one flat bar after changing prices may have positive σ and therefore still affect the lower branch. Returning 50 or sending flat bars to neither branch would be different, legitimate conventions that must be documented.
For nonnegative U and D with a positive total, RVI is bounded by 0 and 100. At 50 the components are equal. At 80, U = 4D. These are algebraic statements about the formula, not probabilities or estimates of future returns.
Worked example: a flat close still contributes
Demonstration only: closes are 100, 102, 101, 101, 103, 102. Set n = 3 and m = 3, so α = 0.5. Bars 1 and 2 are warmup. Values below are rounded to six decimals; calculations retain full precision.
| Bar | Close | σ | Input branch | U | D | RVI |
|---|---|---|---|---|---|---|
| 3 | 101 | 0.816497 | Lower | 0 | 0.816497 | 0.000000 |
| 4 | 101 | 0.471405 | Lower (flat) | 0 | 0.643951 | 0.000000 |
| 5 | 103 | 0.942809 | Upper | 0.471405 | 0.321975 | 59.417258 |
| 6 | 102 | 0.816497 | Lower | 0.235702 | 0.569236 | 29.282032 |
At bar 3, mean(100, 102, 101) = 101, so σ = sqrt(2/3). The down close seeds U = 0 and D = σ. At bar 5, U = 0.5 × 0.942809 = 0.471405 and D = 0.5 × 0.643951 = 0.321975. Their ratio gives 59.417258. Bar 6 crosses back below 50 despite having the same σ as bar 3, because EMA history changes the ratio.
Copyable Pine Script with confirmed crossings
This indicator preserves the close/EMA calculation and makes the initial state explicit. It exposes U and D in the Data Window so you can check the intermediate values. It does not submit trades.
//@version=6
indicator("Relative Volatility Index: close / EMA example", overlay = false)
stdLength = input.int(10, "Close standard deviation length", minval = 2)
emaLength = input.int(14, "Directional EMA length", minval = 1)
sigma = ta.stdev(close, stdLength, true)
delta = ta.change(close)
ready = not na(sigma) and not na(delta)
// This variant assigns unchanged closes to the lower branch.
upInput = ready ? (delta > 0 ? sigma : 0.0) : na
downInput = ready ? (delta > 0 ? 0.0 : sigma) : na
// Explicit EMA seed: first valid directional input, including zero.
alpha = 2.0 / (emaLength + 1.0)
var float upper = na
var float lower = na
if ready
upper := na(upper) ? upInput : alpha * upInput + (1.0 - alpha) * upper
lower := na(lower) ? downInput : alpha * downInput + (1.0 - alpha) * lower
total = upper + lower
rvi = ready and not na(total) and total > 0 ? 100.0 * upper / total : na
plot(rvi, "RVI", color = color.purple, linewidth = 2, style = plot.style_linebr)
plot(upper, "Upper EMA", display = display.data_window)
plot(lower, "Lower EMA", display = display.data_window)
hline(80, "80 reference", color = color.gray)
hline(50, "Equal components", color = color.gray)
hline(20, "20 reference", color = color.gray)
crossUp = ta.crossover(rvi, 50)
crossDown = ta.crossunder(rvi, 50)
confirmedUp = crossUp and barstate.isconfirmed
confirmedDown = crossDown and barstate.isconfirmed
plotshape(confirmedUp, "Confirmed above 50", shape.triangleup, location.bottom, color.blue, size = size.tiny)
plotshape(confirmedDown, "Confirmed below 50", shape.triangledown, location.top, color.orange, size = size.tiny)
alertcondition(confirmedUp, "RVI above 50", "Relative Volatility Index crossed above 50 on a closed bar.")
alertcondition(confirmedDown, "RVI below 50", "Relative Volatility Index crossed below 50 on a closed bar.")The purple line can move on an open bar. Blue and orange markers require a completed cross above or below 50 and bar confirmation. Create an alert from the corresponding condition after adding the script to your chart. This script makes no higher-timeframe requests.
Parameters and a repeatable TradingView check
| Setting | Example default | What changes |
|---|---|---|
| Standard deviation length | 10, minimum 2 | The number of closes used to estimate price dispersion. |
| Directional EMA length | 14, minimum 1 | The decay factor of both components; m = 14 gives α = 2/15. |
| Reference levels | 20, 50, 80 | Only 50 drives the example alerts. 20 and 80 are display references. |
- Paste the script into a new Pine Editor indicator, save it, and add it to a standard candlestick chart.
- Hold symbol, data feed, session, timeframe, and price adjustments fixed. Compare closed bars in the Data Window.
- Match price source, both lengths, smoothing type, flat-bar handling, and initialization before comparing another RVI.
- Check early history and a later interval separately. A different seed can cause a temporary mismatch even when subsequent formulas agree.
- Check a flat-price interval and an open bar. A missing ratio and a changing current value are expected under the stated rules.
Read the ratio without confusing it with trade performance
Above 50 means the upper EMA exceeds the lower EMA. It does not prove that absolute volatility is rising: multiplying both components by the same positive factor leaves RVI unchanged. ATR or the unnormalized standard deviation answers a different question about scale.
A crossing can be a condition to test, but it leaves position size, execution timing, costs, and exits unspecified. For a research specification, one possible rule is to evaluate an upward 50 cross only on a closed bar with close above its 200-bar EMA, then define the next-bar entry, a price-based stop, and a downward-cross exit separately. Those are proposed rules, not results from this example.
Repeated crossings around 50 can create frequent trades in a range. Divergence is also insufficient by itself: the oscillator can weaken while price continues rising. A high RVI does not set a stop distance, and 80 does not mean an 80% chance of a profitable trade. Educational calculation only, not investment advice.
Relative Volatility Index vs. ATR and Relative Vigor Index
| Indicator | Input and calculation | Readout |
|---|---|---|
| Relative Volatility Index | Directional standard deviation components, smoothed and divided | 0 to 100 when defined; relative directional allocation |
| ATR | Smoothed maximum of high-low and distances from the previous close | Nonnegative price units; no directional sign |
| Relative Vigor Index | Smoothed close-open compared with smoothed high-low | Zero-centered ratio; candle body relative to range |
| RSI | Smoothed upward and downward price changes | 0 to 100; changes rather than price dispersion |
Keep the full indicator name in saved scripts and comparison notes. An RVI midpoint of 50 belongs to the volatility formulation here; applying it to Relative Vigor Index would use the wrong scale.
Turn a defined RVI variant into a script with Pineify
Give the Pineify Pine Script AI Coding Agent the calculation contract before asking for alerts or strategy rules. A concrete prompt is: "Use close-price population standard deviation over 10 bars, smooth directional inputs with a 14-period EMA seeded at the first valid input, assign flat closes to the lower branch, return na on a zero total, and confirm 50-level alerts at bar close."
Review the generated source and compare intermediate values bar by bar. If you request a strategy next, specify exits, sizing, fees, and slippage independently. A successful syntax check establishes that the code compiles; it does not establish useful trading performance.
Open Pine Script AI Coding AgentRelative Volatility Index FAQ
Sources and related indicators
Sources checked October 17, 2026. The formula contract and synthetic table describe the code on this page; the sources provide indicator definitions and Pine bar-confirmation behavior.
- TradingView: Relative Volatility Index
- TradingView: Relative Vigor Index
- TradingView: Average True Range
- TradingView Pine Script: bar states
Relative Vigor Index
Compare candle bodies with ranges.
Average True Range
Measure volatility in price units.
Relative Strength Index
Compare directional price changes.