Skip to main content

Rust-implemented time-series utilities exposed to Python via PyO3.

Project description

rust_timeseries — Python bindings for duration models and tests

rust_timeseries is a Python-first library that wraps high-performance Rust code for:

  • modelling event-time durations with ACD-type models,
  • calling a Rust-implemented maximum-likelihood optimizer,
  • extracting fitted parameters and optimizer diagnostics, and
  • running the Escanciano–Lobato (2009) portmanteau test, which is robust to conditional heteroskedasticity.

All heavy computation lives in Rust; the public surface is a small, typed Python API exposed via the compiled _rust_timeseries extension and the stub files:

  • duration_models.pyi
  • statistical_tests.pyi

This README documents only what is actually exposed through those bindings.


1. Installation

1.1 From PyPI (recommended)

Version 1.0.0 is available on PyPI:

pip install rust_timeseries

The project currently ships wheels for Python 3.11–3.13 on common Linux, macOS, and Windows targets.
For unsupported platforms/versions, you can build from source (see below).

1.2 From source (development / contributing)

You’ll need a recent Rust stable toolchain and Python ≥ 3.11.

Clone the repo and create a virtual environment:

git clone https://github.com/mickwise/rust_timeseries.git
cd rust_timeseries

python -m venv .venv
source .venv/bin/activate      # on Windows: .venv\Scripts\activate
pip install -U pip maturin
maturin develop --release

This builds the extension in place and installs it into your current environment. The Python usage is identical to the PyPI installation.


2. Python modules

The compiled extension _rust_timeseries.* is not imported directly; instead, use the public modules:

rust_timeseries/
    duration_models.py      # ACD models and related utilities
    statistical_tests.py    # Escanciano–Lobato test
    _rust_timeseries.*      # compiled extension (internal)

Use:

import rust_timeseries
from rust_timeseries import duration_models, statistical_tests
# or
from rust_timeseries.duration_models import ACD
from rust_timeseries.statistical_tests import EscancianoLobato

Do not import from internal Rust modules (duration, optimization, etc.). Always go through the public Python modules above.


3. Duration models (rust_timeseries.duration_models)

The duration_models module exposes ACD-type processes via the ACD class.

Note: Only the main surface API is documented here.
For full signatures, see the Python type stubs (duration_models.pyi) and the docstrings.

3.1 Minimal example

import numpy as np
from rust_timeseries.duration_models import ACD

# synthetic durations (strictly positive floats)
durations = 1.0 + np.abs(np.random.randn(200))

# unconstrained parameter guess (length 1 + p + q)
theta0 = np.zeros(3, dtype=np.float64)  # (ω, α₁, β₁)

# configure ACD(1,1); see docstring for all options
model = ACD(data_length=len(durations), p=1, q=1)

# fit model in unconstrained parameter space
model.fit(durations=durations, theta0=theta0)

# short-horizon forecast of conditional duration
psi_hat = model.forecast(durations=durations, horizon=5)
print("ψ(5) =", psi_hat)

# classical vs. HAC-robust covariance matrices for θ
cov_classical = model.covariance_matrix(durations, robust=False)
cov_hac       = model.covariance_matrix(durations, robust=True)

print("classical cov shape:", np.asarray(cov_classical).shape)
print("HAC cov shape      :", np.asarray(cov_hac).shape)

Key methods (high level):

  • ACD(data_length: int, p: int, q: int, **options)
    Construct an ACD(p, q) model for a given sample length. Extra options (e.g., stationarity margins, backcasting choices) are documented in the class docstring.

  • fit(durations: np.ndarray, theta0: np.ndarray, ...) -> None
    Estimate parameters in an unconstrained space (internally mapped to a stationary region).

  • forecast(durations: np.ndarray, horizon: int, ...) -> float
    Run an out-of-sample forecast and return the final ψ at the requested horizon.

  • covariance_matrix(durations: np.ndarray, robust: bool = False, ...) -> list[list[float]]
    Return model-based (robust=False) or HAC-robust (robust=True) covariance matrices for the unconstrained parameter vector.

  • standard_errors(...) -> list[float]
    Convenience wrapper that returns just the standard errors (diagonal of the chosen covariance matrix).

  • results -> ACDOptimOutcome
    Optimizer diagnostics (status, iterations, gradient norm, evaluation counts, etc.).

  • fitted_params -> ACDFittedParams
    Fitted model-space parameters (ω, slack, α, β, ψ-lags) that satisfy the stationarity and positivity constraints enforced in Rust.

