Models

Baselines

class omnicast.NaiveForecaster[source]

Bases: BaseForecaster

Random-walk forecast using the most recent observation.

Examples

>>> import pandas as pd
>>> from omnicast import NaiveForecaster
>>> y = pd.Series([10.0, 12.0, 11.0, 13.0, 15.0, 14.0])
>>> model = NaiveForecaster().fit(y)
>>> model.predict(horizon=2).mean.round(2).tolist()
[14.0, 14.0]

Notes

When to use this model

Best for

The floor baseline every other model must beat; no assumptions about the series beyond “tomorrow looks like today”

Avoid when

The series has a visible trend or seasonal cycle – it will systematically lag both

Handles trend

No

Handles seasonality

No

Extra dependencies

None

Min. observations

1

fit(y, X=None)
Return type:

BaseForecaster

Parameters:
fit_predict(y, horizon, **kwargs)
Return type:

ForecastResult

Parameters:
get_params()
Return type:

dict[str, object]

predict(horizon, X=None, level=(80, 95))
Return type:

ForecastResult

Parameters:
class omnicast.SeasonalNaiveForecaster(seasonal_period)[source]

Bases: BaseForecaster

Repeat values from the latest seasonal cycle.

Examples

>>> import pandas as pd
>>> from omnicast import SeasonalNaiveForecaster
>>> y = pd.Series([10.0, 20.0, 15.0, 25.0, 11.0, 21.0, 16.0, 26.0])
>>> model = SeasonalNaiveForecaster(seasonal_period=4).fit(y)
>>> model.predict(horizon=4).mean.round(2).tolist()
[11.0, 21.0, 16.0, 26.0]

Notes

When to use this model

Best for

The baseline to beat whenever a series has real seasonal structure; captures the seasonal swing for free

Avoid when

The series has no repeating cycle, or a trend on top of the cycle that repeating last year’s values would miss

Handles trend

No

Handles seasonality

Yes (repeats the last full cycle)

Extra dependencies

None

Min. observations

seasonal_period + 1

Parameters:

seasonal_period (int)

fit(y, X=None)
Return type:

BaseForecaster

Parameters:
fit_predict(y, horizon, **kwargs)
Return type:

ForecastResult

Parameters:
get_params()
Return type:

dict[str, object]

predict(horizon, X=None, level=(80, 95))
Return type:

ForecastResult

Parameters:
class omnicast.MeanForecaster[source]

Bases: BaseForecaster

Forecast the historical mean.

Examples

>>> import pandas as pd
>>> from omnicast import MeanForecaster
>>> y = pd.Series([10.0, 12.0, 11.0, 13.0, 15.0, 14.0])
>>> model = MeanForecaster().fit(y)
>>> model.predict(horizon=2).mean.round(2).tolist()
[12.5, 12.5]

Notes

When to use this model

Best for

A stability sanity check – does the series have a signal worth modeling at all?

Avoid when

The series has any trend or seasonality; it should almost always lose to a trend-aware model on a proper backtest

Handles trend

No

Handles seasonality

No

Extra dependencies

None

Min. observations

1

fit(y, X=None)
Return type:

BaseForecaster

Parameters:
fit_predict(y, horizon, **kwargs)
Return type:

ForecastResult

Parameters:
get_params()
Return type:

dict[str, object]

predict(horizon, X=None, level=(80, 95))
Return type:

ForecastResult

Parameters:
class omnicast.DriftForecaster[source]

Bases: BaseForecaster

Random walk with drift between the first and last observations.

Examples

>>> import pandas as pd
>>> from omnicast import DriftForecaster
>>> y = pd.Series([10.0, 12.0, 11.0, 13.0, 15.0, 14.0])
>>> model = DriftForecaster().fit(y)
>>> model.predict(horizon=2).mean.round(2).tolist()
[14.8, 15.6]

Notes

When to use this model

Best for

A trending series with no seasonality; a much stronger baseline than NaiveForecaster in that case, at the same cost

Avoid when

The series has seasonality a straight line can’t capture, or the trend is not roughly linear end-to-end

Handles trend

Yes (linear, extrapolated from the first and last observation)

Handles seasonality

No

Extra dependencies

None

Min. observations

2

fit(y, X=None)
Return type:

BaseForecaster

Parameters:
fit_predict(y, horizon, **kwargs)
Return type:

ForecastResult

Parameters:
get_params()
Return type:

dict[str, object]

predict(horizon, X=None, level=(80, 95))
Return type:

ForecastResult

Parameters:

Theta

class omnicast.ThetaForecaster(seasonal_period=None)[source]

Bases: BaseForecaster

Classical Theta method (Assimakopoulos & Nikolopoulos, 2000).

Compatible Python reimplementation of R’s forecast::thetaf (Hyndman, package forecast, GPL-3) – not a call into R, and not yet verified against its numerical output; see CONTRIBUTING.md. It decomposes the series into two “theta lines”: the theta=0 line is the long-term linear trend, and the theta=2 line doubles local curvature around that trend. The theta=2 line is extrapolated with simple exponential smoothing, the theta=0 line is extrapolated linearly, and the two forecasts are averaged with equal weight, following Assimakopoulos & Nikolopoulos (2000), “The theta model: a decomposition approach to forecasting”, International Journal of Forecasting 16(4):521-530.

