Indicator · Pine Script v6 · Own pane

Trend Persistence Score [WavesUnchained]

by casoon

Trend Persistence Score calculates a composite trend-efficiency oscillator plotted in a separate pane, grading trend strength and durability on a 0 to 100 scale.

View on GitHub

GitHub stars9on the repository
Pine versionv6current
Lines of code393
Settings29inputs
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

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

trend_persistence_score.pine
//@version=6
// ============================================================================
// Trend Persistence Score [WavesUnchained]
// Version: 1.1.2
// Author: WavesUnchained
// Build: 2026-10-02 00:00:00
// ============================================================================
// Single-role trend-strength oscillator: how persistent, clean and durable is
// the current trend? Fuses four trend-efficiency sensors (Regression R²,
// Kaufman Efficiency Ratio, ADX strength+slope, Fractal Dimension) onto one
// graded 0-100 persistence axis. Direction-agnostic by design — it grades the
// magnitude of trendiness; direction is shown as visual context only.
//
// Features:
//   ✓ 4-sensor trend-persistence score (R² · ER · ADX · FDI) on a 0-100 axis
//   ✓ Role-level weights — see which sensor drives the verdict (sub-score lines)
//   ✓ State read: Strong / Healthy / Transition / Weak / Dead with hysteresis
//   ✓ Calibration anchors exposed as inputs (no hardcoded thresholds in logic)
//   ✓ Directional context (▲/▼/•) from regression sign — visual only, not scored
//   ✓ Compact info label + debug log on every state change (why it changed)
//   ✓ Weakening / Transition / Recovery / Transition-Risk-High alerts
//
// ============================================================================

indicator("Trend Persistence Score [WavesUnchained]", "TPS", format=format.price, precision=2, overlay=false, max_labels_count=500)

// ============================================================================
// Inputs
// ============================================================================

src       = input.source(close, "Source", group="Core")
len       = input.int(34, "Main Length", minval=10, group="Core")
adxLen    = input.int(14, "ADX Length", minval=5, group="Core")
smoothLen = input.int(5, "Score Smoothing", minval=1, group="Core")

wR2  = input.float(40.0, "Weight: Regression R²", minval=0, group="Sensor Weights")
wER  = input.float(25.0, "Weight: Efficiency Ratio", minval=0, group="Sensor Weights")
wADX = input.float(20.0, "Weight: ADX / Slope", minval=0, group="Sensor Weights")
wFDI = input.float(15.0, "Weight: Fractal Dimension", minval=0, group="Sensor Weights")

// Role-level calibration: each anchor pair maps a sensor's full-range vs.
// full-trend reading onto 0..1. These are the "trend is strong / dead"
// thresholds — kept as inputs, never hardcoded into the signal logic.
adxLo   = input.float(12.0, "ADX: range anchor", group="Calibration", tooltip="ADX at/below this reads as no trend strength")
adxHi   = input.float(35.0, "ADX: trend anchor", group="Calibration", tooltip="ADX at/above this reads as full trend strength")
fdiTrnd = input.float(1.20, "FDI: trend anchor", group="Calibration", tooltip="Fractal Dimension at/below this reads as a clean trend")
fdiRng  = input.float(1.65, "FDI: range anchor", group="Calibration", tooltip="Fractal Dimension at/above this reads as choppy/range")

// ADX measures movement/strength, not directional cleanliness. When BOTH the
// structure sensors (R², ER) are weak, ADX must not be allowed to "rescue" the
// score — its sub-score is damped so the composite reflects the dead structure.
deadThresh = input.float(20.0, "ADX damp: structure-dead threshold", group="Calibration", tooltip="If both R² Score and Efficiency Score are below this, ADX is damped")
adxDamp    = input.float(0.35, "ADX damp: factor", minval=0.0, maxval=1.0, group="Calibration", tooltip="ADX sub-score multiplier while structure is dead")

lvlStrong = input.int(75, "State: Strong ≥", group="State Levels")
lvlHealthy= input.int(60, "State: Healthy ≥", group="State Levels")
lvlTrans  = input.int(45, "State: Transition ≥", group="State Levels")
lvlWeak   = input.int(30, "State: Weak ≥", group="State Levels")

