wbt 0.9.0

Weight-based backtesting engine for quantitative trading
# wbt v0.8.1

> Release date: 2026-08-26
> Crate tag: `crate-v0.8.1` · Python tag: `v0.8.1`

## Summary

PATCH release that restores trade counts by weight precision. Public API
signatures and exported symbols are unchanged; `stats` / `segment_stats` /
`long_alpha_stats` keep the same fields in the same order.

## Fixed

- 交易次数 / 盈利次数 / 亏损次数按权重精度还原(#32 / SKZ-559):`pairs` 内部以
  `weight × 10^digits` 的整数量子存储持仓数量,v0.8.0 直接累加该整数导致
  `digits > 0` 时交易次数虚高 `10^digits` 倍;现除回还原为真实次数。
  `win_rate``single_trade_profit``position_k_days``break_even_point`  加权指标口径不变(分子分母同为量子单位,尺度相消)。
- 报告 HTML 断言与 json 转义形式解耦(#31 / SKZ-516):stdlib json 的 ASCII
  `\u` 转义与 orjson 的原生 UTF-8 输出均被接受——v0.8.0 已知问题中记录的
  测试脆弱性就此关闭。
- 发版 workflow actions 升级到 node24 现行大版本(checkout v5、setup-python
  v6、upload/download-artifact v5)。

## Compatibility

- 无公共 API 增删、无签名变化。
- **输出类型与数值变化(修正目的)**`stats` 类输出中「交易次数」「盈利次数」
  「亏损次数」由 int 变为 float(`120``120.0`);`digits > 0` 时数值同步
  修正(`digits=2` 时约为旧值的 1/100)。Python 侧 `120 == 120.0` 数值等价,
  但严格类型断言或 JSON 快照对比的下游需更新。
- `digits = 0` 时行为与 v0.8.0 完全一致。

## Docs

- `quick_start.ipynb` 重新执行:内嵌 stats 输出更新为新口径(旧输出为更早
  mock 参数时代的陈旧结果,与本口径无对应关系)。
- `BacktestResult.pairs` docstring 补全实际列(交易方向 / 事件序列 / 持仓数量 /
  持仓天数),并注明「持仓数量」为 `× 10^digits` 的整数量子,真实权重需除回。

## Tests

- Rust:`evaluate_restores_counts_by_digits_without_changing_weighted_metrics`
  覆盖按 digits 还原计数、加权指标不变式;234 tests 全绿。
- Python:`test_trade_count_restores_digits_for_all_stat_paths` 在 stats /
  segment / long_alpha 全路径交叉验证还原口径(在 v0.8.0 上会以 100 倍差异
  失败);314 tests 全绿。

## §4 LLM full-repo review

- Scope: `v0.8.0..185e48d``evaluate_pairs.rs` / `backtest.rs` / `report.rs` /
  `backtest.py` 全量精读 + 测试改动真实性核验 + `mod.rs::round_weight`  `lib.rs` stats 序列化段冷读)。
- Conclusion: 无高/中级阻塞项,GO。
- 已处置:notebook 陈旧输出重跑(阻塞项,已解决);过时注释与 `pairs`
  docstring 漂移(顺手修复,随本 PR)。
- Known issues(不阻塞,均为既有行为):
  - `digits ≥ 3` 时三个计数字段的 `round_to_2_digit()` 会截断还原精度
    (如 `digits=4` 时真实 `1.0017` 输出 `1.0`);默认 `digits=2` 精确无影响。
  - `digits` 无合法区间校验:`digits ≥ 309``10^digits` 溢出为 inf,
    统计静默归零(`round_weight` 同表达式同病)。后续版本在 `new()` 加校验。