Skip to content

Latest commit

 

History

History
89 lines (70 loc) · 4.26 KB

File metadata and controls

89 lines (70 loc) · 4.26 KB

wbt v0.5.0

Release date: 2026-07-15 Crate tag: crate-v0.5.0 · Python tag: v0.5.0

Summary

MINOR release. BREAKING CHANGE (SKZ-195): all return / net-value accumulation inside wbt is unified to simple interest (Σr). Previously the yearly return and the is_good_strategy yearly/recent metrics used compound (∏(1+r)-1) while the main stats (absolute return, max drawdown, equity curve) used simple interest — the two conventions were mixed within a single backtest. After this release there is no compound (∏(1+r) / net-value) accumulation anywhere in the framework; everything is single-interest, consistent with daily_performance's absolute return and the np.cumsum equity curve.

Public API signatures are unchanged; only the numeric convention changes.

BREAKING CHANGE: compound → simple interest

WeightBacktest.yearly_return()

  • Yearly return per (year, symbol) changed from compound ∏(1+r)-1 to simple Σr. Schema (year, symbol, return) is unchanged; values differ.

    Old → new (example, daily returns [0.10, 0.10] in one year):

    • old (compound): 1.10 * 1.10 - 1 = 0.21
    • new (simple): 0.10 + 0.10 = 0.20

is_good_strategy() (both history and recent modes)

  • abs_return / alpha_return (per-year, in yearly_metrics) and recent_abs_return / recent_alpha_return: compound ∏(1+r)-1 → simple Σr.
  • alpha_max_drawdown, history_alpha_max_drawdown, recent_alpha_max_drawdown, and history_alpha_max_drawdown_excl_recent: changed from compound net-value drawdown (nav *= 1+r, dd = (peak-nav)/peak) to simple cumsum-underwater (cum += r, dd = peak - cum), identical in semantics to daily_performance::calc_underwater.
  • Note: simple-interest drawdown is an absolute value in return space and has no 1.0 upper bound (unlike a compound net-value ratio). Callers comparing drawdown against thresholds should keep this in mind; a threshold of 1.0 no longer means "effectively disabled".
  • Return-dict keys are unchanged; only the numeric convention of the values above changes. Verdicts near thresholds may therefore differ from v0.4.x.

Migration

  • If you persisted or charted yearly_return() / is_good_strategy() numbers from v0.4.x, recompute them under v0.5.0 — old compound values are not comparable to new simple values.
  • Any downstream (skz) gate that hard-coded a compound-scale drawdown threshold (e.g. max_alpha_dd_threshold assuming a ≤1.0 ratio) should re-tune to the return-space scale.

Removed: vista comparison artifacts

The library no longer relates to vista. Removed:

  • python/scripts/compare_yearly_return_with_vista.py
  • python/tests/test_compare_yearly_return_with_vista_script.py

These were comparison-only tooling and not part of the public API.

Tests

  • src/core/yearly_return.rs, src/core/is_good_strategy.rs: unit tests updated to simple-interest expected values (known_curve drawdown 0.15, cum-zero-with-real-dd 0.5, yearly/recent Σr). history_year_passes_via_abs_return_only raises its max_alpha_dd_threshold bypass 1.0 → 1e9 (test sentinel only; the judge gate logic is unchanged).
  • python/tests/test_yearly_return.py: expected formula updated to sum().
  • Local: cargo fmt / cargo clippy -D warnings clean, cargo test --lib 220 passed; pytest 289 passed. Full CI (ubuntu/macos/windows × py3.10–3.13) green on main.

§4 LLM full-repo review

  • Scope: full diff crate-v0.4.3..HEAD (src/core/{yearly_return,is_good_strategy}.rs, python/wbt/backtest.py, tests, vista removals), plus cold-read of daily_performance.rs.
  • Model: independent review agent.
  • Conclusion: APPROVE for release — no blocking findings. Verified: (1) local_max_drawdown_abs exactly mirrors calc_underwater (same NEG_INFINITY peak init so day-0 never registers drawdown; max(peak-cum) ≡ max(-underwater); empty→0; non-finite→NaN preserved); (2) no compound ∏(1+r) / nav*=1+r / .prod() accumulation remains in src/ (only historical-note doc comments mention it); (3) the 1.0→1e9 change is a test sentinel, production judge logic unchanged; (4) no off-by-one / sign / empty / NaN regressions in the changed functions.
  • Known issues: none.