colorMode    = input.string("Direction × Strength", "Oscillator Color", options=["Direction × Strength", "Persistence State"], group="Display", tooltip="Direction × Strength: line/fill colored by trend direction (corr sign), faded by how weak the trend is. Persistence State: the Strong/Healthy/Transition/Weak/Dead band colors.")
showFill     = input.bool(true, "Show Heat Column (fill to 0)", group="Display")
showZones    = input.bool(true, "Show Background Zones", group="Display")
showTrail    = input.bool(true, "Show Persistence Trail", group="Display")
showMarkers  = input.bool(true, "Show Key Event Labels", group="Display", tooltip="Shows only the alert-level TPS events: Weakening, Transition and Recovery. These are context events, not long/short trade signals.")
markerCooldown = input.int(10, "Event Label Cooldown", minval=0, group="Display", tooltip="Minimum bars between visible event labels, reducing repeated labels in choppy threshold zones")
transitionLead = input.float(3.0, "Transition Lead Buffer", minval=0.0, group="Display", tooltip="Shows T slightly before the hard Transition cross when TPS is falling near the Transition level and transition risk is rising")
showLines    = input.bool(false, "Show Sensor Lines", group="Display")
showLabel    = input.bool(true, "Show Info Label", group="Display", tooltip="Single compact label (mobile-friendly) with score, state, bias and sensor values — replaces the old table")
labelSize    = input.string("Normal", "Label Size", options=["Small", "Normal", "Large"], group="Display")

// ============================================================================
// Helpers
// ============================================================================

f_clamp(x, lo, hi) =>
    math.max(lo, math.min(hi, x))

f_norm(x, lo, hi) =>
    hi == lo ? 0.0 : f_clamp((x - lo) / (hi - lo), 0.0, 1.0)

f_lblSize(s) =>
    s == "Small" ? size.small : s == "Large" ? size.large : size.normal

// ============================================================================
// 1. Linear Regression R²  (magnitude of fit — direction stripped by squaring)
// ============================================================================

corr    = ta.correlation(src, bar_index, len)
r2Raw   = math.pow(nz(corr), 2.0)
r2Score = r2Raw * 100.0

// ============================================================================
// 2. Kaufman Efficiency Ratio
// ============================================================================

change     = math.abs(src - src[len])
volatility = math.sum(math.abs(src - src[1]), len)
erRaw      = volatility == 0.0 ? 0.0 : change / volatility
erScore    = erRaw * 100.0

// ============================================================================
// 3. ADX Strength + ADX Slope
// ============================================================================

[plusDI, minusDI, adx] = ta.dmi(adxLen, adxLen)

adxStrength  = f_norm(adx, adxLo, adxHi)
adxSlope     = ta.ema(adx - adx[1], 3)
adxSlopeNorm = f_norm(adxSlope, -1.0, 1.5)

adxScore = ((adxStrength * 0.7) + (adxSlopeNorm * 0.3)) * 100.0

// Damp ADX when price structure is dead (R² and ER both weak) — ADX activity
// without directional cleanliness should not prop up the persistence score.
structureDead = r2Score < deadThresh and erScore < deadThresh
adxScoreFinal = structureDead ? adxScore * adxDamp : adxScore

// ============================================================================
// 4. Fractal Dimension Index
// Lower FDI = cleaner trend (~1.0 trend, ~1.5 random, ~2.0 noisy/choppy)
// ============================================================================

highestHigh = ta.highest(high, len)
lowestLow   = ta.lowest(low, len)
rangeHL     = highestHigh - lowestLow
pathLength  = math.sum(math.abs(src - src[1]), len)

float fdiRaw = 1.5
if rangeHL > 0.0 and pathLength > 0.0
    fdiRaw := math.log(pathLength / rangeHL) / math.log(len) + 1.0

fdiTrendScore = (1.0 - f_norm(fdiRaw, fdiTrnd, fdiRng)) * 100.0

// ============================================================================
// Composite Score
// ============================================================================

weightSum = wR2 + wER + wADX + wFDI

float tpsRaw = na
if weightSum > 0.0
    tpsRaw := (r2Score * wR2 + erScore * wER + adxScoreFinal * wADX + fdiTrendScore * wFDI) / weightSum

