Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
622dfea
fix(risk): apply configured drawdown reductions
stefan-jansen Sep 23, 2026
ca49f9d
fix(results): preserve feed timezone in exported records
stefan-jansen Sep 23, 2026
3f8957c
fix(execution): charge one commission for a flip fill
stefan-jansen Sep 23, 2026
7435694
fix(execution): isolate commission estimates from model state
stefan-jansen Sep 23, 2026
9c5e10e
feat(funding): account for perpetual funding cash flows
stefan-jansen Sep 24, 2026
8a18b58
feat(feed): decide once after all daily session closes
stefan-jansen Sep 24, 2026
b793fcd
docs(examples): bundle offline multi-asset tutorial data
stefan-jansen Sep 24, 2026
fa7bdaa
docs(quickstart): show a completed first backtest
stefan-jansen Sep 24, 2026
742cf2a
docs(orders): compare causal fills across order types
stefan-jansen Sep 24, 2026
8d92dae
docs(rebalancing): run cross-sectional asset examples
stefan-jansen Sep 24, 2026
e29651d
docs(costs): reconcile fills, fees, impact, and funding
stefan-jansen Sep 24, 2026
1adfd1d
docs(accounts): compare buying power, sizing, and caps
stefan-jansen Sep 24, 2026
71aad3e
docs(risk): trace stops and drawdown reductions
stefan-jansen Sep 24, 2026
e4f9531
docs(profiles): bound parity claims and isolate fill settings
stefan-jansen Sep 24, 2026
252f1ff
docs(results): verify exports and diagnostic handoff
stefan-jansen Sep 24, 2026
c98d81e
docs(book): verify companion paths and repair chapter map
stefan-jansen Sep 24, 2026
3c82c24
ci(docs): include book link checker in release lint scope
stefan-jansen Sep 24, 2026
fde7254
docs(home): provide a runnable entry example and tutorial route
stefan-jansen Sep 24, 2026
0524f8e
validation: retain current synthetic framework parity evidence
stefan-jansen Sep 24, 2026
43de7e6
validation: refresh real-strategy parity for current engine
stefan-jansen Sep 24, 2026
56d7aef
test(validation): exercise certification across measured evidence
stefan-jansen Sep 24, 2026
b361ae8
validation: refresh real-strategy timings and published claims
stefan-jansen Sep 24, 2026
eb368dd
test(funding): verify artifact inconsistency recovery
stefan-jansen Sep 24, 2026
8343029
validation: allow bundled example CSVs in release artifacts
stefan-jansen Sep 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -358,11 +358,19 @@ jobs:
--python "$RUNNER_TEMP/candidate-venv/bin/python" \
dist/*.whl

- name: Check pinned book companion links
run: uv run python validation/check_book_links.py

- name: Execute the documented quick starts against the wheel
run: >-
"$RUNNER_TEMP/candidate-venv/bin/python"
validation/check_documentation_examples.py

- name: Exercise the optional diagnostic handoff against the wheel
run: |
uv pip install --python "$RUNNER_TEMP/candidate-venv/bin/python" "ml4t-diagnostic==0.1.4"
"$RUNNER_TEMP/candidate-venv/bin/python" validation/check_documentation_examples.py docs/tutorials/diagnostic-handoff.md

- name: Verify source provenance
run: |
test "$(git rev-parse HEAD)" = "$GITHUB_SHA"
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ jobs:
echo "ML4T_DOCS_VERSION=$(uv run python -c 'import ml4t.backtest as package; print(package.__version__)')" >> "$GITHUB_ENV"
echo "ML4T_DOCS_COMMIT=$GITHUB_SHA" >> "$GITHUB_ENV"

- name: Check pinned book companion links
run: uv run python validation/check_book_links.py

- name: Build docs
run: uv run mkdocs build --strict

Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,9 @@ jobs:
"$RUNNER_TEMP/published-venv/bin/python" -I -c "import ml4t.backtest as package; assert package.__version__ == '${{ needs.preflight.outputs.version }}'"
"$RUNNER_TEMP/published-venv/bin/python" validation/check_documentation_examples.py

uv pip install --python "$RUNNER_TEMP/published-venv/bin/python" "ml4t-diagnostic==0.1.4"
"$RUNNER_TEMP/published-venv/bin/python" validation/check_documentation_examples.py docs/tutorials/diagnostic-handoff.md

- name: Download and verify GitHub release assets
env:
GH_TOKEN: ${{ github.token }}
Expand Down
42 changes: 23 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ for supported setup paths.

## Quick Start

The [first backtest](https://www.ml4trading.io/docs/backtest/getting-started/quickstart/)
uses bundled synthetic data and explains every fill. The [tutorial sequence](https://www.ml4trading.io/docs/backtest/)
then covers orders, multi-asset portfolios, costs, account rules, risk, and results.

<!-- ml4t-doc-test: readme-quickstart -->
```python
from datetime import datetime
Expand Down Expand Up @@ -336,25 +340,25 @@ The table reports engine-call wall time for all 17 correctness-passing pairs. Th

| Real strategy | Pinned framework | Framework median (95% CI), s | ML4T median (95% CI), s | Framework / ML4T median |
|---|---|---:|---:|---:|
| ETF allocation | [VectorBT Pro 2026.6.27](https://github.com/polakowo/vectorbt.pro) | 0.287 (0.286-0.289) | 0.415 (0.414-0.419) | 0.692x |
| ETF allocation | [VectorBT OSS 1.1.0](https://pypi.org/project/vectorbt/1.1.0/) | 0.171 (0.171-0.174) | 0.415 (0.413-0.417) | 0.412x |
| ETF allocation | [Backtrader 1.9.78.123](https://pypi.org/project/backtrader/1.9.78.123/) | 9.355 (9.303-9.424) | 0.430 (0.426-0.432) | 21.762x |
| ETF allocation | [Zipline Reloaded 3.1.1](https://pypi.org/project/zipline-reloaded/3.1.1/) | 3.872 (3.867-3.910) | 0.632 (0.628-0.638) | 6.127x |
| ETF allocation | [LEAN 18001](https://github.com/QuantConnect/Lean) | 2.564 (2.487-2.599) | 0.750 (0.749-0.757) | 3.418x |
| CME futures | [VectorBT Pro 2026.6.27](https://github.com/polakowo/vectorbt.pro) | 0.286 (0.284-0.289) | 0.432 (0.429-0.435) | 0.663x |
| CME futures | [Backtrader 1.9.78.123](https://pypi.org/project/backtrader/1.9.78.123/) | 2.495 (2.488-2.526) | 0.429 (0.427-0.433) | 5.812x |
| Crypto perpetual funding | [LEAN 18001](https://github.com/QuantConnect/Lean) | 2.801 (2.709-2.891) | 0.657 (0.655-0.661) | 4.266x |
| FX allocation (USD-quoted pairs) | [VectorBT Pro 2026.6.27](https://github.com/polakowo/vectorbt.pro) | 0.283 (0.281-0.286) | 0.146 (0.145-0.147) | 1.939x |
| FX allocation (USD-quoted pairs) | [VectorBT OSS 1.1.0](https://pypi.org/project/vectorbt/1.1.0/) | 0.139 (0.138-0.141) | 0.146 (0.145-0.147) | 0.952x |
| FX allocation (USD-quoted pairs) | [Backtrader 1.9.78.123](https://pypi.org/project/backtrader/1.9.78.123/) | 0.425 (0.420-0.432) | 0.146 (0.145-0.147) | 2.920x |
| FX allocation (USD-quoted pairs) | [LEAN 18001](https://github.com/QuantConnect/Lean) | 0.913 (0.877-0.953) | 0.153 (0.152-0.157) | 5.952x |
| US equity panel | [VectorBT Pro 2026.6.27](https://github.com/polakowo/vectorbt.pro) | 0.795 (0.787-0.838) | 20.555 (20.486-20.600) | 0.039x |
| US equity panel | [VectorBT OSS 1.1.0](https://pypi.org/project/vectorbt/1.1.0/) | 16.995 (16.960-17.024) | 20.495 (20.453-20.534) | 0.829x |
| US equity panel | [Backtrader 1.9.78.123](https://pypi.org/project/backtrader/1.9.78.123/) | 495.553 (494.227-510.273) | 21.470 (21.386-21.543) | 23.082x |
| US equity panel | [Zipline Reloaded 3.1.1](https://pypi.org/project/zipline-reloaded/3.1.1/) | 107.609 (106.834-109.150) | 22.132 (22.082-22.234) | 4.862x |
| US equity panel | [LEAN 18001](https://github.com/QuantConnect/Lean) | 47.683 (47.333-48.015) | 26.368 (26.222-26.473) | 1.808x |

Measured 2026-09-03 on `Linux-6.8.0-138-generic-x86_64-with-glibc2.39` with 24 logical CPUs. Each side used one isolated warm-up process and ten isolated measured processes. The timer includes only the engine call; it excludes input loading, model inference, target construction, adapter preparation, result extraction, serialization, reporting. These measurements apply only to the named strategy, framework version, frozen input bundle, and machine. Raw samples and bootstrap intervals are retained in [real-strategy performance evidence](https://github.com/ml4t/backtest/blob/main/validation/REAL_STRATEGY_PERFORMANCE.json).
| ETF allocation | [VectorBT Pro 2026.6.27](https://github.com/polakowo/vectorbt.pro) | 0.293 (0.290-0.298) | 0.424 (0.421-0.434) | 0.691x |
| ETF allocation | [VectorBT OSS 1.1.0](https://pypi.org/project/vectorbt/1.1.0/) | 0.192 (0.176-0.493) | 0.414 (0.413-0.417) | 0.462x |
| ETF allocation | [Backtrader 1.9.78.123](https://pypi.org/project/backtrader/1.9.78.123/) | 9.631 (9.428-9.710) | 0.439 (0.434-0.444) | 21.954x |
| ETF allocation | [Zipline Reloaded 3.1.1](https://pypi.org/project/zipline-reloaded/3.1.1/) | 3.888 (3.878-3.959) | 0.621 (0.618-0.626) | 6.256x |
| ETF allocation | [LEAN 18001](https://github.com/QuantConnect/Lean) | 2.638 (2.516-2.707) | 0.750 (0.743-0.757) | 3.520x |
| CME futures | [VectorBT Pro 2026.6.27](https://github.com/polakowo/vectorbt.pro) | 0.290 (0.289-0.294) | 0.410 (0.406-0.958) | 0.708x |
| CME futures | [Backtrader 1.9.78.123](https://pypi.org/project/backtrader/1.9.78.123/) | 6.639 (5.831-8.332) | 0.428 (0.422-1.235) | 15.504x |
| Crypto perpetual funding | [LEAN 18001](https://github.com/QuantConnect/Lean) | 2.828 (2.737-2.952) | 1.327 (0.657-2.183) | 2.131x |
| FX allocation (USD-quoted pairs) | [VectorBT Pro 2026.6.27](https://github.com/polakowo/vectorbt.pro) | 0.288 (0.286-0.294) | 0.148 (0.147-0.149) | 1.947x |
| FX allocation (USD-quoted pairs) | [VectorBT OSS 1.1.0](https://pypi.org/project/vectorbt/1.1.0/) | 0.144 (0.142-0.146) | 0.145 (0.145-0.146) | 0.988x |
| FX allocation (USD-quoted pairs) | [Backtrader 1.9.78.123](https://pypi.org/project/backtrader/1.9.78.123/) | 0.434 (0.430-0.440) | 0.147 (0.146-0.149) | 2.947x |
| FX allocation (USD-quoted pairs) | [LEAN 18001](https://github.com/QuantConnect/Lean) | 0.953 (0.936-1.164) | 0.158 (0.155-0.164) | 6.033x |
| US equity panel | [VectorBT Pro 2026.6.27](https://github.com/polakowo/vectorbt.pro) | 3.806 (3.336-4.341) | 23.306 (21.906-25.833) | 0.163x |
| US equity panel | [VectorBT OSS 1.1.0](https://pypi.org/project/vectorbt/1.1.0/) | 17.116 (17.069-17.633) | 25.738 (24.983-27.163) | 0.665x |
| US equity panel | [Backtrader 1.9.78.123](https://pypi.org/project/backtrader/1.9.78.123/) | 668.611 (642.993-718.202) | 26.887 (26.406-29.406) | 24.868x |
| US equity panel | [Zipline Reloaded 3.1.1](https://pypi.org/project/zipline-reloaded/3.1.1/) | 117.445 (116.308-118.391) | 26.821 (25.473-27.644) | 4.379x |
| US equity panel | [LEAN 18001](https://github.com/QuantConnect/Lean) | 48.436 (48.221-48.986) | 27.688 (27.575-27.796) | 1.749x |

Measured 2026-09-24 on `Linux-6.8.0-139-generic-x86_64-with-glibc2.39` with 24 logical CPUs. Each side used one isolated warm-up process and ten isolated measured processes. The timer includes only the engine call; it excludes input loading, model inference, target construction, adapter preparation, result extraction, serialization, reporting. These measurements apply only to the named strategy, framework version, frozen input bundle, and machine. Raw samples and bootstrap intervals are retained in [real-strategy performance evidence](https://github.com/ml4t/backtest/blob/main/validation/REAL_STRATEGY_PERFORMANCE.json).

### Synthetic diagnostic scenarios

Expand Down
2 changes: 2 additions & 0 deletions docs/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Auto-generated from source docstrings.
- sell
- close_position
- reduce_position
- reduce_all_positions
- flatten_all_positions
- order_target_percent
- order_target_value
Expand Down Expand Up @@ -169,6 +170,7 @@ Auto-generated from source docstrings.
- from_parquet
- to_trades_dataframe
- to_fills_dataframe
- to_funding_dataframe
- to_rejected_orders_dataframe
- to_portfolio_state_dataframe
- to_predictions_dataframe
Expand Down
Loading
Loading