Skip to content

zengbin93/wbt

Repository files navigation

wbt

面向量化策略的持仓权重回测引擎 —— Rust 提供高性能、可复现的核心计算,Python 提供研究友好的接入接口。

wbt 回测报告

上图是一份真实报告:5 品种、5 年(2019–2023)模拟权重表,经 WeightBacktestwb.to_result()wbt.plotting 零配置直接产出。样本刻意调成强表现(夏普 ≈ 3.4、年化 ≈ 35.7%、最大回撤 ≈ 9.0%)以便报告图清晰可读——其权重信号是把前瞻 edge 与高斯噪声混合,仅用于演示美观,并非真实策略

English

项目目标

多数策略团队都把目标持仓权重作为信号生成与执行模拟之间的标准接口:信号层决定"持有多大权重",回测层把这些权重转成收益、风险与交易记录。现有工具要么在订单/撮合级别仿真(太细、太慢),要么是纯 Python 循环,撑不住大规模多品种权重表。

wbt 建立在一条统一回测原理上:给定 (dt, symbol, weight, price),资金曲线盈亏是权重变化与 bar 收益的确定性函数。其它一切——日度归因、多空拆分、回撤、交易对、相对基准的超额、以及"这策略能不能搞"——都从这一次计算派生,算一次、处处复用

开发目标:

  1. 统一数据契约承接任意权重策略(时序或截面)。
  2. 高性能且可复现——Rust 核心,并行计算,热路径里没有 Python。
  3. Python 友好接口,无缝接入 pandas / polars 研究流。
  4. 绘图即用输出——一次性算好,绘图层零数据转换。

为什么快

  • Rust + PyO3 核心。 整个回测循环在 Rust 里跑(rayon 线程池,可配 n_jobs),Python 只是入口。PyO3 边界用 Arrow IPC 字节传 DataFrame——没有逐行序列化,计算路径里不抢 GIL。
  • O(N) 计数排序替代 polars 通用排序做 symbol 分组——与行数线性。
  • SoA + 按需物化。 结果以 Struct-of-Arrays 存放(DailysSoA / PairsSoA),pandas/polars DataFrame 只在需要时构建并缓存。你不会为从不读取的表付物化成本。
  • 锁定配套工具链。 pyo3 0.28 + numpy 0.28 + polars 0.53abi3-py310——一份 wheel 覆盖 Python 3.10–3.13。

适用场景

  • 时序截面权重回测(weight_type="ts" | "cs")。
  • 多品种日收益拆解与归因分析。
  • 多空拆分、分段统计和交易对评估。
  • 策略相对基准的超额(alpha)分析。
  • pandas、polars、文件输入等多种数据通路。

非目标

  • 逐笔撮合与盘口微观结构仿真。
  • 交易所撮合机制级别的高频细节模拟。
  • 券商特定执行细节建模。

如果你的策略天然可表示为"随时间变化的目标权重",wbt 会更合适。

仓库结构

  • Rust crate:仓库根目录
  • Python 包:python/
wbt/
|-- Cargo.toml
|-- src/
`-- python/
    |-- pyproject.toml
    |-- README.md
    |-- tests/
    `-- wbt/

Python 快速开始

Python 子项目位于 python/,导入路径保持为 import wbt。

cd python
uv sync --extra dev
uv run maturin develop --release
uv run pytest -v

示例:

import pandas as pd
from wbt import WeightBacktest

df = pd.DataFrame(
    {
        "dt": ["2024-01-02 09:01:00", "2024-01-02 09:02:00", "2024-01-02 09:03:00"],
        "symbol": ["AAPL", "AAPL", "AAPL"],
        "weight": [0.5, 0.0, -0.3],
        "price": [185.0, 186.0, 184.5],
    }
)

wb = WeightBacktest(df, digits=2, fee_rate=0.0002, n_jobs=4, weight_type="ts")

print(wb.stats)
print(wb.long_stats)
print(wb.short_stats)

完整 Python 指南见 python/README_CN.md。

示例报告

下面每张图都来自同一份调优过的模拟权重表(夏普 ≈ 3.4),一次 wb.to_result() 真实输出——和你真实策略数据走的是同一条代码路径。每个绘图函数只消费一个预先算好的 BacktestResult,零数据转换。

