Indicator · Pine Script v6 · Own pane

Market Structure Advanced [WavesUnchained]

by casoon

Calculates continuous structural market bias by detecting swing high and low pivots (higher highs, higher lows, lower highs, and lower lows) using configurable left and right bar lookbacks.

View on GitHub

GitHub stars9on the repository
Pine versionv6current
Lines of code278
Settings15inputs
LicenceMIT
Last updateyesterday27 Oct 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

278 lines of Pine Script v6 from indicators/market_structure/market_structure_advanced/market_structure_advanced.pine, published under MIT. Keep the author's credit and licence lines when you reuse it.

market_structure_advanced.pine
//@version=6
// ============================================================================
// Market Structure Advanced [WavesUnchained]
// Version: 1.0.3
// Author: WavesUnchained
// Build: 2026-10-02 00:00:00
// ============================================================================
// Swing-pivot classification (HH/HL/LH/LL) mapped to a bounded score oscillator.
// Provides a continuous structural bias reading without pattern-matching or labels.
//
// Features:
//   ✓ Swing-pivot detection via configurable left/right bars
//   ✓ Pivot classification: HH (+2), HL (+1), LH (−1), LL (−2)
//   ✓ Windowed score bounded to [−100, +100]
//   ✓ Signal line + fill + 4-state histogram
//   ✓ Gradient line color (bearish ↔ bullish structural bias)
//   ✓ Shadow fills between score and zero
//   ✓ Optional pivot labels on the price chart (overlay)
//   ✓ Structural shift signal markers
//   ✓ Alert conditions
//
// ============================================================================

indicator("Market Structure Advanced [WavesUnchained]", "MS·ADV", format=format.price, precision=2, overlay=false, max_labels_count=500)

// ─────────────────────────────────────────────────────────────────────────────
// INPUTS
// ─────────────────────────────────────────────────────────────────────────────

g_pivot = "1 · Pivot Detection"
pivLeft    = input.int(5,  "Left Bars",              minval=1,  group=g_pivot)
pivRight   = input.int(5,  "Right Bars",             minval=1,  group=g_pivot)
scoreLen   = input.int(10, "Score Window (pivots)",  minval=2,  group=g_pivot,
     tooltip="Number of most recent pivots used in the score. Larger = smoother, more lagged.")
showLabels = input.bool(false, "Show Pivot Labels on Chart", group=g_pivot,
     tooltip="Draws HH/HL/LH/LL labels on the price chart (requires overlay=true in a separate pane or you can enable this in an overlay indicator). Labels appear on the source pane.")

g_smooth = "2 · Smoothing"
sigLen     = input.int(3,  "Signal Length", minval=1, group=g_smooth)
smoothType = input.string("EMA", "Signal Type",
     options=["EMA", "SMA", "RMA", "WMA", "SuperSmoother", "T3", "KAMA", "JMA Approx"],
     group=g_smooth)
jmaPhase   = input.int(50,    "  JMA Phase", minval=-100, maxval=100,             group=g_smooth)
jmaPower   = input.float(2.0, "  JMA Power", minval=1.0, maxval=4.0, step=0.25,  group=g_smooth)

