TradingView Indicators & Pine Script v6

TradingView Range Indicators: Define the Box Before the Breakout

A consolidation range indicator on TradingView marks a price ceiling and floor using an explicit detection rule. ATR and ADR measure historical volatility; neither defines those boundaries by itself. For breakout alerts, specify when the box becomes active, whether its prices can change, and whether a wick or a completed close ends it. The example below freezes each confirmed box and checks subsequent closes against those saved levels.

Build a Custom Range Indicator

Choose a range indicator for the measurement you need

The word range covers several different measurements. A rolling channel always has a high and low, even during a trend. A consolidation detector adds a qualification rule to decide which channels to retain. Neither a tight channel nor a small ATR proves that price will reverse or break out.

  • For ATR or ADR, search the indicator list by its full name and verify its timeframe and smoothing settings. An intraday high-low average is not a daily ADR unless daily data is used.
  • For a community consolidation script, inspect its description and available source: window length, historical box placement, refresh rule, and alert condition matter more than the name.
  • To use the example here, paste the complete script into Pine Editor, save it, and add it to a standard candlestick chart. It is a chart indicator, not a multi-symbol screener.
MeasurementDefinitionWhat it does not establish
Consolidation boxSaved high and low from a window that passes a chosen width or structure test.A universal definition of sideways trading, or a future breakout direction.
Rolling high/low channelHighest high and lowest low over the latest N bars; the window advances each bar.Fixed support and resistance. Old extremes can expire from the window.
ATRSmoothed true range: max(high minus low, absolute high minus previous close, absolute low minus previous close). TradingView defaults to RMA smoothing.A price ceiling, floor, or guaranteed travel distance. ATR is a magnitude, not a band by itself.
ADRAverage daily high minus low across the chosen daily lookback. Unlike true range, it does not separately include the gap from the previous close.A daily limit or an exhaustion signal. Projecting ADR from an open is an additional rule.
Opening rangeHigh and low during a defined session opening window, then held fixed.A consolidation test. The opening window can contain a strong trend.

Define boundaries, width, and duration separately

This example calculates H as the highest high and L as the lowest low over N completed chart bars, including the confirmation bar. Width is H minus L; the midpoint is (H plus L) / 2. A candidate qualifies when width is positive and no greater than ATR times the width multiplier. This is a reproducible compression rule, not proof of market equilibrium. A slowly trending window can also pass it.

  • A touch-count rule would need a tolerance, minimum spacing between touches, and a definition of a rejection. This sample does not implement touch counting.
  • The box starts at the confirmation bar, although its prices come from the preceding window. This avoids drawing a detected range as if it had been known at the beginning of that window.
  • Chart timeframe and session selection change the input bars. The sample has no daily reset and can carry a box across sessions.
Input or measureExample defaultMeaning and tradeoff
Lookback N20 barsThe measured window, not an extra 20-bar waiting period after detection.
ATR length50 barsNormalizes width using chart-timeframe volatility; a prior volatility spike can make the threshold permissive.
Width multiplier2.0A larger threshold accepts wider boxes. No default is claimed to suit every market.
Maximum active age100 subsequent barsExpires an unbroken box so old levels do not persist indefinitely.
Midpoint(H + L) / 2A geometric center only; it does not measure traded volume or establish fair value.

Freeze boundaries before checking a breakout

Updating the ceiling to the current high before comparing close against it can suppress an upward breakout: close cannot exceed that same bar's high. The sample keeps both prices fixed while the box is active. It processes a close outside the saved box before expiry and never creates a replacement box on the same bar.

  • Close confirmation excludes wick-only excursions but cannot prevent a later reversal. It also delays the signal until the bar finishes.
  • The optional volume test compares current volume with a multiple of the previous 20 bars' average. This is not a same-time-of-day volume comparison or evidence of institutional participation.
  • When the volume filter is enabled, missing volume or a missing/nonpositive baseline rejects the alert. With the filter disabled, volume does not affect signals.
  • A retest is a separate rule. For example, require a later low to touch the saved ceiling and that bar to close above it within a specified number of bars. Retest and false-breakout tracking are not implemented here.
EventSample behavior
Wick outside, close inside or exactly on a boundaryKeep the box active with unchanged prices. A boundary touch is not a breakout.
First completed close strictly above H or below LEnd the box. Emit an alert signal only if the optional volume condition passes.
Outside close fails the volume filterEnd and mark the box gray; do not wait for a later outside bar to qualify.
No outside close by the maximum ageExpire the box without an alert. On the expiry bar, an outside close takes precedence.
After breakout or expiryWait for N entirely new completed bars, then test each rolling window until one qualifies.

Pine Script v6: fixed range boxes and close-confirmed alerts

The indicator below changes range state only on confirmed bars and evaluates no higher-timeframe requests. It retains up to 50 boxes, colors qualifying upside breaks green and downside breaks red, and uses gray for expiry or a volume-rejected break. Historical marks show the result of this rule, not simulated trades. Syntax validation does not establish trading performance.

