Skip to content

Lower-side calibration follow-up: fix P80 coverage gap (0.85 vs 0.90 target) #19

Description

@ducroq

What this issue is

Tracker for the post-EXP-014 calibration follow-up explicitly queued in the M4 retrospective (`docs/articles/m4-metric-redesign-story.md` §9, ADR-006 `Consequences`, `docs/hypothesis-log.md`). LightGBM-Quantile's lower-side coverage sits at 0.854 vs the 0.90 target across the full eval log (1728 realised hours, 25 days). The promotion guardrail passed only because both models miss the target — ARF was 0.82, LGBM is 0.85, neither hits 0.90. Same gap inherited from ARF; not made worse by the swap, but unresolved.

Why it matters

Three candidate approaches

The M4 retrospective and the EXP-012 literature pass each independently surfaced these. They are not mutually exclusive; the natural sequence is to evaluate them one at a time as separate experiments (EXP-015, EXP-016, EXP-017).

A. Horizon-conditioned CQR

Current CQR uses one calibration set across all 72 horizons. The retrospective hypothesises that ARF's EWM band wins pinball-at-p10 at long horizons because its residual-std estimate is horizon-agnostic, while CQR widens uniformly based on whatever the trailing 7-day calibration set happens to contain (often dominated by one regime).

Test: split CQR calibration into the same three horizon groups already used by the LGBM forecaster (h+1..h+6 / h+7..h+24 / h+25..h+72). Per-group `q` widens bands differently per horizon.

Implementation: small change in `ml/shadow/update_shadow.py` + `ml/shadow/conformal.py`. Probably the cheapest experiment.

B. Adaptive Conformal Inference (ACI)

Gibbs & Candès 2021 / 2024 — `q` is adjusted online based on rolling coverage, targeting nominal level by a closed-loop control law. Designed exactly for the situation where exchangeability is mildly violated (which is what we have: regime shifts, daily seasonality, calibration set composition drift).

Implementation: replace fixed-target CQR with adaptive update. Reference implementations exist (`Predictive-Conformal-Intervals` libraries). Slightly more invasive than (A).

C. Train at more quantiles (9 or 19 instead of 3) + canonical twCRPS

The article §9 also flagged that the current 3-quantile training has a structural MQS asymmetry (LGBM's 3-quantile pinball average has a ~2× head start over a point forecast's MAE-as-CRPS-equivalent — see EXP-013 review). Training at 9 or 19 quantiles costs more retraining time but:

  • removes the structural asymmetry from any future skill comparison
  • enables a properly-implemented Gneiting-Ranjan canonical twCRPS as a descriptive tail metric
  • gives more honest CDF estimates for diagnostics

This doesn't directly fix coverage but it removes a methodological caveat that bleeds into how we interpret any coverage fix.

Scope of this tracker

  • EXP-015 (most likely first): horizon-conditioned CQR. Pre-commit a hypothesis in `docs/hypothesis-log.md` with target lower-side coverage ≥ 0.88 by horizon group, no group below 0.85, evaluated over a 14-day shadow.
  • EXP-016 (if EXP-015 falls short or as parallel candidate): ACI.
  • EXP-017 (if either of the above passes): retrain at 9 quantiles, recompute skill comparison + canonical twCRPS, update CLAUDE.md and the article.
  • After successful experiment: update `docs/hypothesis-log.md`, append rows to `experiments/registry.jsonl`, update `docs/decisions/006-...` with the new calibration design, update CLAUDE.md known-weakness note.

Each EXP gets its own pre-committed criterion per ADR-007. This issue is the umbrella that ties them together so the work doesn't drift.

Out of scope

Dependencies

Soft dependency on #12: fixing exogenous freshness may itself shift coverage measurably (the LGBM training parquet currently sees 24h-stale forecasts). Worth resolving the freshness story before running the calibration experiments so we don't conflate two effects. Not a hard block — could be re-evaluated after.

References

  • `docs/articles/m4-metric-redesign-story.md` §9 (the four open questions, of which three apply here)
  • `docs/decisions/006-lightgbm-quantile-production-architecture.md` (`Consequences` section flags this)
  • `docs/decisions/007-model-promotion-method.md` (the criterion framework for any EXP-015..017)
  • `docs/hypothesis-log.md` (where pre-commits will land)
  • `docs/metric-redesign-literature-review.md` (CQR / ACI references)
  • `memory/MEMORY.md` → `arf-retired.md` (records the gap as 'queued as next experiment')
  • Current numbers: `ml/shadow/eval_log.jsonl`, `ml/models/shadow/shadow_state.json` calibration_history

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions