Indicators··7 min read

Swing Structure: BOS and CHoCH Marker

0 references, link-verified · inline [n] markersEditor of record: Shane CantyStandards review editorial standard · audit log

This indicator identifies and labels two key market structure events: Break of Structure (BOS) and Change of Character (CHoCH). BOS marks the moment price crosses a previous swing extreme, signaling a potential shift in directional control. CHoCH occurs when the market creates a new swing extreme beyond the prior one in the same direction, indicating strengthening momentum or trend continuation. Traders who study price structure and support-and-resistance frameworks use these markers to identify potential entry points, exits, or changes in market regime.

//@version=6
indicator("Swing Structure: BOS and CHoCH Marker", overlay=true)

// Inputs
lookback = input(5, title="Swing Lookback Period", minval=2, maxval=20)
showSwings = input(true, title="Show Swing Points")
showLabels = input(true, title="Show BOS/CHoCH Labels")

// Track structure state across bars
var float lastSwingHigh = na
var float lastSwingLow = na
var float prevSwingHigh = na
var float prevSwingLow = na

// Detect swing high: current high is greater than all bars in lookback period before it
isSwingHigh = true
for i = 1 to lookback
    if high[i] >= high
        isSwingHigh := false
        break

// Detect swing low: current low is less than all bars in lookback period before it
isSwingLow = true
for i = 1 to lookback
    if low[i] <= low
        isSwingLow := false
        break

// Update structure when new swings form
if isSwingHigh
    prevSwingHigh := lastSwingHigh
    lastSwingHigh := high

if isSwingLow
    prevSwingLow := lastSwingLow
    lastSwingLow := low

// Break of Structure: price crosses the last swing level with conviction
bosHigh = not na(lastSwingHigh) and close > lastSwingHigh and close[1] <= lastSwingHigh
bosLow = not na(lastSwingLow) and close < lastSwingLow and close[1] >= lastSwingLow

// Change of Character: new swing exceeds previous extreme in the same direction
chochHigh = isSwingHigh and not na(prevSwingHigh) and high > prevSwingHigh
chochLow = isSwingLow and not na(prevSwingLow) and low < prevSwingLow

// Offset for label positioning using volatility
offset = ta.atr(14) * 0.5

// Plot swing points as circles
if showSwings
    if isSwingHigh
        plot(high, color=color.new(color.blue, 70), style=plot.style_circles, linewidth=2, title="Swing High")
    if isSwingLow
        plot(low, color=color.new(color.red, 70), style=plot.style_circles, linewidth=2, title="Swing Low")

// Create labels for BOS and CHoCH events
if showLabels
    if bosHigh
        label.new(bar_index, high + offset, "BOS↑", color=color.blue, textcolor=color.white, style=label.style_label_lower, size=size.small)
    if bosLow
        label.new(bar_index, low - offset, "BOS↓", color=color.red, textcolor=color.white, style=label.style_label_upper, size=size.small)
    if chochHigh
        label.new(bar_index, high + offset * 2, "CHoCH↑", color=color.navy, textcolor=color.white, style=label.style_label_lower, size=size.small)
    if chochLow
        label.new(bar_index, low - offset * 2, "CHoCH↓", color=color.maroon, textcolor=color.white, style=label.style_label_upper, size=size.small)

How the code works

The indicator maintains two rolling records of swing extremes: the most recent swing high and low, plus the previous ones before those. On each bar, it checks whether the current high is greater than every bar in the lookback window (confirming a swing high), or the current low is less than every bar in the lookback window (confirming a swing low). When a new swing high forms, the old one is shifted to "previous high"; the same pattern applies to lows.

Break of Structure triggers when close crosses above the stored last swing high (with the prior close below it), or crosses below the last swing low (with the prior close above it). This dual-confirmation prevents false signals from a single bar's wick. Change of Character triggers when a new swing high forms that exceeds the prior swing high, or a new swing low forms that goes below the prior swing low. The label offset scales with 14-period ATR to position labels clearly above and below the bars without fixed pixel distances that fail across different price scales.

Reading it on a chart

Blue and red circles mark swing highs and lows respectively, forming the "structure" that the indicator tracks. A BOS↑ label appears when price closes above the most recent blue circle, signalling a potential bullish shift. A BOS↓ label appears when price closes below the most recent red circle, signalling a potential bearish shift. CHoCH↑ appears when a new swing high forms above the prior swing high, often marking acceleration in an uptrend. CHoCH↓ appears when a new swing low forms below the prior swing low, often marking acceleration in a downtrend.

The lookback period tunes sensitivity: shorter lookback (2-3) captures minor structure and generates frequent signals; longer lookback (8-12) filters out noise and marks only major turning points. Many traders use this to confirm support and resistance levels: if price BOS above a level it repeatedly tested, that level may now be a new support below the market, or the test may mark a valid breakout.

Limitations

The indicator reacts only to closed prices crossing swing levels, introducing inherent lag. A wick may touch the swing high intrabar but not close above it, so no BOS label appears; the signal arrives only on a later bar that closes decisively through. Volatile assets and gaps can bypass levels entirely, leaving the indicator unable to register a BOS event.

Swing detection depends entirely on the lookback parameter. A 5-bar lookback will miss meaningful swings that span 8 bars. Conversely, a very short lookback generates excessive noise and false CHoCH signals as minor bounces are misidentified as directional swings. The correct parameter varies by asset and timeframe and requires manual tuning.

The indicator does not validate the quality of structure. A two-bar BOS followed immediately by a reversal back below the level generates a valid label but does not predict whether the break will hold. Structure markers alone do not confirm trend strength, volatility regime, or volume support. Market context, price action, and broader timeframe analysis remain essential for decision-making.

Key definitions

Break of Structure (BOS): The moment price closes above (or below) a swing level that was previously acting as resistance (or support), signalling potential loss of control by sellers (or buyers).

Change of Character (CHoCH): The formation of a new swing extreme that exceeds the prior extreme in the same direction, indicating momentum continuation or acceleration of the existing trend.

Swing High: A price bar whose high is strictly greater than the highs of a specified number of bars immediately preceding it.

Swing Low: A price bar whose low is strictly less than the lows of a specified number of bars immediately preceding it.

Lookback Period: The number of prior bars used to confirm whether the current bar qualifies as a swing extreme.

Volatility-Scaled Offset: An ATR-based distance used to position labels vertically so they remain visible across different price scales and asset classes.

References

[1] Investopedia, "Support and Resistance," Investopedia (accessed 2025). Educational resource defining price structure concepts foundational to swing analysis.

[2] CME Group, "Price Action & Technical Analysis," CME Education (accessed 2025). Institutional framing of how swing highs and lows function as structural turning points in futures markets.

[3] Wilder, J. W., "New Concepts in Technical Trading Systems," McLaren Publishing (1978). Foundational text on swing analysis and price structure identification in technical analysis.

[4] Tradingview Pine Script Documentation, "Technical Analysis Library Reference (ta)," Tradingview (2025). Reference for ATR calculation and bar history access patterns used in structure detection.


Educational research on historical data only. Not investment advice, not a signal, and never a performance promise. Past results do not predict future performance. Every reference is link-verified before publication and every paper is re-audited weekly against the library's editorial standard.

Last reviewed by the PropLedger research pipeline: 2026-10-25. Educational research on historical data, not financial advice.

Educational research on historical data only. Not investment advice, not a signal, and never a performance promise. Past results do not predict future performance. Every reference is link-verified before publication and every paper is re-audited weekly against the library's editorial standard. Found an error? Email support@prop-ledger.org and the paper is corrected or withdrawn.