MAVP applies an EMA-style exponential smoothing where the period -- and therefore the smoothing constant alpha -- changes on every bar. Each bar receives an externally supplied period value, clamped to [minPeriod, maxPeriod], producing `alpha = 2 / (period + 1)`. The result is a single-pass O(1) IIR filter with an adaptive warmup compensator that tracks the cumulative product of all per-bar `(1 - alpha)` values. With a fixed period MAVP reduces exactly to standard EMA (validated to 1e-9 tolerance against Skender and TA-Lib EMA). With a time-varying period series, it becomes a general-purpose adaptive smoother controlled entirely by external logic.
## Historical Context
TA-Lib introduced `MAVP` (Moving Average Variable Period) as a meta-indicator: feed it a price series and a period series, and it routes each bar through the selected MA type with that bar's period. The original C implementation supports SMA, EMA, WMA, DEMA, TEMA, TRIMA, KAMA, MAMA, and T3 as backends. Most implementations default to SMA, which requires a sliding window that changes size every bar -- an allocation headache and O(n) per bar.
This implementation takes a different approach. Rather than wrapping arbitrary MA types, it uses a pure EMA core with per-bar alpha adaptation. The advantage: O(1) time, O(1) space, zero allocation, no buffer. The warmup compensator `E = product(1 - alpha_i)` generalizes the standard EMA bias correction `E = (1 - alpha)^n` to handle the non-stationary case where alpha varies.
The trade-off is explicit: you get EMA-type smoothing only. If you need variable-period SMA or WMA, use a windowed approach. But for adaptive trend following where lag minimization matters, EMA with variable alpha is the right primitive.
## Architecture and Physics
### 1. Per-Bar Alpha Computation
The period input is first clamped, then converted to an EMA smoothing constant:
When `E <= 1e-10`, compensation is complete and the raw EMA is used directly. IsHot fires when `E <= 0.05` (approximately 95% of steady-state weight accumulated).
### 4. Z-Domain Transfer Function
For a single bar with alpha_i, the transfer function is the standard first-order IIR:
$$H_i(z) = \frac{\alpha_i}{1 - \beta_i z^{-1}}$$
The time-varying system is a sequence of such filters cascaded with changing coefficients. This is a Linear Time-Varying (LTV) system -- not LTI -- so standard frequency-domain analysis does not directly apply. Stability is guaranteed because each individual filter has its pole at `beta_i` which lies in `(0, 1)` for any valid alpha.
## Mathematical Foundation
### EMA Recursion (Variable Alpha)
Given input series $x_0, x_1, \ldots, x_n$ and period series $p_0, p_1, \ldots, p_n$:
TA-Lib's native `MAVP` function uses SMA by default (MAType=0), not EMA. Direct comparison requires MAType=1 (EMA mode), which is validated indirectly through the EMA equivalence proof.
## Common Pitfalls
1.**Assuming MAVP == TA-Lib MAVP**: TA-Lib defaults to SMA-based MAVP; this implementation uses EMA. With `MAType=1` in TA-Lib, results match. Mixing up MA types causes 100% of "validation failure" reports.
2.**Unstable period series**: Rapidly oscillating periods (e.g., period = [2, 30, 2, 30, ...]) create a filter that alternates between very responsive and very sluggish. The output will exhibit ringing. Smooth the period series first if the source is noisy.
3.**Warmup underestimation**: WarmupPeriod is set to maxPeriod, but actual convergence depends on the period sequence. If all periods are maxPeriod, warmup takes ~150 bars. If all periods are minPeriod=2, warmup happens in ~5 bars.
4.**Period clamping ignored**: Periods outside [minPeriod, maxPeriod] are silently clamped. If your external period source produces values like 0.5 or 1000, the effective period will differ from what you expect. Add logging or asserts in your pipeline.
5.**Bar correction with period changes**: When correcting a bar (isNew=false), the period used must be the same period as the original bar. If you change the Period property between the original update and the correction, the rollback restores state but applies a different alpha, producing incorrect results.
6.**Memory of the Period property**: The Period property persists between Update calls. If you set Period=5 for one bar and then call Update without setting Period again, the next bar also uses Period=5. This is by design but can surprise users who expect period to reset.
## References
- Kaufman, P. J. (2013). *Trading Systems and Methods*, 5th Ed. Wiley. Discusses adaptive moving averages.
- TA-Lib documentation: [MAVP - Moving Average with Variable Period](https://ta-lib.org/function.html)