Complete indicator: fixed boundaries, one exit event per boxpinescript
//@version=6
indicator("Pineify Fixed Range Example", overlay = true, max_boxes_count = 60)

int lookback = input.int(20, "Range lookback", minval = 2, maxval = 500)
int atrLength = input.int(50, "ATR length", minval = 1)
float widthMult = input.float(2.0, "Maximum width / ATR", minval = 0.1, step = 0.1)
int maxAge = input.int(100, "Maximum active age", minval = 1)
bool useVolume = input.bool(false, "Require volume filter")
float volumeMult = input.float(1.5, "Volume / previous 20-bar average", minval = 0.1, step = 0.1)

float candidateHigh = ta.highest(high, lookback)
float candidateLow = ta.lowest(low, lookback)
float rangeWidth = candidateHigh - candidateLow
float atrValue = ta.atr(atrLength)
float priorVolume = ta.sma(volume, 20)[1]
bool volumePass = not useVolume or (not na(volume) and not na(priorVolume) and priorVolume > 0 and volume > priorVolume * volumeMult)
bool compressed = bar_index >= lookback - 1 and not na(atrValue) and rangeWidth > 0 and rangeWidth <= atrValue * widthMult

var bool active = false
var float ceiling = na
var float floor = na
var int confirmedAt = na
var int endedAt = na
var box currentBox = na
var array<box> boxes = array.new<box>()
bool bullBreak = false
bool bearBreak = false

if barstate.isconfirmed
    if active
        box.set_right(currentBox, bar_index)
        bool above = close > ceiling
        bool below = close < floor
        bool expired = bar_index - confirmedAt >= maxAge
        if above or below or expired
            bullBreak := above and volumePass
            bearBreak := below and volumePass
            color resultColor = bullBreak ? color.green : bearBreak ? color.red : color.gray
            box.set_border_color(currentBox, resultColor)
            box.set_bgcolor(currentBox, color.new(resultColor, 90))
            active := false
            endedAt := bar_index
    else
        // Require a new, non-overlapping window after the previous box ends.
        bool freshWindow = na(endedAt) or bar_index - endedAt >= lookback
        if freshWindow and compressed
            ceiling := candidateHigh
            floor := candidateLow
            confirmedAt := bar_index
            active := true
            currentBox := box.new(left = bar_index, top = ceiling, right = bar_index, bottom = floor, border_color = color.blue, bgcolor = color.new(color.blue, 90))
            array.push(boxes, currentBox)
            if array.size(boxes) > 50
                box.delete(array.shift(boxes))

plot(active ? (ceiling + floor) / 2 : na, "Range midpoint", color = color.orange, style = plot.style_linebr)
plotshape(bullBreak, title = "Upside close", style = shape.triangleup, location = location.belowbar, color = color.green, size = size.tiny)
plotshape(bearBreak, title = "Downside close", style = shape.triangledown, location = location.abovebar, color = color.red, size = size.tiny)
alertcondition(bullBreak, "Range close above", "Confirmed close above the saved range on {{ticker}} at {{close}}")
alertcondition(bearBreak, "Range close below", "Confirmed close below the saved range on {{ticker}} at {{close}}")

Create alerts and check the behavior

Adding the indicator does not create a running alert. In TradingView's Create Alert dialog, select this indicator and either Range close above or Range close below, then choose Once Per Bar Close. Create separate alerts for both directions if needed. Running alerts use a saved copy of the script and settings; recreate them after changing the code, inputs, symbol, or timeframe.

  • These are reproducible acceptance cases, not reported chart-test or backtest results. Check them on standard candles before adapting the script.
  • To test a trading strategy, separately define entry timing, exits, position size, commissions, and slippage. Compare settings on data outside the tuning period.
  • A midpoint stop is closer than an opposite-boundary stop, but that alone says nothing about realized profit factor. No stop placement or parameter set is claimed to be optimal.
CheckExpected result under this rule
Before enough lookback and ATR history existsNo range is created. A zero-width window is also rejected.
Intrabar movement outside the active boxNo confirmed signal until the candle closes.
A saved box at 100 to 102; high reaches 103 but close is 101.5Keep the 100 and 102 boundaries.
Next bar closes at 102.5 with volume filtering disabledOne upside mark; terminate the box.
Following bars remain above 102No repeated signal from that terminated box.
A fresh candidate after terminationEligible only once the entire N-bar window falls after the termination bar.
Where Pineify fits

Pine Script AI Coding Agent

Use Pineify to draft a custom range indicator from explicit rules. Specify the detection window, width test, frozen or updating boundaries, expiry, and alert timing, then inspect and validate the generated script in TradingView.

Build a Custom Range Indicator

Frequently asked questions

Educational programming example, not investment advice. The settings have not been optimized or performance-tested. Range detection and confirmed alerts do not establish profitable entries or guarantee future price behavior.

Sources and verification

Published by Pineify. Pineify is an independent product and is not affiliated with TradingView. Sources support the technical explanations; examples do not establish trading performance.