OpenQuant
OpenQuant is a library of the building blocks in Advances in Financial Machine Learning (AFML): event-driven bars, CUSUM filters, triple-barrier and meta-labels, sample weights, fractional differentiation, purged cross-validation, backtest statistics, bet sizing, and hierarchical portfolio construction. The numerical core is Rust; a PyO3 extension exposes it to Python. Functions take plain sequences, and the data-loading layer works in Polars frames.
Status
Section titled “Status”Pre-release. Version 0.1.0 is not on PyPI or crates.io, so installing means building from source: about 10–20 minutes the first time, seconds afterwards. The Quickstart takes you from a clone to a printed result.
Releases are published on PyPI as pyopenquant (from v0.1.0, pip install pyopenquant); the import name is openquant. Do not pip install openquant —
that name on PyPI belongs to an unrelated project.
What using it looks like
Section titled “What using it looks like”Sample events from a price series with a CUSUM filter, then label each event by the first barrier its price path touches:
import math, randomfrom datetime import datetime, timedeltafrom openquant import filters, labeling
# 500 one-minute bars of a seeded random walk. No market data needed.random.seed(7)start = datetime(2024, 1, 2, 9, 30)times = [(start + timedelta(minutes=i)).strftime("%Y-%m-%d %H:%M:%S") for i in range(500)]close = [100.0]for _ in range(499): close.append(close[-1] * math.exp(random.gauss(0, 0.001)))
# AFML ch. 2: emit an event only when cumulative drift exceeds 0.4%.events = filters.cusum_filter_timestamps(close, times, 0.004)
# AFML ch. 3: barriers at +/-0.5%, and a vertical barrier 30 minutes out.vertical = labeling.add_vertical_barrier(events, times, num_minutes=30)labels = labeling.triple_barrier_labels( times, close, events, events, [0.005] * len(events), pt=1.0, sl=1.0, vertical_barrier_times=vertical,)
print(f"{len(close)} bars -> {len(events)} events -> {len(labels)} labels")print("first label:", labels[0])print("label counts:", {b: sum(1 for row in labels if row[3] == b) for b in (-1, 1)})The walk is seeded, so this prints the same thing every time:
500 bars -> 42 events -> 41 labelsfirst label: ('2024-01-02 09:49:00', -0.001163909562213905, 0.005, -1, None)label counts: {-1: 18, 1: 23}Each label is (event time, return at first touch, target, label, side). The
first event never reached either ±0.5% barrier: it ran into the 30-minute
vertical barrier with a return of −0.12%, so it is labelled by the sign of that
return. There are 41 labels for 42 events because the last event’s vertical
barrier falls past the end of the data and neither horizontal barrier was
touched: its outcome is not known yet, so it gets no label instead of an invented
one. This example runs in CI on every change to the docs; if the API moves, the
build fails before this page goes stale.
What is implemented
Section titled “What is implemented”Every module is a Rust API. The Python column says whether the compiled extension exposes it today.
| AFML chapters | Modules | Python |
|---|---|---|
| 2 · Data structures | data_structures, filters | yes |
| etf_trick | Rust only | |
| 3 · Labeling | labeling | yes |
| 4 · Sample weights | sampling, sample_weights, sb_bagging | yes |
| 5–6 · Features, ensembles | fracdiff, ensemble_methods | yes |
| 7 · Cross-validation | cross_validation | Rust only |
| 8–9 · Importance, tuning | feature_importance, fingerprint, hyperparameter_tuning | Rust only |
| 10 · Bet sizing | bet_sizing | yes |
| 11–13 · Backtesting | backtesting_engine | Rust only |
| synthetic_backtesting | yes | |
| 14–15 · Statistics, risk | backtest_statistics, risk_metrics, strategy_risk | yes |
| 16 · Portfolio construction | hrp, hcaa, onc, cla, portfolio_optimization | yes |
| 17–19 · Breaks, microstructure | structural_breaks, microstructural_features, codependence | yes |
| 20–22 · HPC | streaming_hpc | yes |
| hpc_parallel, combinatorial_optimization | Rust only |
The Rust-only rows are the gap that matters most for research: purged
cross-validation and the CPCV backtester are not callable from Python yet. The
module index lists everything, including the pure-Python layers
(data, pipeline, research, viz), and
By AFML Chapter maps book sections to APIs.
How far to trust it
Section titled “How far to trust it”- Tests. The Rust suite runs on every pull request. About half of its test files check results against fixtures derived from mlfinlab’s tests; the rest use inline data with no external reference yet.
- Page status. Every page carries a status. Most module pages are still marked generated — assembled from templates and not yet read by a person against the book. Setup, quickstart and workflow pages are reviewed. Coverage has the current counts.
- Examples. Rust snippets on module pages are compiled in CI, and Python snippets are executed, unless a snippet is explicitly marked as illustrative.
- Open work is tracked in GitHub issues.
Timings
Section titled “Timings”Criterion means from the regression baseline CI compares each pull request against, recorded 2026-02-07. The hardware was not recorded and there is no comparison against another library, so read these as orders of magnitude.
| Benchmark | Mean |
|---|---|
| EWMA over 100,000 points | 4.7 ms |
| VaR, expected shortfall and CDaR on the synthetic ticker set | 8.0 ms |
| Sequential bootstrap, 2,000 samples × 600 draws | 384 ms |
SADF structural-break statistic (sm_power) | 602 ms |
Where to go next
Section titled “Where to go next”- To run something: Quickstart, then the Python workflow.
- To work on the Rust core: Prerequisites, Local build, Rust workflow.
- To review methodology: Methodology and leakage controls, then the research gallery.