背景
当前 wbt 的长期目标是:Rust 端和 Python 端提供统一的对外 API。
本次检查发现:目前还没有做到完全一致。现状更像是:Rust crate 提供核心计算能力,Python 包在 Rust 核心之上提供更完整的用户层 API、绘图/report、mock 和辅助工具。
需要明确哪些 API 属于 Rust/Python 必须一致的 canonical API,哪些是 Python-only 展示层能力,哪些需要从 Python 迁移到 Rust 作为共享实现。
当前检查结论
1. Python 顶层 API 明显多于 Rust
Python 顶层 wbt.__all__ 当前暴露:
WeightBacktest
backtest
BacktestResult
daily_performance
top_drawdowns
rolling_daily_performance
cal_yearly_days
generate_backtest_report
mock_symbol_kline
mock_weights
weights_simple_ensemble
cal_trade_price
log_strategy_info
Curve / ReturnDist / MonthlyHeatmap / SymbolReturns / PairsDist / KeyTrade / KeyTrades
Rust 端目前主要暴露:
wbt::core::WeightBacktest
WeightType
daily_performance
top_drawdowns
rolling_daily_performance
cal_yearly_days
Report / StatsReport / SymbolsReport
- 一批内部模块和结构:
native_engine、DailysSoA、PairsSoA、DailyTotals、key_trades helper、trade_dir、period_win_rates 等。
2. 同一能力的 API 形状不一致
例子:
- Python
WeightBacktest(data, ...) 支持 pandas / polars / 文件路径。
- Rust
WeightBacktest::new(df, ...) 接 Polars DataFrame,from_file(...) 单独处理文件。
- Python 以属性暴露:
wb.daily_return、wb.dailys、wb.alpha、wb.pairs,返回 pandas DataFrame。
- Rust 以方法暴露:
daily_return_df()、dailys_df()、alpha_df()、pairs_df(),返回 Polars DataFrame / Option<DataFrame>。
这些能力口径相近,但 API 名称、调用方式、返回类型都不完全一致。
3. Rust 暴露了不少内部实现细节
由于当前 src/lib.rs 直接 pub mod core;,而 core/mod.rs 里多个模块是 pub mod,导致 Rust public surface 包含不少内部实现:
native_engine::DailyTotals
native_engine::DailysSoA
native_engine::PairsSoA
native_engine::NativeEngine
key_trades 内部聚合函数
trade_dir
period_win_rates
这些更像内部实现细节,不一定应该成为稳定对外 API。
4. Rust 核心 + Python wrapper 的函数还不是“完全同形”
以下函数已有 Rust 核心和 Python wrapper:
daily_performance
top_drawdowns
rolling_daily_performance
cal_yearly_days
但 Python wrapper 的入参/返回更用户友好,Rust 端更底层。例如 Python 接 pandas / Series,Rust 接 slice / Polars DataFrame / Arrow IPC 字节。它们目前可认为“计算口径一致”,但不是“API 完全一致”。
已明确的边界
Python-only
以下能力只服务 Python 展示层,后续不要求 Rust 端提供完全同名 API:
wbt.plotting.*
wbt.report.*
generate_backtest_report
HtmlReportBuilder
- plotly / HTML 相关能力
这些应明确标为 Python-only,不纳入 Rust/Python canonical API 对齐范围。
应迁移到 Rust 并共享
mock 应该在 Rust 中实现,然后 Python 和 Rust 共用一套生成逻辑:
mock_symbol_kline
mock_weights
原因:mock 数据用于示例、测试、benchmark。如果 Python/Rust 各自实现,随机序列、字段口径、日期生成逻辑容易分叉,影响跨语言验收。
建议的 canonical API 清单
后续建议以 Rust 为 canonical API 源头,Python 做薄封装和类型适配。
核心回测 API
WeightBacktest
backtest / WeightBacktest::backtest
BacktestResultCore / Python BacktestResult
stats
long_stats
short_stats
daily_return
dailys
alpha
pairs
aggregated_pairs
key_trades
segment_stats
long_alpha_stats
is_good_strategy
to_result
to_dict
to_msgpack
独立指标/工具 API
daily_performance
top_drawdowns
rolling_daily_performance
cal_yearly_days
weights_simple_ensemble(需评估是否迁到 Rust)
cal_trade_price(需评估是否迁到 Rust)
mock_symbol_kline(迁到 Rust)
mock_weights(迁到 Rust)
Python-only 展示 API
plot_cumulative_returns
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
generate_backtest_report
HtmlReportBuilder
建议改造步骤
阶段 1:定义 API 分层文档
新增一份文档,例如 docs/api_surface.md,明确:
- Canonical cross-language API
- Python-only API
- Rust internal API
- Deprecated / transitional API
验收:文档中每个公开 API 都能对应到 Rust / Python 的暴露位置,或明确标注 Python-only / Rust-internal。
阶段 2:收窄 Rust public surface
把 Rust 内部模块从 public API 中收窄:
native_engine 改为 pub(crate) 或私有模块。
- SoA 结构不再作为稳定 API 暴露。
- key_trades 内部 helper 不直接暴露,改由
WeightBacktest / BacktestResultCore 方法承载。
验收:Rust docs 里只出现稳定用户 API;内部结构不进入用户文档。
阶段 3:引入 Rust canonical BacktestResultCore
配合 issue #19:
- Rust 定义
BacktestResultCore 作为结果对象 canonical API。
- Python
BacktestResult 变成薄 wrapper。
to_dict / to_msgpack / stats / curves 等后续逐步由 Rust core 提供。
验收:Python BacktestResult 与 Rust BacktestResultCore 对同一数据输出一致。
阶段 4:mock 迁移到 Rust
在 Rust 中实现 mock 数据生成:
- 稳定 seed。
- 稳定 symbol offset。
- 与现有 Python
mock.py 字段完全一致。
- 通过 PyO3 暴露给 Python。
Python mock_symbol_kline / mock_weights 改为调用 Rust 实现。
验收:同一参数下,Python API 与 Rust API 生成的数据字段、行数、日期、价格、权重完全一致;用于 README 示例和 benchmark 的 mock 数据只维护一份实现。
阶段 5:评估 Python utils 是否迁 Rust
逐个判断:
weights_simple_ensemble:偏核心数据处理,建议迁 Rust 或至少定义 cross-language contract。
cal_trade_price:偏量化数据处理,建议迁 Rust 或定义 cross-language contract。
log_strategy_info:日志展示辅助,可保留 Python-only。
验收标准
- 有明确 API 分层文档。
- Rust/Python canonical API 清单一一对应。
- Python-only API 明确标注,不再要求 Rust 同步实现。
- Rust internal API 不作为稳定 public API 暴露。
- mock 由 Rust 单一实现驱动,Python/Rust 共用。
- 新增 API 对齐测试:同一输入下,Rust 与 Python canonical API 的关键输出一致。
背景
当前 wbt 的长期目标是:Rust 端和 Python 端提供统一的对外 API。
本次检查发现:目前还没有做到完全一致。现状更像是:Rust crate 提供核心计算能力,Python 包在 Rust 核心之上提供更完整的用户层 API、绘图/report、mock 和辅助工具。
需要明确哪些 API 属于 Rust/Python 必须一致的 canonical API,哪些是 Python-only 展示层能力,哪些需要从 Python 迁移到 Rust 作为共享实现。
当前检查结论
1. Python 顶层 API 明显多于 Rust
Python 顶层
wbt.__all__当前暴露:WeightBacktestbacktestBacktestResultdaily_performancetop_drawdownsrolling_daily_performancecal_yearly_daysgenerate_backtest_reportmock_symbol_klinemock_weightsweights_simple_ensemblecal_trade_pricelog_strategy_infoCurve/ReturnDist/MonthlyHeatmap/SymbolReturns/PairsDist/KeyTrade/KeyTradesRust 端目前主要暴露:
wbt::core::WeightBacktestWeightTypedaily_performancetop_drawdownsrolling_daily_performancecal_yearly_daysReport/StatsReport/SymbolsReportnative_engine、DailysSoA、PairsSoA、DailyTotals、key_tradeshelper、trade_dir、period_win_rates等。2. 同一能力的 API 形状不一致
例子:
WeightBacktest(data, ...)支持 pandas / polars / 文件路径。WeightBacktest::new(df, ...)接 PolarsDataFrame,from_file(...)单独处理文件。wb.daily_return、wb.dailys、wb.alpha、wb.pairs,返回 pandasDataFrame。daily_return_df()、dailys_df()、alpha_df()、pairs_df(),返回 PolarsDataFrame/Option<DataFrame>。这些能力口径相近,但 API 名称、调用方式、返回类型都不完全一致。
3. Rust 暴露了不少内部实现细节
由于当前
src/lib.rs直接pub mod core;,而core/mod.rs里多个模块是pub mod,导致 Rust public surface 包含不少内部实现:native_engine::DailyTotalsnative_engine::DailysSoAnative_engine::PairsSoAnative_engine::NativeEnginekey_trades内部聚合函数trade_dirperiod_win_rates这些更像内部实现细节,不一定应该成为稳定对外 API。
4. Rust 核心 + Python wrapper 的函数还不是“完全同形”
以下函数已有 Rust 核心和 Python wrapper:
daily_performancetop_drawdownsrolling_daily_performancecal_yearly_days但 Python wrapper 的入参/返回更用户友好,Rust 端更底层。例如 Python 接 pandas / Series,Rust 接 slice / Polars DataFrame / Arrow IPC 字节。它们目前可认为“计算口径一致”,但不是“API 完全一致”。
已明确的边界
Python-only
以下能力只服务 Python 展示层,后续不要求 Rust 端提供完全同名 API:
wbt.plotting.*wbt.report.*generate_backtest_reportHtmlReportBuilder这些应明确标为 Python-only,不纳入 Rust/Python canonical API 对齐范围。
应迁移到 Rust 并共享
mock应该在 Rust 中实现,然后 Python 和 Rust 共用一套生成逻辑:mock_symbol_klinemock_weights原因:mock 数据用于示例、测试、benchmark。如果 Python/Rust 各自实现,随机序列、字段口径、日期生成逻辑容易分叉,影响跨语言验收。
建议的 canonical API 清单
后续建议以 Rust 为 canonical API 源头,Python 做薄封装和类型适配。
核心回测 API
WeightBacktestbacktest/WeightBacktest::backtestBacktestResultCore/ PythonBacktestResultstatslong_statsshort_statsdaily_returndailysalphapairsaggregated_pairskey_tradessegment_statslong_alpha_statsis_good_strategyto_resultto_dictto_msgpack独立指标/工具 API
daily_performancetop_drawdownsrolling_daily_performancecal_yearly_daysweights_simple_ensemble(需评估是否迁到 Rust)cal_trade_price(需评估是否迁到 Rust)mock_symbol_kline(迁到 Rust)mock_weights(迁到 Rust)Python-only 展示 API
plot_cumulative_returnsplot_drawdownplot_daily_return_distplot_monthly_heatmapplot_symbol_returnsplot_yearly_returnsplot_rolling_metricsplot_pairs_pnl_distplot_pairs_hold_distplot_colored_tableplot_stats_comparisonplot_segment_comparisonplot_key_tradesplot_drawdowns_tableplot_verdictgenerate_backtest_reportHtmlReportBuilder建议改造步骤
阶段 1:定义 API 分层文档
新增一份文档,例如
docs/api_surface.md,明确:验收:文档中每个公开 API 都能对应到 Rust / Python 的暴露位置,或明确标注 Python-only / Rust-internal。
阶段 2:收窄 Rust public surface
把 Rust 内部模块从 public API 中收窄:
native_engine改为pub(crate)或私有模块。WeightBacktest/BacktestResultCore方法承载。验收:Rust docs 里只出现稳定用户 API;内部结构不进入用户文档。
阶段 3:引入 Rust canonical
BacktestResultCore配合 issue #19:
BacktestResultCore作为结果对象 canonical API。BacktestResult变成薄 wrapper。to_dict/to_msgpack/stats/curves等后续逐步由 Rust core 提供。验收:Python
BacktestResult与 RustBacktestResultCore对同一数据输出一致。阶段 4:mock 迁移到 Rust
在 Rust 中实现 mock 数据生成:
mock.py字段完全一致。Python
mock_symbol_kline/mock_weights改为调用 Rust 实现。验收:同一参数下,Python API 与 Rust API 生成的数据字段、行数、日期、价格、权重完全一致;用于 README 示例和 benchmark 的 mock 数据只维护一份实现。
阶段 5:评估 Python utils 是否迁 Rust
逐个判断:
weights_simple_ensemble:偏核心数据处理,建议迁 Rust 或至少定义 cross-language contract。cal_trade_price:偏量化数据处理,建议迁 Rust 或定义 cross-language contract。log_strategy_info:日志展示辅助,可保留 Python-only。验收标准