Real-time forecasting of US retail-sales YoY growth (T1-forecast)
Question
Could the year-over-year (YoY) growth of US retail and food services sales (RSAFS), g_m = 100·ln(L_m/L_{m−12}), have been forecast in real time 1 and 3 months beyond the last published month, using only data published at each of 10 month-end origins (2025-10-31 … 2026-07-31)? Does a simple model of my own design beat the no-change (naive) forecast when errors are measured against the first-release value of each target month? And how large are the revisions between first release and today's data for the h = 1 targets?
Data and exclusions
- Real-time design. The forecast made at origin V uses only
RSAFS_vintage_V.csv(ALFRED vintage dated V). The target at horizon h is last(V)+h, where last(V) is the last month in that vintage; the actual isyoy_first_releasefromfirst_release.csv.RSAFS_current.csvis used only for the revision estimand (d). PAYEMS and UMCSENT files were read and audited but do not enter the chosen model. - Vintage → targets (last month, h = 1 target, h = 3 target):
| origin V | last(V) | h=1 target | h=3 target |
|---|---|---|---|
| 2025-10-31 | 2025-08 | 2025-09 | 2025-11 |
| 2025-11-30 | 2025-09 | 2025-10 | 2025-12 |
| 2025-12-31 | 2025-10 | 2025-11 | 2026-01 |
| 2026-01-31 | 2025-11 | 2025-12 | 2026-02 |
| 2026-02-28 | 2025-12 | 2026-01 | 2026-03 |
| 2026-03-31 | 2026-01 | 2026-02 | 2026-04 |
| 2026-04-30 | 2026-03 | 2026-04 | 2026-06 |
| 2026-05-31 | 2026-04 | 2026-05 | 2026-07 |
| 2026-06-30 | 2026-05 | 2026-06 | 2026-08 |
| 2026-07-31 | 2026-06 | 2026-07 | 2026-09 |
- Publication delays observed. The vintages 2025-10-31 through 2026-03-31 all end two months before the origin month (instead of the normal one month), reflecting the delayed Census release calendar in late 2025/early 2026. The 2026-04-30 vintage catches up by adding two months (2026-02 and 2026-03) at once; therefore 2026-03 is never an h = 1 target and 2026-05 is never an h = 3 target, and targets are not equally spaced in time. PAYEMS vintages show similar irregularities (not used).
- Revisions. The current RSAFS file is 3.8–5.6 % lower in level than the first releases for 2024-06…2026-07 (a benchmark/annual revision first visible in the 2026-09-30 vintage); first-release YoY values are computed inside one vintage, so they are internally consistent, but YoY growth has been revised by up to 2.0 pp.
- Missing values. No missing values or gaps in any RSAFS/PAYEMS vintage or the current RSAFS file; UMCSENT is empty for 210 pre-1978 months (irrelevant here). No observations were excluded. All data issues are listed in
results.json → data_issues.
Method
- Baselines (from the vintage dated V): naive g_{last}; seasonal naive g_{T−12}; AR(1) by OLS of g_m on a constant and g_{m−1} for 1993-02 ≤ m ≤ last(V), re-estimated at every origin, iterated h steps.
- My model — "base-effect drift" (specified before looking at any evaluation result, no estimated parameters). YoY growth at T = last+h is ln L_T − ln L_{T−12}, and ln L_{T−12} is already published at the origin. I forecast ln L_T = ln L_last + h·μ with μ = (ln L_last − ln L_{last−12})/12, the trailing-12-month average monthly log growth. The forecast is 100·(ln L_last + h·μ − ln L_{T−12}) = naive + h·g_last/12 − 100·(ln L_{T−12} − ln L_{last−12}): the naive forecast corrected for the known base effects of the months that drop out of the 12-month window. It uses only the RSAFS vintage V.
- Evaluation. RMSE and MAE over the 10 origins per horizon against first-release YoY. Diebold–Mariano (model vs naive, squared loss): d_t = e²_naive − e²_model, Bartlett/Newey–West long-run variance with truncation lag h−1, no small-sample correction, two-sided normal p-value. Supplementary: Harvey–Leybourne–Newbold-corrected DM with t(9) reference, and a moving-block bootstrap (block length 3, 10 000 draws, seed 20261030) of RMSE_naive − RMSE_model.
- Revision estimand (d). Mean over the 10 h = 1 targets of |g^current_T − yoy_first_release_T|.
Results
Table 1 (out/table1.csv), percent points of YoY growth, n = 10 per cell:
| model | RMSE h=1 | MAE h=1 | RMSE h=3 | MAE h=3 |
|---|---|---|---|---|
| naive | 0.997 | 0.849 | 1.420 | 1.200 |
| seasonal naive | 1.675 | 1.307 | 1.316 | 1.066 |
| AR(1) | 0.941 | 0.798 | 1.187 | 0.953 |
| base-effect drift (model) | 0.550 | 0.486 | 1.142 | 0.934 |
- Relative RMSE improvement over naive: 44.8 % at h = 1, 19.6 % at h = 3.
- DM (model vs naive): h = 1 stat 2.43, p = 0.015 →
model_better_significant; h = 3 stat 1.55, p = 0.122 →model_better_not_significant. - The model has the lowest RMSE and MAE among all four forecasts at both horizons; AR(1) is only marginally better than naive at h = 1, and the seasonal naive is the worst at h = 1.
- Mean absolute revision of first-release YoY for the h = 1 targets: 0.548 pp (range 0.17–0.98 pp), i.e. about the same size as the h = 1 model RMSE: today's data differ from the first release by as much as the best real-time forecast does.
- Figure 1 (
out/figure1.png) shows actuals and naive, AR(1) and model forecasts. The model's largest h = 1 miss is 2026-07 (first-release YoY dropped to 4.9 % from 6.5 %; error −1.11 pp), while the naive forecast's largest miss is 2026-05 (+1.89 pp, the surge to 6.65 %); at h = 3 the model, like the naive forecast, under-predicted the 2026-06 surge (actual 6.50 %, model 4.91 %, naive 3.89 %) and under-predicted the 2026-03 and 2026-04 targets by more than naive (errors +1.59 and +2.37 pp vs +1.49 and +1.65 pp).
Uncertainty
With only 10 origins, inference is fragile. At h = 1 the DM test rejects equal accuracy at 5 % (p = 0.015); the HLN small-sample correction with a t(9) reference gives p = 0.047, just under 5 %; the model beats naive in 8 of 10 origins and the block-bootstrap 95 % interval of RMSE_naive − RMSE_model is [0.29, 0.67] pp (excluding zero). So the h = 1 gain is reasonably convincing, but it rests on 10 points from a period dominated by publication disruptions and should be read as indicative. At h = 3 the point gain (0.28 pp RMSE) is not significant (DM p = 0.12; HLN p = 0.28; bootstrap interval [−0.14, 0.63]; model wins 6 of 10). In addition, h = 3 errors overlap across origins, and a lag-2 Bartlett long-run variance estimated from 10 observations is itself very noisy; the asymptotic normal reference is unreliable at this sample size. The bootstrap with overlapping blocks of 3 out of 10 observations is also only a rough guide.
Limitations and open issues
- 10 origins in one unusual period (delayed releases, catch-up vintage, a large benchmark revision just after the sample); results may not generalise.
- The model was fixed a priori and not tuned, but it is the only model of my own I evaluated; PAYEMS and UMCSENT were not tested as predictors, so the question of whether they add information remains open.
- "First release" is defined at month-end granularity by the task designer; for 2026-02/2026-03 the first observable value came in the same catch-up vintage.
- The revision estimand compares with a current vintage that includes a level-shifting benchmark revision; future revisions may change it further.
- The DM test is reported exactly as specified (no HLN factor); supplementary corrected statistics are in
results.json → supplementary.