# wbt v0.2.3
> Release date: 2026-05-23
> Crate tag: `crate-v0.2.3` · Python tag: `v0.2.3`
## Summary
PATCH release with two related corrections on top of v0.2.2:
1. `segment_stats` / `long_stats` / `short_stats` now apply **kind-aware**
long/short rate semantics: single-side `kind` zeros the opposite rate.
2. HTML report's multi-strategy comparison chart restores the
**volatility-normalized middle subplot** (lost when this repo forked
from czsc) and adds a **多头超额** curve on top of it.
No public API additions/removals.
## Fixes
- **`kind` 单边语义生效到 `多头占比` / `空头占比`**:
v0.2.2 让 `segment_stats(kind=...)` 在三种 `kind` 下都返回同一对 long/short
比例,与 `kind="多头"` 只看多头侧的语义不一致。现修复:
- `kind="多头"` → `空头占比 = 0`,仅保留多头占比;
- `kind="空头"` → `多头占比 = 0`,仅保留空头占比;
- `kind="多空"` → 两者照旧给出 [sdt, edt] 范围内的真实权重行占比。
- `wb.long_stats` / `wb.short_stats` 也遵循同一规则。
- Rust 测试 `segment_stats_contains_long_short_rate` + Python 测试
`TestSegmentStatsLongShortRate::test_kind_single_side_zeros_opposite` 显式覆盖。
- **找回 HTML 报告的「波动率归一收益对比」子图 + 新增「多头超额」曲线**:
`wbt.report._plot_backtest.plot_long_short_comparison` 是从上游 czsc fork 出来
的简化版,错过了 czsc commit `e7610f5` 加入的波动率调整子图。现把图表从 2 行
扩展到 3 行:
- 上:原始累计收益对比
- 中:按 `target_volatility`(默认 20%)归一后的累计收益对比 + **多头超额** 曲线
(`多头超额 = scaled(策略多头).cumsum() − scaled(基准等权).cumsum()`,
口径与 `WeightBacktest.long_alpha_stats` 一致);多头超额用 `#FF1493` 深粉、
3.5px 实线,与策略主曲线明显区分。
- 下:绩效指标对比表
- 配套 `_generator.py` 把 `fig_ls` 高度从 1000 提到 1400 避免压缩。
- 上、中两图通过 `legendgroup` 联动显隐;中图主曲线 `showlegend=False`
避免与上图图例重复。
- 三条 Python 单测覆盖:子图存在、多头超额数值正确(`np.testing.assert_allclose`
与手算 `scaled(策略多头).cumsum() - scaled(基准等权).cumsum()` 比较)、
缺列时优雅跳过。
## Compatibility
- `BREAKING CHANGE`: 严格意义无破坏性。`segment_stats` / `long_stats` /
`short_stats` 三个 dict 的字段集合不变,仅 v0.2.2 新增的 `多头占比` /
`空头占比` 在单边 `kind` 下变成 0;依赖这俩字段恒等于 `wb.stats` 全局占比的
代码会观察到差异——这正是被修复的语义不一致。
- Python: requires ≥ 3.10 (unchanged).
- Rust: edition 2024, `pyo3 = 0.28` / `numpy = 0.28` (unchanged).
## Release checklist outcome
- **§1 SemVer**: 修两处语义错位,公共 API 表面 (`__init__.py` / `_wbt.pyi`)
无 diff → PATCH bump (`0.2.2 → 0.2.3`)。
- **§2 Lint/typecheck**: `cargo fmt --check`、`cargo clippy -D warnings`、
`cargo test --lib`(143 passed)、`ruff check`、`ruff format --check`、
`basedpyright` 全清。
- **§3 Tests**: `pytest` 241 passed / 1 skipped(含 4 条新增测试:
1 条 kind 单边占比、3 条波动率归一子图 / 多头超额曲线 / 缺列保护)。
- **§4 LLM review**: 范围限定在
`src/core/backtest.rs:280`(do_backtest 注入零)+
`src/core/backtest.rs:443`(segment_stats kind-match)+
`python/wbt/report/_plot_backtest.py:636`(subplot 重排 + 多头超额)+
`python/wbt/report/_generator.py:296`(高度调整)。重点核查:
(a) `match kind` 分支覆盖("多头" / "空头" / 其他默认 "多空",对齐
现有 `segment_stats_invalid_kind_defaults_to_all` 单测);
(b) 多头超额的 cumsum 顺序——`A.cumsum() − B.cumsum() ≡ (A − B).cumsum()`,
数值无差;(c) 长度对齐——`adjusted_returns` 与 `dailys_pivot.index` 共享 index,
cumsum 自然按行对齐;(d) `legendgroup` 联动不污染图例显示。
- **§5 doc-vs-code**: 同步更新 `WeightBacktest.segment_stats` docstring,
显式说明 `kind` 单边语义。
## Known issues (carried forward from v0.2.0)
Unchanged; see `docs/release_notes/v0.2.0.md`.