Time SeriesGENERALTASK-SPECIFICCONTESTED

The Forecast Horizon

One step ahead and twelve steps ahead are different problems with different errors. Direct and recursive strategies trade compounding error against training cost — and the horizon that matters is the one the decision needs.

Target & dataWhat to measureWhat must stay true

The problem, the obvious approach, and why it breaks

Every lesson starts where the work starts: someone has a problem, and the first model that comes to mind looks fine offline.

The question

How far ahead does the decision need a forecast, how should a model produce a multi-step forecast, and how does error grow with distance from the origin?

The problem

A warehouse operations lead wants to stop over-staffing. They asked for an hourly forecast of inbound parcels for the next two weeks. The model's next-hour forecast is excellent, its two-week-ahead forecast is noise, and the rota is set weekly on Friday for the following week.

The obvious approach

Train a one-step-ahead model — next hour from the last 168 hours — and roll it forward: feed its own forecast back in as the newest lag, predict the next hour, repeat 336 times. One model, any horizon.

Why it breaks

By hour 40 the recursive forecast is being fed forty of its own predictions as lags. Each carries the previous error, and the errors compound; by day three the forecast has drifted toward the mean and the daily cycle has flattened out.

How it breaks — usually after the offline metric looked fine
  • By hour 40 the recursive forecast is being fed forty of its own predictions as lags. Each carries the previous error, and the errors compound; by day three the forecast has drifted toward the mean and the daily cycle has flattened out.
  • The one-step model was validated one step ahead, where lag-1 does most of the work. At horizon 72 lag-1 is a forecast of a forecast, and the model that was excellent at one step has no idea it is being asked a different question.
  • The hourly two-week curve has an honest interval wider than the rota's shift sizes. The lead reads the point forecast and plans against it; the interval is the only true part.
  • The rota needs per-shift totals for days three to nine. The model spent its capacity on hour-level accuracy at horizons the decision does not use, and its error at the horizons the decision does use was never reported.
ProblemTargetDataRepresentationSplitModelTrainingEvaluationValidationDeploymentInferenceMonitoringDriftRetraining

What is being predicted, and from what data

This domain leads with these two. A target nobody defined precisely is a label nobody can trust, and a dataset nobody can describe is a model nobody can debug.

Target
  • Predict inbound parcel volume per hour for each hour of the next fourteen days. The label is the scanned count at the inbound dock.
  • The decision is the weekly rota: how many people per shift, set on Friday for Monday to Sunday. It needs a per-shift total for days three to nine from the origin, not an hourly curve for fourteen days.
Data
  • Two years of hourly scan counts, with strong daily and weekly cycles, a pre-holiday surge, and a dependence on upstream carrier schedules that are known a few days ahead.
  • A per-shift aggregate at lower resolution, which is what the rota actually consumes.

How it actually works

Precisely enough to predict its behaviour — not a framework API.

  • The horizon h is the distance from the origin to the target. A one-step model predicts y[t+1] from history to t. A multi-step forecast needs y[t+1..t+H], and there are three ways to get it.
  • Recursive: one one-step model, applied H times, feeding its own outputs back as lags. One model to train; errors compound because each step's input contains the previous step's error, and the model was never trained on inputs that were its own forecasts. Direct: H separate models, the h-th trained to predict y[t+h] from history to t. No compounding, each horizon judged on its own; H times the training cost and no guarantee the H forecasts are consistent with each other. Multi-output: one model that emits all H values at once; a middle path, natural for networks, harder for tree models.
  • Error grows with horizon for every strategy, because the future is genuinely less known. What differs is the shape: recursive error grows faster and the forecast collapses toward the unconditional mean; direct error grows with the true uncertainty and stays seasonal. The interval should widen with h under all of them, and a model whose interval does not is lying.

How error grows

At one step ahead the strongest feature is the last observation, and the model is mostly persistence plus a seasonal correction. At seventy-two steps the last observation is three days old and the model's forecast depends on the daily and weekly shape it learned, plus whatever covariates are known that far ahead. The uncertainty is larger because the future is less determined, and that growth is real and should show in the interval.

A recursive forecast adds a second growth on top: each step's input includes the previous step's error. The model was trained on true lags and is being fed forecast lags, which are smoother and biased toward the mean. By day three the recursive curve has flattened toward the average and its daily cycle has damped — not because the series does that, but because the errors do.

