wbt 0.3.2

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

> Release date: 2026-05-30
> Crate tag: `crate-v0.3.1` · Python tag: `v0.3.1`

## Summary

PATCH release. Single semantic fix to the volatility-normalized **excess** curve
introduced in 0.3.0.

## Fix: `curves_voladj['超额']` = `norm(多头) − norm(基准)`

`BacktestResult.curves_voladj['超额']` previously normalized the **raw excess**
series as a whole — `norm(wb.alpha['超额'])`, i.e. compute the original excess
(策略 − 基准) first, then scale it by its own volatility.

That is inconsistent with the volatility-normalized comparison chart, which shows
the normalized 多头 and 基准 curves side by side: the displayed 多头 curve
(`curves['多头']`, from `dailys` `long_return`) is **not** the same series as
alpha's internal 策略 (measured correlation ≈ 0.96, not 1.0), so the old excess
line did not equal the visual gap between the two normalized lines.

0.3.1 redefines it as **normalize 多头 and 基准 each to `target_vol` first, then
subtract daily**:

```
curves_voladj['超额'].daily == curves_voladj['多头'].daily − curves_voladj['基准'].daily
```

The normalized excess curve now exactly equals the difference of the two
normalized lines on the chart. Its annualized volatility is no longer pinned to
`target_vol` (it depends on the 多头/基准 correlation) — this is expected.

Only `curves_voladj['超额']` changes. The raw `curves['超额']`, `stats_by_side`,
`is_good_strategy`, and all other outputs are unchanged.

## Tests

- `python/tests/test_result.py`: `test_curves_voladj_hits_target_vol` now excludes
  `超额` from the target-vol assertion; new `test_curves_voladj_excess_is_diff`
  locks `归一超额 == 归一多头 − 归一基准` (atol 1e-12). Full Python suite:
  **260 passed / 1 skipped**.

## Compatibility

- Behavioral change limited to `BacktestResult.curves_voladj['超额']` (a 0.3.0
  feature). No public API signature change; no Rust change. `STATS_FIELD_ORDER`
  unchanged.
- Python ≥ 3.10; Rust edition 2024, `pyo3 = 0.28` / `numpy = 0.28` (unchanged).

## Known issues (carried forward from v0.2.0)

Unchanged; see `docs/release_notes/v0.2.0.md`.