When seasonal_period is given, the series is deseasonalized first with a multiplicative classical decomposition (statsmodels.seasonal_decompose) and forecasts are reseasonalized afterwards; this requires strictly positive values and at least two full seasonal cycles.

Prediction intervals use the same residual-variance random-walk scaling (sqrt(sigma2 * h)) as NaiveForecaster, an approximation rather than the exact ETS(A,N,N) state-space interval that R’s implementation derives from the SES equivalence proven by Hyndman & Billah (2003), “Unmasking the Theta method”, International Journal of Forecasting 19(2):287-290.

Supported indexes: any index accepted by future_index (PeriodIndex, DatetimeIndex with a regular frequency, RangeIndex, or numeric Index). Minimum sample size: 4 observations, or 2 * seasonal_period when seasonal.

Examples

>>> import pandas as pd
>>> from omnicast import ThetaForecaster
>>> y = pd.Series([10.0, 12.0, 11.0, 13.0, 15.0, 14.0])
>>> model = ThetaForecaster().fit(y)
>>> model.predict(horizon=2).mean.round(2).tolist()
[14.05, 14.49]

Pass seasonal_period to deseasonalize first (multiplicative decomposition) and reseasonalize the forecast afterward; this requires strictly positive values and at least two full seasonal cycles, e.g. ThetaForecaster(seasonal_period=12) on two years of monthly data.

Notes

When to use this model

Best for

A strong, fast default before reaching for a full state-space model; a good general-purpose replacement for the baselines

Avoid when

You need exact parity with R’s forecast::thetaf intervals, or a model that supports exogenous regressors

Handles trend

Yes (linear long-term trend line)

Handles seasonality

Yes, via seasonal_period (multiplicative decomposition)

Extra dependencies

None

Min. observations

4, or 2 * seasonal_period when seasonal

Parameters:

seasonal_period (int | None)

fit(y, X=None)
Return type:

BaseForecaster

Parameters:
fit_predict(y, horizon, **kwargs)
Return type:

ForecastResult

Parameters:
get_params()
Return type:

dict[str, object]

predict(horizon, X=None, level=(80, 95))
Return type:

ForecastResult

Parameters:

Statistical (statsmodels-backed)

class omnicast.ETSForecaster(trend='add', seasonal=None, seasonal_period=None, damped_trend=False)[source]

Bases: BaseForecaster

Error-trend-seasonal state-space model with automatic component defaults.

Examples

>>> import pandas as pd
>>> from omnicast import ETSForecaster
>>> y = pd.Series([10.0, 12.0, 11.0, 13.0, 15.0, 14.0])
>>> model = ETSForecaster(trend="add").fit(y)
>>> model.predict(horizon=2).mean.round(2).tolist()
[15.6, 16.49]

Pass seasonal="add" (or "mul") with seasonal_period set to model a repeating cycle alongside the trend.

Notes

When to use this model

Best for

Series with a known trend/seasonal shape where you want a full statistical fit (AIC/BIC, parameter confidence intervals) rather than an approximation

Avoid when

You want the trend/seasonal order searched for you (see AutoARIMAForecaster) or need exogenous regressors

Handles trend

Yes, via trend ("add", "mul", or None)

Handles seasonality

Yes, via seasonal + seasonal_period

Extra dependencies

None (uses statsmodels)

Min. observations

Enough for statsmodels to estimate the requested components; at least 2 * seasonal_period when seasonal

Parameters:
  • trend (str | None)

  • seasonal (str | None)

  • seasonal_period (int | None)

  • damped_trend (bool)

fit(y, X=None)
Return type:

BaseForecaster

Parameters:
fit_predict(y, horizon, **kwargs)
Return type:

ForecastResult

Parameters:
get_params()
Return type:

dict[str, object]

predict(horizon, X=None, level=(80, 95))
Return type:

ForecastResult

Parameters:
class omnicast.ARIMAForecaster(order=(1, 0, 0), seasonal_order=(0, 0, 0, 0), trend=None)[source]

Bases: BaseForecaster

ARIMA/SARIMA model with optional exogenous regressors.

Examples

>>> import pandas as pd
>>> from omnicast import ARIMAForecaster
>>> y = pd.Series([10.0, 12.0, 11.0, 13.0, 15.0, 14.0])
>>> model = ARIMAForecaster(order=(1, 0, 0)).fit(y)
>>> model.predict(horizon=2).mean.round(2).tolist()
[14.76, 15.55]

Pass seasonal_order=(P, D, Q, m) for SARIMA, and an X DataFrame (with matching index at both fit and predict time) to include exogenous regressors.

Notes

When to use this model

Best for

You already know (or want to fix) the ARIMA/SARIMA order, or need exogenous regressors – the only model in this package that supports them

Avoid when

You want the order searched automatically (see AutoARIMAForecaster)

