mixle.inference.forecast module

forecast – horizon predictions with MODEL-PREDICTIVE Monte Carlo intervals from a fitted sequence model.

The intervals are quantiles of the FITTED MODEL’s own predictive distribution – no held-out calibration is performed here and no coverage-against-reality claim is made (STAT-P20-04): if the model is wrong, the intervals are wrong with it. For bands recalibrated against held-out outcomes, use mixle.inference.price_forecast.forecast_price(), whose receipt states its assumptions.

The forecasting front door for state-space families. For a fitted HMM: filter the history to the current state posterior (the forward-backward’s final step), propagate it through the transition matrix, and at each horizon step draw from the exact predictive mixture over states — so the mean, the central interval, and the per-step state probabilities all come from the model itself, for ANY emission family with a sampler (Gaussian, Gamma, categorical, wrapped, neural, …):

f = forecast(hmm, history, horizon=12, level=0.9)
f.mean, f.lo, f.hi          # (H,) arrays (or lists for non-scalar emissions)
f.state_probs               # (H, S): where the chain is expected to be at each step

Sampling-based on purpose: exact for the state marginals (p_T A^h); the per-step means AND the emission quantiles are Monte Carlo from n draws (STAT-RR17-10 – the mean was previously described as exact while being computed from draws), so the intervals reflect arbitrary (skewed / multimodal / discrete) emission families rather than pretending everything is Gaussian. Forecast.mean_mcse carries the mean’s per-step Monte Carlo standard error and Forecast.n_draws the draw count; raise n to shrink both.

class Forecast(mean, lo, hi, level, state_probs, samples=None, method='monte-carlo (chain-path simulation)', n_draws=0, mean_mcse=None)[source]

Bases: object

Per-step predictive summaries plus the state-marginal trajectory.

mean, lo, and hi are MONTE CARLO estimates from n_draws predictive draws per step (STAT-RR17-10); only state_probs is exact. mean_mcse is the per-step Monte Carlo standard error of mean (draw std / sqrt(n_draws)) so two runs’ means can be read against their own noise instead of as reproducible constants – 25-draw means varied 4.39-4.72 across seeds on a fixed model. method names the estimator.

Parameters:
forecast(model, history, horizon, *, level=0.9, n=4000, seed=0, keep_samples=False)[source]

Forecast horizon steps beyond history under a fitted HMM.

Parameters:
  • model (Any) – a fitted HiddenMarkovModelDistribution (any emission family with a sampler).

  • history (Any) – the observed sequence to condition on (one sequence).

  • horizon (int) – number of future steps to predict.

  • level (float) – central-interval mass (0.9 -> the 5%..95% band).

  • n (int) – Monte-Carlo draws per step for the emission quantiles (state marginals are exact).

  • seed (int) – reproducibility.

  • keep_samples (bool) – also return (H, n) JOINT sample paths – column j is one simulated trajectory of the chain, so cross-step dependence is the model’s own and summing along a column is a valid path functional (scalar emissions only).

Raises:
  • TypeError – if model is not a fitted HMM.

  • ValueError – for a non-exact/non-positive horizon or n, a level outside (0, 1), or an empty history.

Return type:

Forecast

Every control is checked up front, before any state is allocated or any draw is taken. Only the horizon used to be checked, and each remaining control failed somewhere else or not at all: level=-0.5 produced lo=6.75 above hi=2.25 – an interval whose lower endpoint exceeds its upper one, silently returned as an ordinary Forecast – while a NaN level surfaced as NumPy’s generic quantile error and n=0 warned about an empty sample and then raised an opaque IndexError partway through the loop.