3.2 Constructors and variants

The main constructor:

ACD(
    data_length: int,
    p: int,
    q: int,
    *,
    init=None,
    init_fixed=None,
    init_psi_lags=None,
    init_durations_lags=None,
    tol_grad=None,
    tol_cost=None,
    max_iter=None,
    line_searcher=None,
    lbfgs_mem=None,
    psi_guards=None,
)

An exponential innovation distribution is used by default. Two alternative constructors are available:

  • ACD.wacd(...) – Weibull-innovation ACD(p, q) with shape parameter k.
  • ACD.gacd(...) – generalized-gamma-innovation ACD(p, q) with shape parameters p_shape and d_shape.

Both accept the same core configuration arguments as ACD (data_length, p, q, optimizer settings), plus their respective shape parameters.

3.3 Standard errors (ACD.covariance_matrix)

covariance_matrix computes parameter covariance matrix for a given duration series, optionally with HAC corrections:

se = model.covariance_matrix(
    durations=durations,
    unit="seconds",
    t0=None,
    diurnal_adjusted=False,
    robust=True,
    kernel="bartlett",
    bandwidth=None,
    center=False,
    small_sample_correction=True,
)
  • When robust=False, covariance matrix is based on the model-based information matrix.
  • When robust=True, a HAC estimator is used (kernel and bandwidth options are forwarded to the Rust implementation).

3.4 Optimization diagnostics (ACDOptimOutcome)

The results property returns an ACDOptimOutcome object, wrapping the Rust OptimOutcome type.

Attributes:

  • theta_hat: list[float] – unconstrained parameter vector at the solution.
  • value: float – objective value at the solution.
  • converged: bool – whether the optimizer terminated successfully.
  • status: str – human-readable termination reason.
  • iterations: int – number of iterations taken.
  • grad_norm: float | None – norm of the gradient at the solution, when available.
  • fn_evals: list[tuple[str, int]] – evaluation counters keyed by function name.

Typical usage:

outcome = model.results
print("Converged:", outcome.converged, "-", outcome.status)
print("Objective value:", outcome.value)
print("Iterations:", outcome.iterations)
print("Gradient norm:", outcome.grad_norm)
print("Function evals:", outcome.fn_evals)

3.5 Fitted parameters (ACDFittedParams)

The fitted_params property returns an ACDFittedParams instance that mirrors the Rust ACDParams struct:

  • omega: float – baseline level parameter.
  • slack: float – positive slack term used to enforce strict stationarity.
  • alpha: list[float] – ARCH-type coefficients (size p).
  • beta: list[float] – GARCH-type coefficients (size q).
  • psi_lags: list[float] – initialization lags for ψₜ.

Example:

params = model.fitted_params
print("omega:", params.omega)
print("slack:", params.slack)
print("alpha:", params.alpha)
print("beta:", params.beta)
print("psi_lags:", params.psi_lags)

All invariants (positivity, stationarity, shape constraints) are enforced on the Rust side; Python sees only valid parameter configurations.


4. Escanciano–Lobato test (rust_timeseries.statistical_tests)

The statistical_tests module currently exposes a single class, EscancianoLobato, implementing the Escanciano–Lobato heteroskedasticity proxy test.

4.1 Constructing EscancianoLobato

import numpy as np
from rust_timeseries.statistical_tests import EscancianoLobato

residuals = np.asarray(residuals, dtype=float)

el = EscancianoLobato(
    residuals,  # 1-D array-like of float64, no NaNs, length >= 1
    q=2.4,      # positive float proxy order (optional)
    d=None,     # positive integer max lag; default floor(n**0.2)
)

Signature (from statistical_tests.pyi):

class EscancianoLobato:
    def __init__(
        self,
        data,
        q: float | None = 2.4,
        d: int | None = None,
    ) -> None: ...

