Skip to main content

Weight-based backtesting engine for quantitative trading

Project description

wbt

High-performance position-weighted backtesting engine, written in Rust with Python bindings.

中文文档

Overview

wbt (Weight Back Test) is a standalone library for backtesting trading strategies based on position weights. It computes daily P&L attribution, trade pair matching (FIFO), and comprehensive performance statistics — all powered by a zero-copy, cache-friendly Rust core with rayon-based parallelism.

  • Rust crate (wbt): pure Rust library with core engine
  • Python package (wbt): PyO3 bindings + pandas-friendly API via Arrow IPC

Installation

Python

# Requires: Rust toolchain, maturin, Python >= 3.9
git clone <repo-url> && cd wbt
uv venv .venv && source .venv/bin/activate
uv pip install pandas pyarrow numpy maturin
maturin develop --release

Rust

# Cargo.toml
[dependencies]
wbt = "0.1"

Quick Start

Python

import pandas as pd
from wbt import WeightBacktest

# Prepare input: DataFrame with columns [dt, symbol, weight, price]
dfw = pd.DataFrame({
    "dt":     ["2024-01-02 09:01:00", "2024-01-02 09:02:00", "2024-01-03 09:01:00", "2024-01-03 09:02:00"],
    "symbol": ["AAPL", "AAPL", "AAPL", "AAPL"],
    "weight": [0.5, 0.5, 0.0, 0.0],
    "price":  [185.0, 186.0, 187.0, 185.5],
})

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

wb.stats          # dict: Sharpe, Calmar, max drawdown, win rate, etc.
wb.daily_return   # DataFrame: per-symbol daily returns with 'total' column
wb.dailys         # DataFrame: per-symbol daily detail (edge, return, cost, turnover, ...)
wb.alpha          # DataFrame: strategy excess return vs. benchmark
wb.pairs          # DataFrame: all matched trade pairs (FIFO)

Rust

use wbt::core::{WeightBacktest, WeightType};
use polars::prelude::*;

let dfw: DataFrame = /* build your DataFrame with [dt, symbol, weight, price] */;
let mut wb = WeightBacktest::new(dfw, 2, Some(0.0002))?;
wb.backtest(Some(4), WeightType::TS, 252)?;

let report = wb.report.as_ref().unwrap();
println!("Sharpe: {}", report.stats.daily_performance.sharpe_ratio);

Input Format

Column Type Description
dt datetime Bar end time; must be a continuous trading time series with no gaps
symbol str Instrument code
weight float Position weight at bar end; independent across symbols; positive = long, negative = short, 0 = flat
price float Trade price (close, next-bar open, TWAP/VWAP, etc.)

Parameters

Parameter Default Description
digits 2 Decimal places for weight rounding
fee_rate 0.0002 One-way transaction cost (commission + slippage)
n_jobs 1 Number of parallel threads (rayon thread pool)
weight_type "ts" "ts" (time-series: equal-weight average across symbols) or "cs" (cross-section: sum across symbols)
yearly_days 252 Trading days per year for annualization

Output Properties

Property Type Description
stats dict Full performance report (Sharpe, Calmar, drawdown, win rate, trade metrics, ...)
daily_return DataFrame Pivoted daily returns per symbol + total column
dailys DataFrame Per-symbol daily detail: n1b, edge, return, cost, turnover, long/short splits
alpha DataFrame Strategy vs. benchmark excess return
alpha_stats dict Performance statistics on the excess return series
pairs DataFrame All FIFO-matched trade pairs with P&L, hold bars, direction
long_daily_return DataFrame Long-only daily returns
short_daily_return DataFrame Short-only daily returns
long_stats dict Long-only performance statistics
short_stats dict Short-only performance statistics
bench_stats dict Benchmark (equal-weight n1b) performance statistics

Architecture

wbt/
├── src/
│   ├── lib.rs              # PyO3 bindings (Arrow IPC in/out)
│   └── core/               # Pure Rust engine
│       ├── mod.rs           # WeightBacktest struct & public API
│       ├── native_engine.rs # Zero-copy parallel engine (rayon)
│       ├── daily_performance.rs # Sharpe, Calmar, drawdown, etc.
│       ├── evaluate_pairs.rs    # Trade pair statistics
│       ├── backtest.rs      # Orchestration & alpha computation
│       ├── report.rs        # Report structs & JSON serialization
│       ├── trade_dir.rs     # Trade direction & action enums
│       ├── errors.rs        # Error types
│       └── utils.rs         # WeightType, rounding, quantile
└── python/wbt/         # Python API wrapper
    ├── backtest.py     # WeightBacktest class (pandas-friendly)
    └── _df_convert.py  # Arrow <-> pandas conversion

Benchmark

Tested on China A-share daily data (2017-01 to 2025-04), Apple M-series, 8 threads, release build with LTO:

Dataset Rows Symbols Time Throughput
Full A-share daily 8,440,404 5,351 0.63s 13.4M rows/s

