Skip to main content
Open llms.txtCopy tools

AutoForecaster

AutoForecaster is CartoBoost's guarded default forecasting model for demand panels. It is not a black-box hyperparameter search. The Python class normalizes user-facing configuration, fits a fixed candidate roster, validates members on trailing origins, gates fragile candidates, refits selected members, and records prediction metadata.

Use it when you want one reproducible default for panel demand forecasting and you still want to inspect which candidate models earned forecast weight.

Interactive Example

AutoForecaster panel forecast

Runs auto_forecast against a bundled multi-location demand panel sample.

Ready to run in this page.

Python Example

from cartoboost.forecasting import AutoForecaster, ForecastFrame

frame = ForecastFrame.from_pandas(
hourly_demand,
timestamp_col="timestamp",
target_col="demand",
series_id_col="series_id",
static_covariates=["region_id", "market_zone"],
freq="h",
)

model = AutoForecaster(
season_length=24,
validation_window=8,
validation_origin_count=2,
objective="rmse_wape",
rich_calendar_features=True,
)

forecast = model.fit(frame).predict(12)
metadata = model.metadata_

The prediction rows use the model name cartoboost_auto_forecast. fit requires a ForecastFrame; plain lists or arrays should use one of the local forecasters instead. predict(horizon) requires a positive integer horizon and returns the standard ForecastResult shape.

Important configuration behavior:

  • ForecastFrame.static_covariates are passed into the lag feature spine by default.
  • covariate_features=[] explicitly disables automatic static covariate use.
  • covariate_features=[...] overrides the frame static-covariate list.
  • known_future_covariates and historical_covariates remain part of the experiment contract but are not silently promoted into recursive lag features.
  • seed, quantiles, n_threads, and the wrapper's no-hyperopt policy are recorded for API consistency; the current auto path is deterministic and does not run stochastic tuning.

Fit Lifecycle

The model makes every selection from trailing rolling-origin validation, then refits only the selected members on the full frame.

Validation is time ordered. For each series, the model cuts one or more trailing windows from the end of the history. Each origin trains only on rows before the validation window and scores predictions against the held-out rows. If validation_window is omitted, the selector uses the shortest series history:

effective_validation_window = clamp(floor(min_series_history / 5), 1, 8)

If validation_window or validation_origin_count is too large to preserve the required training prefix, fitting fails with the feasible limit. Neither setting is silently capped. A configured zero is also rejected.

Candidate Roster

AutoForecaster scores a fixed internal roster. These candidate names appear in AutoForecaster metadata and artifacts; they are not standalone registry model names. The roster is deterministic, but some members are eligible only when the data support their assumptions.

CandidateWhat it representsEligibility
cartoboost_lagGlobal recursive CartoBoost lag model on levels.Always eligible.
recency_weighted_lagSame lag spine with exponential recency sample weights.Eligible only when a recent level shift is detected.
scaled_lagLag spine wrapped in local standard scaling.Always eligible.
delta_lagLag spine predicting change from the latest value.Always eligible.
scaled_delta_lagDelta lag wrapped in local standard scaling.Always eligible.
seasonal_delta_lagLag spine predicting change from the value one season ago.Eligible only when every validation-training prefix contains the configured season.
scaled_seasonal_delta_lagSeasonal delta lag wrapped in local standard scaling.Same complete-season requirement as seasonal_delta_lag.
ewm_lagLag spine with an extra 90% exponentially weighted mean feature.Always eligible as a candidate; user-provided EWM alphas also feed the lag config.
cartoboost_directHorizon-specific direct CartoBoost forecast model.Skipped when at least 25% of training targets are zero.
cartoboost_rectified_recursiveRecursive forecast with direct residual rectification; correction targets come from a trailing holdout forecast by a prefix-only baseline.Skipped when at least 25% of training targets are zero.
log1p_scaled_lagNonnegative log1p transform around scaled lag.Eligible only when all training targets are nonnegative.
lag_plusLag spine plus residual correction and seasonal bucket shrinkage.Requires a non-empty internal suffix holdout and a prefix that supports the effective lag config.
intermittent_demandSparse nonnegative demand methods for many-zero panels.Eligible only when all targets are nonnegative and at least 25% are zero.
classical_expert_bankNative bank over classical local forecasters.Always eligible.

