Skip to main content

Rust-based tick-level backtester (WIP)

Project description

crypto-rs-backtester

Open In Colab

Japanese version: see README.ja.md.

A tick-level, high-precision backtester powered by Rust × Python (Polars), designed for researchers. WIP.

  • Goal: Combine Python's agility with Rust's deterministic, high-performance simulation to eliminate performance bottlenecks, look-ahead bias, and poor reproducibility.
  • Scope: Mainly crypto spot/futures (CEX). Validates microstructure such as multi-exchange, latency, and queue position.

Key Highlights

  • Performant by design: Rust event-driven core with fixed-point arithmetic; Python focuses on research interface.
  • Zero-copy pipeline: Use Polars (Arrow) in Python and hand off to Rust with minimal copying.
  • Microstructure fidelity: Latency modeling, L2/L3 queue logic, and realistic race conditions (e.g., PendingCancel).
  • Determinism first: Seeded RNGs, stable tie-breaking for identical timestamps.

See docs/SPEC.md for details.

Features (current state)

  • Hybrid architecture: Rust core (event-driven, fixed-point i64) + Python strategy interface.
  • Separated timelines: ts_exchange (ground truth) / ts_local (what the strategy observes) / ts_sim (total order of all events).
  • Look-ahead prevention: Strategies only see MarketView after feed latency. Order arrival and ACK are strictly ordered on ts_sim.
  • Execution modes: Tick mode (on_tick) and Batch mode (on_ticks / on_order_updates).
  • Data ingestion: via Polars LazyFrame (minimal copying), or zero-copy via Arrow C Stream (run_arrow).
  • Determinism: Fixed RNG seed, stable tie-breakers for simultaneous events, lexicographic assignment of symbol IDs.

See docs/SPEC.md for details.


