Skip to content
AuthoredWritten by hand against the code; every example on it is executed by the docs checks. No human has reviewed this page yet.

Python Bindings Setup

OpenQuant is not on PyPI yet. The Python package is a thin pure-Python layer (python/openquant/) over a compiled PyO3 extension (crates/pyopenquant/, built as openquant._core), so getting it means building it. Releases are published on PyPI as pyopenquant (from v0.1.0, pip install pyopenquant installs a prebuilt wheel); the import name is openquant. Do not pip install openquant: that name on PyPI belongs to an unrelated project, so the command succeeds and installs the wrong package.

Before you start: Prerequisites. You need a Rust toolchain, a linker, and uv.

Four commands, from the repository root. The python jobs in .github/workflows/ci.yml run the same build on every PR, on Python 3.11 and 3.13 (CI installs maturin from the dev dependency group rather than with --with; the result is the same).

Terminal window
# 1. Create an isolated interpreter. CI builds against 3.11 and 3.13.
uv venv --python 3.11 .venv
# 2. Compile the extension and install it into that environment.
uv run --python .venv/bin/python --with maturin \
maturin develop --manifest-path crates/pyopenquant/Cargo.toml
# 3. Prove it imports.
uv run --python .venv/bin/python python -c "import openquant; print('openquant bindings import ok')"
# 4. Prove it works.
uv run --python .venv/bin/python --with pytest pytest python/tests -q

Step 2 compiles the whole Rust workspace — polars, nalgebra and their dependency trees. Budget 10–20 minutes on a cold cache; subsequent runs are incremental and take seconds.

Expected output from steps 3 and 4:

openquant bindings import ok
................................ [100%]
32 passed in 2.52s

The same flow is wrapped in the justfile, if you have just:

Terminal window
just py-setup # uv venv --python 3.13 .venv && uv sync --group dev
just py-develop # maturin develop (debug build)
just py-develop-release # maturin develop --release
just py-import-smoke # import openquant; print('openquant bindings OK')
just py-test # pytest python/tests -q

maturin develop compiles a debug extension by default: quick to build, and correct, but unoptimised. That is fine for tests and most of the API. Numerically heavy calls are a different matter — a full-series SADF run can take minutes per model in a debug build. Before timing anything or running a long research job, rebuild with maturin develop --release (or just py-develop-release). maturin build, used for wheels below, already builds in release mode.

maturin develop installs in place, which is what you want for development. To produce a distributable wheel:

Terminal window
uv run --python .venv/bin/python --with maturin \
maturin build --manifest-path crates/pyopenquant/Cargo.toml --out dist

The wheel lands in dist/. It is a stable-ABI (abi3) wheel: pyproject.toml sets [tool.maturin] features = ["pyo3/abi3-py311"], so one wheel installs on CPython 3.11 and every later version, on the platform it was built for. Build from the repository root so maturin reads that setting from pyproject.toml.

Once step 3 passes, this exercises the layer you actually came for. It runs entirely on generated data, so it needs no market data feed:

from openquant.research import make_synthetic_futures_dataset, run_flywheel_iteration
dataset = make_synthetic_futures_dataset(n_bars=192, seed=7)
result = run_flywheel_iteration(dataset)
print(result["summary"])
print(result["promotion"])

result["summary"] is a polars.DataFrame, result["promotion"] a dict of boolean gates. For what the numbers mean, see Python Core Workflow.

import openquant re-exports two different kinds of thing (python/openquant/__init__.py):

AttributeKindComes from
risk, filters, sampling, labeling, bet_sizing, portfolio, fracdiff, fast_ewma, volatility, codependence, backtest_stats, sample_weights, microstructural, strategy_risk, ensemble, structural_breaks, synthetic_bt, ef3m, streaming_hpc, hrp, hcaa, onc, cla, sb_bagging, dynamic_allocationcompiledopenquant._core, i.e. the Rust crate
bars, data, pipeline, backtesting_engine, cross_validation, feature_importance, hyperparameter_tuning, evaluation, feature_diagnostics, research, adapters, vizPythonpython/openquant/*.py

The extension registers 32 submodules: the 25 in the first row, re-exported unchanged, plus bars, data, pipeline, backtesting_engine, cross_validation, feature_importance and hyperparameter_tuning, which the Python modules of the same name wrap (the compiled ones stay reachable as openquant._core.<name>). Only the first row requires the compile step. That is why editing a file under python/openquant/ takes effect immediately, while editing anything under crates/ needs maturin develop re-run.

Runtime dependencies are numpy>=1.26,<3, polars>=1.28.1,<2 and pyarrow>=15,<26 (pyproject.toml); uv installs them for you.