Target-transform candidates retain historical and known covariates while transforming only the target. Local standard scaling maps point forecasts, intervals, additive corrections, and variances back to the original target scale. The log1p wrapper maps points and interval endpoints through expm1; because a nonlinear transform cannot exactly invert a variance without a full distribution, any inner-scale kriging variance remains explicitly labeled in forecast-detail metadata instead of being reported as an exact original-scale variance.

The recent-shift gate compares the latest window to the preceding window. The window length is the greater of season_length, validation_window, and 2, clamped to at most 28. A series counts as shifted when the absolute recent mean change is at least 35% of the combined local scale; the recency-weighted candidate is enabled when at least one quarter of eligible series are shifted.

Feature Spine

The default lag spine starts with:

Feature familyDefault values
Raw lags1, 2, 3, 7, 14, 28 plus configured season_length from the Python wrapper.
Rolling mean windows7, 14, 28 plus configured season_length from the Python wrapper.
Rolling standard deviation windows7, 14, 28 plus configured season_length.
Rolling min and max windows7, 14, 28 plus configured season_length.
Difference lags2, 3, 7, 14, 28 by default, or lag values greater than 1 when trend defaults are built from user lags.
Rolling trend windows7, 14, 28 by default, or rolling windows greater than 1 when trend defaults are built from user windows.
Calendar featuresDay of week, month, and day by default.
Rich calendar featuresOptional lower-cost yearly, elapsed, Fourier, and month-phase features.
Partial rolling meansEmpty by default; opt in with partial_rolling_mean_windows=[...].
EWM target meansEmpty by default; opt in with ewm_alpha_percents=[...], while the ewm_lag candidate adds 90.

Before validation scoring, the model expands the effective lag configuration with supported multiples of season_length. It adds season_length * 1 through season_length * 4 to lag, rolling, trend, and difference features only when the shortest prefix can support those windows after reserving the selector's holdout and any nested LagPlus or rectified-recursive holdout. The automatic model records this adaptation in effective_lag_config; explicit standalone lag models remain strict and do not remove requested features. The final effective lag config is sorted, deduplicated, and saved in metadata.

Scoring Objective

Each candidate is fitted on each validation split and predicts the validation horizon for that split. Predictions are clamped to zero before scoring when the entire training frame is nonnegative. Forecast metrics are computed first, then the configured objective value is extracted.

The default objective is rmse_wape, which blends normalized RMSE and WAPE so selection is sensitive to both scale-aware squared error and aggregate absolute error. Other objective strings such as rmse, mae, or wape can be used when that metric is the scientific target for the panel.

For each candidate, the scorer emits:

  • a global score across all validation predictions;
  • horizon scores for each validation horizon;
  • series scores for panel frames.

Scores from multiple trailing origins are averaged by candidate, metric, series, and horizon before gating.

Gating And Weight Selection

AutoForecaster does not simply pick the lowest validation error. It applies guardrails so small validation differences do not displace the stable lag baseline or create fragile blends.

Default guardrails:

SettingDefaultEffect
baseline_displacement_gain0.03A non-lag candidate must beat cartoboost_lag by at least 3% before it can displace the lag baseline.
hard_winner_relative_gain0.05If the best candidate beats the second-best by at least 5%, the best candidate receives all weight.
min_blend_weight0.15Close-race blends keep each selected candidate above this floor.
max_blend_weight0.85Close-race blends keep each selected candidate below this ceiling.
top_k2 internallyOnly the top two candidates participate in a close-race blend.

The same gating lookup is built at three levels:

  • weights: global weights from global validation scores;
  • horizon_weights: one weight map per validation horizon;
  • series_weights: one weight map per series when panel validation has enough points.

Series-specific weights are emitted only when validation_window * validation_origin_count >= 4. This avoids making series-level routing decisions from too little evidence.

Prediction Flow

After gating, the selector refits only the selected members on the full input frame. During predict, each selected member forecasts the requested horizon. The auto model checks that every member returns the same forecast index, then combines means with the most specific available weight.

