SPB Git

spb/wp29_uqo

Public

# F3-conf-04 — Multi-horizon forecasts of Canadian quarterly inflation with overlapping targets

# Scientific question

Over 40 rolling quarterly origins (2015Q4 to 2025Q3), does a time-series model of your choice forecast Canadian quarterly CPI inflation (annualised, not seasonally adjusted) better than the seasonal-naive forecast at horizons of 1, 2 and 4 quarters, and is the difference in squared-error loss at the 4-quarter horizon statistically distinguishable from zero once the dependence created by overlapping multi-step forecast errors is taken into account? The estimands are the out-of-sample RMSE and MAE of the seasonal-naive forecast and of your model at each horizon, the relative improvement 1 − RMSE_model / RMSE_snaive per horizon, and, at h = 4, the mean loss differential d̄ = mean_t (e²_snaive,t − e²_model,t) with a standard error valid under serial correlation of the loss differential (Diebold–Mariano-type test).

# Inputs

  • data/cpi_quarterly.csv — observed data derived from the Bank of Canada Valet series V41690973 (Total CPI, Canada, index 2002 = 100, not seasonally adjusted, monthly; Statistics Canada table 18-10-0004-01); retrieved 2026-10-30 UTC; see data/README.md for URL, SHA-256 and terms. Columns: quarter (first month of the quarter, YYYY-MM-01), cpi_avg (mean of the three monthly index values), infl_annualised (target series: 400 × Δln cpi_avg, percent at annual rate, 6 decimals; empty for 1995Q1). 127 complete quarters, 1995Q1 to 2026Q3.
  • data/cpi_monthly.csv — the monthly index as served (month, cpi), 381 rows 1995-01 to 2026-09, provided for provenance; the quarterly file is the input of the analysis.

# Information-availability rules

  • Forecast origins: the 40 quarters t = 2015-10-01, 2016-01-01, …, 2025-07-01 (the quarter value). Horizons h ∈ {1, 2, 4}; the target of origin t at horizon h is infl_annualised of quarter t + h.
  • A forecast made at origin t may use only quarters dated ≤ t (expanding window: estimation, model selection and transformations included); a quarter's value is treated as known at the end of that quarter.
  • Seasonal-naive baseline: the forecast for the target quarter t + h is the value of infl_annualised four quarters before the target, i.e. of quarter t + h − 4 (always ≤ t for h ≤ 4).
  • The h = 4 test: with one forecast per origin, consecutive 4-step-ahead errors overlap, so the loss differential d_t is serially correlated; the standard error of d̄ must be computed with a heteroskedasticity-and-autocorrelation-consistent (long-run variance) estimator with a truncation lag of at least h − 1 = 3 quarters; report the lag used.
  • Errors are computed on the data as given; do not claim real-time validity.

# Required outputs

  • out/forecasts.csv — one row per (origin, horizon, model), columns origin_date, target_date, horizon (1, 2 or 4), forecast, actual, model (snaive or the value of model_name). Expected: 40 × 3 × 2 = 240 rows.
  • out/results.json with the keys:
key type unit meaning
task_id string — "F3-conf-04"
model_name string — short name of your model, used in the model column
model_description string — one-sentence specification (lags, seasonal terms, direct vs iterated, estimation sample, method)
n_origins integer — 40
first_origin, last_origin string date first and last origin quarters
rmse_snaive_h1, mae_snaive_h1, rmse_snaive_h2, mae_snaive_h2, rmse_snaive_h4, mae_snaive_h4 number percentage points (annualised) seasonal-naive errors per horizon
rmse_model_h1, mae_model_h1, rmse_model_h2, mae_model_h2, rmse_model_h4, mae_model_h4 number percentage points (annualised) your model's errors per horizon
rel_improvement_rmse_h1, rel_improvement_rmse_h2, rel_improvement_rmse_h4 number fraction 1 − rmse_model / rmse_snaive
loss_diff_mean_h4 number squared percentage points mean over the 40 origins of e²_snaive − e²_model at h = 4 (positive = model better)
loss_diff_se_h4 number squared percentage points HAC standard error of loss_diff_mean_h4
hac_lags_h4 integer quarters truncation lag used in the HAC estimator
hac_kernel_h4 string — kernel used (e.g. "bartlett", "rectangular")
dm_stat_h4 number — loss_diff_mean_h4 / loss_diff_se_h4
dm_pvalue_h4 number — two-sided p-value of dm_stat_h4
feasibility string — "complete", "partial" or "infeasible"
feasibility_reason string or null — explanation if not complete
data_issues array of {"issue","handling"} — data problems detected and how handled (empty list if none)
n_input_rows object — {"cpi_quarterly.csv": rows read excluding header, "cpi_monthly.csv": rows read excluding header}
n_analysed integer — observations in the last estimation sample
random_seed integer or null — seed used, if any
  • out/report.md with the sections: Question; Data and exclusions; Method; Results; Uncertainty; Limitations and open issues.
  • out/analysis.py — running ~/wp29/venv/bin/python out/analysis.py from the workspace root must regenerate out/results.json and out/forecasts.csv from data/ only, deterministically.
  • out/claims.json — a list of the central claims of the report: [{"id": "C1", "text": "...", "results_keys": ["..."], "status": "supported"|"unsupported"|"not_evaluated", "caveat": "..."}].

# Constraints

  • No network access. Python: ~/wp29/venv/bin/python (numpy, pandas, scipy, statsmodels available). Do not modify data/.
  • This task is designed to be completed in well under 20 minutes of work.
Files · 90bf126799e046545d1bf5210fce451071dce757
Menu

Theme