Free lesson · Time series
Forecast horizons, EWMA, and model diagnostics
Open interactive lessonPractice calculationsExplore labs
Start with the idea
A recursive forecast balances adaptation with stability. Fast updates react to shocks but may force costly position changes; slow updates can leave the book exposed to volatility that has already risen.
Symbols, units & horizon
- σ̂ₜ²: variance forecast made before innovation εₜ
- λ: EWMA weight on old variance, between 0 and 1
- εₜ: observed residual return
- μ: AR process mean
- φ: AR coefficient
- h: integer forecast horizon in periods
- E[xₜ₊ₕ|xₜ]: expected future level given the current level
- Hat: estimated quantity
When and why to use this
Use EWMA as a transparent volatility baseline and multi-step forecasts to align the model horizon with the actual holding period.
Unroll an EWMA variance forecast
- Substitute the previous recursion repeatedly: .
- The weights sum to . A shock’s weight halves at .
λ=.94, old variance=.0001, shock=.02 gives .94(.0001)+.06(.0004)=.000118; next SD≈1.086%.
EWMA updates the variance forecast using the last innovation. Larger λ means slower adaptation; the weight half-life is ln(1/2)/ln(λ). Unlike stationary GARCH with an intercept, this form has no fixed long-run variance toward which the forecast reverts.
Iterate the conditional AR forecast
- Write . Conditional mean-zero future innovations disappear under expectation.
- At two steps multiply the current deviation by φ²; induction gives φʰ. Add μ back.
Current spread 5, mean 3, φ=.8, horizon 2: forecast=3+.64(2)=4.28, an expected decline of .72.
For a stable AR(1), the conditional forecast converges toward μ as h grows. A negative φ alternates the sign; a half-life for absolute deviation is not a monotone price-reversion forecast. Validate residual autocorrelation, changing variance and forecast errors at the actual trading horizon.
Python implementation
Self-contained teaching example. Python 3.10+; dependencies and input conventions are shown in the code and notation. Run in your own Python environment.
def ewma_variance(previous_forecast, innovation, decay=.94):
if not 0 < decay < 1 or previous_forecast < 0:
raise ValueError("Require variance >= 0 and decay in (0,1)")
return decay*previous_forecast+(1-decay)*innovation**2
def ar_forecast(current, mean_level, phi, horizon):
if horizon < 0 or int(horizon) != horizon:
raise ValueError("Nonnegative integer horizon required")
return mean_level+phi**horizon*(current-mean_level)
print(ewma_variance(.0001, .02), ar_forecast(12, 10, .8, 2))Continue learning
Time Series Analysis — all lessons- Start with time order, lags and differences
- Before GARCH: mean, shocks and changing variance
- Stationarity: the assumption every test makes and every market breaks
- Autocorrelation: momentum, mean reversion, or coin flips
- GARCH: volatility clusters, and you can model the cluster
- Cointegration: a stationary relationship to test
- Forecast horizons, EWMA, and model diagnostics
- Markov chains: a two-state model you can calculate by hand
- Hidden Markov models: predict, observe, update
Quantitative finance and development glossary · Python resources and libraries · Research sources and limitations