Handles trend

Yes, via differencing (d) and/or trend

Handles seasonality

Yes, via seasonal_order

Extra dependencies

None (uses statsmodels)

Min. observations

Enough for SARIMAX to estimate the requested order; roughly sum(order) + sum(seasonal_order[:3]) + 1 at minimum

Parameters:
fit(y, X=None)[source]
predict(horizon, X=None, level=(80, 95))[source]
fit_predict(y, horizon, **kwargs)
Return type:

ForecastResult

Parameters:
get_params()
Return type:

dict[str, object]

class omnicast.AutoARIMAForecaster(seasonal_period=None, max_p=2, max_d=1, max_q=2, max_P=1, max_D=1, max_Q=1, information_criterion='aicc')[source]

Bases: ARIMAForecaster

Select a non-seasonal or seasonal ARIMA by corrected AIC grid search.

Examples

>>> import pandas as pd
>>> from omnicast import AutoARIMAForecaster
>>> y = pd.Series([10.0, 12.0, 11.0, 13.0, 15.0, 14.0])
>>> model = AutoARIMAForecaster(max_p=1, max_d=1, max_q=0).fit(y)
>>> model.order_
(0, 1, 0)
>>> model.predict(horizon=2).mean.round(2).tolist()
[14.0, 14.0]

Pass seasonal_period to also search (P, D, Q, m).

Notes

When to use this model

Best for

You want ARIMA/SARIMA without hand-picking an order; the default first candidate AutoForecaster tries

Avoid when

Interactive use with a wide search space – cost scales as the product of every max_* bound plus one, and it is often the slowest model in the package to fit

Handles trend

Yes, searched via max_d

Handles seasonality

Yes, searched via seasonal_period + max_P/max_D/max_Q

Extra dependencies

None (uses statsmodels)

Min. observations

Enough for the largest candidate order to be estimated; failed candidates are skipped rather than aborting the search

Parameters:
  • seasonal_period (int | None)

  • max_p (int)

  • max_d (int)

  • max_q (int)

  • max_P (int)

  • max_D (int)

  • max_Q (int)

  • information_criterion (str)

fit(y, X=None)[source]
fit_predict(y, horizon, **kwargs)
Return type:

ForecastResult

Parameters:
get_params()
Return type:

dict[str, object]

predict(horizon, X=None, level=(80, 95))

Neural (optional, torch)

class omnicast.LSTMForecaster(lookback=12, hidden_size=32, num_layers=1, epochs=200, learning_rate=0.01, dropout=0.0, seed=0)[source]

Bases: BaseForecaster

Autoregressive LSTM forecaster wrapping torch.nn.LSTM.

Not an R port – this wraps a major Python deep-learning module the same way ETSForecaster/ARIMAForecaster wrap statsmodels. Requires the optional torch extra (pip install omnicast[torch]); raises a clear ImportError naming the missing package if torch is absent, and the module still imports cleanly without it.

The series is standardized (zero mean, unit variance, computed from training data only) and reframed as a sliding-window supervised regression: lookback consecutive points predict the next one. A single-layer (by default) LSTM is trained with Adam/MSE, full-batch, for epochs iterations – appropriate for the short series typical of this package, not for large-scale training. Multi-step forecasts are produced autoregressively: each predicted point is fed back in as the most recent observation of the next window.

Prediction intervals use the same residual-variance random-walk scaling (sqrt(sigma2 * h)) as NaiveForecaster and ThetaForecaster – an approximation, since the network has no closed-form predictive variance.

Not included in AutoForecaster’s default candidate list: it is optional-dependency and materially slower to backtest than the built-in statistical models. Pass it explicitly via AutoForecaster(models=[…]) to include it.

Minimum sample size: lookback + 2 observations. Training is not deterministic across torch versions/hardware even with a fixed seed; do not rely on exact reproducibility across environments.

Examples

>>> import pandas as pd
>>> from omnicast import LSTMForecaster
>>> y = pd.Series([10.0, 12.0, 11.0, 13.0, 15.0, 14.0, 16.0, 15.0])
>>> model = LSTMForecaster(lookback=2, hidden_size=4, epochs=30, seed=0).fit(y)
>>> forecast = model.predict(horizon=2)  # values vary slightly by platform

Notes

When to use this model

Best for

Exploring a nonlinear, learned alternative once the built-in statistical models have been tried; short series only

Avoid when

You need a fast default, exact reproducibility across machines, or don’t want the optional torch dependency – never included in AutoForecaster’s default candidates for these reasons

Handles trend

Implicitly, via the sliding-window autoregression

Handles seasonality

Only if lookback spans a full cycle; no explicit seasonal component

Extra dependencies

torch (pip install omnicast[torch])

Min. observations

lookback + 2

Parameters:
fit(y, X=None)
Return type:

BaseForecaster

Parameters:
fit_predict(y, horizon, **kwargs)
Return type:

ForecastResult

Parameters:
get_params()
Return type:

dict[str, object]

predict(horizon, X=None, level=(80, 95))
Return type:

ForecastResult

Parameters: