Skip to content

OpenQuant

The methods from López de Prado's Advances in Financial Machine Learning, implemented in Rust and callable from Python.

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.

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.

Sample events from a price series with a CUSUM filter, then label each event by the first barrier its price path touches:

import math, random
from datetime import datetime, timedelta
from 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 labels
first 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.

Every module is a Rust API. The Python column says whether the compiled extension exposes it today.

AFML chaptersModulesPython
2 · Data structuresdata_structures, filtersyes
etf_trickRust only
3 · Labelinglabelingyes
4 · Sample weightssampling, sample_weights, sb_baggingyes
5–6 · Features, ensemblesfracdiff, ensemble_methodsyes
7 · Cross-validationcross_validationRust only
8–9 · Importance, tuningfeature_importance, fingerprint, hyperparameter_tuningRust only
10 · Bet sizingbet_sizingyes
11–13 · Backtestingbacktesting_engineRust only
synthetic_backtestingyes
14–15 · Statistics, riskbacktest_statistics, risk_metrics, strategy_riskyes
16 · Portfolio constructionhrp, hcaa, onc, cla, portfolio_optimizationyes
17–19 · Breaks, microstructurestructural_breaks, microstructural_features, codependenceyes
20–22 · HPCstreaming_hpcyes
hpc_parallel, combinatorial_optimizationRust 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.

  • 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.

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.

BenchmarkMean
EWMA over 100,000 points4.7 ms
VaR, expected shortfall and CDaR on the synthetic ticker set8.0 ms
Sequential bootstrap, 2,000 samples × 600 draws384 ms
SADF structural-break statistic (sm_power)602 ms