累计净值 回撤
累计净值 回撤
月度热力图 年度收益
月度热力图 年度收益
滚动指标 日收益分布
滚动指标 日收益分布
分品种收益 交易对盈亏分布
分品种收益 交易对盈亏分布
指标对比(多头 / 空头 / 多空)
指标对比

Rust 快速开始

在仓库根目录执行:

cargo test

依赖方式:

[dependencies]
wbt = "0.1"

输入数据契约

wbt 的核心输入字段为:

  • dt:K 线结束时间
  • symbol:标的代码
  • weight:该时点目标持仓权重
  • price:成交或估值价格

Python 侧支持输入:

  • pandas.DataFrame
  • polars.DataFrame / polars.LazyFrame
  • 文件路径(csv、parquet、feather、arrow)

关键输出能力

  • wb.stats:多空综合绩效指标。
  • wb.long_stats / wb.short_stats:多头与空头拆分指标。
  • wb.daily_return / wb.dailys:日度收益明细序列。
  • wb.alpha / wb.alpha_stats:相对基准超额分析。
  • wb.pairs:交易对级别评估数据。
  • wb.aggregated_pairs / wb.key_trades(top=3):按 (品种, 开仓时间, 平仓时间) 聚合去重的开平记录,以及每年最赚/最亏各 N 笔关键交易(Rust 计算)。
  • wb.to_result(target_vol=0.20) → BacktestResult:绘图与审核页面的标准输入数据对象(详见下文「可视化」)。
  • wb.segment_stats(...):任意时间区间统计。
  • wb.long_alpha_stats:波动率调整后的多头超额指标。
  • wb.is_good_strategy(mode="history" | "recent", ...):客观判定一个策略能不能搞。返回 dict,含 is_good(bool)、reasonalpha_degenerate(bool)、年度明细(history 模式)或最近窗口指标(recent 模式)以及各条件通过标记。可调参数:target_volmax_dd_thresholdmax_alpha_dd_thresholdmin_full_sharpemin_year_daysrecent_daysmin_history_dayshistory 模式下,逐年三路 OR(绝对收益>0 / α 收益>0 / 当年超额回撤<max_dd_threshold)通过后,还要过两道全样本硬门:全样本超额回撤 ≤ max_alpha_dd_threshold(默认 0.30) 全样本 Sharpe > min_full_sharpe(默认 0.5)。recent 模式下,历史最大回撤在剔除 recent 窗口后的样本上计算(带可配置的 min_history_days floor),与 recent 窗口在时间上完全错开。Alpha 退化(NaN/Inf 或 long/bench 零方差)通过 alpha_degenerate=True 报告,所有 alpha 派生字段为 Noneis_good=False——不会假阳性"零回撤通过"。返回 dict 的 key 按字母序稳定排列;historyrecent 模式返回互斥的 key 集合(按 mode dispatch)。

独立工具函数

除了 WeightBacktest 类,wbt 顶层还导出一组独立工具:

  • daily_performance(returns, yearly_days=252):基于日收益序列的完整绩效指标(Rust 核心)。
  • top_drawdowns(returns, top=10):Top-N 回撤窗口(Rust 核心)。
  • rolling_daily_performance(df, ret_col, window=252, min_periods=100, yearly_days=None):滚动窗口日度绩效(Rust 核心)。
  • cal_yearly_days(dts):根据日期序列自动推断年度交易日数(Rust 核心)。
  • weights_simple_ensemble(df, weight_cols, method="mean", only_long=False, **kwargs):多策略权重集成(mean / vote / sum_clip)。返回新 DataFrame(不修改入参 df)。sum_clip 模式可通过 kwargs 传 clip_min=-1, clip_max=1
  • cal_trade_price(df, digits=None, **kwargs):按品种计算 TWAP / VWAP 与下根 K 线交易价表。kwargs 支持 windows=(5, 10, 15, 20, 30, 60)copy=True
  • log_strategy_info(strategy, df):用 loguru 打印每个品种的权重摘要。
  • mock_symbol_kline(...) / mock_weights(...):快速实验的模拟数据生成器。