Validation rules enforced in the bindings:

  • data must be non-empty and contain no NaNs;
  • q must be positive when provided;
  • d must be positive when provided.

Invalid inputs raise a ValueError from the PyO3 binding.

4.2 Accessing test results

EscancianoLobato wraps a Rust ELOutcome and exposes three read-only properties:

  • statistic: float – the test statistic;
  • pvalue: float – asymptotic p-value under the null;
  • p_tilde: int – data-driven lag choice that maximizes the penalized statistic.

Example:

print("EL statistic:", el.statistic)
print("EL p-value  :", el.pvalue)
print("Selected lag p~:", el.p_tilde)

5. Design notes

  • Python-first. The core lives in Rust, but the bindings are designed so that quantitative researchers can stay in Python. Inputs are standard array-like objects (numpy.ndarray, pandas.Series, lists); outputs are plain Python scalars and lists.
  • Tight coupling to Rust invariants. The PyO3 layer performs shape checks, basic validation, and error mapping. All model invariants (positivity, stationarity, etc.) are enforced in the Rust types (ACDModel, ACDParams, ELOutcome).
  • Explicit error reporting. Rust errors (through the ACDError type) are surfaced as Python exceptions with clear messages. Fitted-state-dependent getters (results, fitted_params) fail loudly if you call them before fit.
  • Minimal, inspectable objects. The Python wrappers (ACD, ACDOptimOutcome, ACDFittedParams, EscancianoLobato) are intentionally small and read-only. They are easy to log, serialize, or convert to dictionaries for downstream analysis.

6. Status and extension points

The current Python API is intentionally narrow and corresponds exactly to the bindings implemented in lib.rs and documented in duration_models.pyi and statistical_tests.pyi.

Natural extensions (planned to be added in Rust and then surfaced via the same binding pattern) include:

  • simulation module for the ACD family.
  • further goodness-of-fit and residual tests under statistical_tests,
  • exposing of covariance estimation through python as a standalone module.

