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).
# 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 -qStep 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.52sThe just equivalents
Section titled “The just equivalents”The same flow is wrapped in the justfile, if you have
just:
just py-setup # uv venv --python 3.13 .venv && uv sync --group devjust py-develop # maturin develop (debug build)just py-develop-release # maturin develop --releasejust py-import-smoke # import openquant; print('openquant bindings OK')just py-test # pytest python/tests -qDebug or release
Section titled “Debug or release”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.
Building a wheel
Section titled “Building a wheel”maturin develop installs in place, which is what you want for
development. To produce a distributable wheel:
uv run --python .venv/bin/python --with maturin \ maturin build --manifest-path crates/pyopenquant/Cargo.toml --out distThe 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.
Smoke test the real surface
Section titled “Smoke test the real surface”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.
What you installed
Section titled “What you installed”import openquant re-exports two different kinds of thing
(python/openquant/__init__.py):
| Attribute | Kind | Comes 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_allocation | compiled | openquant._core, i.e. the Rust crate |
bars, data, pipeline, backtesting_engine, cross_validation, feature_importance, hyperparameter_tuning, evaluation, feature_diagnostics, research, adapters, viz | Python | python/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.
- Python Core Workflow — a runnable end-to-end research loop
- Troubleshooting — when the compile step fails