Rust 端发出的 warning(如 cal_yearly_days 跨度不足时回退到 252)通过 log crate 触发,再由 pyo3-log 桥接到 Python 标准 logging,loguru 用户配置一次 InterceptHandler 即可接管。

HTML 报告生成

wbt.generate_backtest_report(df, output_path) 输出一个自包含的 HTML 报告(回测概览、多空对比、关键交易等标签页)。内部仅做一次 wb.to_result() 预处理,再交由 wbt.plotting 绘图。

可视化

所有绘图函数以 BacktestResult 为标准输入——一次性算好绘图所需的全部数据,绘图函数零数据转换:

result = wb.to_result()            # 标准输入数据对象
from wbt.plotting import plot_cumulative_returns, plot_key_trades
fig = plot_cumulative_returns(result, keys=["多空", "多头", "空头"])
plot_key_trades(result, to_html=True)
result.to_dict(full=True)          # JSON 安全,供审核页面走 HTTP
  • BacktestResult 字段:dates / year_starts / curves(原始曲线,键 多空/多头/空头/基准/超额)/ curves_voladj(波动率归一,按需)/ return_dist / monthly / symbol_returns / pairs_dist / stats / stats_by_side,以及审核字段 drawdowns / key_trades / verdict(均为按需 cached_property)。
  • wbt.plotting(均为单一职责单图,无组合图):plot_cumulative_returnsvoladj=True 为波动率归一)/ plot_drawdown / plot_daily_return_dist / plot_monthly_heatmap / plot_symbol_returns / plot_yearly_returns / plot_rolling_metrics / plot_pairs_pnl_dist / plot_pairs_hold_dist / plot_colored_table / plot_stats_comparison / plot_segment_comparison / plot_key_trades / plot_drawdowns_table / plot_verdict
  • wbt.reportgenerate_backtest_report / HtmlReportBuilder / get_performance_metrics_cards

开发与质量检查

  • Rust 相关命令在仓库根目录执行。
  • Python 相关命令在 python/ 目录执行。
  • CI 会同时校验这两部分。

常用命令:

# 仓库根目录
cargo test

# python 子项目
cd python
uv run pytest -v
uv run ruff format --check .
uv run ruff check . --no-fix
uv run basedpyright

相关文档

  • Python 英文文档:python/README.md
  • Python 中文文档:python/README_CN.md
  • 设计记录:docs/desgin.md

相关开源项目

wbt 处于一组量化研究工具的生态中,几个最相关的项目如下:

  • czsc — 基于缠论的综合性量化交易 Python 框架,覆盖信号、策略、Trader、EDA 与可视化;自 v1.0.x 起将核心算法用 Rust 实现并通过 PyO3 暴露(czsc._native)。与 wbt 的关系: wbt 从 czsc 迁移了 5 个评估 / 工具函数(cal_yearly_daysrolling_daily_performanceweights_simple_ensemblecal_trade_pricelog_strategy_info),并保持数值口径与 czsc 对齐(见 python/tests/test_compare_with_czsc_script.py);czsc 端的策略天然产出可被 wbt 消费的权重表。

  • wmr — 基于 ClickHouse 与 DuckDB 的策略持仓权重管理系统,专注于大规模权重数据的持久化、版本管理与查询。与 wbt 的关系: wmr 是权重表的数据层(存储 / 检索),wbt 是把权重表转化为回测指标、日序列与 HTML 报告的计算层。

  • talib-rs — 纯 Rust 实现的技术分析库,定位为经典 C 版 TA-Lib 的 drop-in 替代(结果逐位对齐、SIMD 加速、无 C 依赖)。与 wbt 的关系: Rust 侧的同侪项目——wbt 聚焦权重回测与绩效指标,talib-rs 覆盖标准技术指标。当策略需要"指标计算 + 权重回测"同时在 Rust/Python 栈里完成时,两者可组合使用。

整体上,三者勾勒出一条典型的研究到评估管线:czsc(信号与策略)→ wmr(权重存储)→ wbt(回测与指标),talib-rs 则在沿线提供可复用的 Rust 原生指标计算能力。

License

MIT

About

Weight Back Test; 策略持仓权重回测模块

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors