# F3-conf-01 — Forecasting Canadian monthly GDP y/y growth under publication lags ## Question At the end of each month t (48 origins, `first_origin` = 2022-05-01 to `last_origin` = 2026-04-01; `n_origins`), how accurately can year-over-year growth of Canadian monthly real GDP be forecast for months t+1 and t+3 using only data published by then, and does a model that also uses the timelier LFS employment growth beat the naive forecast (latest published GDP growth, month t−2)? ## Data and exclusions - One file, `data/canada_gdp_employment.csv`, 345 data rows (`n_input_rows`), 1998-01 to 2026-09; SHA-256 matches `data/README.md`. Audit details are in `out/state/data_audit.md`. - Publication-lag rule: at origin t, GDP is used only up to t−2 and employment only up to t−1. At the last origin, that means GDP up to 2026-02-01 (`last_target_date_available`) and employment up to 2026-03-01 (`last_predictor_date_available`). Every row of `out/forecasts.csv` records the latest dates it actually used, and all of them satisfy the rule (`out/state/checks.md`). - No data row was deleted. When estimating the model, I dropped regression rows whose target or regressor month falls in the COVID window 2020-03..2021-12, where y/y values swing between −16 % and +19 %. I made this choice before computing any out-of-sample error. Exclusion ledger for the last estimation sample (origin 2026-04, h=1), in `out/exclusions.csv`: 345 rows → 338 known at the origin → 335 with lagged regressors available → 310 after the COVID exclusion (`n_analysed`). - Data issues and how I handled them are listed in `data_issues`. The main ones: GDP for 2026-08/09 is not yet published (not needed); the 1998 y/y values cannot be checked against levels (all later values match the levels exactly); the data are the current vintage. ## Method - **Naive:** forecast = `gdp_yoy`(t−2) for both horizons. - **Model `dir_ols_emp`** (`model_name`, `model_description`): a direct h-step OLS of gdp_yoy(s) on a constant, gdp_yoy(s−h−2) and emp_yoy(s−h−1). This mirrors the information gaps at the origin (GDP lags the origin by 2 months, employment by 1). It is re-estimated at every origin on an expanding window starting in 1998, using only training targets ≤ t−2. The forecast plugs in gdp_yoy(t−2) and emp_yoy(t−1). - **Evaluation:** RMSE and MAE in percentage points over the 48 origins per horizon, against `gdp_yoy` of month t+h as given in the file. - **Diagnostics beyond the required outputs:** - A Diebold–Mariano test on squared-error loss, with an HAC variance (h−1 lags) and the Harvey–Leybourne–Newbold correction (`dm_stat_h*`, `dm_pvalue_two_sided_h*`). - An ablation: the same regression without employment (`rmse_ablation_no_emp_h*`). - Nothing is random (`random_seed` = null). `out/analysis.py` regenerates every output. ## Results | horizon | RMSE naive | MAE naive | RMSE model | MAE model | 1 − RMSE ratio | |---|---|---|---|---|---| | h=1 | 0.814 (`rmse_naive_h1`) | 0.642 (`mae_naive_h1`) | 0.743 (`rmse_model_h1`) | 0.604 (`mae_model_h1`) | 0.087 (`rel_improvement_rmse_h1`) | | h=3 | 1.140 (`rmse_naive_h3`) | 0.872 (`mae_naive_h3`) | 0.902 (`rmse_model_h3`) | 0.753 (`mae_model_h3`) | 0.208 (`rel_improvement_rmse_h3`) | - On both RMSE and MAE, the model beats the naive forecast at both horizons. The RMSE reduction is about 9 % at h=1 and 21 % at h=3. - **Employment is not what drives the gain.** The same regression without employment does slightly better: RMSE 0.715 at h=1 (`rmse_ablation_no_emp_h1`) and 0.864 at h=3 (`rmse_ablation_no_emp_h3`). The improvement over naive comes from the autoregressive mean reversion (constant plus a lag coefficient below 1), not from LFS employment growth. ## Uncertainty - The Diebold–Mariano test of equal squared-error accuracy (model vs naive) gives: - h=1: statistic 2.03, p = 0.048 (`dm_stat_h1`, `dm_pvalue_two_sided_h1`) - h=3: statistic 1.64, p = 0.108 (`dm_stat_h3`, `dm_pvalue_two_sided_h3`) - The evidence that the model beats naive is therefore borderline at h=1 and not significant at the 5 % level at h=3. - With only 48 overlapping, serially correlated errors over a single disinflation and slowdown episode (2022–2026), the RMSE estimates are imprecise. I computed no confidence intervals for the RMSEs themselves. - I did not test whether the employment-augmented model differs significantly from the no-employment ablation. ## Limitations and open issues - **Timing only, not real-time:** the data are the current vintage (revised). The exercise simulates publication timing but not the historical first-release values, so no real-time validity is claimed. Errors against first releases would probably be larger. - **COVID exclusion:** dropping 2020-03..2021-12 from estimation is a modelling choice. Other ways of handling that period (dummies, robust estimation) were not tried. - **Short evaluation window:** the 48 origins cover one macro episode, and the ranking of methods may not generalise. - **One specification:** only one model specification was evaluated, beyond the diagnostic ablation, and no model selection was done. - All parts of the task were completed (`feasibility` = "complete").