OPEN-SOURCE SCRIPT

Parkinson Range Oscillator [BackQuant]

169
Parkinson Range Oscillator [BackQuant]

Overview
Parkinson Range Oscillator is a volatility regime indicator built around the Parkinson volatility estimator, a high-low based variance model originally proposed as a more statistically efficient alternative to close-to-close volatility. Instead of measuring volatility from closing returns, this script measures volatility from the intrabar price range using ln(H/L), then converts it into a normalized oscillator (z-score) so you can identify volatility expansion vs compression relative to the asset’s own history.

The indicator is designed to answer questions like:
  • Is volatility currently elevated or suppressed relative to its baseline?
  • Is volatility expanding (risk rising) or compressing (coiling)?
  • How extreme is the current vol state in percentile terms?
  • How does range-based vol compare to a more common ATR-based vol read?


It plots:
  • A Parkinson-based volatility z-score oscillator with gradient fills.
  • A signal line (EMA) for expansion/compression transitions.
  • An ATR-based z-score for context comparison.
  • A dashboard with current vol %, z-score, percentile rank, regime label, and ATR z-score.


Where Parkinson volatility comes from (origin and intuition)
The Parkinson estimator comes from academic finance and the study of volatility estimation. The key insight is simple:

The daily high and low contain more information about variability than the close alone.

Close-to-close volatility only uses one price per bar (the close), throwing away intrabar information. The high-low range captures the realized dispersion inside the bar, so under ideal assumptions it can estimate variance more efficiently.

The Parkinson model is derived assuming:
  • Price follows a continuous-time diffusion process (often framed like geometric Brownian motion).
  • No drift matters for the variance estimate over the interval.
  • No jumps and no microstructure distortions (idealized).


Even though real markets violate these assumptions (gaps, jumps, wicks from order flow), the estimator remains useful because:
  • Range is still a strong proxy for realized volatility.
  • It reacts to intrabar expansion earlier than close-based methods.
  • It is less dependent on where the bar closes.


Core Parkinson formula (what the script implements)
Parkinson variance for a window of n bars is:

  • Var = (1 / (4 * n * ln(2))) * Σ [ ln(H/L)² ]


This script computes it in the common rolling form:
  • logHL2 = (ln(high/low))²
  • parkVar = SMA(logHL2, n) / (4 * ln(2))
  • parkVol = sqrt(parkVar) * 100


Key details:
  • ln(H/L) makes the range scale-invariant (percent-like), so it behaves more consistently across price levels.
  • Squaring gives variance contribution.
  • The 1/(4 ln 2) constant comes from the expected distribution of high-low range under a Brownian diffusion.
  • sqrt converts variance to standard deviation (volatility).
  • *100 expresses it as a percentage for readability.


So parkVol is a “range-based realized volatility proxy” in percent terms.

Why range-based volatility behaves differently than ATR
ATR measures average true range, which is a linear range magnitude measure (high-low plus gaps). Parkinson uses ln(H/L) which is:
  • Log-scaled (closer to a return-based measure).
  • More directly tied to variance estimation theory.


In practice:
  • ATR can be driven by gaps and absolute range.
  • Parkinson is driven by proportional range and tends to emphasize how wide the bar is relative to its price level.
  • Parkinson often reacts sharply when wicks expand even if closes are stable.


Normalization into an oscillator (making it comparable through time)
Raw volatility values are hard to interpret across regimes because every market has different “normal.” This script normalizes Parkinson volatility against its own rolling baseline using a z-score:

  • parkMA = SMA(parkVol, baselineLen)
  • parkSD = stdev(parkVol, baselineLen)
  • osc = (parkVol - parkMA) / parkSD


Interpretation:
  • osc = 0 means current vol is at its baseline average.
  • osc = +1 means 1 standard deviation above normal (high vol).
  • osc = -1 means 1 standard deviation below normal (compressed).
  • osc > +2 flags extreme expansion states.


This is the core output. It turns “volatility” into “volatility regime” in standardized units.

Signal line and expansion/compression transitions
The oscillator is smoothed with an EMA to create a signal line:

  • signal = EMA(osc, signalLen)


Then transitions are defined as:
  • Expansion cross: crossover(osc, signal) and osc > 0
  • Compression cross: crossunder(osc, signal) and osc < 0


Why the extra osc > 0 and osc < 0 conditions:
  • It prevents treating small oscillations around zero as meaningful.
  • It forces expansion signals to occur in above-average volatility territory.
  • It forces compression signals to occur in below-average volatility territory.


So signals are regime-confirming, not constant cross spam.

Percentile rank (how extreme is vol relative to the past)
In addition to the z-score, the script computes the percentile rank of the raw Parkinson volatility:

  • pctRank = percentrank(parkVol, pctRankLookback)


Interpretation:
  • pctRank near 90–100 means current vol is among the highest levels seen in that lookback.
  • pctRank near 0–10 means it is among the lowest (compression).


Z-score tells you “how many SDs from mean.” Percentile tells you “how rare is this state historically.” Those are different but complementary.

ATR comparison line (context, not the main engine)
The indicator also computes an ATR-based volatility proxy and normalizes it in the same way:

  • atrVol = ATR(n) / close * 100
  • atrOsc = zscore(atrVol, baselineLen)


This gives you a direct visual comparison:
  • If Parkinson oscillator is high but ATR oscillator isn’t, range expansion may be happening in a way ATR is not emphasizing (or vice versa).
  • If both agree, you have stronger confirmation of a true volatility regime shift.


ATR is included as a “common benchmark,” not as the primary signal.