Repository Structure

  • backtester-core/: Rust simulation core (src/*.rs, tests/, benches/)
  • backtester-py/: PyO3 wrapper exposing the core to Python
  • python/: Python package rust_backtester/ and tests in python/tests/
  • docs/: Specs and plans (SPEC.md, PLAN.md, etc.)
  • Root Cargo.toml: Rust workspace, pyproject.toml: maturin build

Installation

pip install crypto-rs-backtester

Install & Build (dev)

Prerequisites: Python 3.9+ / Rust toolchain / maturin

# Virtualenv
python -m venv .venv && source .venv/bin/activate

# Dev install (builds Rust extension)
pip install -e .[dev]

# Alternative: direct build
maturin develop

Quickstart (Python)

Required columns: ts_exchange:Int64, price:Int64, qty:Int64, side:Int8 Recommended: seq:Int64 (stable order for same-timestamp), ts_local:Int64 (if missing, applies ts_exchange + feed_latency_ns) Aliases: ts_eventts_exchange, sizeqty

import polars as pl
from rust_backtester import Backtester

# Tiny deterministic dataset (1e-8 fixed point: 100.0 => 100_00000000)
lf = pl.DataFrame({
    "ts_exchange": [1_000, 2_000, 3_000, 4_000],
    "price": [100_00000000, 101_00000000, 99_00000000, 100_00000000],
    "qty":   [  1_00000000,   1_00000000,  1_00000000,   1_00000000],
    "side":  [            1,           -1,           1,           -1],
    "seq": list(range(4)),
}).lazy()

class MyStrategy:
    def on_tick(self, tick: dict, ctx):
        # Example: place a passive order using the received tick
        ctx.submit_order(
            symbol_id=int(tick["symbol_id"]),
            side=1,  # 1=Buy, -1=Sell
            price=int(tick["price"]),
            qty=1_00000000,
        )

bt = Backtester(
    data={"binance:BTC/USDT": lf},
    seed=42,
    python_mode="tick",    # or "batch"
    batch_ms=100,
    feed_latency_ns=1_000,  # applies ts_local = ts_exchange + 1_000 (ns)
)

result = bt.run(MyStrategy())
print(result.stats())
print(result.trades())

Batch mode (higher throughput)

class MyBatch:
    def on_ticks(self, ticks: list[dict], ctx):
        for t in ticks:
            ctx.submit_order(symbol_id=t["symbol_id"], side=1, price=t["price"], qty=1_00000000)

bt = Backtester(data={"binance:BTC/USDT": lf}, seed=42, python_mode="batch", batch_ms=50)
res = bt.run(MyBatch())

Arrow zero-copy path (for large datasets)

# Pass a PyArrow RecordBatchReader implementing __arrow_c_stream__
res = bt.run_arrow(stream=rb_reader, strategy=MyBatch())

Build, Test, Benchmarks

  • Python tests: pytest -q
    • Benchmarks only: pytest -m bench -q
  • Rust build: cargo build -p backtester-core
  • Rust tests: cargo test -p backtester-core
  • Rust benches: cargo bench -p backtester-core

Note: python/tests/conftest.py auto-runs maturin develop if the extension isn't installed.


Benchmark Configuration (Practical Conditions)

Criterion benches in Rust can be tuned via environment variables (defaults: 4 symbols × 250k ticks each):

  • BACKTEST_BENCH_NSYMBOLS (default: 4)
  • BACKTEST_BENCH_TICKS_PER_SYMBOL (default: 250000)
  • BACKTEST_BENCH_DT_NS tick spacing in ns (default: 1000)
  • BACKTEST_BENCH_SYMBOL_STAGGER_NS per-symbol start offset in ns (default: 10000)
  • BACKTEST_BENCH_FEED_LATENCY_NS (default: 2000000)
  • BACKTEST_BENCH_ORDER_UPDATE_LATENCY_NS (default: 1000000)
  • BACKTEST_BENCH_ORDER_LATENCY_NS (default: 500000)
  • BACKTEST_BENCH_SUBMIT_EVERY_N order submission interval in ticks (default: 256)
  • BACKTEST_BENCH_MAX_BATCH_NS batch-mode window in ns (default: 10000000)

Example:

# 8 symbols × 500k ticks per symbol, 5ms batch window
BACKTEST_BENCH_NSYMBOLS=8 \
BACKTEST_BENCH_TICKS_PER_SYMBOL=500000 \
BACKTEST_BENCH_MAX_BATCH_NS=5000000 \
cargo bench -p backtester-core --bench bench_core

The E2E benches (bench_engine_e2e_*) measure both Tick and Batch modes under identical conditions. Synthetic data is deterministic and includes realistic order flow (opposite-side, same-price passive limit orders at a fixed interval).

Profile-Guided Optimization (PGO)

To build with PGO for maximum performance (Linux/macOS):

# Requires llvm-profdata (part of LLVM tools)
make pgo

This runs a 4-step pipeline:

  1. Instrumentation build
  2. Profile generation (runs benchmarks)
  3. Profile merge
  4. Optimized build using profiles

Expected improvement: 5-15% throughput.


Examples (example/)

  • example/colab_backtester_demo.ipynb
    • Minimal E2E demo notebook. Click the badge above to run in Colab.
    • For local use, start Jupyter from the repo root and open files under example/.
  • example/crypto_researcher_adoption_guide.md
    • Practical guide for researchers: onboarding, data schema, strategy modes (tick/batch), performance tuning.

Note: Large datasets are not bundled. Start with the minimal data generated by tests in python/tests/ or the Colab demo.


Coding Style & Core Principles

  • Rust: edition 2024, cargo fmt / cargo clippy. Naming: functions/modules snake_case, types CamelCase.
  • Python: PEP 8, 4-space indent. Type hints required for new/changed code.
  • Determinism first: fixed RNG seeds, stable ordering. Avoid f64 for monetary logic (only at I/O boundaries).

Contribution & Commit Guidelines

  • Start with docs/SPEC.md and docs/PLAN.md.
  • Conventional Commits: e.g., feat(core): add queue model, chore(fmt): rustfmt.
  • Branches: feature/..., fix/..., chore/....
  • PRs should include What/Why, linked issues, test plan (commands + results), and performance notes if core paths changed. Update docs/ when APIs or architecture shift.

Status & Roadmap

This project is under active development (WIP). APIs and internals may change.

  • Technical spec: docs/SPEC.md
  • Plan/tests/benches: docs/PLAN.md
  • Researcher adoption guide: example/crypto_researcher_adoption_guide.md
  • Colab demo: example/colab_backtester_demo.ipynb

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

crypto_rs_backtester-0.1.1.tar.gz (75.4 kB view details)

Uploaded Source

Built Distributions

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

crypto_rs_backtester-0.1.1-cp39-abi3-win_amd64.whl (529.0 kB view details)

Uploaded CPython 3.9+Windows x86-64

crypto_rs_backtester-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (602.1 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

crypto_rs_backtester-0.1.1-cp39-abi3-macosx_11_0_arm64.whl (523.9 kB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

crypto_rs_backtester-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl (561.3 kB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file crypto_rs_backtester-0.1.1.tar.gz.

File metadata

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

File hashes

Hashes for crypto_rs_backtester-0.1.1.tar.gz
Algorithm Hash digest
SHA256 325f3e49ce5207dabbb6ea75940ffbf70b7862c818b903718ccf0350a2d32099
MD5 5ba211d90302fec2bace6ff6016be669
BLAKE2b-256 832e4e34acb3931fcdb37eb901f76270385c09e2a038fdb02d46d97c65af9278

See more details on using hashes here.

Provenance

The following attestation bundles were made for crypto_rs_backtester-0.1.1.tar.gz:

Publisher: release.yml on takurot/crypto-rs-backtester

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

File details

Details for the file crypto_rs_backtester-0.1.1-cp39-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for crypto_rs_backtester-0.1.1-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 5d5a3b0830e5031fe3c8128557e167e3f3ffddc3fa602ac4f032efffa8841a72
MD5 b8851010ac1611dcd17e45e38dfa92e8
BLAKE2b-256 5cb3503caf7ffeeb1900d8c0830a74a02a38fddfe5d554d1c5366bad93e64e3e

See more details on using hashes here.

Provenance

The following attestation bundles were made for crypto_rs_backtester-0.1.1-cp39-abi3-win_amd64.whl:

Publisher: release.yml on takurot/crypto-rs-backtester

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

File details

Details for the file crypto_rs_backtester-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for crypto_rs_backtester-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6d01648b3395871676de05e9c380b0d382ee8dacaafb241b367015be82fa8c9e
MD5 1f59f9760cfddd902ee08983b998a8ba
BLAKE2b-256 e0b355a74fd3508ef4caa6201a4ada040f050d266f7ae15272b148698797e1cf

See more details on using hashes here.

Provenance

The following attestation bundles were made for crypto_rs_backtester-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on takurot/crypto-rs-backtester

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

File details

Details for the file crypto_rs_backtester-0.1.1-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for crypto_rs_backtester-0.1.1-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 db6615dd3d50f1ecf832d44cddfcb8d819001eddb45ec1cb2e9a1be63b6bf386
MD5 0d042482bbf829f795382b3249564215
BLAKE2b-256 1e8129d60168656b766019ba7ebbe0d24fa331ed5d0ce94e1198fdd6a646962a

See more details on using hashes here.

Provenance

The following attestation bundles were made for crypto_rs_backtester-0.1.1-cp39-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on takurot/crypto-rs-backtester

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

File details

Details for the file crypto_rs_backtester-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for crypto_rs_backtester-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 a233cdfc79d4416f9b194f6953f66d1bdc2d9523e7ed67db4df23207a05753cb
MD5 cd96580f34b0c3df89331e7ce54ae6f7
BLAKE2b-256 577d3b682886dfd9915be84c958777024c85cc8d0ec39c1ccfd3ffd0f59a91ca

See more details on using hashes here.

Provenance

The following attestation bundles were made for crypto_rs_backtester-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl:

Publisher: release.yml on takurot/crypto-rs-backtester

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