Changelog
Notable changes to OpenQuant, newest first within each section. The Rust crate is published
on crates.io as openquant and the Python package on PyPI as pyopenquant (import name
openquant). Changes not yet in a tagged release sit under Unreleased; when a version
is tagged, its entries move under a heading with that version and date.
Each entry links the pull request that made the change; the linked issue, where there is
one, is in parentheses. Entries were seeded from the titles of the merged pull requests.
From now on, a pull request with a user-visible effect adds one line to the right section
below, in the same style as its title. The docs site renders this file as its Changelog
page (python3 scripts/docs/generate_site_pages.py --write; CI fails if the page and this
file disagree).
Unreleased
Section titled “Unreleased”0.1.0 - 2026-10-01
Section titled “0.1.0 - 2026-10-01”First release.
- Release: the PyPI distribution name is
pyopenquant(#58) cross_validation: walk-forward splits over the purged k-fold folds, a no-signal null through any splits, and the purged k-fold bias toward features with memory documented; runbooks 11 to 14 audited, no conclusion changed (#217)- Runbook 14, fracdiff features against returns in a purged-CV classifier, net of costs (#209) (#216)
- Docs: a research gallery generated from the executed runbooks, a performance page generated from
benchmarks/, and this changelog on the site; the governance stubs folded into one page (#55) (#207) hcaa: linkage option (single, complete, average, ward), Ward by default (#197) (#203)- Runbooks 11 and 13: a sequential-bootstrap bagging comparison, and the workarounds for #187 removed (#199)
hcaa:distanceoption shared with HRP, pairwise default kept (#188) (#195)- Runbook 13, bet sizing from predicted probabilities (#50) (#191)
- Runbook 12, CPCV backtest with PSR and the deflated Sharpe ratio (#48) (#179)
- Runbook 11, triple-barrier labeling and meta-labeling (#47) (#181)
- Runbook 10, HRP against inverse-variance and CLA out of sample (#51) (#149)
- Runbook 09, fracdiff stationarity versus memory (#49) (#148)
- Notebooks executed with nbclient, committed with outputs and figures, and run in CI (#45) (#146)
- Python bindings for purged CV, CPCV backtesting, feature importance and tuning (#42) (#143)
openquant.data.fetchwith a Parquet cache, the dataset hash in run manifests, andDATA_SOURCES.md(#43) (#141)openquant.evaluation: PSR, DSR, MinTRL and a trial registry (#44) (#139)- Recovered stranded work: purged-CV diagnostics, CPCV and pipeline plots re-ported, outcomes recorded (#33) (#137)
- AFML Chapter 21 pigeonhole-partition trajectory search (#112) (#131)
- The Critical Line Algorithm; the
clamodule was a stub (#76) (#83) streaming_hpcanalytics utilities, AFML Chapter 22 (#12)- Combinatorial optimization adapters, AFML Chapter 21 (#11)
hpc_parallelutilities, AFML Chapter 20 (#10)- Typed error APIs for
bet_sizingandfilters(#9) - Strategy risk diagnostics, AFML Chapter 15 (#8)
- Synthetic backtesting, AFML Chapter 13 (#7)
- Backtesting engine and CPCV, AFML Chapters 11–12 (#6)
hyperparameter_tuning, AFML Chapter 9 (#5)ensemble_methods, AFML Chapter 6 (#4)- AFML notebook platform and a real-data end-to-end research workflow (#3)
- Notebook-first AFML research platform: bindings, pipeline, notebooks, CI (#2)
onc: k-means++ initialisation, as in MLAM Snippet 4.1; results were fragile to the random stream;get_onc_clusters_with_seedand a Pythonseedargument (#218) (#224)data_processing:keep_lastkeeps the last input row of a duplicated key (stable sort), and the calendar join keeps its order explicitly (#220) (#222)- A binding default that always failed, ignored parameters and silent drops (#194) (#202)
- Input validation and minor cleanups from the rustdoc audit (#186) (#204)
- Docs/code mismatches in
pipeline,hcaa,onc,cross_validation,combinatorial_optimization,microstructural_featuresandstreaming_hpc(#185) (#201) sb_baggingrejects a wrong column count and wraps the warm-start seed (#184) (#196)- Typed errors instead of reachable panics, overflows and infinite loops (#184) (#193)
- Python API gaps found by the meta-labeling runbook (#187) (#190)
claerror variants and panic guard,data_processingoff-grid report and gap rule,strategy_riskunreachable targets (#168) (#189)hrpclusters on AFML’s distance of distances by default (#167) (#183)- Chu-Stinchcombe-White: σ²ₜ is the mean of the squared differences (#173) (#182)
get_sadfquadratic and sub/super-martingale models follow AFML §17.4 (#166) (#178)get_yang_zhang_volimplements Yang and Zhang (2000) (#165) (#176)- An event on the last bar with no vertical barrier keeps
t1 = None(#162) (#175) - ETF-trick holdings are sized from the previous bar, per AFML §2.4.1 (#164) (#174)
bet_sizinglimit price defined for reducing, short and sign-flipping moves (#163) (#172)get_weights_ffdhonourslimfor every value, sothresh <= 0cannot hang (#169) (#171)PurgedKFoldembargoes only after each test block, from the end of the purge (#134) (#170)- Python binding ergonomics before the API is published (#77) (#145)
bias_variance_noisereports real noise only given the noiseless target (#128) (#140)ef3mfive-moment variant fits about the mean, so μ₂ can be negative (#115) (#135)streaming_hpcalerts on the CDF of VPIN and weights HHI by volume (#113) (#133)feature_importanceandbacktesting_enginematch their AFML references (#94) (#132)- Python bindings keep sub-second timestamps (#87) (#129)
- MDA shuffles the test-fold column instead of rotating it (#98) (#127)
portfolio_optimizationuses simple returns and reports annual risk and Sharpe ratio (#110) (#126)sb_baggingdraws each estimator’s sample with the sequential bootstrap (#90) (#125)feature_diagnosticsfits a real logistic regression (#99) (#124)- Time-decay weights keep one weight per event when starts coincide (#91) (#122)
- Conditional drawdown at risk averages the drawdown tail (#102) (#121)
- Chu-Stinchcombe-White statistic divides by the standard deviation (#104) (#120)
- Hasbrouck’s lambda regresses the signed return (#105) (#119)
- HCAA allocates down the tree and honours
optimal_num_clusters(#108) (#118) - ONC keeps the re-clustered partition when it scores higher (#107) (#117)
ef3mfit rows report their own error;fit_m2nhonoursn_runs(#116)- Nested partitions and the trajectory path cap in the Chapter 20–22 modules (#114)
efficient_riskfailed on feasible targets (#111)- Weekly and monthly resampling scrambled the price matrix in four modules (#93) (#96)
- Invalid arguments return
Errinstead of panicking (#36) (#84) - The constrained mean-variance problems are solved instead of clamping the unconstrained ones (#82)
- Daily volatility, event resolution and return attribution match AFML (#81)
- Hard-coded HRP, HCAA and ONC answers removed, and the ONC bugs they hid fixed (#75) (#80)
- Python matrices are read as rows of observations, not column-major (#74) (#79)
PurgedKFold::splitleaked: the test window now starts at the first test label’s end time (#65) (#66)- The first tick threshold is consumed, so features align with bars (#67) (#68)
- Unpurged feature-importance CV can no longer happen silently (#27)
get_parkinson_volspelled correctly in the public API (#24)
Changed
Section titled “Changed”- One
util::statsmodule for mean, std_dev, covariance and quantiles (bit-identical results); one shareddollar_bar_sample.csvfixture (#38) (#210) - The docs site and README use the Monograph identity (#57) (#86)
- Typed errors across the Rust core; the bindings raise the core’s message (#35) (#85)
- One visual identity: palette, type, logo (#56) (#72)
- The Python distribution is named
pyopenquant, with accurate metadata (#70) - AFML book-scraping tooling removed (#32) (#69)
- LazyFrame-native
openquant.datapath and a benchmark scaffold (#15)
Documentation
Section titled “Documentation”- Package metadata points at the real docs (rustdoc for the crate, a Changelog URL for Python); README and docs no longer present the PyPI name as decided (#58)
- Rustdoc under
/api/rust/, a generated Python reference, docstrings and.pyistubs (#54) (#192) - Rustdoc and doctests for the remaining
openquantmodules (#37) (#180) - Rustdoc and doctests for 15
openquantmodules (#37) (#144) - Contributor and community files; test fixture provenance recorded (#61) (#136)
- The vendored pyo3-polars patch documented and guarded with a test (#59) (#142)
- Hand-written
hrp,hcaaandoncpages; a claim on therisk_metricspage corrected (#109) - Hand-written
structural_breaksandmicrostructural_featurespages (#106) risk_metrics,strategy_riskandcodependencepages; acodependencepanic fixed (#103)- Hand-written backtesting pages (engine, statistics, synthetic) and a phone-width math fix (#101)
- Hand-written Chapter 8–9 module pages (feature importance, diagnostics, fingerprint, tuning) (#100)
- Hand-written Chapter 5–7 module pages (
fracdiff,ensemble_methods,cross_validation) (#97) - Hand-written Chapter 4 module pages (
sampling,sample_weights,sb_bagging) (#92) - Hand-written
labelingandbet_sizingpages (#89) - Hand-written Chapter 2 module pages, the
authoredstatus and the citation gate (#88) - The two serious known defects named on the landing page (#78)
- The landing page describes the library, not the documentation (#52) (#71)
- The coverage dashboard recomputes itself (#30)
check:exampleswired into CI, the status badge derived, the information architecture consolidated (#26)- The
get_parkinson_volrename propagated into the docs (#25) - The eight setup and workflow pages deliver on their titles (#22)
- Every module page says something true and compile-checked (#21)
- The API-drift gate sees the whole Rust surface (#19)
- The site no longer claims a review that never happened (#18)
- Docs site: 13 production redirects fixed, doc gates wired into CI, sitemap emitted (#17)
- Notebook-first workflow page on the docs site (#14)
- Fixtures and inline values regenerated without mlfinlab provenance (#138) (#147)
- Measured test-sensitivity audit and reference tests for eight modules (#40) (#95)
- Every Python submodule covered and exposed from the package (#39) (#73)
CI, build and tooling
Section titled “CI, build and tooling”- Release workflow: abi3 wheels for Linux, macOS and Windows plus an sdist, each smoke-tested on Python 3.11 to 3.13; PyPI trusted publishing,
cargo publishand a GitHub Release with notes from this file, on av*tag only; a dry run from the Actions tab or a packaging pull request (#60) - The workspace is migrated to Rust edition 2024 (#200)
- Rust caching, parallel lint and test jobs, release-mode parallel notebooks, a docs-only skip (#198)
- CI gates what it claims to gate (#41) (#130)
- Remaining local tooling ignored and the last stale doc lines fixed (#123)
- The workspace is clippy-clean under
-D warnings(#34) (#64) - Repository root cleaned, local tooling ignored, merged branches pruned (#31) (#63)
- AI-DLC adopted and the production-readiness backlog recorded (#62)
- The documented Python examples run in CI, and the three that were broken fixed (#29)
ethnumbumped from 1.5.2 to 1.5.3 so the crate compiles on stable (#28)cargo fmtapplied topyopenquant(#20)- Per-function data-processing benchmark metrics (#16)
- Beads closure history reconciled with the delivered work (#13)
Dependencies
Section titled “Dependencies”rand0.8 → 0.10 andrand_distr0.4 → 0.6, superseding #160. Seeded results change.seq_bootstrap_with_rngandsample_log_uniformnow take a rand 0.10 generator (R: rand::Rng, the formerRngCore), a public API change (#219) (#225)- polars 0.55, PyO3 0.29 and pyo3-polars 0.28 from crates.io; the vendored pyo3-polars patch is gone and Python polars 1.28.1 or later is required (#220) (#222)
- The cargo minor/patch group, 4 updates (#154)
- The Python minor/patch group, 2 updates (#152)