Volatility Stop on TradingView: State, ATR and Reversals
The Volatility Stop indicator is a stateful ATR trailing line. Within an upward state it can only rise; within a downward state it can only fall. A reversal tests price against the candidate stop, then resets the line on the opposite side of price. That order matters when reproducing its values.
This guide defines an auditable close-based version, including its warm-up and equality rules. The table and Pine code use the same algorithm. They are an educational reference, not a claim to reproduce every public or protected VStop script.
Specify the state before comparing lines
TradingView's open-source Volatility Stop describes an ATR trend detector that can also serve as a stop guide. The implementation below uses closes for its running extremes and confirms updates at the chart bar's close. Its explicit initialization is part of the definition.
- Compute volatility. True range is max(high − low, |high − previous close|, |low − previous close|). On the first available bar, use high − low. ATR is Wilder's RMA of true range: seed with the mean of the first N valid true ranges, then ATR = ((N − 1) × previous ATR + current TR) / N. Distance D = multiplier × ATR.
- Initialize once ATR exists. Until then, show no stop. On the first confirmed bar with ATR, set peak = trough = close, state = up, and stop = close − D. Initialization emits no reversal alert. The starting direction is a convention, not evidence that a trend has begun.
- Update extremes and the candidate. Extend peak and trough with the current close. If the previous state is up, candidate = max(previous stop, peak − D). If it is down, candidate = min(previous stop, trough + D).
- Decide the new state. Set next state to up when close ≥ candidate, otherwise down. Compare with the candidate before resetting anything.
- Reset only on a reversal. If the state changed, set both extremes to the current close and the final stop to close − D for up or close + D for down. Otherwise retain the candidate. Save the new state for the next bar.
ATR uses the chart's OHLC data even though the extreme source is close. Changing the source to HL2 does not change the ATR formula or automatically provide close confirmation. See TradingView's ATR documentation and the ta.atr reference.
Eight OHLC bars, including a wick and two gaps
These are synthetic prices in arbitrary price units, not market observations or performance results. Set N = 3, multiplier = 1 and source = close. Bar 1 is the first available bar. Calculations retain full precision; the table rounds to six decimals.
| Bar | Open / High / Low / Close | TR | ATR | Candidate | Final stop | Final state |
|---|---|---|---|---|---|---|
| 1 | 100 / 102 / 100 / 101 | 2 | Not seeded | None | None | Warm-up |
| 2 | 101 / 103 / 101 / 102 | 2 | Not seeded | None | None | Warm-up |
| 3 | 102 / 104 / 101 / 103 | 3 | 2.333333 | Initialize | 100.666667 | Up (seed) |
| 4 | 103 / 107 / 103 / 106 | 4 | 2.888889 | 103.111111 | 103.111111 | Up |
| 5 | 106 / 107 / 101 / 105 | 6 | 3.925926 | 103.111111 | 103.111111 | Up (wick) |
| 6 | 99 / 100 / 97 / 98 | 8 | 5.283951 | 103.111111 | 103.283951 | Down (gap) |
| 7 | 98 / 99 / 95 / 96 | 4 | 4.855967 | 100.855967 | 100.855967 | Down |
| 8 | 103 / 105 / 102 / 104 | 9 | 6.237311 | 100.855967 | 97.762689 | Up (gap) |
Bar 4 ratchet: the highest close is 106. ATR = (2 × 2.333333… + 4) / 3 = 2.888888…. The candidate rises to max(100.666667, 106 − 2.888889) = 103.111111.
Bar 5 intrabar crossing: its low of 101 is below the stop, but its close is 105. The candidate stays at 103.111111 because the new ATR distance would otherwise lower it. This close-confirmed version keeps the upward state. OHLC alone cannot reconstruct every intermediate tick or the order of the high and low.
Bar 6 gap: the previous close is 105, so TR = max(3, 5, 8) = 8, not just high − low = 3. The close of 98 is below the candidate 103.111111. After the flip, both extremes reset to 98 and the new down stop becomes 98 + 5.283951 = 103.283951.
Bar 8 reverse gap: TR = max(3, 9, 6) = 9. The down candidate remains 100.855967, then close 104 selects up. The reset yields 104 − 6.237311 = 97.762689. Comparing close with this final line would obscure which boundary caused the reversal.
Pine Script v6 with explicit close confirmation
Paste this indicator into TradingView's Pine Editor and add it to a standard candlestick chart. The inputs default to 20 and 2; change them to 3 and 1 when checking the synthetic arithmetic separately. The code plots a guide and defines alert conditions. It places no orders.
//@version=6
indicator("Volatility Stop: confirmed-close reference", overlay = true)
int length = input.int(20, "ATR length", minval = 1)
float factor = input.float(2.0, "ATR multiplier", minval = 0.01, step = 0.1)
float atr = ta.atr(length)
var float peak = na
var float trough = na
var float stop = na
var bool up = true
bool flippedUp = false
bool flippedDown = false
// Wait for a seeded ATR. Commit state only when the chart bar closes.
if barstate.isconfirmed and not na(atr)
float distance = factor * atr
if na(stop)
peak := close
trough := close
up := true
stop := close - distance
else
peak := math.max(peak, close)
trough := math.min(trough, close)
float candidate = up ? math.max(stop, peak - distance) : math.min(stop, trough + distance)
bool nextUp = close >= candidate
flippedUp := nextUp and not up
flippedDown := not nextUp and up
if nextUp != up
peak := close
trough := close
stop := nextUp ? close - distance : close + distance
else
stop := candidate
up := nextUp
plot(stop, "Confirmed VStop", color = up ? color.teal : color.red, style = plot.style_stepline)
plot(up ? 1 : -1, "State: up 1, down -1", display = display.data_window)
plot(atr, "ATR", display = display.data_window)
plotshape(flippedUp, title = "Up reversal", style = shape.triangleup, location = location.belowbar, color = color.teal, text = "UP", size = size.tiny)
plotshape(flippedDown, title = "Down reversal", style = shape.triangledown, location = location.abovebar, color = color.red, text = "DOWN", size = size.tiny)
alertcondition(flippedUp, "VStop up reversal", "Confirmed VStop up reversal")
alertcondition(flippedDown, "VStop down reversal", "Confirmed VStop down reversal")The ATR calculation executes on every update, while the persistent state changes only inside barstate.isconfirmed. On an open bar the line retains its previous confirmed value. Pine indicators otherwise recalculate as prices update, with rollback between ticks; using close as a source alone does not make a script close-confirmed. See the Pine execution model and bar-state documentation.
For an alert, select either reversal condition and use Once Per Bar Close. The seed bar does not count as a flip. Recreate an existing alert after changing the script or its inputs because TradingView alerts retain a snapshot of their original configuration. TradingView alert behavior.
VStop versus a rolling Chandelier Exit
A standard Chandelier Exit anchors its long line to the highest high in a fixed lookback and its short line to the lowest low in that lookback. This VStop anchors to closes since its last state reset and applies a one-way ratchet. The ATR length does not define the age of its peak or trough.
Suppose a rolling highest high falls from 110 to 108 when an old bar leaves the window, with ATR distance fixed at 4. The unratcheted Chandelier long level falls from 106 to 104. An upward VStop already at 106 remains at least 106 until reversal. Custom Chandelier scripts can add a ratchet, so compare formulas rather than names.
Conditions that break a naive comparison
- Different history lengths or warm-up fallbacks can produce different starting states. This example deliberately waits for ATR; another script may substitute true range immediately.
- A gap may jump over an executable stop. An indicator line is not a guaranteed fill price, and waiting for close may recognize an exit much later than a resting order.
- Small alternating closes near the candidate can cause repeated reversals. Larger multipliers change that tradeoff but do not establish profitability.
- Adjusted prices, sessions and synthetic chart types can change OHLC, ATR and the resulting state. Compare the same symbol, session, timeframe and standard chart data.
- Zero ATR places the initial stop at the close despite a positive multiplier. Equality follows the stated upward convention; a positive distance is not guaranteed in a flat series.
Educational material only, not investment advice. Syntax validation does not prove signal quality, fills or future returns.
Turn the documented rules into a script you can compare
Pineify's Pine Script AI Coding Agent can create and edit Pine code from a written specification and offers syntax checking. Provide the initialization, ATR smoothing, source, equality rule and close condition together. Review the resulting source before relying on its plots or alerts.
Example request: "Keep the confirmed-close VStop rules on this page. Expose ATR length and multiplier. Add Data Window values for the candidate and the running extremes so I can compare each closed bar. Preserve the no-alert initialization rule."
Compare closed-bar values in TradingView's Data Window before creating alerts. A public formula can be implemented and tested; a protected script's private source cannot be inferred reliably from its name or screenshot.
Open Pine Script AI Coding AgentVolatility Stop questions
Continue with the TradingView indicator library, ATR or Supertrend. Official references checked October 17, 2026.