F3-conf-01 — Forecasting Canadian monthly GDP growth under publication lags
Scientific question
At the end of each month, how well can the year-over-year growth of Canadian monthly real GDP one and three months ahead be forecast from the information that is actually published at that time, and does a model that also uses the (more timely) Labour Force Survey employment growth beat the naive forecast? The estimands are the out-of-sample RMSE and MAE, over a fixed set of 48 rolling (expanding-window) origins and horizons h ∈ {1, 3}, of (a) the naive forecast and (b) one model of your choice, and the relative improvement 1 − RMSE_model / RMSE_naive per horizon.
Inputs
data/canada_gdp_employment.csv— observed data (Statistics Canada, current vintage, retrieved 2026-10-30 UTC via the Web Data Service; seedata/README.mdfor vectors, URL, SHA-256 and licence). Columns:month(YYYY-MM-01),gdp_level(monthly real GDP at basic prices, chained 2017 dollars, SA, millions),gdp_yoy(target: year-over-year growth ofgdp_level, percent, 4 decimals),emp_level(LFS employment, SA, thousands),emp_yoy(predictor: year-over-year employment growth, percent, 4 decimals). 345 monthly rows, 1998-01 to 2026-09; GDP columns are empty after the last published GDP month (2026-07), employment runs to 2026-09.
Information-availability rules
- Forecast origins: the 48 months t = 2022-05-01, 2022-06-01, …, 2026-04-01 (identified by their
monthvalue). The origin is the end of month t. Horizons h ∈ {1, 3}; the target of origin t at horizon h isgdp_yoyof month t + h. - Publication lags (documented in
data/README.md): monthly GDP for a reference month is published about two months after the end of that month; LFS employment for a reference month is published in the first/second week of the following month. Therefore, at origin t, the GDP columns are available only for months ≤ t − 2 and the employment columns only for months ≤ t − 1. A forecast made at origin t (its estimation sample, its model selection, its transformations and the values plugged into the forecast) may use only these observations. Training targets must also be observed at the origin. - Naive baseline: for both horizons, the forecast is the most recent GDP growth value available at the origin, i.e.
gdp_yoyof month t − 2. - The errors are computed on the data as given (current vintage); the exercise simulates publication timing, not historical first-release values — do not claim real-time validity.
Required outputs
out/forecasts.csv— the forecast ledger, one row per (origin, horizon, model), columns:origin_date(YYYY-MM-DD, themonthof the origin),target_date,horizon(integer),forecast,actual(thegdp_yoyvalue of the target month),model(naiveor the value ofmodel_name),last_target_date_used(YYYY-MM-DD: the latestgdp_yoymonth entering the forecast, estimation included),last_predictor_date_used(YYYY-MM-DD: the latestemp_yoymonth used, or empty if the model does not use employment). Expected: 48 × 2 × 2 = 192 rows.out/results.jsonwith the keys:
| key | type | unit | meaning |
|---|---|---|---|
task_id |
string | — | "F3-conf-01" |
model_name |
string | — | short name of your model, used in the model column |
model_description |
string | — | one-sentence specification (lags, predictors, estimation sample, method) |
n_origins |
integer | — | 48 |
first_origin, last_origin |
string | date | first and last origin dates |
last_target_date_available |
string | date | latest gdp_yoy month available at the last origin (2026-04-01) under the rules |
last_predictor_date_available |
string | date | latest emp_yoy month available at the last origin under the rules |
rmse_naive_h1, mae_naive_h1, rmse_naive_h3, mae_naive_h3 |
number | percentage points | naive errors per horizon |
rmse_model_h1, mae_model_h1, rmse_model_h3, mae_model_h3 |
number | percentage points | your model's errors per horizon |
rel_improvement_rmse_h1, rel_improvement_rmse_h3 |
number | fraction | 1 − rmse_model / rmse_naive |
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 | — | {"canada_gdp_employment.csv": number of data rows read, excluding the header} |
n_analysed |
integer | — | observations in the last estimation sample |
random_seed |
integer or null | — | seed used, if any |
out/report.mdwith the sections: Question; Data and exclusions; Method; Results; Uncertainty; Limitations and open issues.out/analysis.py— running~/wp29/venv/bin/python out/analysis.pyfrom the workspace root must regenerateout/results.jsonandout/forecasts.csvfromdata/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 modifydata/. - This task is designed to be completed in well under 20 minutes of work.