Regime classification (human-readable state mapping)
The script labels regimes from osc:

  • osc > 2.0 → EXTREME
  • osc > 1.0 → HIGH
  • osc > 0.0 → ABOVE AVG
  • osc > -1.0 → BELOW AVG
  • else → COMPRESSED


This is a practical mapping for dashboards and quick reads. It is not pretending that 2.0 is a universal constant, it is just a standardized “rare expansion” threshold.

Coloring follows the same logic:
  • More positive = more “expansion” coloring (bearCol).
  • More negative = more “compression” coloring (bullCol).


Note: the color naming is semantic here:
  • “Low Vol / Compression” is bullCol because compression often precedes trend expansion opportunities.
  • “High Vol / Expansion” is bearCol because high vol often implies risk, disorder, liquidation, or unstable conditions.

You can interpret those however you prefer, the tool is measuring volatility regime, not directional bias.

Plot design (why the oscillator is split into positive/negative)
The oscillator is split into two series:
  • oscPos = osc if osc > 0 else na
  • oscNeg = osc if osc < 0 else na


This is purely for visuals:
  • Positive region is drawn with expansion color and expansion gradient fill to zero.
  • Negative region is drawn with compression color and compression gradient fill to zero.


This makes it obvious at a glance which side of “normal volatility” you’re on.

How to interpret the indicator correctly

1) The oscillator is volatility regime, not price direction
High osc does not mean price will go down. It means the market is moving violently relative to its baseline. That can occur in:
  • Selloffs, liquidations, panic.
  • Breakouts and momentum expansions.
  • News-driven repricing.


Low osc does not mean price will go up. It means the market is quiet relative to baseline:
  • Ranges, coils, low realized movement.
  • Slow grind trends with suppressed pullbacks.
  • Pre-breakout compressions.


2) Compression regimes are often “setup states”
When osc is deeply negative (compressed), it often indicates that realized movement has collapsed. In many markets this precedes:
  • Breakouts (vol expansion from compression).
  • Trend acceleration.
  • Mean reversion bursts.

But compression can also persist. This is why the script includes signal crosses and percentile rank to judge when compression is shifting.

3) Expansion regimes are often “risk states”
When osc is positive and rising, the environment is more chaotic:
  • Stops are more likely to be hit.
  • Mean reversion can get violent.
  • Trend continuation can be strong but timing becomes harder.


In those regimes, the tool can be used to:
  • Reduce leverage.
  • Widen stops (if your system supports it).
  • Switch to volatility-aware sizing.
  • Wait for stabilization if you trade mean reversion.


4) Use percentile rank to identify “rare” volatility
Two markets can both show osc = +1, but one might be at the 95th percentile and the other at the 70th depending on distribution shape. Percentile tells you whether the current vol is truly rare in that lookback.

Cross dots (how to treat them)
ExpansionCross and CompressionCross are not buy/sell signals. They are “volatility phase change” markers:
  • ExpansionCross: vol regime moving up, above baseline, acceleration risk increases.
  • CompressionCross: vol regime moving down, below baseline, quieting environment.


These are useful for:
  • Strategy toggles (trend mode vs chop mode).
  • Sizing changes.
  • Timing filters (avoid entries during extreme expansion if your edge hates noise).


Dashboard (what it gives you at a glance)
The table summarizes everything that matters without you needing to interpret plots manually:
  • Parkinson Vol %: current raw range-based volatility level.
  • Z-Score: current standardized regime reading.
  • Percentile: rarity of current vol in the lookback.
  • Regime: discrete label based on z-score thresholds.
  • ATR Z-Score: comparison metric in standardized units.


The dashboard is positioned and sized via inputs so it can fit different chart layouts.

Parameter tuning guidance

Parkinson Length
Controls how quickly the raw Parkinson vol responds:
  • Shorter = more reactive to immediate range changes.
  • Longer = smoother volatility estimate, less noisy.


Baseline Length
Controls what “normal” means:
  • Long baseline (like 100) creates stable regime definitions.
  • Short baseline makes z-scores jump around and can overreact.


Signal Length
Controls how quickly you detect regime turning points:
  • Short signal = more crosses, earlier detection, more noise.
  • Long signal = fewer crosses, later detection, cleaner regime shifts.


Percentile Lookback
Controls rarity context:
  • 252 approximates one trading year on daily charts.
  • On intraday, it becomes “252 bars,” so adjust to match your horizon.


Limitations and what to watch for
  • Parkinson assumes continuous diffusion. Jumps and gaps can distort it.
  • Wicks caused by illiquidity can inflate ln(H/L) and produce false “expansion.”
  • Z-score assumes the baseline distribution is reasonably stable. If volatility distribution shifts structurally, your z-scores can be biased until baseline catches up.
  • Percentile rank is lookback-dependent. Different lookbacks can change “rarity” classification materially.


Summary
Parkinson Range Oscillator converts a statistically grounded high-low volatility estimator into a regime oscillator by z-scoring Parkinson volatility against its own rolling baseline. It highlights expansion vs compression states with clear gradients, flags volatility phase changes via oscillator-signal crosses, ranks current volatility by percentile for rarity context, and overlays an ATR-based z-score for comparison. This makes it a practical tool for volatility-aware trading, regime filtering, sizing adjustments, and identifying compression-to-expansion transitions.

إخلاء المسؤولية

لا يُقصد بالمعلومات والمنشورات أن تكون، أو تشكل، أي نصيحة مالية أو استثمارية أو تجارية أو أنواع أخرى من النصائح أو التوصيات المقدمة أو المعتمدة من TradingView. اقرأ المزيد في شروط الاستخدام.