Release 0.8.0 — Data layer, execution realism, and three breaking correctness fixes
Date: 2026-09-20
Install: pip install quantwave or pip install "quantwave[polars]"
Headline
QuantWave 0.8.0 ships the bundled sample dataset (quantwave.datasets.load_sample()) that the getting-started guide has referenced since 0.7.0 — this release closes that gap. Alongside it: a full execution-realism pass on the backtest engine (order types, risk overlays, rebalance policies, portfolio optimization), new alternative bar types and harmonic pattern detection, a first-class TA-Lib abstract-API registry, two new research modules (conditional-outcome queries, prop-firm challenge simulation), and three breaking correctness fixes that change default behavior for anyone re-running an existing backtest.
Breaking changes — read this before upgrading
portfolio_backtest'ssignal_typenow defaults to"weight"(fraction of total equity) instead of"shares"(a literal share count). A boolean0/1signal used to buy one share and deploy almost none of the book's capital, silently. Backtests re-run without passingsignal_type="shares"explicitly will report much larger, and much more correct, numbers. See the Backtest Quickstart.execution_delaynow defaults to"next_bar"(T+1) instead of"same_bar"(T+0), across every.btentry point. The old default filled on information that only existed once the bar had already closed — a look-ahead a live strategy never has. Existing backtests will report different, generally worse, numbers; that's the look-ahead being removed.ta_beta/ta_correlnow default to TA-Lib's real periods (5 and 30) instead of a blanket 14 — they previously disagreed with their own non-prefixed siblings on the same data.ta_atr/ta_natr/ta_trangenow takeclosein the receiver, matching their siblings' shape; the old positional order silently permutedhigh/low/closeand returned a plausible-but-wrong ATR with no error.- Rust callers only:
talib_rs::MaTypeis replaced by a nativequantwave_core::MaType. Python callers are unaffected —matype=still takes the same integers/strings.
Full detail on all of the above, including before/after code, is in the Changelog.
What's new
Data layer
quantwave.datasets.load_sample()/synthetic()— the bundled sample OHLCV dataset and synthetic-series generator the getting-started guide already documented.load_sample()'s data is synthetic, not real market history.qw.trim_warmup()/qw.warmup_rows()and aquantwave.WarmupWarningon every.btentry point — indicator warmup isNaN, nevernull, sodrop_nulls()was a silent no-op on it; these give you a correct, metadata-driven way to trim it.
Backtest execution realism
- First-class order types: limit / stop / stop-limit / bracket / OCO, wired into the order-driven run loop.
- Risk overlays (vol-target, inverse-vol, position-limit, pre-trade checks) and portfolio rebalance policies.
- Optional Bayesian (TPE) walk-forward optimization, benchmark-relative reporting (alpha/beta/Calmar/VaR/CVaR), and a Rust/nalgebra portfolio optimizer (mean-variance, risk parity, HRP) — all preserving batch↔streaming parity.
New research modules
quantwave.research.conditional_outcome()— "given these conditions on my data, how often did this outcome occur", with a 95% Wilson confidence interval, a minimum-sample-size guard, and a chronological stability split, so a bare hit rate never gets reported without its own trustworthiness attached.quantwave.propfirm.simulate_prop_firm_challenge()— block-bootstrap Monte Carlo simulation of a backtest's trade history against prop-firm-style drawdown/daily-loss/profit-target rules, reporting pass probability with a Wilson CI and a breach-reason breakdown.
Indicators and patterns
- Alternative bar types: Renko, Kagi, constant-range bars, Point & Figure.
- Harmonic pattern detection: AB=CD, Alternate AB=CD, 5-0, and XABCD patterns (Gartley, Bat, Butterfly, Crab, Alternate Bat).
- ML feature namespace: bulk feature extraction, labeling, and leakage-safe CV splits.
- All 60 remaining candlestick patterns ported to native Rust —
talib-rshas left the shipped dependency graph entirely; it's now solely a#[cfg(test)]parity oracle. The "221 native indicators" claim is now literally true.
API introspection
- TA-Lib abstract-API registry (
get_functions()/get_function_groups()-equivalent) anddf.ta.all()bulk compute, matching pandas-ta'sstrategy("all"). - Multi-timeframe (MTF) helpers — lookahead-safe resample/apply/broadcast.
WASM
quantwave-wasmcrate and an experimental in-browser indicator playground.
Notable fixes
mamapanicked on a singleNaNin its input stream — a bad tick from a data vendor could crash a long-running streaming session. It now returns(NaN, NaN)for that one bar without touching any internal state.- 68 indicators silently resolved to a streaming class instead of their batch function —
qw.supertrendwas a class whileqw.rsiwas a function, with no error._resolve_ta_bindingnow raisesImportErroron a build-time mismatch instead of silently substituting the wrong calling convention. _metadata_generated.py'sdata_inputs/outputssilently defaulted to['close']/[slug]for any indicator without a hand-curated overlay entry — corrected for every indicator whose true arity differs.calmar_ratioreturnedinfon a zero-drawdown run while the rest of the metrics bundle returnedNaNfor the same undefined-ratio condition — this could make walk-forward/sweep selection pick a degenerate variant that never lost. Now returnsNaNconsistently.- Four candlestick patterns (
CDLGAPSIDESIDEWHITE,CDLCONCEALBABYSWALL,CDL3STARSINSOUTH,CDLBREAKAWAY) diverged from the TA-Lib reference in ways the random-walk parity tests never reached; fixtures rebuilt to discriminate. MaStreamsilently substituted SMA for every matype except EMA (affectingAPO,PPO,MACDEXT,STOCH,STOCHF,STOCHRSI) — all nine families now dispatch to their real streaming implementation.BBANDSwith a non-SMA matype was O(n²) over a series with unbounded memory — now genuinely O(1) per bar.
Full changelog: docs/changelog.md#0.8.0.
Upgrade notes
- If you have an existing
portfolio_backtestcall relying on share-count sizing, passsignal_type="shares"explicitly to keep old behavior. - If you have an existing backtest relying on same-bar fills (you genuinely trade the closing auction, or your signal only uses data through bar
t-1), passexecution_delay="same_bar"explicitly. - If you called
.ta.ta_beta/.ta.ta_correlwithout an explicittimeperiod, passtimeperiod=14to keep the previous (TA-Lib-incorrect) numbers, or accept the new TA-Lib-correct defaults. - If you called
.ta.ta_atr/.ta.ta_natrpositionally withhighas the receiver, switch the receiver tocloseto match the corrected signature.
Quality gates
What's next
See Roadmap.