Skip to main content

BATS and TBATS time series forecasting

Package provides BATS and TBATS time series forecasting methods described in:

De Livera, A.M., Hyndman, R.J., & Snyder, R. D. (2011), Forecasting time series with complex seasonal patterns using exponential smoothing, Journal of the American Statistical Association, 106(496), 1513-1527.

Installation

From pypi:

python -m pip install tbats

Import via:

from tbats import BATS, TBATS

Minimal working example:

from tbats import TBATS
import numpy as np

# required on windows for multi-processing,
# see https://docs.python.org/2/library/multiprocessing.html#windows
if __name__ == '__main__':
    np.random.seed(2342)
    t = np.array(range(0, 160))
    y = 5 * np.sin(t * 2 * np.pi / 7) + 2 * np.cos(t * 2 * np.pi / 30.5) + \
        ((t / 20) ** 1.5 + np.random.normal(size=160) * t / 50) + 10
    
    # Create estimator
    estimator = TBATS(seasonal_periods=[14, 30.5])
    
    # Fit model
    fitted_model = estimator.fit(y)
    
    # Forecast 14 steps ahead
    y_forecasted = fitted_model.forecast(steps=14)
    
    # Summarize fitted model
    print(fitted_model.summary())

Reading model details

# Time series analysis
print(fitted_model.y_hat) # in sample prediction
print(fitted_model.resid) # in sample residuals
print(fitted_model.aic)

# Reading model parameters
print(fitted_model.params.alpha)
print(fitted_model.params.beta)
print(fitted_model.params.x0)
print(fitted_model.params.components.use_box_cox)
print(fitted_model.params.components.seasonal_harmonics)

See examples directory for more details.

Troubleshooting

BATS and TBATS tries multitude of models under the hood and may appear slow when fitting to long time series. In order to speed it up you can start with constrained model search space. It is recommended to run it without Box-Cox transformation and ARMA errors modelling that are the slowest model elements:

# Create estimator
estimator = TBATS(
    seasonal_periods=[14, 30.5],
    use_arma_errors=False,  # shall try only models without ARMA
    use_box_cox=False  # will not use Box-Cox
)
fitted_model = estimator.fit(y)

In some environment configurations parallel computation of models freezes. Reason for this is unclear yet. If the process appears to be stuck you can try running it on a single core:

estimator = TBATS(
    seasonal_periods=[14, 30.5],
    n_jobs=1
)
fitted_model = estimator.fit(y)

For Contributors

Setup and locked development environment

Install uv 0.12.3, then create the locked development environment:

uv sync --locked

The committed uv.lock is a universal development and CI lock for Python 3.10–3.13. It is not a consumer installation requirement; consumers install the package with pip or another standards-compliant installer. Update it deliberately after dependency changes:

uv lock

Testing

Run the non-R unit and integration suite:

uv run --locked python -m pytest test/

Run the bounded explicit-spawn smoke check for BATS and TBATS:

uv run --locked python scripts/spawn_smoke.py

R forecast package comparison tests are separate from normal development, CI, and release validation. They require R, the R forecast package, and the optional Python R extra:

uv sync --locked --extra r
uv run --locked --extra r python -m pytest test_R/

If R packages live in a custom user library, set R_LIBS_USER for that command (for example, R_LIBS_USER=/path/to/R/library uv run --locked --extra r python -m pytest test_R/).

Release checks

Run the reviewed snapshot validation and build checks before a release:

./prepare_package.sh
uv build --no-sources
uvx --from twine==7.0.0 twine check dist/*

prepare_package.sh runs the locked non-R suite, explicit-spawn smoke check, build, and metadata check. publish_package.sh is a local preflight only; it never uploads or creates tags.

To release a new version, bump tbats.__version__, commit it on master, ensure all CI jobs are green, and create and push the protected signed v<version> tag. Then publish a GitHub Release for that existing tag, for example:

gh release create v1.2.0 --verify-tag --generate-notes --title "tbats 1.2.0"

Publishing the GitHub Release makes it visible on the Releases page and triggers PyPI OIDC. The release workflow checks that the release tag starts with v, checks out that exact tag, and verifies its commit is on master. It then rebuilds a fresh dist/ and fails closed unless it contains exactly one matching wheel and sdist. It validates both embedded metadata files and records SHA-256 hashes before installing and smoking the exact wheel externally. The later upload is bound to those two validated paths; the publish job downloads that exact artifact, validates it again, recomputes and compares both hashes, and only then publishes through PyPI Trusted Publishing. Existing version 1.1.3 cannot be republished.

One-time release administration: configure the PyPI Trusted Publisher with owner intive-DataScience, repository tbats, workflow publish.yml, and environment pypi. Protect the GitHub pypi environment and v* tags. No PyPI token secret is used.

Comparison to R implementation

Python implementation is meant to be as much as possible equivalent to R implementation in forecast package.

Metadata

Release files for tbats 1.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tbats 1.2.0
File Size Uploaded
tbats-1.2.0.tar.gz 34.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tbats 1.2.0
File Interpreter ABI Platform
tbats-1.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 79.7 kB

Release files / tbats-1.2.0.tar.gz

Download URL tbats-1.2.0.tar.gz
Size 34.5 kB
Tags Source
SHA-256 checksum
How to use checksums
fc6002009fc74636109fd2bec308693ead566a84eb6631b67a9edf24b34ab5b0
BLAKE2b-256 checksum
How to use checksums
7f28d51e9813cb06aba55a212c4feae8ec370cc1178fbd379080f5798830ec7f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release files / tbats-1.2.0-py3-none-any.whl

Download URL tbats-1.2.0-py3-none-any.whl
Size 45.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b877fbffd46fb27c7bc6903dfdd42de6d80087f3bcd73381606c6c5af6c554d4
BLAKE2b-256 checksum
How to use checksums
fd2d1a195becb944ac8b9a38067a177dbfffd121a8b983df41e350cb2cbfadb6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.2.0 This release

2 release files

1.1.3

2 release files

1.1.2

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.10

2 release files

1.0.9

2 release files

1.0.8

2 release files

1.0.7

2 release files

1.0.6

2 release files

1.0.5

2 release files

1.0.4

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page