Outputs produced in a single pass:

Output Size Description
dailys 8,435,053 rows × 15 cols Per-symbol daily attribution
pairs 942,679 rows × 11 cols FIFO-matched trade pairs
daily_return 2,023 rows Equal-weight portfolio daily return
alpha 2,023 rows × 4 cols Strategy vs. benchmark excess return
stats 29 metrics Sharpe, Calmar, drawdown, win rate, etc.
Sample stats output (click to expand)
{
  "开始日期": "2016-12-27",       "结束日期": "2025-04-28",
  "绝对收益": 0.4431,             "年化": 0.0552,
  "夏普": 0.345,                  "最大回撤": 0.2234,
  "卡玛": 0.2471,                 "日胜率": 0.5136,
  "日盈亏比": 1.0219,             "日赢面": 0.0384,
  "年化波动率": 0.16,              "下行波动率": 0.1167,
  "非零覆盖": 0.9802,             "盈亏平衡点": 0.9975,
  "新高间隔": 542.0,              "新高占比": 0.0277,
  "回撤风险": 1.3963,             "回归年度回报率": 0.0395,
  "长度调整平均最大回撤": 0.9516,   "交易胜率": 0.2697,
  "单笔收益": 17.51,              "持仓K线数": 9.79,
  "多头占比": 0.4611,             "空头占比": 0.5269,
  "与基准相关性": -0.2835,         "与基准空头相关性": -0.374,
  "波动比": 0.6665,               "与基准波动相关性": 0.1974,
  "品种数量": 5351
}

Performance Design

  • O(N) counting sort for symbol grouping (replaces generic sort)
  • Struct-of-Arrays (SoA) layout for cache-locality in hot loops
  • Lazy DataFrame materialization — internal computation uses raw vectors; DataFrames built only on demand
  • FIFO lot matching via stack-based SoA with dynamic resizing
  • rayon data-parallelism across symbols with configurable thread pool
  • Zero-copy slicing from Polars DataFrames into contiguous memory blocks
  • Arrow IPC for zero-serialization-overhead Python <-> Rust data transfer

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wbt-0.1.2.tar.gz (56.2 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

wbt-0.1.2-cp312-cp312-win_amd64.whl (10.1 MB view details)

Uploaded CPython 3.12Windows x86-64

wbt-0.1.2-cp312-cp312-macosx_11_0_arm64.whl (8.3 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

wbt-0.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (9.5 MB view details)

Uploaded CPython 3.8manylinux: glibc 2.17+ x86-64

File details

Details for the file wbt-0.1.2.tar.gz.

File metadata

  • Download URL: wbt-0.1.2.tar.gz
  • Upload date:
  • Size: 56.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for wbt-0.1.2.tar.gz
Algorithm Hash digest
SHA256 5299e400318841fea7e3c79f91327c1d875de2a65fce38d9dc8845e6603f50f7
MD5 a0f6920ffc902867d4e84ae725de6866
BLAKE2b-256 8bea84922c0e4f414df87edbae06e7b0d64c0fcd8a2eb702e84d4fda8904281d

See more details on using hashes here.

Provenance

The following attestation bundles were made for wbt-0.1.2.tar.gz:

Publisher: release.yml on zengbin93/wbt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file wbt-0.1.2-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: wbt-0.1.2-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 10.1 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for wbt-0.1.2-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 b0c33e6db61cbde42bf9629eb1f73b2099338508dad6920e3ff825e5fd4a0e44
MD5 28c856ad5ed3ed95fbc47eb0bffa527b
BLAKE2b-256 3fd91c97d62c3a40367438aa75f5eb532d9806cf2bbd638db5bda574178badb8

See more details on using hashes here.

Provenance

The following attestation bundles were made for wbt-0.1.2-cp312-cp312-win_amd64.whl:

Publisher: release.yml on zengbin93/wbt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file wbt-0.1.2-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

  • Download URL: wbt-0.1.2-cp312-cp312-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 8.3 MB
  • Tags: CPython 3.12, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for wbt-0.1.2-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 526b82d6f84d090a5a12d05418a130b9c82898b9476165eca444b1c0af67b55c
MD5 b44fa444921c7bbb23f4246a857dd6f8
BLAKE2b-256 bf5270eb9d00827906718d0cdca094d85ac8448d2a8f283cdd88c7316c092a0e

See more details on using hashes here.

Provenance

The following attestation bundles were made for wbt-0.1.2-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: release.yml on zengbin93/wbt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file wbt-0.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for wbt-0.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 19c62f0b6da2439800b9edbf27a7b79b4a993271be9a5b1c249d3823170ac4ee
MD5 ebd442ebe747804e095d05a21c8ee659
BLAKE2b-256 59cde69bc4c91b546325f171353c6ba19b4135ff334c31d9f6e9ee77ab6c9beb

See more details on using hashes here.

Provenance

The following attestation bundles were made for wbt-0.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on zengbin93/wbt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page