quantbt-engine 1.0.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. quantbt/__init__.py +862 -0
  2. quantbt/adapters/__init__.py +5 -0
  3. quantbt/adapters/nautilus/__init__.py +42 -0
  4. quantbt/adapters/nautilus/_dependency.py +53 -0
  5. quantbt/adapters/nautilus/backend.py +639 -0
  6. quantbt/adapters/nautilus/instruments.py +275 -0
  7. quantbt/adapters/nautilus/options.py +465 -0
  8. quantbt/adapters/nautilus/reports.py +231 -0
  9. quantbt/backends/__init__.py +29 -0
  10. quantbt/backends/_native_event_rust.py +2168 -0
  11. quantbt/backends/native_event.py +5048 -0
  12. quantbt/backends/native_option.py +796 -0
  13. quantbt/backends/native_portfolio.py +928 -0
  14. quantbt/backends/native_vectorized.py +1299 -0
  15. quantbt/backtester.py +485 -0
  16. quantbt/benchmarks/__init__.py +1 -0
  17. quantbt/benchmarks/compare_phase9_parity.py +302 -0
  18. quantbt/benchmarks/gamma_scalping_backtestsample.py +802 -0
  19. quantbt/benchmarks/profile_phase7.py +415 -0
  20. quantbt/benchmarks/run_arbitrage_phase_e.py +160 -0
  21. quantbt/benchmarks/run_optimization_overhead.py +195 -0
  22. quantbt/benchmarks/run_options_engine.py +272 -0
  23. quantbt/benchmarks/run_pct_equity_nautilus_smoke.py +227 -0
  24. quantbt/benchmarks/run_phase12_arbitrage_cert.py +402 -0
  25. quantbt/benchmarks/run_phase12_benchmark_nautilus_cert.py +430 -0
  26. quantbt/benchmarks/run_phase13_portfolio_report.py +97 -0
  27. quantbt/benchmarks/run_phase13_wfo_cache.py +162 -0
  28. quantbt/benchmarks/run_phase14_service_loop.py +694 -0
  29. quantbt/benchmarks/run_phase15a_nautilus_certification.py +514 -0
  30. quantbt/benchmarks/run_phase15b_synthetic_depth.py +175 -0
  31. quantbt/benchmarks/run_phase16_performance_debt.py +389 -0
  32. quantbt/benchmarks/run_phase30e_reactive_runner.py +161 -0
  33. quantbt/benchmarks/run_phase31_intrabar.py +441 -0
  34. quantbt/benchmarks/run_phase34a_native_event_memory.py +179 -0
  35. quantbt/benchmarks/run_phase34b_native_event_prepared_score.py +173 -0
  36. quantbt/benchmarks/run_phase34c_native_event_single_pass.py +176 -0
  37. quantbt/benchmarks/run_phase7.py +654 -0
  38. quantbt/benchmarks/run_portfolio_real_parity.py +537 -0
  39. quantbt/core/__init__.py +323 -0
  40. quantbt/core/arbitrage.py +767 -0
  41. quantbt/core/basket.py +234 -0
  42. quantbt/core/certification.py +274 -0
  43. quantbt/core/constraints.py +155 -0
  44. quantbt/core/engine.py +1144 -0
  45. quantbt/core/event.py +869 -0
  46. quantbt/core/execution_contract.py +197 -0
  47. quantbt/core/execution_depth.py +613 -0
  48. quantbt/core/intrabar_kernel.py +1906 -0
  49. quantbt/core/intrabar_reference.py +907 -0
  50. quantbt/core/intrabar_session.py +156 -0
  51. quantbt/core/market_tape.py +480 -0
  52. quantbt/core/native_event_capabilities.py +121 -0
  53. quantbt/core/native_event_parity.py +336 -0
  54. quantbt/core/order_compiler.py +422 -0
  55. quantbt/core/orders.py +319 -0
  56. quantbt/core/portfolio.py +392 -0
  57. quantbt/core/preprocessor.py +256 -0
  58. quantbt/core/reactive.py +173 -0
  59. quantbt/core/results.py +341 -0
  60. quantbt/core/schema.py +211 -0
  61. quantbt/core/scopes.py +96 -0
  62. quantbt/core/structured_orders.py +378 -0
  63. quantbt/core/types.py +87 -0
  64. quantbt/core/vectorized.py +203 -0
  65. quantbt/endpoint.py +4465 -0
  66. quantbt/engines.py +1014 -0
  67. quantbt/metrics/__init__.py +45 -0
  68. quantbt/metrics/options_analytics.py +46 -0
  69. quantbt/metrics/performance.py +541 -0
  70. quantbt/optimization/__init__.py +94 -0
  71. quantbt/optimization/callbacks.py +116 -0
  72. quantbt/optimization/candidate_selection.py +397 -0
  73. quantbt/optimization/config.py +84 -0
  74. quantbt/optimization/constraints.py +22 -0
  75. quantbt/optimization/evaluator.py +21 -0
  76. quantbt/optimization/evaluators/__init__.py +32 -0
  77. quantbt/optimization/evaluators/arbitrage.py +22 -0
  78. quantbt/optimization/evaluators/generic.py +34 -0
  79. quantbt/optimization/evaluators/grid_dca.py +22 -0
  80. quantbt/optimization/evaluators/intrabar.py +54 -0
  81. quantbt/optimization/evaluators/native_event.py +51 -0
  82. quantbt/optimization/evaluators/options.py +22 -0
  83. quantbt/optimization/evaluators/portfolio.py +42 -0
  84. quantbt/optimization/evaluators/signal.py +43 -0
  85. quantbt/optimization/multiseed.py +176 -0
  86. quantbt/optimization/objectives.py +221 -0
  87. quantbt/optimization/optimizer.py +500 -0
  88. quantbt/optimization/result.py +80 -0
  89. quantbt/optimization/samplers.py +84 -0
  90. quantbt/optimization/space.py +223 -0
  91. quantbt/options/__init__.py +215 -0
  92. quantbt/options/cache.py +116 -0
  93. quantbt/options/conventions.py +158 -0
  94. quantbt/options/data.py +177 -0
  95. quantbt/options/execution.py +600 -0
  96. quantbt/options/fees.py +135 -0
  97. quantbt/options/greeks.py +173 -0
  98. quantbt/options/hedging.py +232 -0
  99. quantbt/options/iv.py +188 -0
  100. quantbt/options/ledger.py +263 -0
  101. quantbt/options/lifecycle.py +94 -0
  102. quantbt/options/margin.py +311 -0
  103. quantbt/options/packages.py +147 -0
  104. quantbt/options/pricing.py +191 -0
  105. quantbt/options/schema.py +227 -0
  106. quantbt/options/selectors.py +281 -0
  107. quantbt/options/strategy.py +249 -0
  108. quantbt/options/surface.py +142 -0
  109. quantbt/options/tape.py +226 -0
  110. quantbt/options/templates/__init__.py +33 -0
  111. quantbt/options/templates/packages.py +354 -0
  112. quantbt/portfolio.py +606 -0
  113. quantbt/py.typed +1 -0
  114. quantbt/reporting/__init__.py +38 -0
  115. quantbt/reporting/arbitrage_audit.py +211 -0
  116. quantbt/reporting/nautilus_bundle.py +758 -0
  117. quantbt/reporting/nautilus_certification.py +226 -0
  118. quantbt/reporting/nautilus_diagnostics.py +225 -0
  119. quantbt/reporting/parity.py +496 -0
  120. quantbt/reporting/portfolio_audit.py +206 -0
  121. quantbt/reporting/portfolio_nautilus.py +140 -0
  122. quantbt/sizing/__init__.py +3 -0
  123. quantbt/sizing/fast.py +67 -0
  124. quantbt/sizing/modes.py +162 -0
  125. quantbt/viz/__init__.py +4 -0
  126. quantbt/viz/plots.py +310 -0
  127. quantbt/viz/themes.py +102 -0
  128. quantbt/walkforward.py +3136 -0
  129. quantbt_engine-1.0.7.dist-info/METADATA +891 -0
  130. quantbt_engine-1.0.7.dist-info/RECORD +133 -0
  131. quantbt_engine-1.0.7.dist-info/WHEEL +5 -0
  132. quantbt_engine-1.0.7.dist-info/licenses/LICENSE +21 -0
  133. quantbt_engine-1.0.7.dist-info/top_level.txt +1 -0
@@ -0,0 +1,891 @@
1
+ Metadata-Version: 2.4
2
+ Name: quantbt-engine
3
+ Version: 1.0.7
4
+ Summary: Transparent, high-performance quantitative backtesting engine
5
+ Author-email: Vu Cong Minh <vugioan11022002@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/BobbyAxerol/quantbt
8
+ Project-URL: Repository, https://github.com/BobbyAxerol/quantbt
9
+ Project-URL: Issues, https://github.com/BobbyAxerol/quantbt/issues
10
+ Project-URL: Documentation, https://github.com/BobbyAxerol/quantbt/tree/main/docs
11
+ Project-URL: Changelog, https://github.com/BobbyAxerol/quantbt/blob/main/CHANGELOG.md
12
+ Keywords: backtesting,quant,trading,numba,portfolio,event-driven
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Financial and Insurance Industry
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Office/Business :: Financial :: Investment
21
+ Classifier: Topic :: Scientific/Engineering
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: <3.14,>=3.11
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: numpy<2.3,>=2.2.6
27
+ Requires-Dist: pandas<2.4,>=2.3.3
28
+ Requires-Dist: numba<0.66,>=0.65.1
29
+ Provides-Extra: optimization
30
+ Requires-Dist: optuna<4.9,>=4.8.0; extra == "optimization"
31
+ Requires-Dist: arch<8.1,>=8.0.0; extra == "optimization"
32
+ Requires-Dist: scikit-learn<1.9,>=1.8.0; extra == "optimization"
33
+ Provides-Extra: reports
34
+ Requires-Dist: quantstats==0.0.81; extra == "reports"
35
+ Provides-Extra: viz
36
+ Requires-Dist: matplotlib<3.11,>=3.10.9; extra == "viz"
37
+ Requires-Dist: seaborn<0.14,>=0.13.2; extra == "viz"
38
+ Provides-Extra: validation
39
+ Requires-Dist: nautilus-trader<1.231,>=1.230.0; python_version >= "3.12" and extra == "validation"
40
+ Provides-Extra: native
41
+ Provides-Extra: all
42
+ Requires-Dist: optuna<4.9,>=4.8.0; extra == "all"
43
+ Requires-Dist: arch<8.1,>=8.0.0; extra == "all"
44
+ Requires-Dist: scikit-learn<1.9,>=1.8.0; extra == "all"
45
+ Requires-Dist: quantstats==0.0.81; extra == "all"
46
+ Requires-Dist: matplotlib<3.11,>=3.10.9; extra == "all"
47
+ Requires-Dist: seaborn<0.14,>=0.13.2; extra == "all"
48
+ Requires-Dist: nautilus-trader<1.231,>=1.230.0; python_version >= "3.12" and extra == "all"
49
+ Dynamic: license-file
50
+
51
+ # QuantBT
52
+
53
+ ![Python](https://img.shields.io/badge/python-3.11%2B-blue)
54
+ ![Numba](https://img.shields.io/badge/core-numba-00A86B)
55
+ ![Backtesting](https://img.shields.io/badge/backtesting-vectorized%20%7C%20event--driven-black)
56
+ ![Nautilus](https://img.shields.io/badge/nautilus-optional-6f42c1)
57
+ ![License](https://img.shields.io/badge/license-MIT-lightgrey)
58
+
59
+ QuantBT is a transparent, high-speed backtesting toolkit for crypto,
60
+ multi-symbol portfolios, systematic alphas, and execution validation.
61
+
62
+ It gives notebooks and services one stable endpoint over several simulation
63
+ layers: fast native vectorized research, native event-driven order/fill
64
+ simulation, legacy-compatible portfolio modes, walk-forward optimization, and
65
+ optional NautilusTrader validation for third-party execution/accounting checks.
66
+
67
+ The goal is simple: make alpha research fast enough for iteration, strict
68
+ enough for institutional-style review, and readable enough that stakeholders can
69
+ audit how a result was produced.
70
+
71
+ Current portfolio status: `native_portfolio` is the default multi-symbol
72
+ backend. It supports long/short, market-neutral, directional, equal-weight,
73
+ risk-parity, and beta-neutral portfolio modes, with live-equity sizing and
74
+ target exposure contracts. The legacy portfolio route remains available for
75
+ historical reproduction.
76
+
77
+ ## Why QuantBT
78
+
79
+ - One public API for notebooks, services, portfolio research, and validation.
80
+ - Native vectorized engines for fast sweeps and large parameter grids.
81
+ - Native event-driven engines for market/limit orders, fills, baskets, and
82
+ arbitrage package execution.
83
+ - Prepared service contexts for repeated signal/portfolio replays on the same
84
+ market tape without re-normalizing pandas data each run.
85
+ - Native portfolio engine with target weights, target notionals, target units,
86
+ gross/net exposure, risk parity, beta neutrality, margin reports, and
87
+ per-symbol attribution.
88
+ - Optional NautilusTrader adapter for independent event-driven validation.
89
+ - Nautilus explicit order replay for single-symbol `OrderIntent` validation.
90
+ - Explicit margin, leverage, fees, slippage, funding, and liquidation handling.
91
+ - Stable audit artifacts: metrics, plots, raw reports, trade logs, config JSON,
92
+ run manifest, and optional QuantStats HTML.
93
+ - Nautilus certification bundles with parity CSVs, tolerance profiles, known
94
+ differences, and explicit skip/pass status for optional trustee workflows.
95
+ - Nautilus package-depth preflight with OHLCV volume caps and synthetic-book
96
+ stress tests for spread, queue, participation, partial-fill, and package
97
+ rejection assumptions.
98
+ - Walk-forward and train/test optimization designed to avoid leaking OOS data
99
+ into parameter selection, plus full-sample robust calibration for final
100
+ production parameter discovery.
101
+ - Domain-agnostic Optuna optimization adapters for prepared signal, intrabar,
102
+ portfolio, and generic endpoint workflows.
103
+
104
+ ## Event-Driven Quick Start
105
+
106
+ New event-driven integrations should use the stable facade. Choose an input
107
+ mode, a retention profile, and a public backend; the facade keeps matching,
108
+ fills, fees, slippage, margin, funding, and PnL in the existing native-event
109
+ engine.
110
+
111
+ ```python
112
+ from quantbt import QuantBTEndpoint
113
+
114
+ bt = QuantBTEndpoint.event_driven(
115
+ input_mode="strategy", # strategy | orders
116
+ profile="research", # research | optimize | audit
117
+ backend="auto", # auto | python | rust
118
+ initial_capital=20_000,
119
+ leverage=5,
120
+ fee_rate=0.0005, # one-way fee per fill
121
+ slippage_bps=2.0,
122
+ use_funding=False,
123
+ )
124
+
125
+ result = bt.simulate(data=df, strategy=strategy, symbols=["BTCUSDT"])
126
+ bt.show_metrics()
127
+ ```
128
+
129
+ Use `profile="research"` for compact notebook results, `"optimize"` for
130
+ scalar parameter-search results, and `"audit"` for replay-certified fills and
131
+ event artifacts. For an upstream order planner, switch to
132
+ `input_mode="orders"` and pass `order_commands=[...]`. The default `auto`
133
+ backend follows the release policy; `rust` is an explicit request for the
134
+ optional capability-gated native wheel.
135
+
136
+ The strategy owns signal generation and look-ahead control. QuantBT owns the
137
+ causal order lifecycle and accounting. Advanced users can still call
138
+ `native_event_strategy(...)` or `native_event_lifecycle(...)` directly when a
139
+ custom low-level execution/report combination is required.
140
+
141
+ See [`docs/endpoint.md`](docs/endpoint.md#stable-event-driven-facade) for the
142
+ full strategy protocol, profile matrix, explicit-order example, conflict
143
+ rules, and migration guidance. The broader endpoint map is in
144
+ [`docs/README.md`](docs/README.md).
145
+
146
+ ## Performance Philosophy
147
+
148
+ QuantBT is built for research loops where speed matters as much as accounting
149
+ clarity. The public API stays Pythonic, but the heavy computation path is pushed
150
+ toward NumPy/Numba kernels so large signal matrices, parameter sweeps,
151
+ walk-forward runs, and multi-symbol portfolios can run close to native compiled
152
+ performance without forcing researchers into a C++ or C# codebase.
153
+
154
+ The intent is not to be a black-box replacement for mature execution engines.
155
+ LEAN/QuantConnect brings a large C# institutional platform, NautilusTrader
156
+ brings a Rust-backed event-driven trading stack, vectorbt is excellent for
157
+ vectorized research, and Backtrader remains a widely used Python event-driven
158
+ framework. QuantBT sits between those worlds: fast native-vectorized and
159
+ Numba-accelerated research paths for iteration, native event simulation for
160
+ transparent order accounting, and optional Nautilus validation when a run needs
161
+ third-party execution evidence.
162
+
163
+ Benchmarks are versioned under `benchmarks/` rather than hidden in marketing
164
+ claims. Phase 7 currently measures bars x symbols, order count, event count,
165
+ warmup/compile time, runtime, memory, throughput, and threshold pass/fail across
166
+ native vectorized, native event, portfolio, and optional Nautilus routes. The
167
+ rule is simple: keep hot loops near C/C++-style runtime with Numba first, profile
168
+ before optimizing, and only consider Cython/C++ when a proven hotspot cannot be
169
+ fixed safely in the Python/Numba stack.
170
+
171
+ Latest Phase 7 standard runtime benchmark after the Phase 11E native portfolio
172
+ default switch on this workspace:
173
+
174
+ | Route | Workload | Runtime | Throughput | Peak Memory | Threshold |
175
+ |---|---:|---:|---:|---:|---|
176
+ | `native_vectorized` | 25,000 bars x 20 symbols | 0.463s | 1,079,402 bar-symbols/s | 145.3 MB | pass |
177
+ | `native_event` | 25,000 explicit orders, cold preparation | 3.041s | 164,442 events/s | 99.4 MB | threshold miss; profiling target |
178
+ | `native_event_prepared` | 25,000 explicit orders, prepared replay | 1.621s | 308,545 events/s | 30.4 MB | threshold miss; faster reuse path |
179
+ | `portfolio_legacy` | 25,000 bars x 20 symbols | 1.669s | 299,575 bar-symbols/s | 236.3 MB | threshold miss |
180
+ | `native_portfolio` | 25,000 bars x 20 symbols | 1.750s | 285,724 bar-symbols/s | 236.1 MB | default; full audit/report route |
181
+ | `nautilus` | optional validation route | skipped | - | - | run with `--include-nautilus` |
182
+
183
+ The portfolio numbers measure the full facade with diagnostics, exposure
184
+ reports, per-symbol attribution, contract validation, and equity-aware sizing.
185
+ They are intentionally treated as correctness-first default routes; pure kernel
186
+ and reporting-layer profiling remains the next speed follow-up before any
187
+ Cython/C++ work. See `benchmarks/phase9_optimization_report.md`,
188
+ `benchmarks/phase7_profile_report.md`, and
189
+ `benchmarks/portfolio_real_parity_report.md` for parity and optimization
190
+ history.
191
+
192
+ Latest Phase 14C service-loop optimization benchmark:
193
+
194
+ | Workload | Cold / full route | Prepared / minimal route | Speedup | Parity |
195
+ |---|---:|---:|---:|---|
196
+ | Single-symbol WFO | 1.007s | 0.883s | 1.14x | pass |
197
+ | Portfolio WFO | 0.440s | 0.326s | 1.35x | pass |
198
+ | Native-event order replay | 0.0096s | 0.0046s | 2.10x | pass |
199
+ | Arbitrage package replay | 0.0746s | 0.0663s | 1.13x | pass |
200
+ | Native portfolio reports | 0.0410s full | 0.0233s minimal | 1.76x | pass |
201
+
202
+ Phase 14C added run-local prepared market-array reuse for WFO/service loops and
203
+ `report_level="full" | "standard" | "minimal"` for native portfolio reports.
204
+ The default remains `full`; lighter report levels are opt-in for optimizers and
205
+ services, and parity tests lock core accounting equality before any speed claim.
206
+
207
+ Latest Phase 16 service-context closure benchmark:
208
+
209
+ | Workload | Normal endpoint | Prepared context | Speedup | Parity |
210
+ |---|---:|---:|---:|---|
211
+ | Single-symbol signal_notional replays | 0.0711s | 0.0390s | 1.82x | pass |
212
+ | Native portfolio replays | 0.3115s | 0.0695s | 4.48x | pass |
213
+ | Native portfolio reports | 0.0755s full | 0.0394s minimal | 1.92x | pass |
214
+
215
+ Phase 16 adds `endpoint.prepare_service_context(...)`, an opt-in helper for
216
+ services that replay many signals or position matrices against one fixed market
217
+ tape. Normal `.backtest(...)` remains defensive and backward-compatible.
218
+ Cython/C++ remains deferred because the larger benchmark still points to
219
+ facade/report overhead rather than pure Numba kernels.
220
+
221
+ Latest Phase 31 intrabar execution benchmark:
222
+
223
+ | Route | Workload | Runtime | Throughput | Ratio | Parity |
224
+ |---|---:|---:|---:|---:|---|
225
+ | `close_target_v2_pure_kernel` | 25,000 bars | 0.0087s | 2,879,313 bars/s | baseline | baseline |
226
+ | `intrabar_bracket_v1_minimal` | 25,000 bars, 2,000 fills | 0.0118s | 2,115,865 bars/s | 1.36x close-target | oracle-checked |
227
+ | `intrabar_bracket_v1_audit` | 25,000 bars, fill ledger | 0.0527s | 474,427 bars/s | 4.46x minimal | pass |
228
+ | `intrabar_session_bracket_v1_minimal` | 25,000 bars, session state | 0.0117s | 2,145,495 bars/s | 0.99x minimal | reference-checked |
229
+ | `intrabar_session_bracket_v1_audit` | 25,000 bars, session ledger | 0.0499s | 501,156 bars/s | 4.22x minimal | pass |
230
+ | `intrabar_reference_python` | 25,000 bars | 0.2394s | 104,419 bars/s | 20.26x slower than minimal | truth model |
231
+ | `fill_replay_v1_kernel` | 25,000 bars, 2,000 fills | 0.0124s | 2,013,664 bars/s | 1.05x minimal | accounting |
232
+ | `native_event_explicit_orders_facade` | 25,000 bars, 2,000 market orders | 0.0761s | 328,618 bars/s | 6.44x minimal | speed reference |
233
+
234
+ Phase 31 adds execution-contract certification for close-target, fast intrabar
235
+ SL/TP/trailing, optional session-aware intraday execution state, and explicit
236
+ fill replay paths. The fast intrabar kernel is about 20.3x faster than the
237
+ readable Python oracle on the committed benchmark; the session kernel keeps the
238
+ non-session hot path separate while adding entry windows, EOD force-flat,
239
+ per-session quota, stale-signal cancellation, and re-entry suppression.
240
+
241
+ Latest Phase 32C optimization overhead benchmark:
242
+
243
+ | Measurement | Result |
244
+ |---|---:|
245
+ | Optimizer overhead | 0.0174s for 24 trials |
246
+ | Optimizer overhead / trial | 0.000723s |
247
+ | Prepared signal evaluator | 2.03x faster than normal endpoint replay |
248
+ | Intrabar first vs warm run | 3.70x first/warm ratio |
249
+ | Parity | pass, final equity diff 0.0 |
250
+
251
+ Phase 32C consolidates safe walk-forward optimization primitives with the new
252
+ domain-agnostic optimizer core while keeping WFO fold isolation and robust
253
+ selection semantics inside `walkforward.py`. Read
254
+ [`docs/optimization.md`](docs/optimization.md) and
255
+ `benchmarks/results/optimization_overhead.md` for signal, intrabar, portfolio,
256
+ arbitrage/grid/options fallback examples and benchmark details.
257
+
258
+ ### Phase 46F package and dual-backend release evidence
259
+
260
+ The core distribution is packaged as `quantbt-engine` and imports as
261
+ `quantbt`. Its release gate is independent from the optional experimental Rust
262
+ wheel:
263
+
264
+ | Release artifact | Current status | Backend policy |
265
+ |---|---|---|
266
+ | `quantbt-engine==1.0.7` wheel/sdist | release-ready after local/TestPyPI approval | Python canonical; all existing endpoints remain available |
267
+ | `quantbt-native` PyO3 wheel | experimental, not published | explicit `native_backend="rust"` only |
268
+ | `quantbt-engine[native]` | intentionally empty | no dependency is advertised before native certification |
269
+
270
+ The committed Phase 46F rerun compares the same prepared static tape and keeps
271
+ Python/Rust accounting parity at 100%:
272
+
273
+ | Workload | Python median | Rust median | Python throughput | Rust throughput | Peak RSS | Parity |
274
+ |---|---:|---:|---:|---:|---:|---|
275
+ | Low churn, 2,000 bars | 20.33 ms | 0.109 ms | 98,385 bars/s | 18.30M bars/s | 181.97 MB | pass |
276
+ | High churn, 2,000 bars | 36.16 ms | 0.140 ms | 55,308 bars/s | 14.33M bars/s | 181.94 MB | pass |
277
+ | Prepared RSS reduction | - | - | - | - | -26.1% / -7.6%; absolute budget pass | gate fail |
278
+
279
+ These are score-kernel measurements, not claims about full facade/report
280
+ runtime. The table reports raw median time and bars/second from five warmed
281
+ repetitions so the result is readable without an internal speedup convention.
282
+ The earlier Phase 45F end-to-end reference is retained in the JSON evidence
283
+ for historical comparison. The evidence files are
284
+ [`phase46e_release_gate.json`](benchmarks/native_event/phase46e_release_gate.json),
285
+ [`phase46f_release_gate.json`](benchmarks/native_event/phase46f_release_gate.json),
286
+ [`phase46d1_score_rss.json`](benchmarks/native_event/phase46d1_score_rss.json),
287
+ and [`phase45f_release_gate.json`](benchmarks/native_event/phase45f_release_gate.json).
288
+
289
+ Phase 47C Grid integration evidence uses the external read-only Grid alpha on
290
+ the same deterministic 2,000-bar tape in both long-only and long-short modes:
291
+
292
+ | Mode | Python scalar median | Rust scalar median | Python peak RSS | Rust peak RSS | Fingerprint parity |
293
+ |---|---:|---:|---:|---:|---|
294
+ | Long-only | 1.138 s | 1.245 s | 265.6 MB | 273.2 MB | pass |
295
+ | Long-short | 1.846 s | 1.985 s | 291.1 MB | 293.4 MB | pass |
296
+
297
+ These are full reactive facade measurements, not pure Rust kernel claims. Rust
298
+ is currently slightly slower on this Grid integration but produces the same
299
+ command/fill/accounting fingerprint and is explicit fail-fast; `auto` remains
300
+ Python. The benchmark runner, five-run RSS slope gate, and scalar/audit
301
+ fingerprint contract are documented in
302
+ [`docs/grid_native_event_phase47c.md`](docs/grid_native_event_phase47c.md),
303
+ with raw JSON under `benchmarks/native_event/results/phase47c/`. The RSS
304
+ figures are the current Grid facade evidence; they are not compared directly
305
+ to the older ~180 MB core-process profile without a like-for-like baseline.
306
+
307
+ ### Phase 47D Grid optimizer evidence
308
+
309
+ Phase 47D profiles the real prepared Grid optimizer path by separating alpha
310
+ preparation, strategy construction, engine score, and public report work. The
311
+ safe patch removes per-bar Grid diagnostics and diagnostic alias columns only
312
+ from scalar trials, while public/audit defaults remain unchanged. On the same
313
+ 2,000-bar deterministic tape:
314
+
315
+ | Grid mode | Python scalar | Rust scalar | Python throughput | Rust throughput | Peak RSS Python/Rust | Parity |
316
+ |---|---:|---:|---:|---:|---:|---|
317
+ | Long-only | 0.850 s | 1.086 s | 2,354 bars/s | 1,842 bars/s | 265.4 / 271.2 MB | pass |
318
+ | Long-short | 1.412 s | 1.831 s | 1,416 bars/s | 1,092 bars/s | 291.0 / 293.6 MB | pass |
319
+
320
+ The apples-to-apples prepared scalar profile measured `0.813s` in the local
321
+ five-repeat profile. The timing breakdown shows the reactive engine callback
322
+ at about `97.9%` and alpha preparation at about `2.2%`, so an indicator cache
323
+ was deliberately not added. This evidence does not claim that Rust is faster
324
+ for the Python reactive Grid facade; Rust remains explicit experimental and
325
+ `auto` remains Python. See
326
+ [`docs/grid_native_event_phase47c.md`](docs/grid_native_event_phase47c.md)
327
+ for the scalar retention contract, RSS interpretation, and remaining debt.
328
+ Raw Phase 47D artifacts are kept under
329
+ `benchmarks/native_event/results/phase47d/`.
330
+
331
+ ### Phase 48F final release handoff
332
+
333
+ The core `quantbt-engine` 1.0.7 artifact gate is now implemented locally and
334
+ in the release workflows: exact version/ref validation, wheel and sdist
335
+ `twine check`, archive allowlist and secret scan, clean import plus `pip check`,
336
+ and a SHA256 release manifest. The TestPyPI workflow is manual and OIDC
337
+ protected; it must be run with an unused matching RC version/tag and reviewed
338
+ before production PyPI publication. See
339
+ [`docs/testpypi_release_checklist.md`](docs/testpypi_release_checklist.md).
340
+ `quantbt-native` is intentionally excluded from this core upload, `auto`
341
+ remains Python, and explicit Rust remains capability-gated.
342
+
343
+ ### Phase 48C stable event-driven facade evidence
344
+
345
+ The stable `QuantBTEndpoint.event_driven()` facade was benchmarked on the same
346
+ deterministic **2,000-bar** single-symbol baseline as the direct native-event
347
+ strategy constructor. Each route ran in a fresh process with five measured
348
+ repetitions. The Grid workload is reported separately because indicator
349
+ preparation and reactive state-machine work are part of its runtime.
350
+
351
+ | Common route | Median runtime | Throughput | Peak RSS | Fills | Final Equity | Parity |
352
+ |---|---:|---:|---:|---:|---:|---|
353
+ | `native_event_strategy` | 161.20 ms | 12,407 bars/s | 184.2 MB | 109 | 19,998.269072 | baseline |
354
+ | `event_driven(profile="research")` | 154.54 ms | 12,942 bars/s | 183.4 MB | 109 | 19,998.269072 | pass |
355
+
356
+ Separate reactive Grid benchmark on 2,000 bars:
357
+
358
+ | Grid route | Median runtime | Throughput | Peak RSS | Fills | Final Equity | Parity |
359
+ |---|---:|---:|---:|---:|---:|---|
360
+ | direct `native_event_strategy` | 1.4187 s | 1,410 bars/s | 274.5 MB | 839 | 28,972.788456 | baseline |
361
+ | `event_driven(profile="audit")` | 1.3986 s | 1,430 bars/s | 274.5 MB | 839 | 28,972.788456 | pass |
362
+
363
+ Both comparisons have identical accounting fingerprints, including equity,
364
+ positions, fees, funding, margin, lifecycle counters, fills, and liquidation
365
+ state. The facade adds no second execution loop; the small runtime difference
366
+ is measurement noise and configuration resolution. Reproduce with
367
+ `benchmarks/benchmark_phase48c_event_driven.py`; raw evidence is in
368
+ [`phase48c_event_driven_facade.md`](benchmarks/phase48c_event_driven_facade.md)
369
+ and [`phase48c_event_driven_facade.json`](benchmarks/phase48c_event_driven_facade.json).
370
+
371
+ The release workflow is documented in
372
+ [`docs/release_packaging.md`](docs/release_packaging.md): build and inspect
373
+ wheel/sdist, run clean-install and `pip check`, publish an RC to TestPyPI with
374
+ OIDC, then publish the final core package through the protected PyPI
375
+ environment. The exact handoff fields and artifact-hash procedure are in
376
+ [`docs/testpypi_release_checklist.md`](docs/testpypi_release_checklist.md).
377
+ No long-lived token is required. Native optimization remains an
378
+ open, domain-preserving roadmap for portfolio, arbitrage, options, vectorized,
379
+ intrabar, and Nautilus adapter workloads; each future route needs its own
380
+ parity and RSS certification.
381
+
382
+ ### Pre-48E apples-to-apples native event evidence
383
+
384
+ The native-event headline below uses one deterministic **2,000-bar**,
385
+ single-symbol tape, a fresh process per route, the same compiled command tape,
386
+ separate score/audit runs, and seven measured warm repetitions. Runtime is in
387
+ seconds, throughput is bars per second, and RSS is peak resident memory. Every
388
+ Python/Rust score and audit fingerprint passed accounting and lifecycle parity
389
+ (equity, positions, fees, funding, margin, fills, and event counters).
390
+
391
+ | Workload | Route | Runtime s | Throughput | Peak RSS MB | Parity |
392
+ |---|---|---:|---:|---:|---|
393
+ | Common low churn | Python score | 0.087736 | 22,796 bars/s | 183.2 | pass |
394
+ | Common low churn | Rust score | 0.188448 | 10,613 bars/s | 185.7 | pass |
395
+ | Common low churn | Python audit | 0.087327 | 22,902 bars/s | 240.8 | pass |
396
+ | Common low churn | Rust audit | 0.176075 | 11,359 bars/s | 243.9 | pass |
397
+ | Common high churn | Python score | 0.086609 | 23,092 bars/s | 182.9 | pass |
398
+ | Common high churn | Rust score | 0.188299 | 10,621 bars/s | 186.1 | pass |
399
+ | Common high churn | Python audit | 0.119269 | 16,769 bars/s | 241.2 | pass |
400
+ | Common high churn | Rust audit | 0.198521 | 10,074 bars/s | 243.1 | pass |
401
+
402
+ The safe Python patch improved the common low-churn score from `0.148483s`
403
+ to `0.087736s` on the frozen pre-patch baseline, without skipping any domain
404
+ accounting or quantity preflight when constraints are enabled. Explicit order
405
+ and Rust full-tape results are also recorded, but they are kept as route-level
406
+ evidence rather than used to imply that every reactive strategy is faster in
407
+ Rust. Reactive Grid has a separate workload and remains outside this common
408
+ native-event headline.
409
+
410
+ Reproduce the gate with
411
+ [`benchmark_pre48e.py`](benchmarks/native_event/benchmark_pre48e.py). Read the
412
+ full before/after table and parity fingerprints in
413
+ [`pre48e/report.md`](benchmarks/native_event/results/pre48e/report.md); the
414
+ raw JSON artifacts are versioned beside it.
415
+
416
+ ### Phase 48E native-event boundary evidence
417
+
418
+ The Phase 48E rerun keeps the same 2,000-bar tape, seven warm repetitions,
419
+ fresh-process routes, separate score/audit profiles, and `atol <= 1e-12`
420
+ accounting parity. The full raw result is in
421
+ [`phase48e/after.md`](benchmarks/native_event/results/phase48e/after.md).
422
+ The common rows are the comparable native-event/event-driven workload; the
423
+ explicit rows are a separate compiled-tape workload and must not be read as a
424
+ claim that Rust is faster for every Python callback strategy.
425
+
426
+ | Workload | Route | Runtime s | Throughput | Peak RSS MB | Parity |
427
+ |---|---|---:|---:|---:|---|
428
+ | Common low churn | Python score | 0.094448 | 21,176 bars/s | 182.0 | pass |
429
+ | Common low churn | Rust score | 0.179506 | 11,142 bars/s | 183.9 | pass |
430
+ | Common low churn | Python audit | 0.093893 | 21,301 bars/s | 239.0 | pass |
431
+ | Common low churn | Rust audit | 0.178550 | 11,201 bars/s | 242.6 | pass |
432
+ | Common high churn | Python score | 0.107369 | 18,627 bars/s | 183.5 | pass |
433
+ | Common high churn | Rust score | 0.188549 | 10,607 bars/s | 185.2 | pass |
434
+ | Common high churn | Python audit | 0.106375 | 18,801 bars/s | 241.1 | pass |
435
+ | Common high churn | Rust audit | 0.208654 | 9,585 bars/s | 241.3 | pass |
436
+
437
+ Phase 48E also reduced the static explicit Rust score to `0.000302s`
438
+ (`6,614,704 bars/s`) on the low-churn tape and `0.000392s`
439
+ (`5,103,342 bars/s`) on the high-churn tape. Those numbers benefit from the
440
+ scalar Rust output contract and prepared command-tape reuse, so they are
441
+ reported separately from callback execution. Rust and Python fingerprints,
442
+ fees, positions, fills, events, rejection counters, and final equity passed.
443
+ `backend="auto"` remains Python and `[native]` remains empty until the public
444
+ `quantbt-native` wheel matrix is clean-install certified.
445
+
446
+ ### Phase 48E.1 native production-closure evidence
447
+
448
+ The Phase 48E.1 rerun uses the same isolated 2,000-bar tape, fresh subprocesses,
449
+ seven warm runs, separate score/audit routes, and exact Python/Rust fingerprints.
450
+ The complete report is [`phase48e1/after.md`](benchmarks/native_event/results/phase48e1/after.md).
451
+ This table separates the explicit prepared-tape path from the generic callback
452
+ facade; it is not a universal Rust speed claim.
453
+
454
+ | Workload | Route | Runtime s | Throughput | Peak RSS MB | Parity |
455
+ |---|---|---:|---:|---:|---|
456
+ | Common low churn | Python score | 0.085853 | 23,296 bars/s | 182.2 | pass |
457
+ | Common low churn | Rust score | 0.218293 | 9,162 bars/s | 185.7 | pass |
458
+ | Common low churn | Python audit | 0.095110 | 21,028 bars/s | 239.4 | pass |
459
+ | Common low churn | Rust audit | 0.230769 | 8,667 bars/s | 242.1 | pass |
460
+ | Common high churn | Python score | 0.091562 | 21,843 bars/s | 182.1 | pass |
461
+ | Common high churn | Rust score | 0.222166 | 9,002 bars/s | 185.1 | pass |
462
+ | Common high churn | Python audit | 0.104712 | 19,100 bars/s | 239.6 | pass |
463
+ | Common high churn | Rust audit | 0.237654 | 8,416 bars/s | 241.4 | pass |
464
+ | Explicit low churn | Python score | 0.023777 | 84,114 bars/s | 180.4 | pass |
465
+ | Explicit low churn | Rust score | 0.000289 | 6,921,851 bars/s | 181.6 | pass |
466
+ | Explicit low churn | Python audit | 0.007385 | 270,814 bars/s | 237.7 | pass |
467
+ | Explicit low churn | Rust audit | 0.004357 | 459,060 bars/s | 182.0 | pass |
468
+ | Explicit high churn | Python score | 0.021689 | 92,214 bars/s | 180.2 | pass |
469
+ | Explicit high churn | Rust score | 0.000366 | 5,461,021 bars/s | 181.9 | pass |
470
+ | Explicit high churn | Python audit | 0.013703 | 145,952 bars/s | 239.6 | pass |
471
+ | Explicit high churn | Rust audit | 0.006469 | 309,174 bars/s | 183.1 | pass |
472
+
473
+ Phase 48E.1 also locks typed API 0.4 step results, count-only score sinks,
474
+ reusable SoA audit buffers, separate command/lifecycle/fill reports, compact
475
+ validated Rust order state, and reset/compaction parity. `auto` remains Python;
476
+ the native extra remains empty until the CPython 3.11/3.12/3.13 manylinux
477
+ clean-install workflow passes.
478
+
479
+ Ecosystem positioning:
480
+
481
+ | Tool | Core strength | Runtime model | QuantBT role beside it |
482
+ |---|---|---|---|
483
+ | QuantBT | transparent research, WFO, portfolio, arbitrage, validation endpoints | Python API with NumPy/Numba hot paths | primary alpha research and auditable simulation layer |
484
+ | LEAN / QuantConnect | large institutional C# platform and live/research ecosystem | C# engine | external benchmark for platform breadth, but heavier adapter work for custom notebooks |
485
+ | NautilusTrader | high-fidelity event-driven execution and accounting | Rust-backed trading stack | optional third-party trustee for execution/account validation |
486
+ | vectorbt | very fast vectorized research | NumPy/Numba vectorization | closest research-speed peer; QuantBT adds domain-specific accounting and validation routes |
487
+ | Backtrader | classic Python event-driven strategy simulation | Python event loop | useful reference style; QuantBT focuses on faster vectorized/event hybrid workflows |
488
+
489
+ ## Engine Stack
490
+
491
+ | Layer | Backend | Best use case |
492
+ |---|---|---|
493
+ | Fast research | `native_vectorized` | broad sweeps, signal research, WFO scoring |
494
+ | Order simulation | `native_event` | explicit orders, fills, baskets, pair trades |
495
+ | Native portfolio | `native_portfolio` | default multi-symbol portfolio matrix with risk/exposure reports |
496
+ | Legacy compatibility | `legacy`, `legacy_portfolio` | historical reproduction and single-symbol legacy routes |
497
+ | Third-party validation | `nautilus` | smaller high-fidelity event-driven checks |
498
+
499
+ Use the native engines for research velocity. Use Nautilus when the result needs
500
+ an external event-driven accounting layer with raw order, fill, position, and
501
+ account reports.
502
+
503
+ ## Features
504
+
505
+ ### Single-Symbol Backtests
506
+
507
+ - `signal_notional`: fixed units between signal changes.
508
+ - `%_equity`: legacy equity-fraction sizing.
509
+ - `notional`, `unit`, and target-unit style execution through V2 engines.
510
+ - Margin, leverage, fee, slippage, funding, liquidation, and contract size
511
+ controls.
512
+ - `use_pyramiding=False` snaps signals to `-1/0/1`; `True` preserves fractional
513
+ scales such as `1.4`.
514
+ - For crypto, `contract_size` is a notional/PnL multiplier. Exchange fractional
515
+ lots are governed by shared venue constraints:
516
+ `qty_step`/`lot_size`/`slot_size`/`min_qty`/`min_notional`, applied across
517
+ native legacy, native vectorized, native event/order, native portfolio, and
518
+ Nautilus validation routes.
519
+
520
+ ### DCA And Grid
521
+
522
+ - Structural DCA ladder signals where `0` is flat, `1` is base order, `2+` are
523
+ safety-order levels.
524
+ - High/low intrabar limit-touch detection.
525
+ - Fill at trigger/grid price rather than free-market close.
526
+ - Designed for DCA ladder and grid strategies where position is a structural
527
+ level, not a continuously rebalanced weight.
528
+
529
+ ### Portfolio And Basket
530
+
531
+ - Multi-symbol portfolio endpoint over position matrices. The default backend
532
+ is `native_portfolio`; use `backend="legacy_portfolio"` only for historical
533
+ reproduction.
534
+ - Portfolio modes: `longshort`, `market_neutral`, `directional`,
535
+ `equal_weight`, `risk_parity`, and `beta_neutral`.
536
+ - Portfolio sizing: `signal_notional`, `%_equity`, `target_weight`,
537
+ `target_notional`, `target_units`, `fixed_notional`, `gross_exposure`, and
538
+ `net_exposure`.
539
+ - Basket and pair-trading endpoint with frozen hedge-ratio units.
540
+ - Native event engine support for package-style component orders.
541
+
542
+ ### Arbitrage
543
+
544
+ Supported executable specs:
545
+
546
+ - `BasisArbitrageSpec`
547
+ - `StatArbPairSpec`
548
+ - `CalendarSpreadSpec`
549
+ - `FundingArbitrageSpec`
550
+ - `SpotPerpCashCarrySpec`
551
+ - `IndexBasketArbSpec`
552
+
553
+ Schema-only specs, reserved for specialized engines:
554
+
555
+ - `CrossExchangeArbSpec`
556
+ - `TriangularArbSpec`
557
+ - `OptionsVolArbSpec`
558
+
559
+ Use `QuantBTEndpoint.arbitrage_support_matrix()` to check safe routes before a
560
+ service creates a run.
561
+
562
+ ### Walk-Forward Optimization
563
+
564
+ - Walk-forward split/stitch engine with OOS-scoped metrics.
565
+ - Single train/test split endpoint using the same optimization framework.
566
+ - Optuna-supported modes:
567
+ - `mode_1_decay`
568
+ - `mode_2_sbb`
569
+ - `mode_3_flat_minima`
570
+ - `mode_4_is_only_robust`
571
+ - `mode_5_full_robust`
572
+ - Endpoint-backed scoring for supported single-symbol modes, so objective
573
+ metrics match the actual QuantBT backtest route.
574
+ - Train-only robust candidate selection such as `is_plateau_robust` and
575
+ `is_only_robust`.
576
+ - Full-sample robust calibration selectors: `full_robust`,
577
+ `full_plateau_robust`, `full_temporal_robust`, and `full_best`.
578
+ - Optional trade-count penalty to avoid overfit low-trade Sharpe traps.
579
+ - Shared domain-agnostic optimizer primitives for search-space parsing,
580
+ duplicate detection, early stopping, objective helpers, constraints, and
581
+ candidate selection.
582
+
583
+ ### Nautilus Validation Reports
584
+
585
+ The Nautilus adapter can validate single-symbol signal strategies with:
586
+
587
+ - `signal_notional`
588
+ - `notional`
589
+ - `unit`
590
+ - `%_equity`
591
+
592
+ It can also replay explicit single-symbol `OrderIntent` orders through
593
+ `QuantBTEndpoint.orders(backend="nautilus", ...)` for market, limit,
594
+ stop-market, and stop-limit order factory routes where Nautilus supports the
595
+ instrument/order combination.
596
+
597
+ For validation work, `build_native_nautilus_parity_report(native, nautilus)`
598
+ creates an audit table comparing requested order quantities, fill prices, fees,
599
+ positions, equity, and diffs between native event replay and Nautilus replay.
600
+ Use `QuantBTEndpoint.nautilus_support_matrix()` to inspect which Nautilus routes
601
+ are supported, experimental, or planned before wiring a service.
602
+ Experimental Nautilus package validation is available for DCA/grid,
603
+ bracket/OCO, basket, and portfolio workflows by compiling strategy state into
604
+ explicit order packages.
605
+
606
+ Package-depth validation is opt-in. `depth_model="ohlcv_volume_cap"` is the
607
+ default Level-1 preflight, `depth_model="synthetic_book"` creates deterministic
608
+ Level-2 stress books from spread/depth assumptions, and future
609
+ `depth_model="l2_replay"` is intentionally gated until real venue snapshots,
610
+ incremental updates, and trade prints are provided.
611
+
612
+ Supported Binance perpetual validation instruments:
613
+
614
+ `BTCUSDT-PERP.BINANCE`, `ETHUSDT-PERP.BINANCE`, `BNBUSDT-PERP.BINANCE`,
615
+ `SOLUSDT-PERP.BINANCE`, `DOGEUSDT-PERP.BINANCE`, `ARBUSDT-PERP.BINANCE`,
616
+ `LINKUSDT-PERP.BINANCE`.
617
+
618
+ The report bundle exports:
619
+
620
+ - `account_report.csv`
621
+ - `orders_report.csv`
622
+ - `fills_report.csv`
623
+ - `positions_report.csv`
624
+ - `trade_log.csv`
625
+ - `fill_log.txt`
626
+ - `equity_curve.csv`
627
+ - `returns.csv`
628
+ - `metrics_summary.json`
629
+ - `run_manifest.json`
630
+ - `config.json`
631
+ - optional `quantstats_daily.html`
632
+
633
+ These artifacts make the run easier to present to stakeholders: the metrics are
634
+ not just a final equity number, but an auditable trail from config to orders,
635
+ fills, positions, account state, and performance report.
636
+
637
+ ## Install
638
+
639
+ Install the released core package:
640
+
641
+ ```bash
642
+ pip install quantbt-engine==1.0.7
643
+ ```
644
+
645
+ Optional reports and third-party validation:
646
+
647
+ ```bash
648
+ pip install "quantbt-engine[reports,validation]==1.0.7"
649
+ ```
650
+
651
+ Development from this repository:
652
+
653
+ ```bash
654
+ uv sync --extra optimization --extra reports --extra viz --dev
655
+ .venv/bin/python -m pytest -q --ignore=tests/test_real.py --ignore=tests/test_real_endpoints.py --ignore=tests/native_event
656
+ ```
657
+
658
+ For core-only package/build validation, use the smaller dependency boundary
659
+ used by the native gate:
660
+
661
+ ```bash
662
+ uv sync --dev
663
+ uv build
664
+ uv run twine check dist/*
665
+ ```
666
+
667
+ Pool Alpha and notebooks can continue using an editable checkout while a
668
+ feature is under development:
669
+
670
+ ```bash
671
+ pip install -e /root/bobby/pool_alpha/quantbt
672
+ ```
673
+
674
+ After the release is approved, downstream services should use
675
+ `pip install quantbt-engine==1.0.7` and keep the unchanged import
676
+ `from quantbt import QuantBTEndpoint`.
677
+
678
+ ## Quick Start
679
+
680
+ ```python
681
+ from quantbt import QuantBTEndpoint
682
+
683
+ bt = QuantBTEndpoint.signal_notional(
684
+ backend="native_vectorized",
685
+ initial_capital=20_000,
686
+ leverage=5,
687
+ alloc_per_trade=10_000,
688
+ fee_rate=0.0002,
689
+ slippage_bps=1.0,
690
+ use_funding=False,
691
+ )
692
+
693
+ result = bt.backtest(
694
+ data=df, # OHLCV DataFrame
695
+ signal_col="pos_weight", # 1.0 / -1.0 / 0.0 style signal
696
+ symbols=["ETHUSDT"],
697
+ )
698
+
699
+ result.show_metrics()
700
+ result.quick_plot()
701
+ ```
702
+
703
+ ## Public Endpoint
704
+
705
+ ```python
706
+ QuantBTEndpoint.pct_equity(...) # legacy % equity sizing
707
+ QuantBTEndpoint.signal_notional(...) # fixed units between signal changes
708
+ QuantBTEndpoint.dca_ladder(...) # DCA/grid structural levels
709
+ QuantBTEndpoint.orders(...) # explicit OrderIntent simulation
710
+ QuantBTEndpoint.nautilus_dca_grid(...) # Nautilus DCA/grid package validation
711
+ QuantBTEndpoint.nautilus_bracket_orders(...) # Nautilus bracket/OCO validation
712
+ QuantBTEndpoint.basket(...) # pair/basket event simulation
713
+ QuantBTEndpoint.arbitrage(...) # arbitrage spec execution
714
+ QuantBTEndpoint.portfolio(...) # multi-symbol portfolio matrix
715
+ QuantBTEndpoint.walk_forward(...) # walk-forward OOS stitching
716
+ QuantBTEndpoint.train_test_split(...) # single holdout split
717
+ QuantBTEndpoint.nautilus_validation(...) # optional Nautilus validation
718
+ ```
719
+
720
+ The native portfolio parity audit is stored at
721
+ `benchmarks/portfolio_real_parity_report.md`.
722
+
723
+ ## Nautilus Example
724
+
725
+ ```python
726
+ from quantbt import QuantBTEndpoint, export_nautilus_report_bundle
727
+ from quantbt.adapters.nautilus import NautilusBackendConfig
728
+
729
+ bt = QuantBTEndpoint.nautilus_validation(
730
+ initial_capital=20_000,
731
+ leverage=5,
732
+ alloc_per_trade=0.5,
733
+ hedge_type="%_equity",
734
+ fee_rate=0.0005,
735
+ slippage=0.0002,
736
+ use_funding=False,
737
+ use_pyramiding=False,
738
+ nautilus_config=NautilusBackendConfig(
739
+ timeframe="1h",
740
+ starting_balance=20_000,
741
+ trade_notional=0.5,
742
+ close_positions_on_stop=False,
743
+ ),
744
+ )
745
+
746
+ result = bt.simulate(
747
+ data=df,
748
+ signal_col="pos_weight",
749
+ symbols=["ETHUSDT-PERP.BINANCE"],
750
+ show_order_logs=True,
751
+ order_log_mode="fills_only",
752
+ order_log_limit=200,
753
+ )
754
+
755
+ result.show_metrics()
756
+
757
+ diag = bt.nautilus_pct_equity_diagnostic(
758
+ data=df,
759
+ signal_col="pos_weight",
760
+ native_fee_round_trip=0.0005,
761
+ native_use_funding=False,
762
+ native_slippage=0.0002,
763
+ )
764
+
765
+ report_dir = export_nautilus_report_bundle(
766
+ result=result,
767
+ output_dir="reports",
768
+ strategy_id="eth_validation",
769
+ make_quantstats=True,
770
+ quantstats_periods_per_year=365,
771
+ )
772
+ ```
773
+
774
+ ## Walk-Forward Example
775
+
776
+ ```python
777
+ from quantbt import QuantBTEndpoint
778
+
779
+ wf = QuantBTEndpoint.train_test_split(
780
+ strategy_class=strategy,
781
+ test_start="2025-01-01",
782
+ target_mode="pct_equity",
783
+ optimization_mode="mode_1_decay",
784
+ optimization_config={
785
+ "scoring_backend": "endpoint",
786
+ "candidate_selection_metric": "is_plateau_robust",
787
+ "top_is_fraction": 0.10,
788
+ "min_trades_per_year": 100,
789
+ "trade_penalty_factor": 0.5,
790
+ "use_numba": True,
791
+ },
792
+ optuna_trials=300,
793
+ random_seed=42,
794
+ initial_capital=20_000,
795
+ leverage=5,
796
+ alloc_per_trade=0.5,
797
+ fee=0.0005,
798
+ slippage=0.0002,
799
+ use_pyramiding=False,
800
+ )
801
+
802
+ result = wf.backtest(data=df, param_ranges=param_ranges)
803
+ wf.show_metrics(scope="auto")
804
+ ```
805
+
806
+ `scope="auto"` reports only the tested/OOS segment for walk-forward and
807
+ train/test runs. Pass `scope="full"` when you need to audit the full stitched
808
+ timeline.
809
+
810
+ ## Result Helpers
811
+
812
+ ```python
813
+ result.show_metrics()
814
+ result.full_report()
815
+ result.quick_plot()
816
+ result.tearsheet()
817
+
818
+ bt.order_report
819
+ bt.fills_report
820
+ bt.export_orders("orders.csv")
821
+ bt.export_fills("fills.csv")
822
+ ```
823
+
824
+ Example console output:
825
+
826
+ ```text
827
+ Initial Capital $ 20,000
828
+ Final Equity $ 106,884.96
829
+ Total Return +434.42%
830
+ CAGR +33.54%
831
+ Sharpe Ratio 1.981
832
+ Sortino Ratio 0.875
833
+ Calmar Ratio 2.885
834
+ Omega Ratio 2.190
835
+ Max Drawdown 11.63%
836
+ Profit Factor 2.190
837
+ Number of Trades 228
838
+ Liquidated No
839
+ ```
840
+
841
+ ## Documentation
842
+
843
+ Start with the [documentation map](docs/README.md) if you are deciding which
844
+ backend, endpoint, or strategy route to use.
845
+
846
+ | Need | Read |
847
+ |---|---|
848
+ | Public API contract for notebooks/services | [Endpoint contract](docs/endpoint.md) |
849
+ | Backend choice by strategy type | [Backend selection](docs/backend_selection.md) |
850
+ | Speed vs execution-fidelity tradeoff | [Vectorized vs event-driven](docs/vectorized_vs_event_driven.md) |
851
+ | Leverage, buying power, margin, liquidation | [Margin and leverage](docs/margin_leverage.md) |
852
+ | Market/limit/stop fill behavior | [Order fill policies](docs/order_fill_policies.md) |
853
+ | Nautilus validation and report bundles | [Nautilus backend](docs/nautilus_backend.md) |
854
+ | Pair, basket, hedge-ratio package behavior | [Pair and basket guide](docs/pair_basket_guide.md) |
855
+ | Walk-forward methodology and anti-leakage scoring | [Walk-forward methodology](docs/walkforward_methodology_vi.md) |
856
+ | Runnable smoke templates | [Examples index](examples/README.md) |
857
+
858
+ Key examples:
859
+
860
+ - [DCA/grid ladder](examples/dca_grid_ladder.py)
861
+ - [Multi-symbol portfolio](examples/multi_symbol_portfolio.py)
862
+ - [Pair/basket event package](examples/pair_basket_event.py)
863
+ - [Basis arbitrage](examples/arbitrage_basis.py)
864
+ - [Walk-forward train/test split](examples/walk_forward_train_test.py)
865
+ - [Nautilus validation](examples/nautilus_validation.py)
866
+ - [Nautilus explicit orders](examples/nautilus_explicit_orders.py)
867
+
868
+ ## Development
869
+
870
+ ```bash
871
+ uv sync --extra optimization --extra reports --extra viz --dev
872
+ .venv/bin/python -m pytest -q --ignore=tests/test_real.py --ignore=tests/test_real_endpoints.py --ignore=tests/native_event
873
+ ```
874
+
875
+ Contribution workflow:
876
+
877
+ - work from `dev` or feature branches;
878
+ - keep endpoint contracts stable for notebooks and services;
879
+ - add focused tests for every engine or accounting change;
880
+ - prefer Numba/vectorized paths for hot loops;
881
+ - use Nautilus validation where execution/accounting evidence matters.
882
+
883
+ ## Design Principle
884
+
885
+ QuantBT is not trying to hide the backtest engine behind a black box. It is
886
+ designed so a researcher can move from a signal series to a reproducible audit
887
+ trail: parameters, market data alignment, target sizing, order generation,
888
+ fills, account reports, equity curve, metrics, and optional third-party
889
+ Nautilus validation.
890
+
891
+ That transparency is the product.