Indicator · Pine Script v6 · Own pane

Volatility Contraction Score

by MeridianAlgo

Volatility Contraction Score is a separate-pane indicator that scores how tightly price and volume are contracting.

View on GitHub

GitHub stars9on the repository
Pine versionv6current
Lines of code142
Settings16inputs
LicenceMIT
Last update4 months ago29 Jun 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

142 lines of Pine Script v6 from examples/Volatility_Contraction_Score.pine, published under MIT. Keep the author's credit and licence lines when you reuse it.

Volatility_Contraction_Score.pine
//@version=6
indicator("Volatility Contraction Score", shorttitle="VCS", overlay=false)

// ==========================================
// 1. Settings
// ==========================================
grpCore   = "VCP Logic Settings"
grpScreen = "Screener Data for Pine Screener"

// --- VCS Logic Settings (Calculation Only) ---
lenShortInput = input.int(13, "Short Term", minval=3, group=grpCore)
lenLongInput  = input.int(63, "Long Term", minval=20, group=grpCore)
lenVolInput   = input.int(50, "Volume Average (Logic)", minval=10, group=grpCore)
sensitivity   = 2.0

// --- Trend Filter ---
grpTrend = "Trend Filter"
trendPenaltyWeight = input.float(1.0, "Trend Penalty Strength", minval=0.0, maxval=5.0, step=0.5, group=grpTrend)

// --- Structure ---
grpStruct = "Structure Settings"
hlLookbackInput = input.int(63, "Structure Lookback", minval=20, group=grpStruct)
penaltyFactor   = input.float(0.75, "Penalty for Lower Low", minval=0.0, maxval=1.0, step=0.05, group=grpStruct)

// --- Consistency ---
grpBonus = "Consistency Weight"
bonusMax = input.int(15, "Max Consistency Points", minval=5, maxval=30, group=grpBonus)

// --- Screener Settings (Display Only) ---
scr_vol_len  = input.int(50, "Avg Volume Length", minval=10, group=grpScreen) 
rs_benchmark = input.symbol("SPY", "RS Benchmark", group=grpScreen)
rs_len       = input.int(21, "RS Period", group=grpScreen)
adr_len      = input.int(20, "ADR Period", group=grpScreen)