When extending the library, keep the following steps:

  1. Add functionality in the Rust core.
  2. Expose it through a PyO3 wrapper (#[pyclass] / #[pymethods]).
  3. Update the .pyi stubs to match.
  4. Update this README to document the new public surface.

This keeps the README, stubs, and compiled extension in sync.


7. License

rust_timeseries is released under the MIT license. See LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rust_timeseries-1.1.0.tar.gz (1.2 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

rust_timeseries-1.1.0-cp313-cp313-win_amd64.whl (438.7 kB view details)

Uploaded CPython 3.13Windows x86-64

rust_timeseries-1.1.0-cp313-cp313-manylinux_2_34_x86_64.whl (612.6 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.34+ x86-64

rust_timeseries-1.1.0-cp313-cp313-macosx_11_0_arm64.whl (529.8 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

rust_timeseries-1.1.0-cp312-cp312-win_amd64.whl (439.0 kB view details)

Uploaded CPython 3.12Windows x86-64

rust_timeseries-1.1.0-cp312-cp312-manylinux_2_34_x86_64.whl (612.9 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.34+ x86-64

rust_timeseries-1.1.0-cp312-cp312-macosx_11_0_arm64.whl (530.0 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

rust_timeseries-1.1.0-cp311-cp311-win_amd64.whl (438.4 kB view details)

Uploaded CPython 3.11Windows x86-64

rust_timeseries-1.1.0-cp311-cp311-manylinux_2_34_x86_64.whl (612.5 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.34+ x86-64

rust_timeseries-1.1.0-cp311-cp311-macosx_11_0_arm64.whl (535.7 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

File details

Details for the file rust_timeseries-1.1.0.tar.gz.

File metadata

  • Download URL: rust_timeseries-1.1.0.tar.gz
  • Upload date:
  • Size: 1.2 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for rust_timeseries-1.1.0.tar.gz
Algorithm Hash digest
SHA256 25dfd40c117c77d753354918bc67ba822671cb2bb58bf8d32bd44fd190d5ed67
MD5 62e3f77e440b3ec6b0327883996bf092
BLAKE2b-256 7f8aa3eea5219d8d13a8e8001d510b3fb1ba2abcc1f8812953a8f59ada1d85a3

See more details on using hashes here.

File details

Details for the file rust_timeseries-1.1.0-cp313-cp313-win_amd64.whl.

File metadata

File hashes

Hashes for rust_timeseries-1.1.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 8c60849f87c8bd19d47729c0b73509edbb071724088ab7f1260fb592a99bb9ad
MD5 61b8524c63e63e87eb7f557107ca8d8c
BLAKE2b-256 a7696e657b0fb0812add91dd00fdd7ecf7df0b4eba43f2977c1f2aabd58de9f0

See more details on using hashes here.

File details

Details for the file rust_timeseries-1.1.0-cp313-cp313-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for rust_timeseries-1.1.0-cp313-cp313-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 02fe42719b674181a60198d1fa105c405d4ea7976d78b79ca9b5c205c77e6409
MD5 7573af68b0d1cf7008148f90e706ca2a
BLAKE2b-256 054610f38f868900228bd36b5cc43737e198d5fbc8546e5331e13575e1d8a05a

See more details on using hashes here.

File details

Details for the file rust_timeseries-1.1.0-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for rust_timeseries-1.1.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 42f9b0e085a9b26841e7d0fa000fd4501d0389c21d28d1a82426d762d8b0f1af
MD5 87fc5ce43663d673fe4f5f1252631e0d
BLAKE2b-256 1425f213bf317b3e9530aaf324dfd36a55cf8153cc83b8b1dfea5c6dc7c9e550

See more details on using hashes here.

File details

Details for the file rust_timeseries-1.1.0-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for rust_timeseries-1.1.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 91768b55805713949068c21abab08d3220d83d3eaed24d9b27953b395b48949e
MD5 1ec90cda1d382dfbf589f3d4fa9c3bbf
BLAKE2b-256 c64bfdcdc56f46387a96cb68ed87cc5d2b6d062995986b7ca06db2a989149314

See more details on using hashes here.

File details

Details for the file rust_timeseries-1.1.0-cp312-cp312-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for rust_timeseries-1.1.0-cp312-cp312-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 e20b18b7cd5f2ee5ae1f6603ad7a81f6c1a4c999ccf65531b3babdc2140a27da
MD5 bd2a008b3e3214d2b44bcaac8be69e73
BLAKE2b-256 36ce7f7a67e3dc8465589abdf9fc108cc2b684e759d50086643e939d2e2c42a1

See more details on using hashes here.

File details

Details for the file rust_timeseries-1.1.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for rust_timeseries-1.1.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7e026b126e46050fe2a54b0dbb1b4f46c8f77bf4723341c1d0322b3d187dfdaa
MD5 ef999872b48ff10618a3785f8b4f32c4
BLAKE2b-256 97a8673174733ba7502f26393e946de24ca1205af4e4cb0a51bc532d81e06a47

See more details on using hashes here.

File details

Details for the file rust_timeseries-1.1.0-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for rust_timeseries-1.1.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 3fe45c2c2dcb945b59817c65e5583afd2f8f0e2e3f15f3415f86818701193d31
MD5 e18b61d94d9fda26ef82c7b175ec340f
BLAKE2b-256 390b2a1045482dd166e684f0013ea1bfac3740626813525e65a31602b2ec72bc

See more details on using hashes here.

File details

Details for the file rust_timeseries-1.1.0-cp311-cp311-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for rust_timeseries-1.1.0-cp311-cp311-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 acc046ee5b8c2dcad32220278fe2a302c62310383184aea15993c64fdb6d95e5
MD5 baec035ad9d249ee0bcd42d3d22845d7
BLAKE2b-256 660cf0b10e38ef5b50287daaf12c0db211a237b2b6a44911842889d713c05b65

See more details on using hashes here.

File details

Details for the file rust_timeseries-1.1.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for rust_timeseries-1.1.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e2a5062b621a525dc6164c0e5d606f0cf8a37d1207613f49cc7f34048f86f4dd
MD5 2a281bbb01ea38b932882c668321406c
BLAKE2b-256 0d1a09dd6664254f10d61a7826e7b94b865cc1365421914702773bee705e3879

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page