SPB Git

spb/wp29_uqo

Public

# F3-dev-01 — Rolling-origin forecasts of the US unemployment rate: AR(2) on differences vs naive

# Question

Over the 36 expanding-window forecast origins 2023-07-01 … 2026-06-01 (n_origins, first_origin, last_origin), does a simple autoregressive model forecast the US civilian unemployment rate (FRED UNRATE, SA, %) better than the naive no-change forecast at horizons of 1 and 3 months? Estimands: out-of-sample RMSE and MAE (percentage points) of both forecasts and the relative RMSE improvement 1 − RMSE_model/RMSE_naive per horizon.

# Data and exclusions

  • data/UNRATE.csv, 945 data rows (n_input_rows), 1948-01 to 2026-09, SHA-256 matching the README; no duplicate or skipped months (see out/state/data_audit.md).
  • One missing value: 2025-10-01 (listed in data_issues). How it was handled: (i) at origin 2025-10-01 the naive forecast is the 2025-09 value, and the AR forecast is iterated from 2025-09; (ii) the pairs (origin 2025-09, h=1) and (origin 2025-07, h=3) have no actual. They stay in out/forecasts.csv with an empty actual and are excluded from the error statistics. So n_evaluated_h1 = 35 and n_evaluated_h3 = 35; (iii) in later training windows, regression rows that touch the missing month are dropped. The forecasting state uses linear interpolation between observations dated ≤ origin.
  • Exclusion ledger (out/exclusions.csv, last training window): 945 rows → drop 1 missing → drop 3 observations dated after the last origin (used only as actuals) → 941 = n_analysed. The AR regression in the last window uses 935 rows (n_regression_rows_last_window), because differencing, the two lags and the missing month each cost rows.
  • The COVID spike (2020-04: 14.8%) is kept as genuine data in every training window.

# Method

  • Naive: the forecast at every horizon is the latest observation dated ≤ origin.
  • Model AR2_diff (model_name, model_description): AR(2) with intercept on monthly first differences, estimated by OLS on an expanding window that starts in 1948-01 and is re-estimated at every origin. Level forecasts come from iterating the difference recursion h steps ahead (plus one extra step at the origin with the missing value). I fixed the specification before looking at any evaluation errors. No model selection was done, so selection cannot leak test information.
  • Information rule: at every origin the code keeps only observations dated ≤ origin, before any estimation or transformation. A leakage test supports this: I set all values after 2024-12 to 9.9 in a temporary copy of the data, and the forecasts for origins ≤ 2024-12 did not change (out/state/checks.md).
  • Errors: actual − forecast on the final-vintage data, over pairs with a non-missing actual. The method is deterministic, so no random seed is used (random_seed = null).

# Results

horizon n evaluated RMSE naive RMSE AR2_diff MAE naive MAE AR2_diff 1 − RMSE ratio
h=1 35 (n_evaluated_h1) 0.1171 (rmse_naive_h1) 0.1199 (rmse_model_h1) 0.0914 (mae_naive_h1) 0.0957 (mae_model_h1) −0.0235 (rel_improvement_rmse_h1)
h=3 35 (n_evaluated_h3) 0.1586 (rmse_naive_h3) 0.1598 (rmse_model_h3) 0.1200 (mae_naive_h3) 0.1213 (mae_model_h3) −0.0076 (rel_improvement_rmse_h3)

The AR(2)-on-differences model does not beat the naive forecast at either horizon. Its RMSE is about 2.3% higher at h=1 and 0.8% higher at h=3, and its MAE is also slightly higher at both horizons. In the last window the estimated coefficients are close to zero (intercept ≈ 0.0003, lag coefficients ≈ 0.04 and −0.04; recorded in out/state/log.md, not a results key). So the model behaves almost like a random walk, and its forecasts differ from the naive ones by only a few hundredths of a point.

# Uncertainty

  • Diebold–Mariano test of equal squared-error loss (model minus naive), with the Harvey–Leybourne–Newbold small-sample correction, a rectangular HAC variance with h−1 lags, and t(n−1) reference:
    • h=1: mean loss difference 0.00065 (mean_loss_diff_h1), DM = 2.50 (dm_stat_h1), p = 0.017 (dm_pvalue_h1). At the 5% level the model is significantly worse than naive, but the difference in magnitude is tiny.
    • h=3: mean loss difference 0.00038 (mean_loss_diff_h3), DM = 1.36 (dm_stat_h3), p = 0.18 (dm_pvalue_h3). The difference is not significant.
  • With only 35 evaluated pairs per horizon, overlapping h=3 errors and a calm sample period (UNRATE stayed between 3.5% and 4.5% from 2023-07 to 2026-09; descriptive check recorded in out/state/checks.md, not a results key), these comparisons have little power and depend on the period chosen. They should not be generalised to other periods.

# Limitations and open issues

  • Final vintage: the errors are computed on revised data. This measures how forecastable the revised series is, not real-time accuracy, and no real-time validity is claimed.
  • I evaluated only one model specification, chosen a priori. Other specifications (e.g. a shorter estimation window, or treating the COVID observations as outliers) might do differently. They were deliberately not tried, to avoid choosing a specification on the test errors. The 2020 spike probably pushes the full-sample AR coefficients towards zero.
  • The handling of the 2025-10 gap (interpolating the forecasting state, dropping regression rows) is a documented choice. It affects only a few origins.
  • The DM test with n = 35 and a HAC variance is approximate.
Files · main
Menu

Theme