StrategyModels to trainError growth with hConsistency across hWhen it fits
RecursiveOne (one-step)Compounds — feeds its own errors back; collapses toward the meanConsistent by constructionShort horizons; series with strong persistence; when training cost dominates
DirectOne per horizonGrows with true uncertainty only; stays seasonalNo guarantee — adjacent horizons can disagreeThe decision reads specific horizons; compounding is visible; covariates differ by horizon
Multi-outputOne (H outputs)Grows with true uncertainty; outputs share structureConsistent — one model, one passLong dense series; networks; enough data for a joint fit

Direct models, one per horizon that matters

The rota reads days three to nine. Train seven models, one per day, each predicting that day's per-shift total from history to the Friday origin and from whatever covariates are known at the origin for that day. Each is evaluated on its own horizon against the seasonal naive at that horizon.

The covariate rule is the subtle part. A carrier schedule published three days ahead is known at the origin for days one to three and not for day four onward. The day-seven model must be trained without it, or it will be trained on a feature production cannot supply (Feature Freshness).

Direct multi-horizon targets with horizon-aware covariates
1def build_direct_rows(series, origins, horizons, covariate_lead_days):
2 """One training row per (origin, horizon). Features read history <= origin;
3 a covariate is included only if it is known covariate_lead_days before target."""
4 rows = []
5 for t in origins: # every Friday in the training range
6 hist = series[series.ts <= t]
7 base = {
8 "lag_7d_total": hist.y.values[-7:].sum(),
9 "lag_14d_total": hist.y.values[-14:].sum(),
10 "dow_shape": hist.y.values[-28:].reshape(4, 7).mean(axis=0).tolist(),
11 }
12 for h in horizons: # 3..9 — the days the rota reads
13 target_day = t + h
14 row = dict(base, horizon=h, dow=target_day.dayofweek)
15 if h <= covariate_lead_days: # schedule known 3 days ahead
16 row["carrier_planned"] = schedule_as_of(t, target_day)
17 row["y"] = series.loc[series.ts == target_day, "y"].item()
18 rows.append(row)
19 return rows
20
21# then: one model per h, or one model with h as a feature — either way,
22# score each h separately against seasonal_naive(series, t, h)

schedule_as_of(t, target_day) reads the schedule as it was published at the origin, not the final one. A schedule table without an as-of dimension cannot answer that question, and the feature is then a leak at every horizon the schedule was revised for.

The horizon the decision needs

The request was hourly for two weeks. The decision was per-shift for days three to nine. Everything outside that window is capacity the model spent on nothing, and everything inside it was reported as part of a pooled number that mostly measured the next-hour forecast. The first question in a forecasting project is what the decision reads, and it changes the target, the resolution, the strategy and the evaluation.

A seven-day stock order does not need an hourly forecast. A rota set on Friday does not need Saturday's forecast for tomorrow. A trading system does not need day nine. Naming the horizon is not a modelling detail; it is the formulation, and a model tuned for the wrong horizon is a precise answer to a question nobody asked.

Which horizon, which resolution, which strategy

What does the decision actually read from the forecast?

A weekly order or rota set days ahead

when The decision reads a coarse total over a window that starts a few days out. Forecast at that resolution, direct models for those horizons, evaluate each against seasonal naive.

cost Several models to train and keep consistent; the near-horizon signal is deliberately discarded.

A real-time control or alert

when The decision reads the next step and nothing else. A one-step model, validated one step ahead, is the whole problem; multi-step strategy is irrelevant.

cost The model must be fast and the features fresh; nothing far-horizon is learned, which is fine.

A board-level plan months out

when The decision reads a few far horizons at monthly resolution. The interval matters more than the point; a classical model with explicit trend and an honest band is usually right.

cost The far horizon is dominated by regime assumptions (Trend and Seasonality); the model cannot narrow it, and pretending otherwise is the failure.

Everything at every resolution

when Nobody has asked what the decision reads. Do not build this; go and ask.

cost Capacity spent on horizons nobody uses, a pooled metric that describes none of them, and a rota planned against noise.

How to build it

Most important first.

  • Start from the decision. Which horizons does it read, at what resolution, with what lead time? The rota reads per-shift totals for days three to nine. That is the target; hourly for fourteen days is a target nobody asked for (Decision Before Model).
  • Forecast at the resolution the decision consumes, or aggregate before evaluating. A per-shift forecast is a smaller problem with less noise than an hourly one summed, and it is what the rota needs.
  • Use direct models for the horizons that matter when compounding is visible in the recursive forecast, and evaluate each horizon separately (Forecast Evaluation). Report error per horizon; a single number over all horizons hides where the model stops being useful.
  • Give the model the covariates that are known at the horizon — carrier schedules published three days ahead are a feature for horizons up to three days and not beyond. A feature's availability depends on h.

What to measure

Which number actually maps to the decision — and which numbers look relevant and are not.

  • Error per horizon, for the horizons the decision reads, at the resolution it reads them, relative to the seasonal naive at the same horizon. This is the number that says whether the model helps the rota.
  • Coverage of the forecast interval per horizon: does the true value fall inside the stated band as often as the band claims? A band that is right at h=1 and wrong at h=72 is a model that does not know its horizon.
  • Do not measure a single pooled error across all 336 hourly horizons. It averages the one-step number that does not matter with the ten-day number that does, and the result describes neither.

What must stay true after deployment

The field this whole domain exists for. A model is a set of assumptions with weights attached; these are the ones a monitor or a test should be checking.

Assumptions
  • The lead time between the origin and the decision is what training assumed — the Friday origin with Monday to Sunday targets — and a change in when the rota is set changes which horizons matter.
  • Every covariate used at horizon h is genuinely known at the origin for that h; a schedule that is sometimes published late makes the feature intermittently unavailable at exactly the horizons it was most useful for.
  • The relationship between the near horizon and the far one — the daily and weekly shape — persists, so a direct model for day nine trained on last year's shape is forecasting this year's.
How to verify — offline, online, and over time
  • Offline: rolling-origin evaluation with the origin on each Friday, scoring per-shift totals for days three to nine against seasonal naive, per horizon, over the last year of Fridays.
  • Online: for each week's rota, log the forecast per shift with its interval and compare to the scanned count when it arrives; track coverage per horizon week by week.
  • Over time: if the near-horizon error stays flat and the far-horizon error grows, the seasonal shape is changing and the far-horizon models are stale first — they see the change last.

What can go wrong

Failure modes in production
  • The direct model for horizon seven is trained on carrier schedules that are only published three days ahead; in production the feature is missing at that horizon and the serving path fills it with zero (Missing Data).
  • The H direct models are retrained on different schedules; the day-three and day-four forecasts come from models trained on different data and the forecast has a step between them.
  • The forecast is aggregated to shifts after being produced hourly, and the hourly interval is summed as if the hours were independent, giving a shift interval far narrower than the truth.
What the recommended approach costs
  • Direct models multiply training and serving cost by the number of horizons and can produce forecasts that disagree with each other; recursive is cheap and consistent and compounds its errors.
  • Forecasting at shift resolution throws away the hourly signal the data has; it also throws away hourly noise the decision never needed.
  • Reporting per horizon makes the far-horizon numbers visible, which is uncomfortable and is the point.
Misreads
  • "The model is accurate — look at the next-hour error." Next-hour error is mostly persistence and the decision never reads it. The relevant number is at day five, and it was never reported.
  • "A longer horizon just needs more data." More history sharpens the near horizon. The far horizon is limited by how much the future genuinely depends on the past, and no amount of data changes that; the honest response is a wider interval.
  • "We should forecast hourly so we can aggregate however we like later." Aggregating hourly point forecasts is fine; aggregating their intervals is not, and the hourly model spent its capacity on structure the decision does not use.

Where this applies

ML advice is stated as universal far more often than it is. These labels say what each claim is specific to — and where CONTESTED appears, the note gives the strongest form of the opposing view.

  • GENERALThat error grows with horizon, that recursive forecasts compound error, and that the decision defines the horizon apply to every series and model family; the size of the effects depends on how much the series depends on its own past.
  • TASK-SPECIFICA staffing or ordering decision reads a few specific horizons at coarse resolution; a real-time control or trading decision reads the one-step forecast almost exclusively, and for it the recursive-versus-direct question is moot and the near-horizon number is the right one.
  • CONTESTEDA reasonable position holds that a single multi-output model — a network emitting the whole horizon — dominates both recursive and direct strategies, avoiding compounding without training H separate models. On long dense series with enough data that is often true; the reply is that on short or sparse series it underfits every horizon at once, and that H direct boosted models on lag features remain a strong and legible default.

Where the depth lives

This domain teaches the model and hands the rest off by name.

Data Engineeringtumbling-windowsgrain
Observability & Performancecapacity-planning