TradingView Indicators

TradingView BOS and CHOCH indicators: define the break before the alert

A BOS/CHOCH indicator labels breaks of selected swing levels: BOS usually means a break in the existing direction; CHOCH means a break against it. The labels depend on how the script selects swings and defines its directional state. For an existing TradingView script, inspect the open-source Market Structure CHoCH/BOS (Fractal) [LuxAlgo] or Smart Money Concepts (SMC) [LuxAlgo]. For custom rules, the complete example below uses confirmed pivots and emits labels only on the bar when a break is known.

Build custom structure rules

Choose an existing indicator or define your own rules

These options are based on the linked authors' documentation, not a side-by-side chart test or performance ranking. Open the exact publication from Sources, check the author and select Use on chart. Inspect the settings and source before comparing labels: two indicators can disagree because their swing definitions differ.

OptionDocumented scopeWhat to inspect
Market Structure CHoCH/BOS (Fractal) [LuxAlgo]Open-source fractal-based structure with optional support/resistance and a dashboardFractal length and missed swings; the author describes this as an experimental approach
Smart Money Concepts (SMC) [LuxAlgo]Open-source internal and swing BOS/CHOCH plus other SMC overlaysWhich structure scale is enabled and which conditions drive alerts
Pineify example on this pageOne latest-confirmed-pivot scale, wick/close modes and four break alertsExplicit initialization and ambiguous-bar handling; intentionally simpler than protected-swing models

BOS and CHOCH are classifications of a chosen structure

A common convention calls an upward break during a bullish state BOS and a downward break CHOCH; the bearish case is the reverse. CHOCH is a possible change of direction, not proof of reversal. Some methods require a protected higher low or lower high, while others use the latest local pivot. Those are different algorithms and should not be presented as interchangeable.

  • The example uses the direction of the previous unambiguous break as state. It does not infer a full sequence of higher highs and higher lows.
  • Every newly confirmed pivot replaces the active level on that side. A protected-swing implementation would need additional rules for selecting and retaining levels.
  • An illustrative bullish state with a high at 105 and a low at 98 classifies a close above 105 as BOS and a close below 98 as CHOCH. These are example prices, not observed trades.
State before breakHigh breaksLow breaks
Uninitialized (0)Initialize bullish; no BOS/CHOCHInitialize bearish; no BOS/CHOCH
Bullish (+1)Bullish BOS; stay bullishBearish CHOCH; become bearish
Bearish (-1)Bullish CHOCH; become bullishBearish BOS; stay bearish

When a pivot becomes available

ta.pivothigh() and ta.pivotlow() identify local extremes using bars on both sides. With five right bars, a pivot at bar T can be accepted at the close of T + 5. The script below waits for that close and plots the level from its confirmation bar without a negative offset. All break labels are placed on the current event bar.

  • A historical marker at T may have been created at T + 5. Check the time the information became available, not just the marker position.
  • Window lengths are measured in chart bars, not fixed minutes. Market closures and missing bars affect elapsed time.
  • Different lengths change the selected swings. No universal setting or signal frequency is established here.
Right barsEarliest confirmationInterpretation
2Close of T + 2Short confirmation window
5Close of T + 5Longer delay than two right bars
10Close of T + 10Requires more subsequent bars

Wick versus close: choose the price test and the evaluation time

A close beyond a level and an intrabar excursion beyond it are different events. A candle can trade above a swing high and finish below it. Close confirmation rejects that particular event, but it can also react later; this page makes no measured claim about win rate or false-break reduction.

  • Equality is not a break in either mode. A close beyond a level does not require the whole candle body to be outside it.
  • Wick mode here does not issue immediate intrabar alerts. Both modes wait for barstate.isconfirmed.
  • If one completed candle crosses both active levels, OHLC data does not establish which break happened first. The example consumes both levels, prints AMBIGUOUS and leaves direction unchanged.
  • A wick alone cannot establish a stop hunt, identify a participant or prove that resting orders were absorbed.
Mode in this exampleUpward / downward testEvaluation time
Closeclose > high level / close < low levelConfirmed bar close
Wickhigh > high level / low < low levelConfirmed bar close, using completed extremes

Complete Pine Script v6 example

Paste the complete indicator into Pine Editor, save it and add it to a chart. It stores confirmed pivots, classifies each break from the prior state and clears the broken level regardless of display settings. The first break receives an INIT label rather than an invented CHOCH. Labels identify event time; no drawing is moved back to the original pivot candle.

  • The opposite unbroken level remains active until consumed or replaced. This can differ from a protected-swing reset after a trend change.
  • The indicator keeps approximately the latest 200 labels through TradingView drawing garbage collection. Older labels disappearing is a display limit, not a recalculated signal.
  • No orders, stop losses, position sizing or profitability evaluation are included. A compiler check alone does not validate trading behavior.
