SPB Git

spb/wp29_uqo

Public
8.1 KB · 46 lines markdown
1# Real-time forecasting of US retail-sales YoY growth from ALFRED vintages (T1-forecast)23## Question4Using only the data published at each of 10 month-end origins (2025-10-31 … 2026-07-31; `first_origin`, `last_origin`, `n_origins`), how accurately can the year-over-year growth g_m = 100·ln(L_m/L_{m−12}) of RSAFS (US retail and food services sales, SA) be forecast h = 1 and h = 3 months beyond the last published month last(V)? And does a model of my own design beat the naive no-change forecast when errors are measured against the first-release value of each target month?56## Data and exclusions7- Inputs (row counts in `n_input_rows`): 10 RSAFS and 10 PAYEMS ALFRED vintages, UMCSENT (current vintage), RSAFS current vintage, and `first_release.csv` (28 target months). All SHA-256 hashes match the README (see `out/state/data_audit.md`).8- **Real-time design.** The forecast made at origin V uses only `RSAFS_vintage_V.csv` (`vintage_used` = origin date for all 80 rows of `out/forecasts.csv`). The last published month last(V) was 2025-08, 2025-09, 2025-10, 2025-11, 2025-12, 2026-01, 2026-03, 2026-04, 2026-05, 2026-06 for the 10 origins in order (`supplementary.real_time_design`). Publication delays: the first six origins (2025-10-31 … 2026-03-31) end two calendar months before the origin month; the 2026-04-30 vintage adds two months at once (2026-02 and 2026-03), after which the lag is one month. Consequently the h = 1 targets are 2025-09 … 2026-02 and 2026-04 … 2026-07 (2026-03 is never an h = 1 target) and the h = 3 targets are 2025-11 … 2026-02, 2026-03, 2026-04, 2026-06 … 2026-09.9- Actuals are `yoy_first_release` from `first_release.csv`; all 20 targets are present, so the exclusion ledger (`out/exclusions.csv`) removes nothing: 20 pairs analysed for the model (`n_analysed`), 80 forecast rows overall.10- `RSAFS_current.csv` is used only for the revision estimand (d), after all forecasts are computed. PAYEMS and UMCSENT were read and audited but are not used by the chosen model.11- Data issues and their handling are listed in `data_issues` (irregular publication timing, simultaneous first release of 2026-02/2026-03, PAYEMS benchmark revision in the 2026-02-28 vintage, a large RSAFS benchmark level revision after the last origin, pre-1978 gaps in UMCSENT, COVID observations in the AR(1) sample).1213## Method14- Baselines, all from vintage V: **naive** g_{last(V)} for both horizons; **seasonal naive** g_{T−12}; **AR(1)** OLS of g_m on a constant and g_{m−1} for 1993-02 ≤ m ≤ last(V), iterated h steps.15- **My model (`model_name` = RW-drift-base-effect; full text in `model_description`).** A random walk with drift in log levels that is aware of base effects: ln L̂_T = ln L_{last} + h·δ with δ = average monthly log change over the 12 months ending at last(V); the YoY forecast is 100·ln(L̂_T / L_{T−12}), where the base level L_{T−12} is already published in the vintage. The idea: the change in YoY growth over the next h months equals the new monthly changes minus the monthly changes of the corresponding months a year earlier that drop out of the 12-month window. The second part is already known at the origin, and the naive forecast ignores it. The model has no estimated parameters. Its specification was fixed and logged (`out/state/log.md`) before any evaluation error was computed. Because nothing was selected on the evaluation sample, there is no look-ahead in model choice.16- Evaluation: RMSE and MAE over the 10 origins per horizon against first-release actuals. The Diebold–Mariano test uses d_t = e²_naive − e²_model and a Bartlett (Newey–West) long-run variance with truncation lag h − 1, without the HLN correction, with a two-sided N(0,1) p-value. Revision (d) is the mean over the 10 h = 1 targets of |g^current − g^first|. The script is deterministic (`random_seed` = null; no resampling is used).1718## Results19RMSE / MAE in percentage points (`out/table1.csv`; keys `rmse_<model>_h<h>`, `mae_<model>_h<h>`):2021| model | h=1 RMSE | h=1 MAE | h=3 RMSE | h=3 MAE |22|---|---|---|---|---|23| naive | 0.997 | 0.849 | 1.420 | 1.200 |24| seasonal naive | 1.675 | 1.307 | 1.316 | 1.066 |25| AR(1) | 0.941 | 0.798 | 1.187 | 0.953 |26| RW-drift-base-effect | 0.550 | 0.486 | 1.142 | 0.934 |2728- At h = 1 the model's RMSE is 45% below the naive forecast's (`rel_improvement_rmse_h1` = 0.448). Its squared error is lower at 8 of the 10 origins (`supplementary.n_origins_model_sqerr_lower_h1`). DM = 2.43, p = 0.015 (`dm_stat_h1`, `dm_pvalue_h1`), so `conclusion_code_h1` = model_better_significant.29- At h = 3 the improvement is 20% (`rel_improvement_rmse_h3` = 0.196), with lower squared error at 6 of 10 origins (`supplementary.n_origins_model_sqerr_lower_h3`). DM = 1.55, p = 0.122 (`dm_stat_h3`, `dm_pvalue_h3`), so `conclusion_code_h3` = model_better_not_significant.30- The model also has the lowest RMSE and MAE of all four methods at both horizons. The AR(1) beats the naive forecast only slightly (`rmse_ar1_h1`, `rmse_ar1_h3`). The seasonal naive forecast is the worst at h = 1 and second-best among the baselines at h = 3 (`rmse_snaive_h1`, `rmse_snaive_h3`).31- Revision: the first-release YoY growth of the 10 h = 1 target months differs from today's published growth by 0.548 pp on average in absolute value (`mean_abs_revision_h1_targets`). All of these revisions are downward: the signed mean is −0.548 (`supplementary.mean_revision_h1_targets_signed`). This revision is about the size of the model's h = 1 MAE (`mae_model_h1`), so evaluating against current data would give materially different error levels.32- Figure: `out/figure1.png` shows the first-release actuals and the naive and model forecasts by target month.3334## Uncertainty35- Only 10 origins are available per horizon, so the DM statistic's normal approximation is weak. The 10 origins also cover a single episode (a dip in growth around 2025-12 followed by a rise to about 6.5% in mid-2026).36- At h = 1 the evidence is moderately strong. The p-value is 0.015 (`dm_pvalue_h1`), and with the HLN small-sample correction and Student-t(9) reference it is 0.047 (`supplementary.dm_pvalue_hln_t_h1`, sensitivity only), just under 5%. So the h = 1 significance survives the small-sample correction, but only barely.37- At h = 3 the overlapping 3-step errors are serially correlated, and the long-run variance rests on only two autocovariance lags estimated from 10 points. The test does not reject (`dm_pvalue_h3` = 0.122; the HLN version gives 0.277, `supplementary.dm_pvalue_hln_t_h3`). The 20% RMSE gain at h = 3 is therefore not statistically distinguishable from zero.38- No bootstrap interval was computed: with 10 serially dependent pairs, a block bootstrap would add little information.3940## Limitations and open issues41- **Gate conflict (open issue).** The provided gate checks `origin_date < target_date` for every row of `out/forecasts.csv`. The 40 rows with h = 1 fail this check. This is not information leakage. Under the task's own definition, the target is last(V)+1 and `target_date` is the first day of that month. Because RSAFS is published with a 1–2 month lag, that date always lies before the month-end origin date. The real-time condition that matters, target month > last(V) (the target is not yet published in vintage V), holds for all 80 rows (`out/state/checks.md`). I kept the column exactly as TASK.md specifies rather than relabel dates. As a result, the latest gate receipt reports `passed: false` for this item only.42- Small evaluation sample (10 origins, one macro episode). The ranking could change over a different period.43- The model uses no external predictors (PAYEMS, UMCSENT). I did not test whether they would add information, and I make no claim about it.44- Actuals use the month-end "first release" definition of `first_release.csv`. The 2026-08 and 2026-09 targets (h = 3, last two origins) are first released after a large benchmark level revision. Growth rates are computed within a single vintage, which limits the effect, but those two actuals are on a revised basis.45- The AR(1) baseline is estimated on the full sample including the COVID swings, as prescribed. This probably biases its slope, but that is part of the baseline's definition.46
Files · 76f9a44a3a85fb2bc2b0b370a4ae4eed9b95e579
Menu

Theme