chronos-ts is a pure-Rust, parallelized time-series analysis and forecasting
library with optional Python bindings (pyo3). It ships two complementary
modelling engines:
- Auto-ARIMA / SARIMA / SARIMAX — automatic order selection with real coefficient estimation by Conditional Sum of Squares (CSS).
- Prophet-style decomposition — additive/multiplicative structural models with trend changepoints, Fourier seasonalities, holidays, logistic growth and Monte-Carlo uncertainty intervals.
It has no LAPACK/BLAS/MKL dependency and needs no C toolchain — all linear algebra is implemented in Rust, so it builds cleanly on every platform.
- Real ARIMA estimation, two ways. Coefficients are fitted by fast Conditional
Sum of Squares (default) or exact Gaussian maximum likelihood via the Kalman
filter (
EstimationMethod::Mle).auto_arimachooses the order by AIC/AICc/BIC using a stepwise (or full-grid) search, parallelized withrayon. A mean/drift term is estimated automatically, and a stationarity guard keeps fits stable. - SARIMAX. Exogenous regressors are supported end-to-end (fit and forecast).
- Uncertainty everywhere. Coefficient standard errors, 80%/95% prediction intervals from the model's exact MA(∞) forecast variance, and an optional Box-Cox/log transform (forecasts auto back-transformed).
- Diagnostics & validation. In-sample residuals feed ACF/PACF, Ljung-Box and
Jarque-Bera tests;
arima_cross_validationgives rolling-origin MAE/RMSE/MAPE. - Statistical safety. Guards against zero-variance/near-constant inputs; the Augmented Dickey-Fuller test maps its statistic through the Dickey-Fuller distribution (not a naive t-distribution).
- Serde persistence. Full JSON serialization of fitted model state.
- Python bindings.
auto_arima,SarimaModelandProphetexposed throughpyo3/numpy, PEP 561 typed (.pyistubs +py.typed).
Runnable examples live in examples/:
cargo run --example arima_forecast
cargo run --example prophet_forecastCriterion benchmarks (auto_arima across several series sizes, plus a Prophet fit):
cargo benchResults are written to target/criterion/ (HTML reports enabled). Numbers are
hardware-dependent, so none are quoted here — measure on your own machine.
[dependencies]
chronos-ts = "0.1"
ndarray = "0.15"
serde_json = "1.0"use chronos_ts::arima::{auto_arima, AutoArimaOptions};
use ndarray::Array1;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. Load your time series.
let data = Array1::linspace(10.0, 50.0, 100);
// 2. Configure the search.
let opts = AutoArimaOptions {
max_p: 3,
max_q: 3,
..Default::default()
};
// 3. Fit the optimal model (coefficients estimated by CSS).
let model = auto_arima(&data, opts)?;
println!("Selected order: {:?}", model.order);
// 4. Forecast 10 steps with 80% and 95% bounds.
let forecast = model.forecast_with_intervals(&data, 10);
println!("Point forecast: {:?}", forecast.mean);
println!("95% interval: [{:?}, {:?}]", forecast.lower_95, forecast.upper_95);
Ok(())
}use chronos_ts::{ProphetDecomposition, SeasonalityMode};
use chrono::{Duration, NaiveDate};
use ndarray::Array1;
let start = NaiveDate::from_ymd_opt(2023, 1, 1).unwrap();
let dates: Vec<NaiveDate> = (0..90).map(|i| start + Duration::days(i)).collect();
let y = Array1::from_shape_fn(90, |i| {
10.0 + 0.1 * i as f64 + 2.0 * (2.0 * std::f64::consts::PI * i as f64 / 7.0).sin()
});
let mut model = ProphetDecomposition::new(10, 0.05);
model.seasonality_mode = SeasonalityMode::Additive;
model.add_seasonality("weekly", 7.0, 3);
model.fit(&dates, &y, None, None).unwrap();
let prediction = model.predict(&dates).unwrap();
println!("yhat: {:?}", prediction.yhat);use chronos_ts::arima::SarimaModel;
let json_repr = serde_json::to_string(&model)?;
let restored: SarimaModel = serde_json::from_str(&json_repr)?;Install (built with maturin):
pip install chronos-tsimport numpy as np
import chronos_ts
# --- ARIMA ---
data = np.linspace(10.0, 50.0, 100) + np.random.normal(0, 1, 100)
model = chronos_ts.auto_arima(data, max_p=3, max_q=3)
print("order:", model.order)
res = model.forecast_with_intervals(data, steps=10)
print("mean:", res["mean"])
print("95% upper:", res["upper_95"])
# --- Prophet ---
dates = [f"2023-{(i // 28) + 1:02d}-{(i % 28) + 1:02d}" for i in range(90)]
y = np.array([10.0 + 0.1 * i for i in range(90)])
prophet = chronos_ts.Prophet(n_changepoints=10, changepoint_prior_scale=0.05)
prophet.add_seasonality("weekly", 7.0, 3)
prophet.fit(dates, y)
pred = prophet.predict(dates)
print("yhat:", pred["yhat"])| Feature | Description |
|---|---|
default |
Pure-Rust library (rlib). No C toolchain or BLAS/LAPACK required. |
python |
Builds the cdylib and enables the pyo3/numpy Python extension. |
Build the Python extension locally:
maturin develop --features pythonMIT — see LICENSE.