tps = ta.ema(tpsRaw, smoothLen)

// Transition Risk — derived inverse of TPS (NOT a structure-break detector;
// that is a separate reversal module). Blends inverse-TPS with inverse-ER so a
// low-efficiency tape reads as elevated risk even when ADX lingers.
transitionRisk = (100.0 - tps) * 0.7 + (100.0 - erScore) * 0.3

// ============================================================================
// State (with one-band hysteresis so it does not flip on score noise)
// ============================================================================

f_stateIdx(v) =>
    int idx = 0
    if v >= lvlStrong
        idx := 4
    else if v >= lvlHealthy
        idx := 3
    else if v >= lvlTrans
        idx := 2
    else if v >= lvlWeak
        idx := 1
    idx

rawIdx = f_stateIdx(tps)
var int stateIdx = rawIdx
// upgrade immediately; downgrade only after a clear overshoot below the band
// edge (hysteresis), so the state does not flip on score noise
if rawIdx > stateIdx
    stateIdx := rawIdx
else if rawIdx < stateIdx
    edge = stateIdx == 4 ? lvlStrong : stateIdx == 3 ? lvlHealthy : stateIdx == 2 ? lvlTrans : lvlWeak
    if tps < edge - 3.0
        stateIdx := rawIdx

string state = "Trend Dead"
if stateIdx == 4
    state := "Trend Strong"
else if stateIdx == 3
    state := "Trend Healthy"
else if stateIdx == 2
    state := "Transition"
else if stateIdx == 1
    state := "Weak / Range"

// Project accent palette
color cBull = #16a34a
color cWarn = #f59e0b
color cBear = #dc2626
color cMute = #64748b
color cGrid = #94a3b8
color cInk  = #1f2937
// Strength ramp — neutral cool palette, kept distinct from the green/red
// direction language so color never carries two meanings at once.
color cStrong  = #1d4ed8
color cHealthy = #3b82f6

color stateColor = cGrid
if stateIdx == 4
    stateColor := cStrong
else if stateIdx == 3
    stateColor := cHealthy
else if stateIdx == 2
    stateColor := cWarn
else if stateIdx == 1
    stateColor := cMute

// ============================================================================
// Directional context — VISUAL ONLY, never fed into the score
// ============================================================================

dirUp = corr > 0.15
dirDn = corr < -0.15

// Compression — MEASURED (not inferred from low TPS, which can also be high-vol
// chop). Bollinger-width percentile rank; a low rank = volatility contraction.
basis    = ta.sma(src, len)
dev      = ta.stdev(src, len)
bbWidth  = basis == 0.0 ? 0.0 : (4.0 * dev) / basis
compress = ta.percentrank(bbWidth, 100) < 30

flatTxt = compress ? "• Compress" : "• Flat"
biasTxt = dirUp ? "▲ Up" : dirDn ? "▼ Down" : flatTxt
biasCol = dirUp ? cBull : dirDn ? cBear : (compress ? cWarn : color.new(cMute, 10))

string driver = "Fit"
driverVal = r2Score
if erScore > driverVal
    driver := "Efficiency"
    driverVal := erScore
if adxScoreFinal > driverVal
    driver := structureDead ? "ADX damped" : "ADX building"
    driverVal := adxScoreFinal
if fdiTrendScore > driverVal
    driver := "Clean path"
    driverVal := fdiTrendScore

string drag = "Weak fit"
dragVal = r2Score
if erScore < dragVal
    drag := "Low efficiency"
    dragVal := erScore
if adxScoreFinal < dragVal
    drag := structureDead ? "Dead structure" : "Weak ADX"
    dragVal := adxScoreFinal
if fdiTrendScore < dragVal
    drag := "Choppy path"
    dragVal := fdiTrendScore

readTxt = state + "  ·  " + biasTxt
reasonTxt = tps >= lvlHealthy ? "Driver: " + driver : "Drag: " + drag
moveTxt = dirUp ? "Up-move" : dirDn ? "Down-move" : compress ? "Compression" : "No clear move"

// ============================================================================
// Plot
// ============================================================================