// ==========================================
// 2. Color & Thresholds
// ==========================================
grpColor = "Color & Thresholds"
thHigh = input.int(80, "Level 2 (High)", minval=60, maxval=100, group=grpColor)
thLow  = input.int(60, "Level 1 (Base)", minval=0, maxval=80, group=grpColor)
cHigh = input.color(#00E676, "Level 2 Color", group=grpColor) 
cLow  = input.color(#2962FF, "Level 1 Color", group=grpColor) 
cBase = input.color(#787B86, "Base Color (<60)", group=grpColor)    

// ==========================================
// 3. VCS Calculation
// ==========================================
barCount = bar_index + 1
lenLong  = math.min(barCount, lenLongInput)
lenShort = math.min(barCount, lenShortInput)
lenVol   = math.min(barCount, lenVolInput)

// --- A. Price Compression (SMA Base) ---
trVal = ta.tr(true)
trShort = ta.sma(trVal, lenShort) 
trLongAvg  = ta.sma(trVal, lenLong) 
ratioATR = trShort / math.max(trLongAvg, 0.000001)

// --- B. Price Stability (SMA Base) ---
stdShort = ta.stdev(close, lenShort)
stdLongAvg = ta.stdev(close, lenLong) 
ratioStd = stdShort / math.max(stdLongAvg, 0.000001)

// --- C. Volume Contraction ---
volAvg = ta.sma(volume, lenVol)
volShortAvg = ta.sma(volume, 5)
volRatio = volShortAvg / math.max(volAvg, 1.0) 

// --- D. Efficiency Filter ---
netChange = math.abs(close - close[lenShort]) 
totalTravel = math.sum(ta.tr(true), lenShort) 
efficiency = netChange / math.max(totalTravel, 0.000001) 

trendFactor = math.max(0.0, 1.0 - (efficiency * trendPenaltyWeight))

// --- E. Structure Check ---
lowRecent = ta.lowest(low, lenShort)
barsBeforeShort = barCount - lenShortInput
hasHistory = barsBeforeShort > 0
lowBase = 0.0
isHigherLow = true 
if hasHistory
    lowBase := ta.lowest(low, hlLookbackInput)[lenShortInput]
    isHigherLow := lowRecent >= lowBase

// ==========================================
// 4. Score Calculation
// ==========================================
s_atr = math.max(0.0, 1.0 - nz(ratioATR, 1.0)) * sensitivity
s_std = math.max(0.0, 1.0 - nz(ratioStd, 1.0)) * sensitivity
s_vol = math.max(0.0, 1.0 - nz(volRatio, 1.0))

rawScore = (s_atr * 0.4) + (s_std * 0.4) + (s_vol * 0.2)

// Apply Trend Filter
filteredScore = rawScore * trendFactor

physicsScore = math.min(100, filteredScore * 100)
smoothPhysics = ta.ema(physicsScore, 3)

// ==========================================
// 5. Final Output
// ==========================================
isTight = smoothPhysics >= 70
var int daysTight = 0
daysTight := isTight ? daysTight + 1 : 0
weightPhysics = (100.0 - bonusMax) / 100.0
weightedPhysicsScore = smoothPhysics * weightPhysics
consistencyScore = math.min(bonusMax, daysTight)
totalScore = weightedPhysicsScore + consistencyScore
finalScore = isHigherLow ? totalScore : (totalScore * penaltyFactor)
finalScore := nz(finalScore, 0.0)

// Plot VCS
colZone = finalScore >= thHigh ? cHigh : 
          finalScore >= thLow  ? cLow : 
          cBase

plot(finalScore, "VCS", color=colZone, style=plot.style_histogram, linewidth=1)
hline(thLow, "Threshold", color=color.gray, linestyle=hline.style_dotted)

// ==========================================
// 6. Screener Data Outputs
// ==========================================
// 1. Avg Volume
scr_vol_val = ta.sma(volume, scr_vol_len)
plot(scr_vol_val, "Avg Vol", display=display.data_window)

// 2. Market Cap
mCapBasic = request.financial(syminfo.tickerid, "MARKET_CAP_BASIC", "D", ignore_invalid_symbol = true)
mCapFinal = na(mCapBasic) ? (nz(syminfo.shares_outstanding_total) * close) : mCapBasic
plot(mCapFinal, "Market Cap", display=display.data_window)

// 3. ADR %
adr_val = 100 * (ta.sma(high / low, adr_len) - 1)
plot(adr_val, "ADR %", display=display.data_window)

// 4. Relative Strength
benchmark_close = request.security(rs_benchmark, timeframe.period, close, ignore_invalid_symbol=true)
rs_ratio = close / benchmark_close
rs_rank = ta.percentrank(rs_ratio, rs_len)
plot(rs_rank, "Relative Strength", display=display.data_window)

Overview

Volatility Contraction Score compares short and long true-range averages and close standard deviations, then folds in a five-bar volume ratio against a longer volume average. An efficiency filter reduces the score when price travel is large relative to net change, and a structure check penalizes a recent lower low versus a longer lookback. Users set the lookbacks, penalty weights, consistency cap, and two color thresholds. Extra inputs expose average volume, relative strength versus a chosen benchmark, and average daily range for screening.

Details

Published by

MeridianAlgo on GitHub

Type

Indicator, Pine Script v6

Draws

Separate pane below the chart

Category

Volatility & bands, Volume

Markets

Stocks

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

code-converterconverterjavascriptpinescripttranspilercode-reviewmeridianalgocode-conversionpinescript-algorithms

Settings

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

SettingTypeDefaultVariable
Short Termint13lenShortInput
Long Termint63lenLongInput
Volume Average (Logic)int50lenVolInput
Trend Penalty Strengthfloat1.0trendPenaltyWeight
Structure Lookbackint63hlLookbackInput
Penalty for Lower Lowfloat0.75penaltyFactor
Max Consistency Pointsint15bonusMax
Avg Volume Lengthint50scr_vol_len
RS BenchmarksymbolSPYrs_benchmark
RS Periodint21rs_len
ADR Periodint20adr_len
Level 2 (High)int80thHigh
Show all 16 settings
SettingTypeDefaultVariable
Level 1 (Base)int60thLow
Level 2 Colorcolor#00E676cHigh
Level 1 Colorcolor#2962FFcLow
Base Color (<60)color#787B86cBase
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
114 stars

This indicator standardizes price inputs using z-score normalization before calculating a relative strength index (RSI). It generates trade signals when standardized price components cross over or under the standardized RSI feature. Signals can be filtered by

Indicator v4 Oscillators & momentumVolatility & bands Repaints
Updated 1 year ago · None stated GitHub repository of Preprosessed & Standardized RSI
99 stars

This script calculates Bill Williams' Market Facilitation Index (BW MFI) to evaluate price movement efficiency relative to trading volume. It computes the range between the high and low prices divided by volume for each bar, returning zero when volume is zero.

Indicator v6 VolumeVolatility & bands
Updated 4 weeks ago · Apache-2.0 GitHub repository of Market Facilitation Index (MARKETFI)

PPO ATR Bands

by cryptorife
75 stars

PPO ATR Bands plots a percentage price oscillator in a separate pane. It compares a Hull average of typical price with a volume-weighted exponential average of Parabolic SAR, then scales three true-range bands around the slow average into matching oscillator l

Indicator v4 Oscillators & momentumMoving averages
Updated 3 years ago · GPL-3.0 GitHub repository of PPO ATR Bands

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