Latest confirmed pivot model; chart timeframe; both modes wait for bar closepinescript
//@version=6
indicator("BOS and CHOCH example [Pineify]", overlay = true, max_labels_count = 200)

leftBars = input.int(5, "Pivot left bars", minval = 1, maxval = 100)
rightBars = input.int(5, "Pivot right bars", minval = 1, maxval = 100)
breakMode = input.string("Close", "Break test", options = ["Close", "Wick"])
showBos = input.bool(true, "Show BOS labels")
showChoch = input.bool(true, "Show CHOCH labels")

ph = ta.pivothigh(high, leftBars, rightBars)
pl = ta.pivotlow(low, leftBars, rightBars)
var float activeHigh = na
var float activeLow = na
var int direction = 0

bool bullBos = false
bool bearBos = false
bool bullChoch = false
bool bearChoch = false

if barstate.isconfirmed
    if not na(ph)
        activeHigh := ph
    if not na(pl)
        activeLow := pl

    float upPrice = breakMode == "Close" ? close : high
    float downPrice = breakMode == "Close" ? close : low
    bool upBreak = not na(activeHigh) and upPrice > activeHigh
    bool downBreak = not na(activeLow) and downPrice < activeLow

    if upBreak and downBreak
        // Intrabar ordering is unknown. Wait for fresh pivots on both sides.
        label.new(bar_index, high, "AMBIGUOUS", style = label.style_label_down, color = color.gray, textcolor = color.white)
        activeHigh := na
        activeLow := na
    else if upBreak
        bullBos := direction == 1
        bullChoch := direction == -1
        if direction == 0 or (bullBos and showBos) or (bullChoch and showChoch)
            string tag = direction == 0 ? "INIT UP" : bullBos ? "BOS UP" : "CHOCH UP"
            label.new(bar_index, high, tag, style = label.style_label_down, color = color.teal, textcolor = color.white)
        direction := 1
        activeHigh := na
    else if downBreak
        bearBos := direction == -1
        bearChoch := direction == 1
        if direction == 0 or (bearBos and showBos) or (bearChoch and showChoch)
            string tag = direction == 0 ? "INIT DOWN" : bearBos ? "BOS DOWN" : "CHOCH DOWN"
            label.new(bar_index, low, tag, style = label.style_label_up, color = color.red, textcolor = color.white)
        direction := -1
        activeLow := na

// Levels begin when confirmed; there is no backdated offset.
plot(activeHigh, "Active confirmed high", color = color.teal, style = plot.style_linebr)
plot(activeLow, "Active confirmed low", color = color.red, style = plot.style_linebr)
alertcondition(bullBos, "Bullish BOS", "Bullish BOS on {{ticker}} {{interval}}")
alertcondition(bearBos, "Bearish BOS", "Bearish BOS on {{ticker}} {{interval}}")
alertcondition(bullChoch, "Bullish CHOCH", "Bullish CHOCH on {{ticker}} {{interval}}")
alertcondition(bearChoch, "Bearish CHOCH", "Bearish CHOCH on {{ticker}} {{interval}}")

Set alerts and review event timing

Create an alert from the chart after adding the indicator. Choose one of its four named BOS/CHOCH conditions and select Once Per Bar Close. Pine code exposes conditions; it does not create a running alert automatically. TradingView saves an alert snapshot, so recreate the alert after changing code, inputs, symbol or timeframe.

  • Replay check: step through a candidate pivot and verify its level is unavailable until the required right bars close. An event must never appear on an earlier pivot bar.
  • State check: verify the first break is INIT, a same-direction break is BOS, and an opposite-direction break is CHOCH. Repeated closes beyond a consumed level must not repeat the alert.
  • Display check: disable BOS or CHOCH labels and confirm that the underlying conditions and level consumption still work.
  • Wick check: find a bar that crosses both levels and verify it produces AMBIGUOUS with no directional alert. A wick beyond only one level can qualify even if its close returns inside.
  • These are proposed behavioral checks, not reported chart-test results. Replay helps review historical timing; verify actual alert delivery separately in realtime.
Where Pineify fits

Pine Script AI Coding Agent

Describe your swing selection, state transitions and alert timing to generate a custom Pine Script draft. Specify protected-swing rules if you need them, then review and test the generated behavior in TradingView.

Build custom structure rules

Frequently asked questions

Educational programming information, not investment advice. Structure labels do not establish future direction or profitable entries. The example is an indicator, not a tested trading strategy.

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.