# API Reference
This document provides a comprehensive reference for all public APIs in the `anofox-forecast` crate. The crate provides 35+ forecasting models, 76+ time series features, and extensive utilities for time series analysis.
## Table of Contents
- [Core Types](#core-types)
- [TimeSeries](#timeseries)
- [TimeSeriesBuilder](#timeseriesbuilder)
- [Forecast](#forecast)
- [ForecastError](#forecasterror)
- [Missing Value Imputation](#missing-value-imputation)
- [MissingValuePolicy](#missingvaluepolicy)
- [Imputation Methods](#imputation-methods)
- [Metadata Helpers](#metadata-helpers)
- [Forecaster Trait](#forecaster-trait)
- [Baseline Models](#baseline-models)
- [Naive](#naive)
- [SeasonalNaive](#seasonalnaive)
- [RandomWalkWithDrift](#randomwalkwithdrift)
- [HistoricAverage](#historicaverage)
- [WindowAverage](#windowaverage)
- [SeasonalWindowAverage](#seasonalwindowaverage)
- [Exponential Smoothing](#exponential-smoothing)
- [SimpleExponentialSmoothing](#simpleexponentialsmoothing)
- [Holt](#holt)
- [HoltWinters](#holtwinters)
- [ETS](#ets)
- [AutoETS](#autoets)
- [SeasonalES](#seasonales)
- [ARIMA Models](#arima-models)
- [ARIMA](#arima)
- [SARIMA](#sarima)
- [AutoARIMA](#autoarima)
- [Theta Models](#theta-models)
- [Theta](#theta)
- [OptimizedTheta](#optimizedtheta)
- [DynamicTheta](#dynamictheta)
- [DynamicOptimizedTheta](#dynamicoptimizedtheta)
- [AutoTheta](#autotheta)
- [Intermittent Demand Models](#intermittent-demand-models)
- [Croston](#croston)
- [TSB](#tsb)
- [ADIDA](#adida)
- [IMAPA](#imapa)
- [Advanced Models](#advanced-models)
- [MFLES](#mfles)
- [MSTLForecaster](#mstlforecaster)
- [TBATS](#tbats)
- [AutoTBATS](#autotbats)
- [GARCH](#garch)
- [Ensemble](#ensemble)
- [Decomposition](#decomposition)
- [STL](#stl)
- [MSTL](#mstl)
- [Spectral Analysis](#spectral-analysis)
- [Welch Periodogram](#welch-periodogram)
- [Feature Extraction](#feature-extraction)
- [Transformations](#transformations)
- [Validation](#validation)
- [Changepoint Detection](#changepoint-detection)
- [Utilities](#utilities)
- [Probabilistic Postprocessing](#probabilistic-postprocessing)
- [PointForecasts](#pointforecasts)
- [QuantileForecasts](#quantileforecasts)
- [PredictionIntervals](#predictionintervals)
- [ConformalPredictor](#conformalpredictor)
- [HistoricalSimulator](#historicalsimulator)
- [NormalPredictor](#normalpredictor)
- [IDRPredictor](#idrpredictor)
- [QRAPredictor](#qrapredictor)
- [PostProcessor](#postprocessor)
- [Backtesting](#backtesting)
- [Conformalize](#conformalize)
---
## Core Types
### TimeSeries
Container for time series data with timestamps and multivariate values.
```rust
pub struct TimeSeries {
// Fields are private, use methods to access
}
```
#### Constructor Methods
| `TimeSeries::new(timestamps, values, labels)` | Create with full configuration |
| `TimeSeries::univariate(values)` | Create simple single-dimension series |
#### Key Methods
| `len()` | `usize` | Number of observations |
| `dimensions()` | `usize` | Number of dimensions |
| `is_empty()` | `bool` | Check if series is empty |
| `is_multivariate()` | `bool` | Check if multi-dimensional |
| `timestamps()` | `&[DateTime<Utc>]` | Get timestamps |
| `values(dimension)` | `Result<&[f64]>` | Get values for dimension |
| `primary_values()` | `&[f64]` | Get first dimension values |
| `slice(start, end)` | `Result<TimeSeries>` | Extract subsequence |
| `has_missing_values()` | `bool` | Check for NaN/Inf |
| `missing_mask()` | `Vec<bool>` | Boolean mask: true where NaN/Inf (primary dimension) |
| `missing_count()` | `Vec<usize>` | Count of missing values per dimension |
| `interpolated(fill_edges)` | `TimeSeries` | Linear interpolation for NaN values |
| `sanitized(policy)` | `Result<TimeSeries>` | Apply missing value policy |
| `imputed_forward_backward()` | `TimeSeries` | Forward-fill then backward-fill |
| `imputed_moving_average(window)` | `Result<TimeSeries>` | Centered moving average imputation |
| `imputed_seasonal(period)` | `Result<TimeSeries>` | Seasonal median imputation |
| `with_imputed_regressors(policy)` | `Result<TimeSeries>` | Impute NaN in regressor vectors |
[Back to top](#api-reference)
---
### TimeSeriesBuilder
Builder pattern for constructing TimeSeries.
```rust
let ts = TimeSeriesBuilder::new()
.timestamps(timestamps)
.values(values)
.frequency(Duration::days(1))
.build()?;
```
| `new()` | Create new builder |
| `timestamps(Vec<DateTime<Utc>>)` | Set timestamps |
| `values(Vec<f64>)` | Set univariate values |
| `multivariate_values(Vec<Vec<f64>>, ValueLayout)` | Set multivariate values |
| `labels(Vec<String>)` | Set dimension labels |
| `frequency(Duration)` | Set time frequency |
| `build()` | Build the TimeSeries |
[Back to top](#api-reference)
---
### Forecast
Prediction output containing point forecasts and optional confidence intervals.
```rust
pub struct Forecast {
// Fields are private, use methods to access
}
```
#### Constructor Methods
| `Forecast::new()` | Create empty forecast |
| `Forecast::from_values(values)` | Create from point forecasts |
| `Forecast::from_values_with_intervals(values, lower, upper)` | Create with intervals |
#### Key Methods
| `horizon()` | `usize` | Number of forecast steps |
| `primary()` | `&[f64]` | Get point forecasts |
| `lower()` | `Option<&[Vec<f64>]>` | Get lower bounds |
| `upper()` | `Option<&[Vec<f64>]>` | Get upper bounds |
| `has_lower()` | `bool` | Check if lower bounds exist |
| `has_upper()` | `bool` | Check if upper bounds exist |
[Back to top](#api-reference)
---
### ForecastError
Error types for forecasting operations.
```rust
pub enum ForecastError {
EmptyData,
InsufficientData { needed: usize, got: usize, hint: Option<String> },
InvalidParameter(String),
DimensionMismatch { expected: usize, got: usize },
FitRequired,
MissingValues,
ComputationError(String),
// ... other variants
}
```
| `EmptyData` | Input data is empty |
| `InsufficientData` | Not enough data points |
| `InvalidParameter` | Invalid parameter value |
| `DimensionMismatch` | Dimension mismatch in data |
| `FitRequired` | Model not fitted before prediction |
| `MissingValues` | Missing values detected |
| `ComputationError` | Numerical computation error |
[Back to top](#api-reference)
---
## Missing Value Imputation
Tools for handling NaN/Inf values before model fitting. All models reject missing values at `fit()` time, so imputation must be applied beforehand.
### MissingValuePolicy
```rust
pub enum MissingValuePolicy {
Drop, // Remove observations with NaN/Inf
Fill(f64), // Replace with specific value
ForwardFill, // Carry last valid value forward
BackwardFill, // Carry next valid value backward
FillMean, // Replace with mean of finite values
FillMedian, // Replace with median of finite values
Interpolate, // Linear interpolation (edges filled)
Error, // Return error if any missing
}
```
**Usage:**
```rust
use anofox_forecast::core::{TimeSeries, MissingValuePolicy};
// Apply policy via sanitized()
let clean = ts.sanitized(MissingValuePolicy::FillMean)?;
let clean = ts.sanitized(MissingValuePolicy::BackwardFill)?;
let clean = ts.sanitized(MissingValuePolicy::Interpolate)?;
```
### Imputation Methods
| `sanitized(policy)` | Apply any `MissingValuePolicy` variant |
| `imputed_forward_backward()` | Forward-fill then backward-fill — handles both leading and trailing NaN |
| `imputed_moving_average(window)` | Centered window mean with multi-pass for adjacent gaps. Window must be odd. Remaining NaN filled with global mean. |
| `imputed_seasonal(period)` | Fill NaN with median of same seasonal position across cycles. Requires at least 1 full cycle. Errors if >50% missing in any bucket. |
| `with_imputed_regressors(policy)` | Apply fill policy to each regressor vector independently. Supports `Fill`, `ForwardFill`, `BackwardFill`, `FillMean`, `FillMedian`, `Interpolate`. |
### Metadata Helpers
| `has_missing_values()` | `bool` | True if any NaN/Inf in any dimension |
| `missing_mask()` | `Vec<bool>` | Per-observation mask for primary dimension |
| `missing_count()` | `Vec<usize>` | Count of NaN/Inf per dimension |
**Example — seasonal imputation:**
```rust
// Weekly data with gaps
let clean = ts.imputed_seasonal(7)?; // Fill using same-weekday median
```
**Example — regressor imputation:**
```rust
let clean = ts.with_imputed_regressors(MissingValuePolicy::FillMean)?;
```
[Back to top](#api-reference)
---
## Forecaster Trait
Main trait interface that all forecasting models implement.
```rust
pub trait Forecaster {
fn fit(&mut self, series: &TimeSeries) -> Result<()>;
fn predict(&self, horizon: usize) -> Result<Forecast>;
fn predict_with_intervals(&self, horizon: usize, level: f64) -> Result<Forecast>;
fn fitted_values(&self) -> Option<&[f64]>;
fn residuals(&self) -> Option<&[f64]>;
fn name(&self) -> &str;
fn is_fitted(&self) -> bool;
}
```
| `fit` | `series: &TimeSeries` | `Result<()>` | Fit model to data |
| `predict` | `horizon: usize` | `Result<Forecast>` | Generate point forecasts |
| `predict_with_intervals` | `horizon: usize, level: f64` | `Result<Forecast>` | Forecasts with confidence intervals |
| `fitted_values` | - | `Option<&[f64]>` | Get in-sample fitted values |
| `residuals` | - | `Option<&[f64]>` | Get residuals (actual - fitted) |
| `name` | - | `&str` | Model name |
| `is_fitted` | - | `bool` | Check if model is fitted |
[Back to top](#api-reference)
---
## Baseline Models
### Naive
Repeats the last observed value for all forecast horizons.
```rust
pub struct Naive;
impl Naive {
pub fn new() -> Self;
}
```
**Example:**
```rust
let mut model = Naive::new();
model.fit(&ts)?;
let forecast = model.predict(12)?;
```
[Back to top](#api-reference)
---
### SeasonalNaive
Repeats values from the same season in the previous cycle.
```rust
pub struct SeasonalNaive {
period: usize,
}
impl SeasonalNaive {
pub fn new(period: usize) -> Self;
}
```
| `period` | `usize` | Seasonal period (e.g., 12 for monthly data) |
[Back to top](#api-reference)
---
### RandomWalkWithDrift
Random walk model with trend drift component.
```rust
pub struct RandomWalkWithDrift;
impl RandomWalkWithDrift {
pub fn new() -> Self;
}
```
The drift is estimated as the average change between consecutive observations.
[Back to top](#api-reference)
---
### HistoricAverage
Forecasts the mean of all historical observations.
```rust
pub struct HistoricAverage;
impl HistoricAverage {
pub fn new() -> Self;
}
```
[Back to top](#api-reference)
---
### WindowAverage
Moving window average forecaster.
```rust
pub struct WindowAverage {
window: usize,
}
impl WindowAverage {
pub fn new(window: usize) -> Self;
}
```
| `window` | `usize` | Number of observations to average |
[Back to top](#api-reference)
---
### SeasonalWindowAverage
Seasonal window-based averaging.
```rust
pub struct SeasonalWindowAverage {
period: usize,
window: usize,
}
impl SeasonalWindowAverage {
pub fn new(period: usize, window: usize) -> Self;
}
```
| `period` | `usize` | Seasonal period |
| `window` | `usize` | Number of seasonal cycles to average |
[Back to top](#api-reference)
---
## Exponential Smoothing
### SimpleExponentialSmoothing
Simple exponential smoothing for non-seasonal, non-trending data.
```rust
pub struct SimpleExponentialSmoothing {
alpha: Option<f64>,
}
impl SimpleExponentialSmoothing {
pub fn new(alpha: f64) -> Self;
pub fn auto() -> Self;
pub fn alpha(&self) -> Option<f64>;
pub fn level(&self) -> Option<f64>;
}
```
| `alpha` | `f64` | Smoothing parameter (0 < alpha < 1) |
| `auto()` | `Self` | Create with auto-optimized alpha |
| `alpha()` | `Option<f64>` | Get fitted alpha value |
| `level()` | `Option<f64>` | Get final level |
[Back to top](#api-reference)
---
### Holt
Holt's linear trend method (double exponential smoothing).
```rust
pub struct Holt {
alpha: Option<f64>,
beta: Option<f64>,
}
impl Holt {
pub fn new(alpha: f64, beta: f64) -> Self;
pub fn auto() -> Self;
}
```
| `alpha` | `f64` | Level smoothing (0 < alpha < 1) |
| `beta` | `f64` | Trend smoothing (0 < beta < 1) |
[Back to top](#api-reference)
---
### HoltWinters
Holt-Winters seasonal exponential smoothing.
```rust
pub struct HoltWinters {
period: usize,
seasonal_type: SeasonalType,
alpha: Option<f64>,
beta: Option<f64>,
gamma: Option<f64>,
}
impl HoltWinters {
pub fn new(period: usize, seasonal_type: SeasonalType) -> Self;
pub fn with_params(period: usize, seasonal_type: SeasonalType,
alpha: f64, beta: f64, gamma: f64) -> Self;
pub fn auto(period: usize, seasonal_type: SeasonalType) -> Self;
}
pub enum SeasonalType {
Additive,
Multiplicative,
}
```
| `period` | `usize` | Seasonal period |
| `seasonal_type` | `SeasonalType` | Additive or Multiplicative |
| `alpha` | `f64` | Level smoothing |
| `beta` | `f64` | Trend smoothing |
| `gamma` | `f64` | Seasonal smoothing |
[Back to top](#api-reference)
---
### ETS
Error-Trend-Seasonal state-space model following the [FPP3 taxonomy](https://otexts.com/fpp3/taxonomy.html).
```rust
pub struct ETS {
spec: ETSSpec,
}
impl ETS {
pub fn new(spec: ETSSpec, period: usize) -> Self;
}
pub struct ETSSpec {
pub error: ErrorType,
pub trend: TrendType,
pub seasonal: SeasonalType,
}
pub enum ErrorType { Additive, Multiplicative }
pub enum TrendType { None, Additive, AdditiveDamped }
pub enum SeasonalType { None, Additive, Multiplicative }
```
#### ETS Model Taxonomy
This implementation follows the ETS taxonomy from [Forecasting: Principles and Practice (FPP3)](https://otexts.com/fpp3/taxonomy.html).
**Valid ETS Specifications (16 of 18 combinations):**
| ANN | Simple exponential smoothing | `ETSSpec::ann()` |
| AAN | Holt's linear method | `ETSSpec::aan()` |
| AAdN | Additive damped trend | `ETSSpec::aadn()` |
| ANA | Seasonal (no trend, additive) | `ETSSpec::ana()` |
| ANM | Seasonal (no trend, multiplicative) | `ETSSpec::anm()` |
| AAA | Holt-Winters additive | `ETSSpec::aaa()` |
| AAM | Holt-Winters multiplicative seasonal | `ETSSpec::aam()` |
| AAdA | Damped Holt-Winters additive | `ETSSpec::aada()` |
| AAdM | Damped Holt-Winters multiplicative | `ETSSpec::aadm()` |
| MNN | Multiplicative error simple smoothing | `ETSSpec::mnn()` |
| MAN | Multiplicative error with trend | `ETSSpec::man()` |
| MAdN | Multiplicative error damped trend | `ETSSpec::madn()` |
| MNM | Multiplicative error and seasonal | `ETSSpec::mnm()` |
| MAM | Multiplicative Holt-Winters | `ETSSpec::mam()` |
| MAdM | Damped multiplicative Holt-Winters | `ETSSpec::madm()` |
**Invalid/Unstable (rejected):**
| MAA | Multiplicative error + additive trend + additive seasonal |
| MAdA | Multiplicative error + damped trend + additive seasonal |
#### Parsing ETS Notation
```rust
impl ETSSpec {
/// Parse from notation string like "AAA", "MAM", "AAdM"
pub fn from_notation(notation: &str) -> Result<Self>;
/// Check if this combination is valid
pub fn is_valid(&self) -> bool;
}
```
**Example:**
```rust
use anofox_forecast::models::exponential::ETSSpec;
// Parse notation
let spec = ETSSpec::from_notation("AAA")?; // Holt-Winters additive
let spec = ETSSpec::from_notation("MAdM")?; // Damped multiplicative
// Invalid combinations return error
assert!(ETSSpec::from_notation("MAA").is_err());
```
[Back to top](#api-reference)
---
### AutoETS
Automatic ETS model selection using information criteria.
```rust
pub struct AutoETS {
config: AutoETSConfig,
}
impl AutoETS {
pub fn new() -> Self;
pub fn with_config(config: AutoETSConfig) -> Self;
pub fn with_period(period: usize) -> Self;
}
pub struct AutoETSConfig {
pub criterion: SelectionCriterion,
pub seasonal_period: Option<usize>,
pub allow_multiplicative: bool,
}
pub enum SelectionCriterion { AIC, BIC, AICc }
```
[Back to top](#api-reference)
---
### SeasonalES
Multiplicative seasonal exponential smoothing.
```rust
pub struct SeasonalES {
period: usize,
}
impl SeasonalES {
pub fn new(period: usize) -> Self;
}
```
[Back to top](#api-reference)
---
## ARIMA Models
### ARIMA
Non-seasonal ARIMA(p,d,q) model.
```rust
pub struct ARIMA {
spec: ARIMASpec,
}
impl ARIMA {
pub fn new(p: usize, d: usize, q: usize) -> Self;
pub fn spec(&self) -> &ARIMASpec;
pub fn ar_coefficients(&self) -> &[f64];
pub fn ma_coefficients(&self) -> &[f64];
pub fn intercept(&self) -> f64;
pub fn aic(&self) -> Option<f64>;
pub fn bic(&self) -> Option<f64>;
}
pub struct ARIMASpec {
pub p: usize, // AR order
pub d: usize, // Differencing order
pub q: usize, // MA order
}
```
| `p` | `usize` | Autoregressive order |
| `d` | `usize` | Differencing order |
| `q` | `usize` | Moving average order |
[Back to top](#api-reference)
---
### SARIMA
Seasonal ARIMA(p,d,q)(P,D,Q)\[s\] model.
```rust
pub struct SARIMA {
spec: SARIMASpec,
}
impl SARIMA {
pub fn new(p: usize, d: usize, q: usize,
cap_p: usize, cap_d: usize, cap_q: usize, s: usize) -> Self;
}
pub struct SARIMASpec {
pub p: usize, pub d: usize, pub q: usize, // Non-seasonal
pub cap_p: usize, pub cap_d: usize, pub cap_q: usize, // Seasonal
pub s: usize, // Seasonal period
}
```
| `p, d, q` | `usize` | Non-seasonal orders |
| `P, D, Q` | `usize` | Seasonal orders |
| `s` | `usize` | Seasonal period |
[Back to top](#api-reference)
---
### AutoARIMA
Automatic ARIMA order selection.
```rust
pub struct AutoARIMA {
config: AutoARIMAConfig,
}
impl AutoARIMA {
pub fn new() -> Self;
pub fn with_config(config: AutoARIMAConfig) -> Self;
}
pub struct AutoARIMAConfig {
pub max_p: usize,
pub max_d: usize,
pub max_q: usize,
pub seasonal_period: Option<usize>,
pub criterion: SelectionCriterion,
pub stepwise: bool,
pub true_stepwise: bool, // Neighbor-based hill climbing
}
impl AutoARIMAConfig {
pub fn with_true_stepwise(self, enabled: bool) -> Self;
pub fn exhaustive(self) -> Self;
}
```
| `stepwise` | Use stepwise search (faster, fewer models) |
| `true_stepwise` | Use neighbor-based hill climbing (60-70% fewer evaluations) |
**Parallel Execution:**
Enable with `--features parallel` for 4-8x speedup on multi-core systems:
```toml
[dependencies]
anofox-forecast = { version = "0.3", features = ["parallel"] }
```
[Back to top](#api-reference)
---
## Theta Models
### Theta
Standard Theta Model (STM) for forecasting.
```rust
pub struct Theta {
theta: f64,
seasonal_period: usize,
decomposition: DecompositionType,
}
impl Theta {
pub fn new() -> Self;
pub fn with_theta(theta: f64) -> Self;
pub fn seasonal(period: usize) -> Self;
pub fn seasonal_with_type(period: usize, decomposition: DecompositionType) -> Self;
}
pub enum DecompositionType {
Additive,
Multiplicative,
}
```
| `theta` | `f64` | Theta parameter (default: 2.0) |
| `period` | `usize` | Seasonal period (0 for non-seasonal) |
| `decomposition` | `DecompositionType` | Seasonal decomposition type |
[Back to top](#api-reference)
---
### OptimizedTheta
Theta model with optimized alpha and theta parameters.
```rust
pub struct OptimizedTheta;
impl OptimizedTheta {
pub fn new() -> Self;
}
```
Parameters are optimized using Nelder-Mead minimization of MSE.
[Back to top](#api-reference)
---
### DynamicTheta
Theta with dynamic linear coefficient updates.
```rust
pub struct DynamicTheta {
period: Option<usize>,
}
impl DynamicTheta {
pub fn new(period: Option<usize>) -> Self;
}
```
[Back to top](#api-reference)
---
### DynamicOptimizedTheta
Combines dynamic updates with parameter optimization.
```rust
pub struct DynamicOptimizedTheta {
period: Option<usize>,
}
impl DynamicOptimizedTheta {
pub fn new(period: Option<usize>) -> Self;
}
```
[Back to top](#api-reference)
---
### AutoTheta
Automatic Theta model selection.
```rust
pub struct AutoTheta;
impl AutoTheta {
pub fn new() -> Self;
}
```
Selects the best Theta variant based on cross-validation performance.
[Back to top](#api-reference)
---
## Intermittent Demand Models
### Croston
Croston's method for intermittent demand forecasting.
```rust
pub struct Croston {
variant: CrostonVariant,
alpha: f64,
}
impl Croston {
pub fn new() -> Self; // Classic variant
pub fn classic() -> Self;
pub fn sba() -> Self; // Syntetos-Babai adjusted
pub fn with_alpha(alpha: f64) -> Self;
}
pub enum CrostonVariant {
Classic,
SBA, // Syntetos-Babai Approximation
}
```
| `Classic` | Original Croston method |
| `SBA` | Bias-corrected Syntetos-Babai variant |
[Back to top](#api-reference)
---
### TSB
Teunter-Syntetos-Babai method for intermittent demand.
```rust
pub struct TSB {
alpha: f64,
beta: f64,
}
impl TSB {
pub fn new() -> Self;
pub fn with_params(alpha: f64, beta: f64) -> Self;
}
```
[Back to top](#api-reference)
---
### ADIDA
Aggregate-Disaggregate Intermittent Demand Approach.
```rust
pub struct ADIDA {
aggregation_level: usize,
}
impl ADIDA {
pub fn new() -> Self;
pub fn with_aggregation(level: usize) -> Self;
}
```
[Back to top](#api-reference)
---
### IMAPA
Intermittent Multiple Aggregation Prediction Algorithm.
```rust
pub struct IMAPA;
impl IMAPA {
pub fn new() -> Self;
}
```
Combines forecasts from multiple aggregation levels.
[Back to top](#api-reference)
---
## Advanced Models
### MFLES
Multiple Fourier Linear Exponential Smoothing - gradient boosted decomposition.
```rust
pub struct MFLES {
seasonal_periods: Vec<usize>,
}
impl MFLES {
pub fn new(seasonal_periods: Vec<usize>) -> Self;
pub fn with_max_rounds(rounds: usize) -> Self;
}
```
| `seasonal_periods` | `Vec<usize>` | Seasonal periods to model |
| `max_rounds` | `usize` | Maximum boosting iterations |
[Back to top](#api-reference)
---
### MSTLForecaster
MSTL decomposition-based forecaster for multiple seasonalities.
```rust
pub struct MSTLForecaster {
seasonal_periods: Vec<usize>,
}
impl MSTLForecaster {
pub fn new(seasonal_periods: Vec<usize>) -> Self;
}
```
[Back to top](#api-reference)
---
### TBATS
Trigonometric seasonality, Box-Cox transformation, ARMA errors, Trend, Seasonal components.
```rust
pub struct TBATS {
seasonal_periods: Vec<usize>,
}
impl TBATS {
pub fn new(seasonal_periods: Vec<usize>) -> Self;
}
```
Handles complex seasonal patterns with trigonometric representation.
[Back to top](#api-reference)
---
### AutoTBATS
Automatic TBATS configuration selection.
```rust
pub struct AutoTBATS;
impl AutoTBATS {
pub fn new(seasonal_periods: Vec<usize>) -> Self;
}
```
[Back to top](#api-reference)
---
### GARCH
Generalized Autoregressive Conditional Heteroskedasticity for volatility modeling.
```rust
pub struct GARCH {
p: usize,
q: usize,
}
impl GARCH {
pub fn new(p: usize, q: usize) -> Self;
}
```
| `p` | `usize` | GARCH order (variance lags) |
| `q` | `usize` | ARCH order (squared residual lags) |
[Back to top](#api-reference)
---
## Ensemble
Combines multiple forecasting models.
```rust
pub struct Ensemble {
models: Vec<Box<dyn Forecaster>>,
method: CombinationMethod,
}
impl Ensemble {
pub fn new(models: Vec<Box<dyn Forecaster>>) -> Self;
pub fn with_method(method: CombinationMethod) -> Self;
pub fn with_weights(weights: Vec<f64>) -> Self;
}
pub enum CombinationMethod {
Mean,
Median,
WeightedMSE,
Custom,
}
```
| `Mean` | Simple average of forecasts |
| `Median` | Median of forecasts |
| `WeightedMSE` | Inverse MSE weighting |
| `Custom` | User-provided weights |
[Back to top](#api-reference)
---
## Decomposition
### STL
Seasonal-Trend decomposition using LOESS.
```rust
pub struct STL {
period: usize,
}
impl STL {
pub fn new(period: usize) -> Self;
pub fn decompose(&self, series: &[f64]) -> Result<STLResult>;
}
pub struct STLResult {
pub seasonal: Vec<f64>,
pub trend: Vec<f64>,
pub remainder: Vec<f64>,
}
```
[Back to top](#api-reference)
---
### MSTL
Multiple Seasonal-Trend decomposition using LOESS.
```rust
pub struct MSTL {
periods: Vec<usize>,
}
impl MSTL {
pub fn new(periods: Vec<usize>) -> Self;
pub fn decompose(&self, series: &[f64]) -> Result<MSTLResult>;
}
pub struct MSTLResult {
pub seasonal_components: Vec<Vec<f64>>,
pub trend: Vec<f64>,
pub remainder: Vec<f64>,
}
```
[Back to top](#api-reference)
---
## Spectral Analysis
### Welch Periodogram
Welch's method for reduced variance spectral estimation using overlapping windowed segments.
```rust
/// Welch's periodogram for reduced variance spectral estimation
pub fn welch_periodogram(
signal: &[f64],
window_size: usize, // Segment size (power of 2 recommended)
overlap: f64, // Overlap ratio (0.0-0.9, typically 0.5)
) -> Vec<(usize, f64)>;
```
| `signal` | `&[f64]` | Input time series |
| `window_size` | `usize` | Segment size (power of 2 for efficiency) |
| `overlap` | `f64` | Overlap ratio between segments (0.0-0.9) |
**Returns:** Vector of `(period, power)` tuples sorted by period (largest first).
**Example:**
```rust
use anofox_forecast::detection::welch_periodogram;
let signal: Vec<f64> = (0..256)
.map(|i| (2.0 * std::f64::consts::PI * i as f64 / 12.0).sin())
.collect();
let psd = welch_periodogram(&signal, 64, 0.5);
```rust
pub fn skewness(series: &[f64]) -> f64;
pub fn kurtosis(series: &[f64]) -> f64;
pub fn quantile(series: &[f64], q: f64) -> f64;
pub fn variation_coefficient(series: &[f64]) -> f64;
```
### Autocorrelation Features
```rust
pub fn autocorrelation(series: &[f64], lag: usize) -> f64;
pub fn partial_autocorrelation(series: &[f64], lag: usize) -> f64;
```
### Entropy Features
```rust
pub fn approximate_entropy(series: &[f64], m: usize, r: f64) -> f64;
pub fn sample_entropy(series: &[f64], m: usize, r: f64) -> f64;
pub fn permutation_entropy(series: &[f64], order: usize) -> f64;
```
### Complexity Features
```rust
pub fn cid_ce(series: &[f64], normalize: bool) -> f64;
pub fn lempel_ziv_complexity(series: &[f64], threshold: Option<f64>) -> f64;
```
### Trend Features
```rust
pub fn linear_trend(series: &[f64]) -> LinearTrendResult;
pub fn ar_coefficient(series: &[f64], k: usize) -> f64;
```
[Back to top](#api-reference)
---
## Transformations
### Box-Cox
```rust
pub fn boxcox(series: &[f64], lambda: f64) -> Result<BoxCoxResult>;
pub fn boxcox_auto(series: &[f64]) -> Result<BoxCoxResult>;
pub fn inv_boxcox(transformed: &[f64], lambda: f64) -> Result<Vec<f64>>;
pub fn boxcox_lambda(series: &[f64]) -> Result<f64>;
pub struct BoxCoxResult {
pub transformed: Vec<f64>,
pub lambda: f64,
}
```
### Scaling
```rust
pub fn standardize(series: &[f64]) -> ScaleResult;
pub fn normalize(series: &[f64]) -> ScaleResult;
pub fn robust_scale(series: &[f64]) -> ScaleResult;
pub struct ScaleResult {
pub scaled: Vec<f64>,
pub mean: f64,
pub std: f64,
}
```
### Window Functions
```rust
pub fn rolling_mean(series: &[f64], window: usize, center: bool) -> Vec<f64>;
pub fn rolling_std(series: &[f64], window: usize, center: bool) -> Vec<f64>;
pub fn rolling_min(series: &[f64], window: usize, center: bool) -> Vec<f64>;
pub fn rolling_max(series: &[f64], window: usize, center: bool) -> Vec<f64>;
pub fn expanding_mean(series: &[f64]) -> Vec<f64>;
pub fn ewm_mean(series: &[f64], span: f64) -> Vec<f64>;
```
[Back to top](#api-reference)
---
## Validation
### Residual Tests
```rust
pub fn ljung_box(residuals: &[f64], nlags: Option<usize>, seasonal: usize) -> LjungBoxResult;
pub fn box_pierce(residuals: &[f64], nlags: Option<usize>, seasonal: usize) -> LjungBoxResult;
pub fn durbin_watson(residuals: &[f64]) -> DurbinWatsonResult;
pub struct LjungBoxResult {
pub statistic: f64,
pub p_value: f64,
pub degrees_of_freedom: usize,
}
pub struct DurbinWatsonResult {
pub statistic: f64, // Values near 2 indicate no autocorrelation
}
```
### Stationarity Tests
```rust
pub fn adf_test(series: &[f64], nlags: Option<usize>) -> StationarityResult;
pub fn kpss_test(series: &[f64], nlags: Option<usize>) -> StationarityResult;
pub struct StationarityResult {
pub test_statistic: f64,
pub p_value: f64,
pub is_stationary: bool,
}
```
[Back to top](#api-reference)
---
## Changepoint Detection
PELT (Pruned Exact Linear Time) algorithm for changepoint detection.
```rust
pub fn pelt_detect(series: &[f64], config: &PeltConfig) -> PeltResult;
pub struct PeltConfig {
pub penalty: f64,
pub min_segment_length: usize,
pub cost_fn: CostFunction,
}
impl PeltConfig {
pub fn default() -> Self;
pub fn penalty(penalty: f64) -> Self;
pub fn with_bic_penalty(n: usize) -> Self;
}
pub enum CostFunction {
L2, // Squared cost (default)
L1, // Absolute cost, robust to outliers
Normal, // Normal likelihood
Poisson, // Poisson likelihood for count data
LinearTrend, // Detects slope/trend changes
MeanVariance, // Joint mean and variance changes
Cusum, // Sustained mean shifts
}
pub struct PeltResult {
pub changepoints: Vec<usize>,
pub n_changepoints: usize,
}
```
[Back to top](#api-reference)
---
## Utilities
### Accuracy Metrics
```rust
pub fn calculate_metrics(actual: &[f64], predicted: &[f64],
seasonal_period: Option<usize>) -> Result<AccuracyMetrics>;
pub struct AccuracyMetrics {
pub mae: f64, // Mean Absolute Error
pub mse: f64, // Mean Squared Error
pub rmse: f64, // Root Mean Squared Error
pub mape: f64, // Mean Absolute Percentage Error
pub smape: f64, // Symmetric MAPE
pub mase: f64, // Mean Absolute Scaled Error
pub r_squared: f64,
}
```
### Cross-Validation
```rust
pub fn cross_validate<F>(config: &CVConfig, series: &TimeSeries,
model_factory: F) -> Result<CVResults>;
pub struct CVConfig {
pub horizon: usize,
pub initial_window: usize,
pub step_size: usize,
pub strategy: CVStrategy,
}
pub enum CVStrategy {
Rolling, // Fixed window slides forward
Expanding, // Window grows over time
}
pub struct CVResults {
pub n_folds: usize,
pub aggregated: AggregatedMetrics,
pub fold_metrics: Vec<AccuracyMetrics>,
}
```
### Optimization
```rust
pub fn nelder_mead(objective: fn(&[f64]) -> f64, initial: Vec<f64>,
config: &NelderMeadConfig) -> Result<NelderMeadResult>;
pub struct NelderMeadConfig {
pub max_iter: usize,
pub tolerance: f64,
}
pub struct NelderMeadResult {
pub parameters: Vec<f64>,
pub value: f64,
pub iterations: usize,
}
```
[Back to top](#api-reference)
---
### Bootstrap Intervals
Bootstrap methods for empirical confidence intervals.
```rust
pub struct BootstrapConfig {
pub n_samples: usize, // Number of bootstrap samples (default: 1000)
pub block_size: Option<usize>, // Block size for block bootstrap
pub seed: Option<u64>, // Random seed for reproducibility
}
impl BootstrapConfig {
pub fn new(n_samples: usize) -> Self;
pub fn with_block_size(self, block_size: usize) -> Self;
pub fn with_seed(self, seed: u64) -> Self;
}
pub struct BootstrapResult {
pub lower: Vec<f64>, // Lower bounds per horizon step
pub upper: Vec<f64>, // Upper bounds per horizon step
pub level: f64, // Confidence level used
pub n_samples: usize, // Number of samples used
}
/// Generate bootstrap confidence intervals
pub fn bootstrap_intervals<M: Forecaster + Clone>(
model: &M,
series: &TimeSeries,
horizon: usize,
level: f64,
config: &BootstrapConfig,
) -> Result<BootstrapResult>;
/// Generate forecast with bootstrap intervals
pub fn bootstrap_forecast<M: Forecaster + Clone>(
model: &M,
series: &TimeSeries,
horizon: usize,
level: f64,
config: &BootstrapConfig,
) -> Result<Forecast>;
```
| Residual Bootstrap | Resamples fitted residuals with replacement |
| Block Bootstrap | Preserves autocorrelation structure |
**Example:**
```rust
use anofox_forecast::utils::bootstrap::{bootstrap_forecast, BootstrapConfig};
let config = BootstrapConfig::new(500).with_seed(42);
let forecast = bootstrap_forecast(&model, &ts, 12, 0.95, &config)?;
```
[Back to top](#api-reference)
---
## Probabilistic Postprocessing
The postprocessing module provides methods to convert point forecasts into calibrated
predictive distributions with coverage guarantees. It follows the approach of
[PostForecasts.jl](https://github.com/lipiecki/PostForecasts.jl).
### Core Types
#### PointForecasts
Point forecasts with optional timestamps and metadata.
```rust
pub struct PointForecasts {
timestamps: Vec<DateTime<Utc>>,
values: Vec<f64>,
model_name: Option<String>,
}
impl PointForecasts {
pub fn new(timestamps: Vec<DateTime<Utc>>, values: Vec<f64>) -> Result<Self>;
pub fn from_values(values: Vec<f64>) -> Self;
pub fn empty() -> Self;
pub fn with_model_name(self, name: impl Into<String>) -> Self;
pub fn len(&self) -> usize;
pub fn values(&self) -> &[f64];
pub fn timestamps(&self) -> &[DateTime<Utc>];
}
```
#### QuantileForecasts
Multi-quantile forecasts representing a discrete predictive distribution.
```rust
pub struct QuantileForecasts {
timestamps: Vec<DateTime<Utc>>,
quantiles: Vec<f64>,
values: Vec<Vec<f64>>, // values[time][quantile]
}
impl QuantileForecasts {
pub fn new(timestamps: Vec<DateTime<Utc>>, quantiles: Vec<f64>, values: Vec<Vec<f64>>) -> Result<Self>;
pub fn from_values(quantiles: Vec<f64>, values: Vec<Vec<f64>>) -> Result<Self>;
pub fn n_times(&self) -> usize;
pub fn n_quantiles(&self) -> usize;
pub fn quantiles(&self) -> &[f64];
pub fn at_time(&self, idx: usize) -> Option<&[f64]>;
pub fn at_quantile(&self, idx: usize) -> Option<Vec<f64>>;
pub fn median(&self) -> Option<Vec<f64>>;
pub fn to_prediction_intervals(&self, coverage: f64) -> Option<PredictionIntervals>;
}
```
#### PredictionIntervals
Lower and upper bounds with coverage level.
```rust
pub struct PredictionIntervals {
timestamps: Vec<DateTime<Utc>>,
lower: Vec<f64>,
upper: Vec<f64>,
coverage: f64,
}
impl PredictionIntervals {
pub fn new(timestamps: Vec<DateTime<Utc>>, lower: Vec<f64>, upper: Vec<f64>, coverage: f64) -> Result<Self>;
pub fn from_bounds(lower: Vec<f64>, upper: Vec<f64>, coverage: f64) -> Result<Self>;
pub fn lower(&self) -> &[f64];
pub fn upper(&self) -> &[f64];
pub fn coverage(&self) -> f64;
pub fn widths(&self) -> Vec<f64>;
pub fn midpoints(&self) -> Vec<f64>;
pub fn contains(&self, values: &[f64]) -> Vec<bool>;
pub fn empirical_coverage(&self, actuals: &[f64]) -> Option<f64>;
}
```
[Back to top](#api-reference)
---
### ConformalPredictor
Distribution-free prediction intervals with coverage guarantees.
```rust
pub struct ConformalPredictor {
coverage: f64,
method: ConformalMethod,
}
pub enum ConformalMethod {
Split { cal_fraction: f64 },
CrossVal { n_folds: usize },
JackknifePlus,
}
impl ConformalPredictor {
pub fn new(coverage: f64, method: ConformalMethod) -> Self;
pub fn split(coverage: f64) -> Self;
pub fn cross_val(coverage: f64, n_folds: usize) -> Self;
pub fn jackknife_plus(coverage: f64) -> Self;
pub fn fit(&self, forecasts: &[f64], actuals: &[f64]) -> Result<ConformalResult>;
pub fn predict(&self, result: &ConformalResult, forecasts: &PointForecasts) -> PredictionIntervals;
pub fn predict_values(&self, result: &ConformalResult, values: &[f64]) -> PredictionIntervals;
}
pub struct ConformalResult {
pub fn scores(&self) -> &[f64];
pub fn quantile_value(&self) -> f64;
pub fn coverage(&self) -> f64;
pub fn method(&self) -> &ConformalMethod;
}
```
| `Split` | Fast method using a holdout calibration set |
| `CrossVal` | Uses all data via k-fold cross-validation |
| `JackknifePlus` | Leave-one-out with finite sample validity |
**Example:**
```rust
use anofox_forecast::postprocess::{ConformalPredictor, ConformalMethod, PointForecasts};
let predictor = ConformalPredictor::split(0.90);
let result = predictor.fit(&historical_forecasts, &historical_actuals)?;
let new_forecasts = PointForecasts::from_values(vec![20.0, 21.0, 22.0]);
let intervals = predictor.predict(&result, &new_forecasts);
```
[Back to top](#api-reference)
---
### HistoricalSimulator
Non-parametric empirical error distribution for uncertainty quantification.
```rust
pub struct HistoricalSimulator {
quantiles: Vec<f64>,
window_size: Option<usize>,
}
impl HistoricalSimulator {
pub fn new(quantiles: Vec<f64>) -> Self;
pub fn with_window(quantiles: Vec<f64>, window_size: usize) -> Self;
pub fn fit(&self, forecasts: &[f64], actuals: &[f64]) -> Result<HistoricalSimResult>;
pub fn predict_values(&self, result: &HistoricalSimResult, values: &[f64]) -> Result<QuantileForecasts>;
}
```
[Back to top](#api-reference)
---
### NormalPredictor
Gaussian error assumption baseline for uncertainty quantification.
```rust
pub struct NormalPredictor {
quantiles: Vec<f64>,
}
impl NormalPredictor {
pub fn new(quantiles: Vec<f64>) -> Self;
pub fn fit(&self, forecasts: &[f64], actuals: &[f64]) -> Result<NormalResult>;
pub fn predict_values(&self, result: &NormalResult, values: &[f64]) -> Result<QuantileForecasts>;
}
```
[Back to top](#api-reference)
---
### IDRPredictor
Isotonic Distributional Regression for state-of-the-art calibration.
```rust
pub struct IDRPredictor {
quantiles: Vec<f64>,
}
impl IDRPredictor {
pub fn new(quantiles: Vec<f64>) -> Self;
pub fn fit(&self, forecasts: &[f64], actuals: &[f64]) -> Result<IDRResult>;
pub fn predict_values(&self, result: &IDRResult, values: &[f64]) -> Result<QuantileForecasts>;
}
```
[Back to top](#api-reference)
---
### QRAPredictor
Quantile Regression Averaging for ensemble combining.
```rust
pub struct QRAPredictor {
quantiles: Vec<f64>,
regularization: QRARegularization,
}
pub enum QRARegularization {
None,
L1(f64),
L2(f64),
}
impl QRAPredictor {
pub fn new(quantiles: Vec<f64>) -> Self;
pub fn with_regularization(quantiles: Vec<f64>, reg: QRARegularization) -> Self;
}
```
[Back to top](#api-reference)
---
### PostProcessor
Unified interface for all postprocessing methods.
```rust
pub struct PostProcessor {
model: PostModel,
}
pub enum PostModel {
Conformal { coverage: f64, method: ConformalMethod },
HistoricalSim { quantiles: Vec<f64>, window_size: Option<usize> },
Normal { quantiles: Vec<f64> },
IDR { quantiles: Vec<f64> },
}
impl PostProcessor {
pub fn new(model: PostModel) -> Self;
pub fn conformal(coverage: f64) -> Self;
pub fn historical_sim(quantiles: Vec<f64>) -> Self;
pub fn normal(quantiles: Vec<f64>) -> Self;
pub fn idr(quantiles: Vec<f64>) -> Self;
pub fn train(&self, forecasts: &PointForecasts, actuals: &[f64]) -> Result<TrainedModel>;
pub fn predict_intervals(&self, trained: &TrainedModel, forecasts: &PointForecasts) -> Result<PredictionIntervals>;
pub fn predict_quantiles(&self, trained: &TrainedModel, forecasts: &PointForecasts) -> Result<QuantileForecasts>;
pub fn point_to_quantiles(&self, train_forecasts: &PointForecasts, train_actuals: &[f64], predict_forecasts: &PointForecasts) -> Result<QuantileForecasts>;
}
pub enum TrainedModel {
Conformal(ConformalResult),
HistoricalSim(HistoricalSimResult),
Normal(NormalResult),
IDR(IDRResult),
}
```
**Example:**
```rust
use anofox_forecast::postprocess::{PostProcessor, PointForecasts};
// Create a conformal processor with 90% coverage
let processor = PostProcessor::conformal(0.90);
// Train on historical data
let train_forecasts = PointForecasts::from_values(historical_f);
let trained = processor.train(&train_forecasts, &historical_actuals)?;
// Generate prediction intervals
let new_forecasts = PointForecasts::from_values(new_f);
let intervals = processor.predict_intervals(&trained, &new_forecasts)?;
```
[Back to top](#api-reference)
---
### Backtesting
Rolling/expanding window backtesting with horizon-aware calibration.
```rust
pub struct BacktestConfig {
pub initial_window: usize,
pub step: usize,
pub horizon: usize,
pub expanding: bool,
pub horizon_aware: bool,
}
impl BacktestConfig {
pub fn new() -> Self;
pub fn initial_window(self, size: usize) -> Self;
pub fn step(self, step: usize) -> Self;
pub fn horizon(self, horizon: usize) -> Self;
pub fn expanding(self, expanding: bool) -> Self;
pub fn horizon_aware(self, aware: bool) -> Self;
}
pub struct BacktestResult {
pub fn n_folds(&self) -> usize;
pub fn config(&self) -> &BacktestConfig;
pub fn folds(&self) -> impl Iterator<Item = &BacktestFold>;
pub fn coverage(&self) -> f64;
pub fn calibration_error(&self, target_coverage: f64) -> f64;
pub fn interval_widths(&self) -> f64;
pub fn coverage_by_horizon(&self) -> &HashMap<usize, f64>;
pub fn calibrated_model(&self, processor: &PostProcessor) -> Result<TrainedModel>;
pub fn calibrated_model_by_horizon(&self, processor: &PostProcessor) -> Result<CalibratedModelByHorizon>;
}
pub struct BacktestFold {
pub fold_idx: usize,
pub train_start: usize,
pub train_end: usize,
pub test_start: usize,
pub test_end: usize,
pub intervals: PredictionIntervals,
pub actuals: Vec<f64>,
pub coverage: f64,
pub avg_width: f64,
}
```
**Example:**
```rust
use anofox_forecast::postprocess::{PostProcessor, BacktestConfig, PointForecasts};
let processor = PostProcessor::conformal(0.90);
let config = BacktestConfig::new()
.initial_window(100)
.step(10)
.horizon(7)
.horizon_aware(true);
let forecasts = PointForecasts::from_values(all_forecasts);
let results = processor.backtest(&forecasts, &all_actuals, config)?;
println!("Coverage: {:.1}%", results.coverage() * 100.0);
println!("Calibration error: {:.3}", results.calibration_error(0.90));
```
[Back to top](#api-reference)
---
### Conformalize
Recalibrate quantile forecasts using conformal prediction.
```rust
pub fn conformalize(
forecasts: &QuantileForecasts,
calib_forecasts: &QuantileForecasts,
calib_actuals: &[f64],
) -> Result<ConformalizeResult>;
pub fn conformalize_with_config(
forecasts: &QuantileForecasts,
calib_forecasts: &QuantileForecasts,
calib_actuals: &[f64],
config: ConformalizeConfig,
) -> Result<ConformalizeResult>;
pub struct ConformalizeConfig {
method: ConformalMethod,
symmetric: bool,
}
impl ConformalizeConfig {
pub fn new() -> Self;
pub fn method(self, method: ConformalMethod) -> Self;
pub fn symmetric(self, symmetric: bool) -> Self;
}
pub struct ConformalizeResult {
pub fn forecasts(&self) -> &QuantileForecasts;
pub fn into_forecasts(self) -> QuantileForecasts;
pub fn adjustments(&self) -> &[f64];
pub fn original_coverage(&self) -> &[f64];
}
```
**Example:**
```rust
use anofox_forecast::postprocess::{conformalize, QuantileForecasts};
// Calibrate quantile forecasts
let calibrated = conformalize(&test_forecasts, &calib_forecasts, &calib_actuals)?;
// Get the recalibrated forecasts
let improved = calibrated.into_forecasts();
```
[Back to top](#api-reference)
---
## Prelude
Convenience re-exports for common usage:
```rust
pub use crate::core::{Forecast, TimeSeries};
pub use crate::error::{ForecastError, Result};
pub use crate::models::Forecaster;
pub use crate::utils::{calculate_metrics, AccuracyMetrics};
```
**Usage:**
```rust
use anofox_forecast::prelude::*;
```
[Back to top](#api-reference)