Weight precedence is deliberate:

  1. Use series_weights when the current series has enough validation evidence.
  2. Otherwise use horizon_weights when the requested horizon was validated.
  3. Otherwise use global weights.

For horizons beyond the validation window, the model naturally falls back to global weights unless series weights are present.

Metadata To Inspect

model.metadata_ combines fitted selector metadata with Python configuration. The selector section records the fitted state:

metadata = model.metadata_

metadata["model"] # "cartoboost_auto_forecast"
metadata["weights"] # global selected-member weights
metadata["horizon_weights"] # per-horizon selected-member weights
metadata["series_weights"] # per-series selected-member weights
metadata["validation_scores"] # global, horizon, and series scores
metadata["effective_lag_config"] # lag feature config after expansion
metadata["members"] # fitted selected-member metadata
metadata["nonnegative_output"] # whether predictions are clamped
metadata["auto_forecaster"] # Python wrapper settings

For an auditable benchmark report, include the selected weights, validation scores, effective lag config, validation window, origin count, objective, target column, frequency, horizon, split definition, RMSE, MAE, WAPE, training time, and prediction time.

Configuration Reference

Python argumentDefaultNative effect
season_lengthNone, passed as 7 when omittedAdds seasonal lag/window candidates and configures seasonal-delta, lag-plus, classical-bank, and recency windows.
objective"rmse_wape"Metric used for candidate scoring and gating.
validation_windowNoneConfigured trailing validation window, or automatic window.
validation_origin_count2Number of trailing validation origins to average when history supports them.
baseline_displacement_gain0.03Required relative improvement over cartoboost_lag before baseline displacement.
hard_winner_relative_gain0.05Required best-vs-second relative improvement for single-winner routing.
min_blend_weight0.15Lower bound for close-race blend weights.
max_blend_weight0.85Upper bound for close-race blend weights.
max_direct_horizon28Full-frame refit horizon for direct and rectified-recursive members; validation scoring uses each split horizon.
covariate_featuresNoneNone uses frame static covariates; [] disables them; a list overrides them.
covariate_calendar_interactionsFalseAllows configured covariates to interact with calendar features in lag features.
rich_calendar_featuresFalseEnables the richer calendar feature set.
ewm_alpha_percents()Adds explicit EWM target-mean features to the lag config. Values must be unique integers in 1..=100.
partial_rolling_mean_windows()Adds partial rolling-mean windows. Values must be unique positive integers.
n_estimators, learning_rate, max_depth, min_samples_leaf, min_gain, split_policyBooster defaultsPassed into the typed CartoBoost booster config used by tree-based candidates.
target_mode"level"Base lag target mode before auto candidates add delta and seasonal-delta alternatives.

recursive=False is not supported for the current auto model.

Failure Modes

AutoForecaster fails instead of silently changing algorithms when:

  • fit receives anything other than a ForecastFrame;
  • validation_origin_count, validation_window, or max_direct_horizon are zero;
  • blend bounds are invalid;
  • no validation split can be built from the available history;
  • an eligible candidate fails to fit or produce its complete series-by-horizon validation output;
  • prediction is requested before fitting;
  • selected members return different forecast indexes.

Only documented eligibility rules omit a candidate before fitting. Once an eligible candidate run begins, its fitting, prediction, or index failure is reported and the selector stops; it is not reinterpreted as evidence for the remaining roster.

Use When

Use a simpler model when the scientific question requires a single interpretable assumption:

AutoForecaster is the right default when the study needs a reproducible, guarded hybrid and the metadata will be inspected as part of the evidence.

Validation

Evaluate the final selector on rolling origins that were not used for candidate weighting or gating. Report selected candidates, the validation objective, holdout RMSE/MAE/WAPE, per-horizon errors, fit and prediction time, and seasonal naive on the identical rows.

Limitations

  • Selection cannot rescue a roster that omits the relevant mechanism.
  • Short histories may not support internal selection plus an honest external holdout.
  • Selection metadata is part of the result; one aggregate score is insufficient for diagnosis.
  • Do not use automatic selection where a prespecified model policy must remain fixed.