viewof sigmaEta = Inputs.range([0.05, 2], {
value: 0.3, step: 0.05,
label: "σ_η — state noise (how fast the world changes)"
})
viewof sigmaEps = Inputs.range([0.05, 2], {
value: 0.8, step: 0.05,
label: "σ_ε — measurement noise (how bad the data is)"
})
viewof seed = Inputs.range([1, 60], {
value: 7, step: 1,
label: "simulation seed"
})
viewof outage = Inputs.toggle({
label: "data outage for t ∈ [90, 110) — the ragged edge",
value: false
})Kalman Filter Playground
The local level model, live
The simplest state space model: a random-walk level \alpha_t observed with noise, y_t = \alpha_t + \varepsilon_t. The Kalman filter sees only the gray dots and must infer the orange line. You control the two variances. Watch what the optimal filter does with them — and switch on the data outage to see how the filter handles the ragged edge: uncertainty fans out while data is missing, then snaps shut on the first new observation.
The shaded band is the filter’s own 95% uncertainty about the state. It is not decoration — it is the honest answer to “how sure are you?”, and during the outage it is the entire output of the model.
The gain: how much attention each observation deserves
Things to try
- Slide σ_ε up with σ_η low. The gain collapses toward zero — the filter nearly ignores each individual dot, and the blue line becomes very smooth. This is what “the data is noisy, trust the model” looks like, derived.
- Slide σ_η up with σ_ε low. Gain near one: the filter chases the data, because yesterday’s level genuinely tells you little about today’s.
- Turn on the outage. Watch the band fan out linearly in variance (that’s P_{t+1|t} = P_{t|t} + \sigma^2_\eta compounding), then collapse on the first observation after the gap — which receives a much larger gain than its neighbors. The filter knows it has been flying blind and treats the first new data point accordingly. That single frame is the entire ragged-edge logic of a production nowcasting system.
- Change the seed. The qualitative story survives every draw — it’s a property of the filter, not of luck.
The math behind this page is derived in the Session 1 notes.