{ "cells": [ { "cell_type": "markdown", "id": "8361129b", "metadata": {}, "source": [ "# Real-time S&P 500 volatility: bayesloop versus GARCH\n", "\n", "*Volatility clustering*, the tendency for calm and turbulent days to arrive in runs, is the\n", "strongest stylised fact in financial returns and the one that launched the ARCH/GARCH\n", "literature (Engle, Nobel 2003). A natural description is a process whose volatility is a\n", "time-varying parameter. This example runs *bayesloop* fully online over a decade of daily\n", "S&P 500 returns. We ask three things of it: whether we can forecast next-day risk in real\n", "time, whether modelling time-varying volatility predicts returns better than holding it\n", "constant, and whether we can flag volatility shocks (the Feb-2018 \"Volmageddon\", the\n", "March-2020 COVID crash, the 2022 bear, the 2025 tariff selloff) the moment they happen.\n", "\n", "This is an example of comparing bayesloop against an established model. The standard model\n", "for return volatility is GARCH(1,1), and we benchmark bayesloop against it directly,\n", "out-of-sample, using the `arch` library, in both a Gaussian and a Student-t form and in\n", "fixed and rolling-refit variants. The components of the toolbox we use are `bl.om.WhiteNoise`\n", "(and a custom Student-t observation model) for time-varying volatility, an `OnlineStudy`\n", "that performs real-time model selection between a *calm* (`GaussianRandomWalk`) and a\n", "*turbulent* (`RegimeSwitch`) volatility process, and the *prequential predictive\n", "log-likelihood* as a fully causal out-of-sample score. The result, worked out below, is\n", "that within a matched (Gaussian) likelihood bayesloop beats the rolling-refit GARCH by\n", "+6.6 log₁₀, it is competitive with a Student-t GARCH, and it additionally provides a live\n", "regime probability and a full posterior over volatility as a by-product of the same filter.\n", "\n", "