// Two-dimensional read: HEIGHT = persistence (tps), COLOR = direction (corr
// sign), SATURATION = strength (faded when the trend is weak/dead). One color
// language driven by colorMode.
useDir  = colorMode == "Direction × Strength"
dirBase = dirUp ? cBull : dirDn ? cBear : cMute

// transparency scaled by tps: strong trend = vivid, dead market = pale
lineT = f_clamp(60.0 - tps * 0.55, 0.0, 60.0)
fillT = f_clamp(93.0 - tps * 0.35, 55.0, 93.0)

oscCol  = useDir ? color.new(dirBase, lineT) : stateColor
heatCol = useDir ? color.new(dirBase, fillT) : color.new(stateColor, 80)

trailCol = color.new(useDir ? dirBase : stateColor, 82)

plot(showTrail ? tps : na, "Persistence Trail", color=trailCol, linewidth=7)
pTps  = plot(tps, "Trend Persistence Score", color=oscCol, linewidth=3)
pZero = plot(0, "", color=color.new(color.gray, 100), display=display.none, editable=false)
fill(pTps, pZero, color=showFill ? heatCol : na, title="Heat Column")

plot(showLines ? r2Score : na, "R² Score", color=color.new(#2563eb, 45), linewidth=1)
plot(showLines ? erScore : na, "Efficiency Ratio", color=color.new(#0d9488, 45), linewidth=1)
plot(showLines ? adxScoreFinal : na, "ADX Score (effective)", color=color.new(#f97316, 45), linewidth=1)
plot(showLines ? fdiTrendScore : na, "FDI Trend Score", color=color.new(#7c3aed, 45), linewidth=1)

hTop     = hline(100, "Top", color=color.new(cGrid, 92), linestyle=hline.style_dotted)
hStrong  = hline(lvlStrong, "Strong Trend", color=color.new(cStrong, 35), linestyle=hline.style_dashed)
hHealthy = hline(lvlHealthy, "Healthy Trend", color=color.new(cHealthy, 60), linestyle=hline.style_dashed)
hTrans   = hline(lvlTrans, "Transition", color=color.new(cWarn, 48), linestyle=hline.style_dashed)
hWeak    = hline(lvlWeak, "Weak", color=color.new(cMute, 58), linestyle=hline.style_dashed)
hBase    = hline(0, "Base", color=color.new(cGrid, 88), linestyle=hline.style_dotted)

fill(hTop, hStrong, color=showZones ? color.new(cStrong, 93) : na, title="Strong Zone")
fill(hStrong, hHealthy, color=showZones ? color.new(cHealthy, 95) : na, title="Healthy Zone")
fill(hHealthy, hTrans, color=showZones ? color.new(cWarn, 94) : na, title="Transition Zone")
fill(hTrans, hWeak, color=showZones ? color.new(cMute, 95) : na, title="Weak Zone")
fill(hWeak, hBase, color=showZones ? color.new(cMute, 95) : na, title="Dead Zone")

// ============================================================================
// Info label + state markers — compact mobile read, no table
// ============================================================================

tc = cInk
trCol = transitionRisk >= 70 ? cWarn : tc

var label infoLbl = na
if showLabel and barstate.islast
    label.delete(infoLbl)
    txt = "TPS " + str.tostring(tps, "#.0") + "  ·  " + readTxt + "\n" +
         reasonTxt + "  ·  Risk " + str.tostring(transitionRisk, "#.0") + "\n" +
         "R² " + str.tostring(r2Score, "#") +
         "   ER " + str.tostring(erScore, "#") +
         "   ADX " + str.tostring(adxScoreFinal, "#") +
         "   FDI " + str.tostring(fdiTrendScore, "#")
    tip = "Trend Persistence Score\n" +
         "Height: trend persistence from 0 to 100.\n" +
         "Color: visual direction context only.\n" +
         "Driver/Drag names the strongest or weakest sensor.\n" +
         "Transition Risk is derived from TPS and ER; it is not a break detector."
    infoLbl := label.new(bar_index + 3, 100, txt,
         xloc=xloc.bar_index, yloc=yloc.price, style=label.style_label_left,
         color=color.new(color.white, 8), textcolor=trCol,
         size=f_lblSize(labelSize), textalign=text.align_left, tooltip=tip)
else if not showLabel and barstate.islast
    label.delete(infoLbl)

weakeningEvent      = ta.crossunder(tps, lvlHealthy)
transitionHardEvent = ta.crossunder(tps, lvlTrans)
transitionLeadEvent = ta.crossunder(tps, lvlTrans + transitionLead) and tps > lvlTrans and tps < tps[1] and transitionRisk > transitionRisk[1]
transitionEvent     = transitionHardEvent or transitionLeadEvent
recoveryEvent       = ta.crossover(tps, lvlHealthy)

string eventText = ""
string eventTip = ""
color eventColor = cMute

if transitionEvent
    eventText := "T"
    eventColor := cWarn
    eventTip := transitionLeadEvent
         ? "Transition building\n" + moveTxt + ": clean trend phase is starting to fail.\nContinuation edge is fading before the hard Transition cross."
         : "Transition\n" + moveTxt + ": clean trend phase is ending.\nContinuation edge is off. Expect pause, range, chop or structure-break context."
else if weakeningEvent
    eventText := "W"
    eventColor := #f97316
    eventTip := "Weakening\n" + moveTxt + ": strength is fading.\nThe move can continue, but follow-through quality is deteriorating."
else if recoveryEvent
    eventText := "R"
    eventColor := cHealthy
    eventTip := "Recovery\n" + moveTxt + ": strong clean move confirmed.\nContinuation filter is back on. If price is already extended, wait for structure or pullback timing."

hasKeyEvent = eventText != ""
var int lastEventBar = na
var int lastTransitionBar = na
transitionReady = not transitionEvent or na(lastTransitionBar) or bar_index - lastTransitionBar >= markerCooldown
eventReady = transitionReady and (transitionEvent or na(lastEventBar) or bar_index - lastEventBar >= markerCooldown)

if showMarkers and barstate.isconfirmed and hasKeyEvent and eventReady
    label.new(bar_index, tps, eventText,
         xloc=xloc.bar_index, yloc=yloc.price, style=label.style_label_center,
         color=color.new(eventColor, 8), textcolor=color.white,
         size=size.tiny,
         tooltip=eventTip + "\nTPS: " + str.tostring(tps, "#.0") +
              "\n" + reasonTxt +
              "\nR² " + str.tostring(r2Score, "#.0") +
              " · ER " + str.tostring(erScore, "#.0") +
              " · ADX " + str.tostring(adxScoreFinal, "#.0") +
              " · FDI " + str.tostring(fdiTrendScore, "#.0"))
    lastEventBar := bar_index
    if transitionEvent
        lastTransitionBar := bar_index

// ============================================================================
// Debug — log on every state change: WHY it changed (which sensor drove it)
// ============================================================================

if barstate.isconfirmed and stateIdx != stateIdx[1]
    log.info("TPS STATE {0} -> {1} | tps={2} TR={3} R2={4} ER={5} ADX={6}{7} FDI={8} bias={9}",
         state[1], state, str.tostring(tps, "#.0"), str.tostring(transitionRisk, "#.0"),
         str.tostring(r2Score, "#.0"), str.tostring(erScore, "#.0"),
         str.tostring(adxScoreFinal, "#.0"), structureDead ? "(damped)" : "",
         str.tostring(fdiTrendScore, "#.0"), biasTxt)

// ============================================================================
// Alerts
// ============================================================================

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

alertcondition(alertOk and (ta.crossunder(tps, lvlHealthy)), "TPS Weakening", "TPS · WEAKENING · {{ticker}} {{interval}}")
alertcondition(alertOk and (ta.crossunder(tps, lvlTrans)), "TPS Transition", "TPS · TRANSITION · {{ticker}} {{interval}}")
alertcondition(alertOk and (ta.crossover(tps, lvlHealthy)), "TPS Recovery", "TPS · RECOVERY · {{ticker}} {{interval}}")
alertcondition(alertOk and (ta.crossover(transitionRisk, 70)), "TPS Transition Risk High", "TPS · TRANSITION RISK HIGH · {{ticker}} {{interval}}")

Overview

Trend Persistence Score [WavesUnchained] integrates four distinct metrics: linear regression R-squared, Kaufman Efficiency Ratio, ADX with slope, and Fractal Dimension Index. Users can calibrate individual sensor weights, range and trend anchors, ADX damping thresholds, and state levels defining strong, healthy, transition, or weak conditions. Linear regression slope supplies visual directional context. The script includes background state zones, historical trail plots, event markers, and configurable bar-close alerts.

Details

Published by

casoon on GitHub

Type

Indicator, Pine Script v6

Draws

Separate pane below the chart

Category

Trend, Volatility & bands

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
Sourcesourceclosesrc
Main Lengthint34len
ADX Lengthint14adxLen
Score Smoothingint5smoothLen
Weight: Regression R²float40.0wR2
Weight: Efficiency Ratiofloat25.0wER
Weight: ADX / Slopefloat20.0wADX
Weight: Fractal Dimensionfloat15.0wFDI
ADX: range anchorfloat12.0adxLo
ADX: trend anchorfloat35.0adxHi
FDI: trend anchorfloat1.20fdiTrnd
FDI: range anchorfloat1.65fdiRng
Show all 29 settings
SettingTypeDefaultVariable
ADX damp: structure-dead thresholdfloat20.0deadThresh
ADX damp: factorfloat0.35adxDamp
State: Strong ≥int75lvlStrong
State: Healthy ≥int60lvlHealthy
State: Transition ≥int45lvlTrans
State: Weak ≥int30lvlWeak
Oscillator ColorstringDirection × StrengthcolorMode
Show Heat Column (fill to 0)booltrueshowFill
Show Background ZonesbooltrueshowZones
Show Persistence TrailbooltrueshowTrail
Show Key Event LabelsbooltrueshowMarkers
Event Label Cooldownint10markerCooldown
Transition Lead Bufferfloat3.0transitionLead
Show Sensor LinesboolfalseshowLines
Show Info LabelbooltrueshowLabel
Label SizestringNormallabelSize
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

This indicator plots a Supertrend-based trend-following setup in a separate pane and skips conditions it treats as a sideways market. A volatility range is built from an ATR value, with RMA, SMA, EMA, or WMA smoothing, or from a fixed point distance. Optional

Indicator v5 TrendVolatility & bands
Updated 1 year ago · MPL-2.0 GitHub repository of Trend Following Setup - Sideways Market Skipper
147 stars

This indicator generates trade entry signals and target levels optimized for 1-hour timeframes, designed for external signal extraction. It calculates 7-period and 16-period EMAs alongside 10-period RSI and ATR filters. Long signals occur when the fast EMA cro

Indicator v5 TrendOscillators & momentum
Updated 6 weeks ago · MIT GitHub repository of Signal Strategy 100 Candles of 1H Timeframe

MultiIndicator

by capissimo
114 stars

MultiIndicator combines multiple technical indicators into a single separate pane to save chart space. It calculates and displays market regime detection based on ordinary least squares regression, a Holt exponential smoothing crossover, normalized RSI, ADX, a

Indicator v4 Oscillators & momentumTrend
Updated 1 year ago · None stated GitHub repository of MultiIndicator

This indicator plots an oscillator in a separate pane. It builds several SuperTrend series across a user-defined factor range and step, using ATR as the band width. On each bar it measures the distance between the close and each SuperTrend output, then groups

Indicator v5 TrendVolatility & bands
Updated 2 years ago · GPL-3.0 GitHub repository of AI SuperTrend Clustering Oscillator [LuxAlgo]

Choppiness Index

by mihakralj
99 stars

The script plots the Choppiness Index in a separate pane. It sums true range over a lookback and compares that sum with the highest-high to lowest-low range, then scales the result from 0 to 100. Lower readings indicate a trending market and higher readings in

Indicator v6 TrendVolatility & bands
Updated 4 weeks ago · Apache-2.0 GitHub repository of Choppiness Index

This indicator combines Chaikin Money Flow (CMF), a SuperTrend baseline, and an Average True Range (ATR) calculation inside a separate sub-pane. It calculates a standard 20-period CMF plotted as a line and colored histogram columns around a zero baseline, trac

Indicator v6 TrendVolume
Updated 6 months ago · Apache-2.0 GitHub repository of Institutional View: CMF & SuperTrend

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