g_col = "3 · Colors"
colBull = input.color(#00bcd4, "Bull", group=g_col)
colBear = input.color(#f06292, "Bear", group=g_col)

g_disp = "4 · Display"
showShadow  = input.bool(true,  "Shadow Fill (Score vs Zero)", group=g_disp)
showFill    = input.bool(true,  "Fill Score / Signal",         group=g_disp)
showHist    = input.bool(true,  "Show Histogram",              group=g_disp)
showSignals = input.bool(true,  "Show Signal Markers",          group=g_disp)

// ─────────────────────────────────────────────────────────────────────────────
// SMOOTHING FUNCTIONS
// ─────────────────────────────────────────────────────────────────────────────

f_supersmoother(series float x, simple int len) =>
    float pi = math.pi
    float a1 = math.exp(-1.414 * pi / len)
    float b1 = 2.0 * a1 * math.cos(1.414 * pi / len)
    float c2 = b1
    float c3 = -(a1 * a1)
    float c1 = 1.0 - c2 - c3
    var float ss = na
    ss := c1 * (x + nz(x[1])) / 2.0 + c2 * nz(ss[1]) + c3 * nz(ss[2])
    ss

f_t3(series float x, simple int len) =>
    float b  = 0.7
    float e1 = ta.ema(x, len)
    float e2 = ta.ema(e1, len)
    float e3 = ta.ema(e2, len)
    float e4 = ta.ema(e3, len)
    float e5 = ta.ema(e4, len)
    float e6 = ta.ema(e5, len)
    float c1 = -(b * b * b)
    float c2 =  3.0 * b * b + 3.0 * b * b * b
    float c3 = -6.0 * b * b - 3.0 * b - 3.0 * b * b * b
    float c4 =  1.0 + 3.0 * b + b * b * b + 3.0 * b * b
    c1 * e6 + c2 * e5 + c3 * e4 + c4 * e3

f_kama(series float x, simple int len) =>
    float change   = math.abs(x - x[len])
    float vol      = math.sum(math.abs(x - x[1]), len)
    float er       = vol != 0.0 ? change / vol : 0.0
    float sc       = math.pow(er * (2.0 / 3.0 - 2.0 / 31.0) + 2.0 / 31.0, 2)
    var float kama = na
    kama := nz(kama[1], x) + sc * (x - nz(kama[1], x))
    kama

f_jma(series float x, simple int len, simple int phase, simple float power) =>
    var float jma = na
    var float e0  = na
    var float e1  = na
    var float e2  = na
    float phaseRatio = phase < -100 ? 0.5 : phase > 100 ? 2.5 : phase / 100.0 + 1.5
    float beta       = 0.45 * (len - 1) / (0.45 * (len - 1) + 2.0)
    float alpha      = math.pow(beta, power)
    e0  := (1.0 - alpha) * x + alpha * nz(e0[1], x)
    e1  := (x - e0) * (1.0 - beta) + beta * nz(e1[1], 0.0)
    e2  := (e0 + phaseRatio * e1 - nz(jma[1], x)) * math.pow(1.0 - alpha, 2.0) + math.pow(alpha, 2.0) * nz(e2[1], 0.0)
    jma := nz(jma[1], x) + e2
    jma

f_smooth(series float x, simple int len, simple string mode) =>
    switch mode
        "SMA"           => ta.sma(x, len)
        "RMA"           => ta.rma(x, len)
        "WMA"           => ta.wma(x, len)
        "SuperSmoother" => f_supersmoother(x, len)
        "T3"            => f_t3(x, len)
        "KAMA"          => f_kama(x, len)
        "JMA Approx"    => f_jma(x, len, jmaPhase, jmaPower)
        =>                 ta.ema(x, len)

// ─────────────────────────────────────────────────────────────────────────────
// PIVOT DETECTION
// ─────────────────────────────────────────────────────────────────────────────

pivHigh = ta.pivothigh(high, pivLeft, pivRight)
pivLow  = ta.pivotlow(low,  pivLeft, pivRight)

// ─────────────────────────────────────────────────────────────────────────────
// PIVOT CLASSIFICATION
// ─────────────────────────────────────────────────────────────────────────────

var float lastHigh  = na
var float lastLow   = na
var float prevHigh  = na
var float prevLow   = na
var int   pivScore  = na

float curScore = na

if not na(pivHigh)
    prevHigh := lastHigh
    lastHigh := pivHigh
    if not na(prevHigh)
        curScore := pivHigh > prevHigh ? 2.0 : -1.0

if not na(pivLow)
    prevLow := lastLow
    lastLow := pivLow
    if not na(prevLow)
        curScore := na(curScore) ? (pivLow > prevLow ? 1.0 : -2.0) :
             curScore + (pivLow > prevLow ? 1.0 : -2.0)

// ─────────────────────────────────────────────────────────────────────────────
// SCORE WINDOW
// ─────────────────────────────────────────────────────────────────────────────

var float[] scoreRing = array.new_float(0)

if not na(curScore)
    array.push(scoreRing, curScore)
    if array.size(scoreRing) > scoreLen
        array.shift(scoreRing)

float rawScore = 0.0
int   n        = array.size(scoreRing)

if n > 0
    float s = 0.0
    for i = 0 to n - 1
        s := s + array.get(scoreRing, i)
    rawScore := s

float maxPossible = float(scoreLen) * 2.0
float score       = maxPossible > 0.0 ? 100.0 * rawScore / maxPossible : 0.0
score := math.max(math.min(score, 100.0), -100.0)

signal = f_smooth(score, sigLen, smoothType)
hist   = score - signal

// ─────────────────────────────────────────────────────────────────────────────
// SIGNALS (on raw score)
// ─────────────────────────────────────────────────────────────────────────────

bullCross = ta.crossover(score, signal)
bearCross = ta.crossunder(score, signal)
bullZero  = ta.crossover(score, 0.0)
bearZero  = ta.crossunder(score, 0.0)

// ─────────────────────────────────────────────────────────────────────────────
// COLORS
// ─────────────────────────────────────────────────────────────────────────────

color lineCol  = color.from_gradient(score, -50, 50, colBear, colBull)
color lineCol2 = color.from_gradient(signal, -50, 50, color.new(colBear, 40), color.new(colBull, 40))

histRising = hist >= hist[1]
histColor  = hist >= 0.0
     ? (histRising ? colBull                     : color.new(colBull, 55))
     : (not histRising ? colBear                 : color.new(colBear, 55))

// ─────────────────────────────────────────────────────────────────────────────
// HLINES
// ─────────────────────────────────────────────────────────────────────────────

hline( 50, "+50", color=color.new(#00bcd4, 65), linestyle=hline.style_dashed, linewidth=1)
hline(  0, "Zero", color=color.new(color.gray, 60), linestyle=hline.style_dotted, linewidth=1)
hline(-50, "−50", color=color.new(#f06292, 65), linestyle=hline.style_dashed, linewidth=1)

// ─────────────────────────────────────────────────────────────────────────────
// PLOTS
// ─────────────────────────────────────────────────────────────────────────────

plot(showHist ? hist : na, "Histogram", style=plot.style_columns, color=histColor)

pZero = plot(0.0, display=display.none)
pSig  = plot(signal, "Signal", color=lineCol2, linewidth=1)
pMS   = plot(score,  "Score",  color=lineCol,  linewidth=2)

fill(pMS, pZero, 50.0,   0.0, color.new(colBull, 78), color.new(colBull, 100),
     title="Bull Shadow", display=showShadow ? display.all : display.none)
fill(pMS, pZero, 0.0, -50.0,  color.new(colBear, 100), color.new(colBear, 78),
     title="Bear Shadow", display=showShadow ? display.all : display.none)

fill(pMS, pSig,
     color=showFill ? (score >= signal ? color.new(colBull, 88) : color.new(colBear, 88)) : na,
     title="Score Fill")

// ─────────────────────────────────────────────────────────────────────────────
// PIVOT LABELS (overlay on price chart)
// ─────────────────────────────────────────────────────────────────────────────

if showLabels and not na(pivHigh)
    bool isHH = not na(prevHigh) and pivHigh > prevHigh
    label.new(bar_index - pivRight, pivHigh,
         text=isHH ? "HH" : "LH",
         style=label.style_label_down,
         color=isHH ? color.new(colBull, 80) : color.new(colBear, 80),
         textcolor=isHH ? colBull : colBear,
         size=size.small)

if showLabels and not na(pivLow)
    bool isHL = not na(prevLow) and pivLow > prevLow
    label.new(bar_index - pivRight, pivLow,
         text=isHL ? "HL" : "LL",
         style=label.style_label_up,
         color=isHL ? color.new(colBull, 80) : color.new(colBear, 80),
         textcolor=isHL ? colBull : colBear,
         size=size.small)

// ─────────────────────────────────────────────────────────────────────────────
// SIGNAL MARKERS
// ─────────────────────────────────────────────────────────────────────────────

plotshape(showSignals and bullCross ? score : na, "Bull Signal Cross",
     style=shape.triangleup, location=location.absolute,
     color=colBull, size=size.small)

plotshape(showSignals and bearCross ? score : na, "Bear Signal Cross",
     style=shape.triangledown, location=location.absolute,
     color=colBear, size=size.small)

plotshape(showSignals and bullZero ? score : na, "Bull Zero Cross",
     style=shape.circle, location=location.absolute,
     color=color.new(colBull, 20), size=size.tiny)

plotshape(showSignals and bearZero ? score : na, "Bear Zero Cross",
     style=shape.circle, location=location.absolute,
     color=color.new(colBear, 20), size=size.tiny)

// ─────────────────────────────────────────────────────────────────────────────
// ALERTS
// ─────────────────────────────────────────────────────────────────────────────

bool alertsOnBarClose = input.bool(true, "Alerts only on bar close (confirmed)", group="Alerts")
bool alertOk = not alertsOnBarClose or barstate.isconfirmed

alertcondition(alertOk and (bullCross), "MS Bull Cross",      "MSA · BULL CROSS LONG · {{ticker}} {{interval}}")
alertcondition(alertOk and (bearCross), "MS Bear Cross",      "MSA · BEAR CROSS SHORT · {{ticker}} {{interval}}")
alertcondition(alertOk and (bullZero),  "MS Cross Above Zero", "MSA · CROSS ABOVE ZERO LONG · {{ticker}} {{interval}}")
alertcondition(alertOk and (bearZero),  "MS Cross Below Zero", "MSA · CROSS BELOW ZERO SHORT · {{ticker}} {{interval}}")

Overview

Market Structure Advanced [WavesUnchained] assigns weighted values to classified pivots within a rolling window to produce a bounded score oscillator ranging from -100 to +100. The oscillator is smoothed using customizable moving average algorithms (including EMA, JMA, and SuperSmoother) to generate a signal line, histogram, and structural shift markers in a separate pane. Note that pivot confirmation depends on right-bar lookbacks, introducing a confirmation delay.

Details

Published by

casoon on GitHub

Type

Indicator, Pine Script v6

Draws

Separate pane below the chart

Category

SMC / ICT / price action, Trend, Support & resistance

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Topics

pine-scriptpinescripttechnical-analysistrading-indicatorstrading-strategiestradingview

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Left Barsint5pivLeft
Right Barsint5pivRight
Score Window (pivots)int10scoreLen
Show Pivot Labels on ChartboolfalseshowLabels
Signal Lengthint3sigLen
Signal TypestringEMAsmoothType
JMA Phaseint50jmaPhase
JMA Powerfloat2.0jmaPower
Bullcolor#00bcd4colBull
Bearcolor#f06292colBear
Shadow Fill (Score vs Zero)booltrueshowShadow
Fill Score / SignalbooltrueshowFill
Show all 15 settings
SettingTypeDefaultVariable
Show HistogrambooltrueshowHist
Show Signal MarkersbooltrueshowSignals
Alerts only on bar close (confirmed)booltruealertsOnBarClose
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

575 stars

This indicator detects equal highs and lows by comparing prices within user-defined left and right bars using a tolerance percentage. It plots horizontal lines on the price chart for equal highs in one color and lows in another. A screener allows input of mult

Indicator v5 Support & resistanceTrend
Updated 1 year ago · MPL-2.0 GitHub repository of ICT Equal Highs and Lows with Screener

This Pine Script indicator plots a ZigZag on the price chart. It identifies reversal points when price moves more than a set percentage from the last pivot. The script calculates forecasts using zigzag data and labels detected geometric patterns including harm

Indicator v4 TrendSupport & resistance
218 stars

This indicator plots market structure on the price chart by identifying swing highs and lows. It connects these points with lines to visualize trend direction and detect Break of Structure (BOS) when price breaks a prior swing in the current trend. Change of C

Indicator v6 TrendSupport & resistance
Updated 3 months ago · None stated GitHub repository of Market Structure - BOS & CHoCH

Open Source Fractal

by cantolab
183 stars

This indicator implements the Fractal Model concept to plot market structure shifts, liquidity sweeps, and Change in State of Delivery (CISD) levels. It overlays custom higher-timeframe candle previews, open prices, and time markers directly on the price chart

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated 2 months ago · MIT GitHub repository of Open Source Fractal
56 stars

BigBeluga Smart Money Concepts identifies and overlays market structure and volumetric order blocks directly on the price chart. It analyzes market swings, trend sweeps, and mapping structure using customizable pivot lengths and calculation modes. The indicato

Indicator v5 SMC / ICT / price actionSupport & resistance
Updated 2 months ago · None stated GitHub repository of BigBeluga - Smart Money Concepts
53 stars

Apex Trend & Liquidity Master calculates a trend cloud using customizable moving averages expanded by a volatility multiplier directly on the main price chart. It identifies dynamic support and resistance liquidity zones from swing high and low pivots, extendi

Indicator v6 TrendSupport & resistance
Updated 2 months ago · MPL-2.0 GitHub repository of Apex Trend & Liquidity Master

More indicators

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers