A Java library for time-series analysis, forecasting, evaluation, and data-quality workflows.
- exponential smoothing: single, double, and triple
- moving averages: simple, cumulative, exponential, and weighted
- transformations: log, roots, Box-Cox, differencing, and seasonal differencing
- statistics: mean, variance, autocovariance, ACF, and PACF
- stationarity testing with Augmented Dickey-Fuller and KPSS
- model-based forecasting with ARIMA, SARIMA, and ARIMAX
- decomposition with STL-style trend/seasonal/remainder extraction
- compact state-space forecasting with a local-level Kalman model
- forecast evaluation: train/test splits, rolling-origin backtests, metrics, and Ljung-Box diagnostics
- prediction intervals for ARIMA, SARIMA, and local-level forecasts
- auto-selection helpers for ARIMA/SARIMA and exponential smoothing
- data-quality utilities for missing values, outliers, and winsorization
- release-hardening helpers: wrapper bootstrap scripts, publishing scaffolding, CI workflows, and model benchmark utilities
The project targets Java 17 and uses Gradle.
./gradlew testThis snapshot now includes a lightweight ./gradlew bootstrap script that reads gradle/wrapper/gradle-wrapper.properties, downloads the configured Gradle distribution when needed, and then runs the build. It is intended to keep CI and contributor onboarding working even without committing a generated gradle-wrapper.jar.
Primary implementation packages:
tslib.collecttslib.dataqualitytslib.decompositiontslib.diagnosticstslib.evaluationtslib.mathtslib.model.arimatslib.model.expsmoothingtslib.model.statespacetslib.movingaveragetslib.selectiontslib.teststslib.transformtslib.util
Compatibility aliases added in this patch series:
tslib.model.*forwards totslib.model.expsmoothing.*tslib.model.ARIMAforwards totslib.model.arima.ARIMAtslib.model.SARIMAforwards totslib.model.arima.SARIMAtslib.model.ARIMAXforwards totslib.model.arima.ARIMAXtslib.model.LocalLevelModelforwards totslib.model.statespace.LocalLevelModeltslib.stats.Statsforwards totslib.util.Stats
| Use case | Start with | Compare against | Notes |
|---|---|---|---|
| Level-only or gently trending series | DoubleExpSmoothing |
ARIMA, LocalLevelModel |
Good lightweight baseline. |
| Strong repeating seasonality | TripleExpSmoothing |
SARIMA |
Prefer SARIMA when seasonal autocorrelation matters. |
| Differenced stationary dynamics | ARIMA |
LocalLevelModel |
Inspect ADF/KPSS and ACF/PACF first. |
| Seasonality plus differencing | SARIMA |
TripleExpSmoothing |
Use the seasonal period consistently across preprocessing and backtests. |
| External drivers available | ARIMAX |
ARIMA |
Validate regressor alignment and holdout availability. |
| Smooth latent state / baseline uncertainty | LocalLevelModel |
ARIMA |
Good compact state-space benchmark. |
For a longer guide, see docs/MODEL_SELECTION_GUIDE.md.
import java.util.List;
import tslib.dataquality.MissingValueImputer;
import tslib.evaluation.BacktestResult;
import tslib.evaluation.IntervalForecast;
import tslib.evaluation.RollingOriginBacktest;
import tslib.model.ARIMA;
import tslib.model.ARIMAX;
import tslib.model.LocalLevelModel;
import tslib.selection.AutoArima;
import tslib.tests.KPSSTest;
import tslib.transform.Differencing;
List<Double> raw = MissingValueImputer.linearInterpolation(java.util.Arrays.asList(10.0, null, 12.0, 13.0, 14.0));
List<Double> diff = Differencing.difference(raw);
KPSSTest kpss = new KPSSTest(diff);
ARIMA arima = new ARIMA(1, 1, 0).fit(raw);
IntervalForecast intervals = arima.forecastWithIntervals(3, 0.95);
ARIMAX arimax = new ARIMAX(0, 0, 0).fit(
List.of(7.0, 9.0, 11.0, 13.0),
new double[][] {{1.0}, {2.0}, {3.0}, {4.0}});
List<Double> arimaxForecast = arimax.forecast(new double[][] {{5.0}, {6.0}});
RollingOriginBacktest backtest = new RollingOriginBacktest(4, 1);
BacktestResult result = backtest.run(raw, (train, horizon) -> new ARIMA(0, 1, 0).forecast(train, horizon));
AutoArima autoArima = new AutoArima(2, 1, 2, tslib.model.arima.ArimaOrderSearch.Criterion.AIC).fit(raw);
LocalLevelModel localLevel = new LocalLevelModel().fit(raw);tslib is benchmarked against equivalent implementations in Python (statsmodels · pmdarima · pandas · scipy) and R (forecast · tseries · vars · KFAS · TTR · zoo).
Full methodology, raw CSVs, and cross-language comparison are in benchmarks/.
| Algorithm | tslib (ms) | Python (ms) | R (ms) | vs Python | vs R |
|---|---|---|---|---|---|
| Single ETS (α=0.3) | 0.008 | 0.371 | 4.119 | 46× faster | 515× faster |
| Double ETS (α=0.3, γ=0.1) | 0.020 | 1.008 | 8.651 | 50× faster | 433× faster |
| Holt-Winters (α=0.3, s=12) | 0.045 | 1.441 | 38.360 | 32× faster | 852× faster |
| SARIMA(1,1,1)(1,1,0,12) | 0.626 | 49.420 | 8.535 | 79× faster | 14× faster |
| VAR(1) | 0.064 | 0.321 | 4.734 | 5× faster | 74× faster |
| Local Level (MLE) | 0.668 | 3.821 | 14.024 | 6× faster | 21× faster |
| ARIMA(1,1,1) | 2.649 | 12.549 | 6.661 | 5× faster | 3× faster |
| Auto ARIMA (AIC, max p,d,q=3) | 92.74 | 90.563 | 23.881 | ~tie | 2.6× slower |
| Linear imputation (10 NAs) | 0.018 | 0.046 | 0.020 | 3× faster | ~tie |
| Box-Cox λ search | 0.365 | 3.935 | 0.777 | 11× faster | 2× faster |
Measured on macOS Apple Silicon (Java 17 · Python 3.12 · R 4.6). CI (Linux x86) timings are higher; ratios are representative.
| Algorithm | Dataset | tslib | Python | R |
|---|---|---|---|---|
| ARIMA(1,1,1) | hotel (n=168, holdout=12) | 87.41 | 95.20 | 95.20 |
| SARIMA(1,1,1)(1,1,0,12) | airpassengers (n=144, holdout=12) | 18.94 | 16.64 | 16.79 |
| Holt-Winters (α=0.3, β=0.2, γ=0.1) | airpassengers (n=144, holdout=12) | 12.98 | 17.55 | 17.05 |
| Auto ARIMA (AIC) | hotel (n=168, holdout=12) | 88.84 | 95.75 | 95.75 |
| Local Level (MLE) | jj (n=84, holdout=8) | 3.48 | 3.64 | 3.64 |
tslib wins or ties 6 of 8 head-to-heads by MAE. Fixed-parameter models (ETS, VAR, SMA, EMA, WMA) produce numerically identical results across all three libraries.
ARIMA accuracy differences arise from estimation method: tslib uses CLS, Python defaults to innovations-MLE, and R uses CSS. All are valid estimators; CLS generalises better on the hotel series and worse on airpassengers (SARIMA).
The benchmark.yml workflow runs on every push or PR that touches src/ or benchmarks/. It runs the full Java benchmark suite and then executes PerformanceGuard, which fails the build if:
- any accuracy metric (MAE, RMSE, MAPE, smoothing error, remainder variance, …) degrades by more than 2% from the stored baseline
- any execution time exceeds 20× the baseline (generous for CI machine variance)
- any test statistic or model output (ADF statistic, KPSS statistic, Ljung-Box Q, Box-Cox λ) drifts more than 5% from the baseline
To accept an intentional improvement, update benchmarks/results/baseline.csv.
tslib ships a Spring Boot REST API in the tslib-api/ module that exposes the library over HTTP.
Run locally:
./gradlew :tslib-api:bootRunBuild a fat JAR and run:
./gradlew :tslib-api:bootJar
java -jar tslib-api/build/libs/<jar-name>.jarThe server starts on http://localhost:8080. All endpoints are POST with a JSON body, mounted under /api/<group>/.
Explore interactively with the Swagger UI:
http://localhost:8080/swagger-ui
Example clients are in examples/api/:
curl_examples.sh— curl commands for every endpointpython_client.py— Python requestsr_client.R— R httr calls
Docker:
The tslib-api/ module includes a Dockerfile and docker-compose.yml. The image requires the fat JAR to be built first.
- Build the JAR:
./gradlew :tslib-api:bootJar- Build and run the image:
docker build -t tslib-api tslib-api/
docker run -p 8080:8080 tslib-apiOr use Compose (runs from repo root):
docker compose -f tslib-api/docker-compose.yml up --buildThe server is available at http://localhost:8080 in both cases. Compose also wires a healthcheck against /api-docs with a 30s interval.
tslib.transform.Differencingtslib.model.arima.ARIMAtslib.model.ARIMA
tslib.model.arima.SARIMAtslib.model.arima.InformationCriteriatslib.model.arima.ArimaOrderSearchtslib.model.SARIMA
tslib.decomposition.STLDecompositiontslib.tests.KPSSTest
tslib.model.statespace.KalmanFiltertslib.model.statespace.LocalLevelModeltslib.model.LocalLevelModel
tslib.evaluation.ForecastMetricstslib.evaluation.TrainTestSplittslib.evaluation.RollingOriginBacktesttslib.evaluation.BacktestResulttslib.diagnostics.LjungBoxTest
tslib.evaluation.PredictionIntervaltslib.evaluation.IntervalForecast- interval support for ARIMA, SARIMA, and local-level models
tslib.selection.AutoArimatslib.selection.AutoETS
tslib.model.arima.ARIMAXtslib.model.ARIMAX
tslib.dataquality.MissingValueImputertslib.dataquality.OutlierDetectortslib.dataquality.Winsorizer
- release hardening via Gradle bootstrap scripts and publishing config
- CI + tag-based release workflows
- model-selection and release-checklist docs
tslib.evaluation.ModelBenchmarktslib.evaluation.BenchmarkSummary
- release-candidate hardening via stronger edge-case and workflow tests
- README model chooser and testing guidance
- benchmark markdown/report helpers and benchmark-results template
- package-level Javadocs for primary public packages
- Java 17/21 CI matrix plus nightly verification workflow
This snapshot adds release-oriented repo plumbing:
- lightweight
./gradlewbootstrap scripts for Unix and Windows maven-publish, signing, and local build-repo publishing tasks- CI and tag-driven release workflows under
.github/workflows/ docs/MODEL_SELECTION_GUIDE.md,docs/RELEASE_CHECKLIST.md, anddocs/BENCHMARKING.md- a small benchmark helper via
tslib.evaluation.ModelBenchmarkandBenchmarkSummary
For local validation:
./gradlew publishToMavenLocal
./gradlew publishFor tagged builds, see docs/RELEASE_CHECKLIST.md and .github/workflows/release.yml.
See the examples/ directory for runnable snippets:
ForecastExample.javaTransformExample.javaArimaExample.javaSarimaExample.javaStlAndKpssExample.javaLocalLevelExample.javaBacktestExample.javaIntervalsExample.javaAutoSelectionExample.javaArimaxExample.javaDataQualityExample.javaBenchmarkComparisonExample.javaGenerateBenchmarkReportExample.javaHotelBenchmarkComparisonExample.java
Run the full verification flow locally with:
./gradlew clean test jacocoTestReport javadocThe console is configured to print individual test results. HTML reports are generated under build/reports/tests/test and build/reports/jacoco/test/html.
For a release candidate pass, also review docs/RELEASE_CHECKLIST.md, docs/TESTING_GUIDE.md, and docs/BENCHMARK_RESULTS.md.
The ARIMA/SARIMA, state-space, and evaluation additions are intentionally compact and dependency-light. They are designed for readable forecasting workflows inside this library rather than exhaustive econometric coverage.