SPB Git

spb/wp29_uqo

Public

# F3-conf-01 — Forecasting Canadian monthly GDP y/y growth under publication lags

# Question

At the end of each month t (48 origins, 2022-05 to 2026-04), how well can y/y growth of Canadian monthly real GDP at t+1 and t+3 be forecast from what is published at that time? And does a model that adds the more timely LFS employment growth beat the naive forecast (the latest published GDP growth, month t−2)?

# Data and exclusions

  • data/canada_gdp_employment.csv: 345 rows (1998-01 to 2026-09). GDP is available to 2026-07 and employment to 2026-09. There are no gaps and no duplicate months. The gdp_yoy/emp_yoy columns match the level columns to within rounding (max abs diff ≈ 5e-5).
  • Information rule, applied by masking: at origin t, GDP is used only for months ≤ t−2 and employment only for months ≤ t−1. The ledger (out/forecasts.csv, 192 rows) records the last GDP and employment month used by every forecast. I checked these columns in code: none goes past the rule. At the last origin (2026-04-01) the latest available GDP month is 2026-02 and the latest available employment month is 2026-03.
  • Exclusion (model estimation only): I dropped training rows whose target or regressor month falls between 2020-03 and 2021-12, because COVID-period swings (GDP y/y ranged from −16.2% to +18.5%) would dominate OLS. This choice relies only on information that was already available at every origin (all origins are 2022-05 or later). The naive forecast and the evaluation sample (targets 2022-06 to 2026-07) are not affected.
  • The data are the current vintage. The exercise simulates publication timing only, not first-release values, so no real-time validity is claimed.

# Method

  • Naive: ŷ(t+h) = gdp_yoy(t−2) for h = 1 and h = 3.
  • Model ardl_emp_direct: a separate direct OLS for each horizon, gdp_yoy(s) = a + b·gdp_yoy(s−h−2) + c·emp_yoy(s−h−1). The window expands from 1998 and includes only targets s ≤ t−2, so every training target is observed at the origin. The model is re-estimated at each origin. The forecast plugs in gdp_yoy(t−2) and emp_yoy(t−1). The lag gaps used in estimation are the same as the publication gaps at forecast time.
  • Metrics: RMSE and MAE over the 48 origins per horizon, and relative improvement 1 − RMSE_model/RMSE_naive. As a supplementary check I ran a Diebold–Mariano test (squared loss, HAC with h−1 lags, Harvey small-sample correction, t(47) reference). There is no randomness (random_seed = null). At the last origin the training sample has 310 rows for h=1 and 306 for h=3.

# Results (percentage points)

RMSE naive RMSE model MAE naive MAE model 1 − RMSE ratio
h=1 0.814 0.743 0.642 0.604 0.087
h=3 1.140 0.902 0.872 0.753 0.208

The employment-augmented model beats the naive forecast at both horizons on RMSE and MAE: by about 9% in RMSE at h=1 and about 21% at h=3.

# Uncertainty

  • Diebold–Mariano test of equal squared loss: at h=1, DM = −2.03, p ≈ 0.048; at h=3, DM = −1.65, p ≈ 0.105. The h=1 gain is borderline significant at 5%. The larger h=3 gain is not significant, partly because overlapping 3-step errors are autocorrelated and there are only 48 origins.
  • Both methods over-predict on average over the evaluation period: mean error is about +0.30 (naive) and +0.33 (model) at h=1, and +0.46 / +0.47 at h=3. This reflects the post-2022 slowdown in growth. Most of the model's gain comes from lower error variance, not lower bias.
  • Results come from one 4-year evaluation window and may not carry over to other periods.

# Limitations and open issues

  • Current-vintage data: GDP and LFS revisions mean that real-time accuracy would probably be worse than shown, and the ranking could change.
  • I specified one model ex ante and did not search over alternatives. I did not run a sensitivity check with the COVID rows kept in the training sample.
  • The COVID exclusion window (2020-03 to 2021-12) is a judgement call.
  • The y/y target overlaps month to month, so the 48 errors are strongly dependent. The effective sample is much smaller than 48.
Files · main
Menu

Theme