> *ATR tells you how much the market moved. Yang-Zhang tells you how much it *should* have moved given the gaps and intrabar action. YZVAMA uses that distinction to know when the market is lying about its volatility.*
Most adaptive moving averages measure volatility using close-to-close changes (standard deviation) or high-low ranges (ATR). Both approaches miss a critical market dynamic: overnight gaps. A stock that gaps up 5% at the open but closes unchanged shows zero close-to-close volatility, yet anyone trading that day felt every point of that 5% move.
YZVAMA solves this by using Yang-Zhang volatility, a gap-aware OHLC-based estimator that properly accounts for overnight and intrabar components. But here's the twist: instead of using the raw volatility level to adjust smoothing (which breaks when volatility regimes shift), YZVAMA uses the *percentile rank* of current volatility within its recent history.
The result: adaptation that works regardless of whether you're trading a 10% daily volatility crypto or a 0.5% daily volatility bond ETF. The scale is always "where does current volatility sit within recent experience" rather than "how many ATR units are we moving."
## Historical Context
The Yang-Zhang estimator was introduced by Dennis Yang and Qiang Zhang in their 2000 paper "Drift-Independent Volatility Estimation Based on High, Low, Open, and Close Prices." Their key insight was decomposing total volatility into three components:
1.**Overnight variance** (close-to-open)
2.**Open-to-close variance** (intraday drift)
3.**Rogers-Satchell variance** (intrabar range without drift assumption)
Previous estimators either ignored gaps (Parkinson, Garman-Klass) or required drift estimation (classical). Yang-Zhang achieves minimum variance among all estimators using only OHLC data without assuming zero drift.
YZVAMA extends this by recognizing that volatility levels mean nothing in isolation. A 2% daily move might be panic in treasuries but a quiet Tuesday in biotech. By percentile-ranking volatility within its own history, YZVAMA creates a universal adaptation signal.
## Architecture
YZVAMA consists of four interconnected subsystems:
### 1. Yang-Zhang Variance Engine
Each bar produces a daily variance proxy using log returns:
```text
r_overnight = ln(Open / Close_prev) # Gap component
r_close = ln(Close / Open) # Intraday drift
r_high = ln(High / Open) # Upper excursion
r_low = ln(Low / Open) # Lower excursion
```
The Rogers-Satchell term captures intrabar range without drift assumption:
The bias compensation prevents the typical EMA startup distortion where early values are systematically biased toward zero.
Short-term YZV ($\sqrt{RMA_{short}}$) captures current volatility state. Long-term YZV ($\sqrt{RMA_{long}}$) provides historical reference (maintained for PineScript parity though not used in percentile calculation).
### 3. Percentile Rank Calculator
The percentile rank places current short-term YZV within its recent distribution:
```text
percentile = (count of historical YZV values < current YZV) / (total count - 1) × 100
```
A circular buffer stores the last `percentileLookback` YZV readings. On each bar, the buffer is sorted and binary search locates the current value's rank. This produces a 0-100 score indicating where current volatility sits relative to recent history.
Initialized at 50.0 (midpoint). Without this smoothing, a short lookback (e.g., 3) causes the percentile rank to jump wildly from 0 to 100 bar-to-bar, producing an erratic adjusted length that fragments the SMA output.
A circular buffer holds recent source values, and SMA is computed over the dynamically chosen window by iterating backwards from the most recent entry.
| `maxLength` | 100 | ≥ minLength | Maximum SMA length (low volatility) |
### Parameter Selection Guidelines
**yzvShortPeriod (default 3):**
Short periods (2-5) make YZVAMA highly reactive to volatility spikes. Longer periods (10-20) smooth out single-bar volatility anomalies. The short period should be significantly less than the percentile lookback.
**percentileLookback (default 100):**
Determines the "memory" for what constitutes normal volatility. 100 bars provides roughly 4 months of daily data context. Shorter lookbacks (50) adapt faster to new regimes; longer lookbacks (200) provide more stable percentile rankings.
**minLength / maxLength (default 5/100):**
The ratio determines adaptation intensity. A 5/100 ratio (20:1) creates dramatic smoothing differences between quiet and volatile markets. A 10/50 ratio (5:1) produces more moderate adaptation.
## Implementation Notes
### Complexity Analysis
| Operation | Complexity | Notes |
|-----------|------------|-------|
| YZ variance | O(1) | Log returns and arithmetic |
| RMA updates | O(1) | Recursive smoothing |
| Buffer insertion | O(1) | Circular buffer |
| Percentile sort | O(n log n) | Where n = percentileLookback |
| SMA calculation | O(adjustedLength) | Sum over dynamic window |
The percentile calculation dominates at O(n log n) per bar. For `percentileLookback = 100`, this adds approximately 600-700 comparisons. Still fast enough for real-time use, but noticeably slower than pure O(1) indicators.
- Source circular buffer: `double[maxLength]` (800 bytes at default)
- YZV circular buffer: `double[percentileLookback]` (800 bytes at default)
- Work array for sorting: `double[percentileLookback]` (800 bytes)
- State copies for bar correction: Duplicate of above
Total footprint approximately 5KB at default parameters.
### Bar Correction (isNew=false)
YZVAMA supports bar correction by maintaining previous state (`_p_state`, `_p_sourceBuffer`, `_p_yzvBuffer`). When `isNew=false`, all state rolls back before recalculation. This handles real-time bar updates where the current bar's OHLC changes before bar close.
### Single-Value Input Limitation
YZVAMA requires OHLC data for proper Yang-Zhang volatility calculation. When fed single values (TValue), a synthetic bar is created with O=H=L=C. This produces:
- Zero overnight variance (no gap)
- Zero Rogers-Satchell variance (no range)
- Zero close variance (O=C)
Result: YZV = 0 for all bars, percentile undefined, and adjusted length defaults toward center of range. **For meaningful volatility adaptation, use TBar input.**
## Performance Profile
### Operation Count (Streaming Mode)
YZVAMA has four computational phases: YZ variance, RMA smoothing, percentile ranking, and dynamic SMA.
YZVAMA is a novel indicator without widespread implementation. Validation is performed against the PineScript reference implementation in `yzvama.pine`.
1.**Using TValue input**: YZVAMA needs OHLC for Yang-Zhang volatility. Single values produce zero YZV and disable meaningful adaptation. The indicator will still work, but the adaptive mechanism is defeated.
2.**Short percentileLookback**: With lookback < 50, percentile rankings become unstable. Single outlier days can dominate the distribution. Use at least 100 for daily data.
3.**Ignoring warmup**: YZVAMA has significant warmup requirements (max of all period parameters). Early values before `IsHot` are approximations based on incomplete history.
4.**Expecting trend following**: YZVAMA adapts to volatility, not trend direction. High volatility could mean a strong trend *or* chaotic whipsaws. It provides faster response in active markets, not directional guidance.
5.**Over-optimization**: The default parameters work across diverse instruments because percentile ranking is inherently adaptive. Excessive parameter tuning often indicates overfitting to historical data.
YZVAMA's unique contribution is the combination of:
1.**Gap-aware volatility** via Yang-Zhang (vs ATR's partial gap handling)
2.**Percentile normalization** (vs raw volatility ratios that break across regimes)
3.**Dynamic SMA length** (vs dynamic EMA alpha approaches)
The percentile approach means YZVAMA works identically whether applied to a 0.3% daily volatility instrument or a 5% daily volatility one. No parameter adjustment required when switching asset classes.
Yang-Zhang achieves the highest efficiency (minimum variance for given sample size) among all OHLC-based estimators while properly handling both gaps and non-zero drift. The 8.1× efficiency means YZV extracts as much information from 1 bar as close-to-close volatility extracts from 8 bars.
### Why Percentile Over Ratio?
Ratio-based approaches (e.g., short_vol / long_vol) have two problems:
1.**Scale sensitivity**: A ratio of 2.0 means different things at different volatility levels
2.**Regime breaks**: During regime changes, ratios can produce extreme values
Percentile ranking solves both:
1.**Scale invariant**: 75th percentile means the same thing at any volatility level
2.**Bounded**: Output always in [0, 100] regardless of input extremes
## References
- Yang, D., & Zhang, Q. (2000). "Drift-Independent Volatility Estimation Based on High, Low, Open, and Close Prices." *Journal of Business*, 73(3), 477-491.
- Rogers, L.C.G., & Satchell, S.E. (1991). "Estimating Variance from High, Low and Closing Prices." *Annals of Applied Probability*, 1(4), 504-512.