SPB Git

spb/wp29_uqo

Public

# F3-conf-03 — Rolling-origin ridge forecasts of US industrial production growth

# Question

Does a fixed-penalty ridge regression (λ = 50; lambda) on eight standardised predictors forecast next-month US industrial production growth (100 × Δln INDPRO) better than the naive (last value) forecast and the expanding historical mean? I evaluated this over 60 rolling origins (n_origins), from first_origin = 2021-09-01 to last_origin = 2026-08-01, at horizon h = 1. The estimands are each model's out-of-sample RMSE and MAE, and the ridge model's relative RMSE improvement over each baseline.

# Data and exclusions

The input is data/ip_predictors.csv: 417 rows (n_input_rows), monthly from 1992-01 to 2026-09. It is current-vintage FRED data, and its SHA-256 matches the README. There are no duplicate or missing months. The only empty cells are neworder_chg for 1992-01 and 1992-02. All data problems and how I handled them are listed in data_issues:

  • The README says the 1992-01 cells of every change series are empty. In the file, three of them (ip_growth, oil_chg, permit_chg) have values. I used the values as given.
  • The extreme COVID-19 months (2020-03 to 2020-06) are kept in every training window.
  • The data are revised (current vintage), and publication lags are ignored.

Exclusion ledger (out/exclusions.csv), counted at the last origin: start with 417 rows. Dropping months before 1992-03-01 (the training start set in the specification) leaves 415. Dropping months whose target would fall after the origin leaves 413 training rows (n_analysed).

# Method

  • Naive forecast: ip_growth at the origin t.
  • Mean forecast: the arithmetic mean of ip_growth from 1992-04 to t.
  • Ridge model: trained on rows s from 1992-03 to t−1, with target ip_growth at s+1.
    • Features (n_features = 8): ip_growth at s, s−1 and s−2, plus oil_chg, fedfunds, permit_chg, neworder_chg and tcu.
    • Each feature is standardised with the mean and the sample standard deviation (ddof = 1) of that origin's training rows. These statistics are recomputed at every origin (normalisation_window = "expanding").
    • The target is centred on its training mean ȳ, and b = (Z′Z + 50 I)⁻¹ Z′(y − ȳ). The intercept is not penalised.
    • Forecast = ȳ + z̃_t·b, where z̃_t is the origin's feature vector standardised with the same statistics.
  • Evaluation: errors are forecast − actual over the 60 target months, 2021-10 to 2026-09.
  • No randomness is involved (random_seed = null).

# Results

model RMSE (pp/month) MAE (pp/month)
naive 0.883 (rmse_naive) 0.699 (mae_naive)
expanding mean 0.544 (rmse_mean) 0.429 (mae_mean)
ridge λ=50 0.561 (rmse_ridge) 0.451 (mae_ridge)
  • Ridge vs naive: ridge reduces RMSE by 36.5% (rel_improvement_vs_naive = 0.365).
  • Ridge vs expanding mean: ridge does not beat the mean. Its RMSE is 3.1% higher (rel_improvement_vs_mean = −0.031), and its MAE is also higher (mae_ridge vs mae_mean).

The individual forecasts are in out/forecasts.csv: 180 rows, 60 per model.

# Uncertainty

I ran Diebold–Mariano tests on squared-error loss for h = 1, with the Harvey–Leybourne–Newbold correction and a t(59) reference distribution:

  • Ridge vs naive: DM = 3.36, p = 0.0014 (dm_stat_vs_naive, dm_pvalue_vs_naive). The ridge model's advantage over the naive forecast is statistically significant.
  • Ridge vs mean: DM = −0.54, p = 0.59 (dm_stat_vs_mean, dm_pvalue_vs_mean). The two forecasts' accuracy cannot be told apart statistically.

With only 60 forecast errors, the RMSE estimates are imprecise. I did not compute confidence intervals for the RMSEs themselves.

# Limitations and open issues

  • Not real-time: the data are current-vintage (revised) INDPRO, TCU and NEWORDER, and publication lags are ignored. These are pseudo-out-of-sample results, not real-time forecast performance.
  • Fixed specification: λ is fixed at 50 and not tuned, and the model is linear. Every training window includes the COVID-19 extremes, which may distort the coefficients. The specification defines the windows without exclusions, so I kept them.
  • Narrow evaluation: the window is short (60 months) and covers a single period, 2021–2026.
  • README discrepancy: the README's statement about empty 1992-01 cells does not match the file (see data_issues).
  • Feasibility: the task was completed in full (feasibility = "complete").
Files · 76f9a44a3a85fb2bc2b0b370a4ae4eed9b95e579
Menu

Theme