mixle.inference.price_forecast module¶
forecast_price – commodity-price / cost forecasting with horizon-matched conformal intervals.
Wraps the generic HMM front door (mixle.inference.forecast.forecast()) with a
recalibration pass so each reported [lo, hi] lead uses held-out residuals from that same lead:
pf = forecast_price(model, price_history, horizon=12, level=0.9)
pf.mean, pf.lo, pf.hi # (horizon,) point forecast + calibrated band
pf.paths # (horizon, n) Monte-Carlo scenario draws for downstream DCF (J2)
The forecast itself is exact where the model is exact (HMM state marginals p_T A^h) and
Monte-Carlo only where it has to be (emission quantiles for arbitrary, possibly skewed or
multimodal, price/cost emission families) – see mixle.inference.forecast. What this module
adds is the recalibration: reserve the most recent cal_frac of history and, within that
window, run a rolling-origin backtest of the SAME horizon-step-ahead point forecast the caller
is about to receive, scoring each origin’s forecast against what actually happened. That gives a
sample of real horizon-step-ahead residuals at the depth that matters (rather than mixing in
easier short-horizon or harder long-horizon errors), which recalibrates the requested band via
split conformal (mixle.inference.conformal.split_conformal()). This is what makes the band
eligible for marginal coverage under the usual held-out exchangeability assumption. Time-series
dependence or distribution shift can violate that assumption, so the result records the calibration
count and assumptions rather than claiming unconditional real-world coverage.
- class PriceForecast(mean, lo, hi, paths, level, calibration_count=0, interval_method='horizon_matched_split_conformal', coverage_assumptions=('held_out_exchangeability', 'stable_data_generating_process'), model_fit_length=0)[source]
Bases:
NamedTupleA price/cost forecast with a horizon-matched interval calibration receipt.
- Parameters:
- mean: ndarray
Alias for field number 0
- lo: ndarray
Alias for field number 1
- hi: ndarray
Alias for field number 2
- paths: ndarray
Alias for field number 3
- level: float
Alias for field number 4
- calibration_count: int
Alias for field number 5
- interval_method: str
Alias for field number 6
- model_fit_length: int
Alias for field number 8
- forecast_price(model, history, horizon, *, level=0.9, cal_frac=0.3, seed=0, model_fit_length=None)[source]
Forecast
horizonsteps of a price/cost series with a conformally-calibrated band.- Parameters:
model (Any) – a fitted
HiddenMarkovModelDistributionover the price/cost series (any scalar emission family with a sampler – seemixle.inference.forecast.forecast()).history (Any) – the observed series to condition on (one sequence, oldest first).
horizon (int) – number of future steps to forecast.
level (float) – central-interval mass (
0.9-> the calibrated 5%..95% band).cal_frac (float) – the fraction of
history(most recent) reserved for calibration. Within that reserved window, a rolling-origin backtest of the samehorizon-step-ahead forecast is scored against the real outcomes to build the calibration residuals.seed (int) – reproducibility for the calibration and requested-horizon Monte Carlo draws.
model_fit_length (int | None) – REQUIRED DECLARATION (STAT-RR17-06) – how many leading observations of
historythe fittedmodelconsumed (0when it was built from prior knowledge or other data;len(history)when it was fitted on everything). The rolling-origin calibration reuses the model at every pseudo-origin without refitting, so when the model was fitted through ANY calibration-window outcome the residuals are partly in-sample and the band is optimistic: the receipt’sinterval_methodandcoverage_assumptionsthen disclose exactly that instead of claiming a held-out guarantee (a spy measured a first origin at 13 with a model fitted through 19 – six future outcomes exposed). The clean alternative is refitting per origin, which this API deliberately does not fake by silently truncating your model.
- Returns:
A
PriceForecastwith the calibrated(lo, hi)intervals, the point forecastmean, the raw per-step predictive drawspaths(for Monte-Carlo DCF scenario analysis downstream), andlevel.- Return type:
PriceForecast
What
(lo, hi)is: one MARGINAL interval PER LEAD, each with coverage AT LEASTlevelat its own horizon depth – NOT a simultaneous band, and not exact: split conformal is a lower-bound guarantee, so each lead can be conservative. Whole-path coverage is therefore NOT controlled in either direction by the per-lead guarantee: independent misses at exactly nominal would compound towardlevel**horizon, while conservative, strongly dependent leads can push joint coverage ABOVElevel(an earlier version of this text said joint coverage “never exceeds” the requested level, which is false for a lower-bound guarantee – STAT-RR21-13). A plotted “tube” must not be read as containing the path withlevelprobability in either direction; for path-level statements, work frompathsdirectly.Read
calibration_countbefore trusting the exact level. At the defaults the reserved window yields on the order of 20 residuals per lead; split conformal’s finite-sample quantile moves in steps of1/(n_cal + 1), so small counts make the interval coarse and typically conservative – and consecutive rolling origins are one step apart, so theirhorizon-step windows OVERLAP and the residuals are serially dependent: the exchangeability behind the conformal guarantee holds only approximately across overlapping origins. More history (or a largercal_frac) buys both more residuals and less overlap distortion.