ml4t-backtest 0.1.0__tar.gz

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 (194) hide show
  1. ml4t_backtest-0.1.0/.gitignore +53 -0
  2. ml4t_backtest-0.1.0/CHANGELOG.md +348 -0
  3. ml4t_backtest-0.1.0/LICENSE +21 -0
  4. ml4t_backtest-0.1.0/PKG-INFO +473 -0
  5. ml4t_backtest-0.1.0/README.md +387 -0
  6. ml4t_backtest-0.1.0/pyproject.toml +254 -0
  7. ml4t_backtest-0.1.0/src/ml4t/backtest/__init__.py +131 -0
  8. ml4t_backtest-0.1.0/src/ml4t/backtest/_compat.py +46 -0
  9. ml4t_backtest-0.1.0/src/ml4t/backtest/_validation/__init__.py +1 -0
  10. ml4t_backtest-0.1.0/src/ml4t/backtest/_validation/backtrader_runner.py +153 -0
  11. ml4t_backtest-0.1.0/src/ml4t/backtest/_validation/case_study_lean.py +280 -0
  12. ml4t_backtest-0.1.0/src/ml4t/backtest/_validation/lean_runner.py +350 -0
  13. ml4t_backtest-0.1.0/src/ml4t/backtest/_validation/vectorbt_runner.py +167 -0
  14. ml4t_backtest-0.1.0/src/ml4t/backtest/_validation/zipline_runner.py +380 -0
  15. ml4t_backtest-0.1.0/src/ml4t/backtest/_validation_imports.py +65 -0
  16. ml4t_backtest-0.1.0/src/ml4t/backtest/_version.py +24 -0
  17. ml4t_backtest-0.1.0/src/ml4t/backtest/accounting/__init__.py +47 -0
  18. ml4t_backtest-0.1.0/src/ml4t/backtest/accounting/account.py +162 -0
  19. ml4t_backtest-0.1.0/src/ml4t/backtest/accounting/gatekeeper.py +331 -0
  20. ml4t_backtest-0.1.0/src/ml4t/backtest/accounting/policy.py +727 -0
  21. ml4t_backtest-0.1.0/src/ml4t/backtest/analytics/__init__.py +37 -0
  22. ml4t_backtest-0.1.0/src/ml4t/backtest/analytics/annualization.py +154 -0
  23. ml4t_backtest-0.1.0/src/ml4t/backtest/analytics/bridge.py +155 -0
  24. ml4t_backtest-0.1.0/src/ml4t/backtest/analytics/equity.py +178 -0
  25. ml4t_backtest-0.1.0/src/ml4t/backtest/analytics/metrics.py +180 -0
  26. ml4t_backtest-0.1.0/src/ml4t/backtest/analytics/trades.py +527 -0
  27. ml4t_backtest-0.1.0/src/ml4t/backtest/broker.py +2423 -0
  28. ml4t_backtest-0.1.0/src/ml4t/backtest/calendar.py +857 -0
  29. ml4t_backtest-0.1.0/src/ml4t/backtest/config.py +1455 -0
  30. ml4t_backtest-0.1.0/src/ml4t/backtest/core/__init__.py +23 -0
  31. ml4t_backtest-0.1.0/src/ml4t/backtest/core/execution_engine.py +719 -0
  32. ml4t_backtest-0.1.0/src/ml4t/backtest/core/fill_engine.py +239 -0
  33. ml4t_backtest-0.1.0/src/ml4t/backtest/core/order_book.py +580 -0
  34. ml4t_backtest-0.1.0/src/ml4t/backtest/core/portfolio_ledger.py +51 -0
  35. ml4t_backtest-0.1.0/src/ml4t/backtest/core/risk_engine.py +275 -0
  36. ml4t_backtest-0.1.0/src/ml4t/backtest/core/shared.py +81 -0
  37. ml4t_backtest-0.1.0/src/ml4t/backtest/core/state.py +63 -0
  38. ml4t_backtest-0.1.0/src/ml4t/backtest/datafeed.py +461 -0
  39. ml4t_backtest-0.1.0/src/ml4t/backtest/engine.py +910 -0
  40. ml4t_backtest-0.1.0/src/ml4t/backtest/execution/__init__.py +58 -0
  41. ml4t_backtest-0.1.0/src/ml4t/backtest/execution/fill_executor.py +793 -0
  42. ml4t_backtest-0.1.0/src/ml4t/backtest/execution/impact.py +186 -0
  43. ml4t_backtest-0.1.0/src/ml4t/backtest/execution/limits.py +186 -0
  44. ml4t_backtest-0.1.0/src/ml4t/backtest/execution/rebalancer.py +624 -0
  45. ml4t_backtest-0.1.0/src/ml4t/backtest/execution/result.py +40 -0
  46. ml4t_backtest-0.1.0/src/ml4t/backtest/execution/schedule.py +981 -0
  47. ml4t_backtest-0.1.0/src/ml4t/backtest/export.py +329 -0
  48. ml4t_backtest-0.1.0/src/ml4t/backtest/lifecycle.py +111 -0
  49. ml4t_backtest-0.1.0/src/ml4t/backtest/models.py +312 -0
  50. ml4t_backtest-0.1.0/src/ml4t/backtest/preopen.py +999 -0
  51. ml4t_backtest-0.1.0/src/ml4t/backtest/profiles.py +490 -0
  52. ml4t_backtest-0.1.0/src/ml4t/backtest/py.typed +0 -0
  53. ml4t_backtest-0.1.0/src/ml4t/backtest/result.py +1621 -0
  54. ml4t_backtest-0.1.0/src/ml4t/backtest/risk/__init__.py +75 -0
  55. ml4t_backtest-0.1.0/src/ml4t/backtest/risk/portfolio/__init__.py +44 -0
  56. ml4t_backtest-0.1.0/src/ml4t/backtest/risk/portfolio/limits.py +605 -0
  57. ml4t_backtest-0.1.0/src/ml4t/backtest/risk/portfolio/manager.py +252 -0
  58. ml4t_backtest-0.1.0/src/ml4t/backtest/risk/position/__init__.py +34 -0
  59. ml4t_backtest-0.1.0/src/ml4t/backtest/risk/position/composite.py +103 -0
  60. ml4t_backtest-0.1.0/src/ml4t/backtest/risk/position/dynamic.py +505 -0
  61. ml4t_backtest-0.1.0/src/ml4t/backtest/risk/position/protocol.py +38 -0
  62. ml4t_backtest-0.1.0/src/ml4t/backtest/risk/position/signal.py +48 -0
  63. ml4t_backtest-0.1.0/src/ml4t/backtest/risk/position/static.py +246 -0
  64. ml4t_backtest-0.1.0/src/ml4t/backtest/risk/types.py +151 -0
  65. ml4t_backtest-0.1.0/src/ml4t/backtest/sessions.py +424 -0
  66. ml4t_backtest-0.1.0/src/ml4t/backtest/spec_bridge.py +31 -0
  67. ml4t_backtest-0.1.0/src/ml4t/backtest/strategies/__init__.py +44 -0
  68. ml4t_backtest-0.1.0/src/ml4t/backtest/strategies/templates.py +455 -0
  69. ml4t_backtest-0.1.0/src/ml4t/backtest/strategy.py +48 -0
  70. ml4t_backtest-0.1.0/src/ml4t/backtest/types.py +706 -0
  71. ml4t_backtest-0.1.0/tests/__init__.py +1 -0
  72. ml4t_backtest-0.1.0/tests/accounting/__init__.py +1 -0
  73. ml4t_backtest-0.1.0/tests/accounting/test_cash_account_policy.py +524 -0
  74. ml4t_backtest-0.1.0/tests/accounting/test_crypto_account_policy.py +343 -0
  75. ml4t_backtest-0.1.0/tests/accounting/test_gatekeeper.py +520 -0
  76. ml4t_backtest-0.1.0/tests/accounting/test_margin_account_policy.py +855 -0
  77. ml4t_backtest-0.1.0/tests/accounting/test_position.py +409 -0
  78. ml4t_backtest-0.1.0/tests/accounting/test_settlement_delay.py +174 -0
  79. ml4t_backtest-0.1.0/tests/benchmark/test_backtrader_zipline_runners.py +87 -0
  80. ml4t_backtest-0.1.0/tests/benchmark/test_case_study_lean.py +57 -0
  81. ml4t_backtest-0.1.0/tests/benchmark/test_cross_framework_selected.py +107 -0
  82. ml4t_backtest-0.1.0/tests/benchmark/test_hotpath_benchmarks.py +247 -0
  83. ml4t_backtest-0.1.0/tests/benchmark/test_lean_adapter.py +78 -0
  84. ml4t_backtest-0.1.0/tests/benchmark/test_vectorbt_runner.py +64 -0
  85. ml4t_backtest-0.1.0/tests/compatibility/snapshots/v0.1.json +4132 -0
  86. ml4t_backtest-0.1.0/tests/compatibility/test_stable_boundary.py +117 -0
  87. ml4t_backtest-0.1.0/tests/conftest.py +34 -0
  88. ml4t_backtest-0.1.0/tests/contracts/test_book_parity_behaviors.py +199 -0
  89. ml4t_backtest-0.1.0/tests/contracts/test_broker_state_ownership.py +870 -0
  90. ml4t_backtest-0.1.0/tests/contracts/test_changelog_generation.py +55 -0
  91. ml4t_backtest-0.1.0/tests/contracts/test_cross_engine_contracts.py +114 -0
  92. ml4t_backtest-0.1.0/tests/contracts/test_distribution_policy.py +60 -0
  93. ml4t_backtest-0.1.0/tests/contracts/test_documentation_contract.py +53 -0
  94. ml4t_backtest-0.1.0/tests/contracts/test_documentation_examples.py +51 -0
  95. ml4t_backtest-0.1.0/tests/contracts/test_exact_validation_comparator.py +248 -0
  96. ml4t_backtest-0.1.0/tests/contracts/test_execution_contracts.py +224 -0
  97. ml4t_backtest-0.1.0/tests/contracts/test_ledger_invariants.py +77 -0
  98. ml4t_backtest-0.1.0/tests/contracts/test_parity_claim_generation.py +55 -0
  99. ml4t_backtest-0.1.0/tests/contracts/test_performance_baseline_policy.py +155 -0
  100. ml4t_backtest-0.1.0/tests/contracts/test_platform_safe_validation_paths.py +34 -0
  101. ml4t_backtest-0.1.0/tests/contracts/test_profile_parity_basics.py +130 -0
  102. ml4t_backtest-0.1.0/tests/contracts/test_public_api_surface.py +64 -0
  103. ml4t_backtest-0.1.0/tests/contracts/test_python_support_policy.py +125 -0
  104. ml4t_backtest-0.1.0/tests/contracts/test_quality_gates.py +100 -0
  105. ml4t_backtest-0.1.0/tests/contracts/test_release_workflow.py +174 -0
  106. ml4t_backtest-0.1.0/tests/contracts/test_security_policy.py +181 -0
  107. ml4t_backtest-0.1.0/tests/contracts/test_static_analysis_policy.py +114 -0
  108. ml4t_backtest-0.1.0/tests/contracts/test_validation_cli_outcomes.py +242 -0
  109. ml4t_backtest-0.1.0/tests/contracts/test_validation_import_bridge.py +8 -0
  110. ml4t_backtest-0.1.0/tests/contracts/test_validation_scenarios.py +248 -0
  111. ml4t_backtest-0.1.0/tests/contracts/test_vectorbt_pro_adapter.py +95 -0
  112. ml4t_backtest-0.1.0/tests/contracts/test_zipline_validation_adapter.py +27 -0
  113. ml4t_backtest-0.1.0/tests/execution/__init__.py +1 -0
  114. ml4t_backtest-0.1.0/tests/execution/test_impact.py +247 -0
  115. ml4t_backtest-0.1.0/tests/execution/test_limits.py +241 -0
  116. ml4t_backtest-0.1.0/tests/execution/test_rebalancer.py +1566 -0
  117. ml4t_backtest-0.1.0/tests/execution/test_rebalancer_futures.py +577 -0
  118. ml4t_backtest-0.1.0/tests/execution/test_schedule.py +950 -0
  119. ml4t_backtest-0.1.0/tests/fixtures/artifacts/v0.1.0b22/config.yaml +84 -0
  120. ml4t_backtest-0.1.0/tests/fixtures/artifacts/v0.1.0b22/daily_pnl.parquet +0 -0
  121. ml4t_backtest-0.1.0/tests/fixtures/artifacts/v0.1.0b22/equity.parquet +0 -0
  122. ml4t_backtest-0.1.0/tests/fixtures/artifacts/v0.1.0b22/fills.parquet +0 -0
  123. ml4t_backtest-0.1.0/tests/fixtures/artifacts/v0.1.0b22/fixture.json +53 -0
  124. ml4t_backtest-0.1.0/tests/fixtures/artifacts/v0.1.0b22/metrics.json +6 -0
  125. ml4t_backtest-0.1.0/tests/fixtures/artifacts/v0.1.0b22/portfolio_state.parquet +0 -0
  126. ml4t_backtest-0.1.0/tests/fixtures/artifacts/v0.1.0b22/spec.yaml +90 -0
  127. ml4t_backtest-0.1.0/tests/fixtures/artifacts/v0.1.0b22/trades.parquet +0 -0
  128. ml4t_backtest-0.1.0/tests/futures/__init__.py +4 -0
  129. ml4t_backtest-0.1.0/tests/futures/conftest.py +177 -0
  130. ml4t_backtest-0.1.0/tests/futures/test_commission.py +139 -0
  131. ml4t_backtest-0.1.0/tests/futures/test_contract_spec.py +101 -0
  132. ml4t_backtest-0.1.0/tests/futures/test_fill_execution.py +117 -0
  133. ml4t_backtest-0.1.0/tests/futures/test_margin.py +138 -0
  134. ml4t_backtest-0.1.0/tests/futures/test_notional.py +150 -0
  135. ml4t_backtest-0.1.0/tests/futures/test_pnl.py +155 -0
  136. ml4t_backtest-0.1.0/tests/futures/test_portfolio.py +197 -0
  137. ml4t_backtest-0.1.0/tests/futures/test_slippage.py +119 -0
  138. ml4t_backtest-0.1.0/tests/futures/test_trade_record.py +157 -0
  139. ml4t_backtest-0.1.0/tests/helpers/__init__.py +21 -0
  140. ml4t_backtest-0.1.0/tests/helpers/data.py +129 -0
  141. ml4t_backtest-0.1.0/tests/helpers/invariants.py +311 -0
  142. ml4t_backtest-0.1.0/tests/helpers/strategies.py +199 -0
  143. ml4t_backtest-0.1.0/tests/oracle/__init__.py +12 -0
  144. ml4t_backtest-0.1.0/tests/oracle/engine.py +270 -0
  145. ml4t_backtest-0.1.0/tests/oracle/test_oracle_self.py +203 -0
  146. ml4t_backtest-0.1.0/tests/property/test_accounting_invariants.py +56 -0
  147. ml4t_backtest-0.1.0/tests/property/test_order_sequence_invariants.py +59 -0
  148. ml4t_backtest-0.1.0/tests/property/test_order_type_invariants.py +218 -0
  149. ml4t_backtest-0.1.0/tests/property/test_pnl_invariants.py +288 -0
  150. ml4t_backtest-0.1.0/tests/regression/__init__.py +6 -0
  151. ml4t_backtest-0.1.0/tests/regression/test_golden_strategies.py +404 -0
  152. ml4t_backtest-0.1.0/tests/risk/__init__.py +1 -0
  153. ml4t_backtest-0.1.0/tests/risk/test_composite_rules.py +277 -0
  154. ml4t_backtest-0.1.0/tests/risk/test_dynamic_rules.py +567 -0
  155. ml4t_backtest-0.1.0/tests/risk/test_portfolio_limits.py +1049 -0
  156. ml4t_backtest-0.1.0/tests/risk/test_portfolio_manager.py +456 -0
  157. ml4t_backtest-0.1.0/tests/risk/test_rule_priority.py +517 -0
  158. ml4t_backtest-0.1.0/tests/risk/test_short_trailing_stop.py +443 -0
  159. ml4t_backtest-0.1.0/tests/risk/test_signal_rules.py +222 -0
  160. ml4t_backtest-0.1.0/tests/risk/test_static_rules.py +465 -0
  161. ml4t_backtest-0.1.0/tests/scenarios/__init__.py +9 -0
  162. ml4t_backtest-0.1.0/tests/scenarios/factory.py +150 -0
  163. ml4t_backtest-0.1.0/tests/scenarios/test_parametric.py +124 -0
  164. ml4t_backtest-0.1.0/tests/test_analysis.py +270 -0
  165. ml4t_backtest-0.1.0/tests/test_artifact_spec.py +240 -0
  166. ml4t_backtest-0.1.0/tests/test_bracket_lifecycle.py +302 -0
  167. ml4t_backtest-0.1.0/tests/test_bracket_orders_short.py +359 -0
  168. ml4t_backtest-0.1.0/tests/test_broker.py +3702 -0
  169. ml4t_backtest-0.1.0/tests/test_calendar.py +516 -0
  170. ml4t_backtest-0.1.0/tests/test_calendar_integration.py +818 -0
  171. ml4t_backtest-0.1.0/tests/test_causal_lifecycle.py +522 -0
  172. ml4t_backtest-0.1.0/tests/test_config_wiring.py +1518 -0
  173. ml4t_backtest-0.1.0/tests/test_core.py +1179 -0
  174. ml4t_backtest-0.1.0/tests/test_cost_validation.py +339 -0
  175. ml4t_backtest-0.1.0/tests/test_datafeed_memory.py +615 -0
  176. ml4t_backtest-0.1.0/tests/test_deferred_exit_reentry.py +375 -0
  177. ml4t_backtest-0.1.0/tests/test_direction_matrix.py +464 -0
  178. ml4t_backtest-0.1.0/tests/test_equity_curve.py +85 -0
  179. ml4t_backtest-0.1.0/tests/test_export.py +431 -0
  180. ml4t_backtest-0.1.0/tests/test_extreme_conditions.py +454 -0
  181. ml4t_backtest-0.1.0/tests/test_oracle_differential.py +135 -0
  182. ml4t_backtest-0.1.0/tests/test_order_type_matrix.py +408 -0
  183. ml4t_backtest-0.1.0/tests/test_order_type_moc.py +24 -0
  184. ml4t_backtest-0.1.0/tests/test_partial_close_accounting.py +160 -0
  185. ml4t_backtest-0.1.0/tests/test_preopen_intents.py +1284 -0
  186. ml4t_backtest-0.1.0/tests/test_quantity_zero_tolerance.py +151 -0
  187. ml4t_backtest-0.1.0/tests/test_rejected_order_results.py +293 -0
  188. ml4t_backtest-0.1.0/tests/test_result.py +1397 -0
  189. ml4t_backtest-0.1.0/tests/test_sessions.py +545 -0
  190. ml4t_backtest-0.1.0/tests/test_strategy_templates.py +540 -0
  191. ml4t_backtest-0.1.0/tests/test_trade_cost_decomposition.py +578 -0
  192. ml4t_backtest-0.1.0/tests/test_trade_mfe_mae.py +363 -0
  193. ml4t_backtest-0.1.0/tests/test_trading_stats.py +592 -0
  194. ml4t_backtest-0.1.0/tests/typing/public_api_consumer.py +35 -0
@@ -0,0 +1,53 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ *.egg-info/
8
+ dist/
9
+ build/
10
+ site/
11
+ eggs/
12
+ *.egg
13
+
14
+ # Virtual environments
15
+ .venv/
16
+ .venv-*/
17
+ venv/
18
+ ENV/
19
+
20
+ # IDE
21
+ .idea/
22
+ .vscode/
23
+ *.swp
24
+ *.swo
25
+
26
+ # Testing
27
+ .pytest_cache/
28
+ .hypothesis/
29
+ .coverage
30
+ htmlcov/
31
+ .tox/
32
+ .nox/
33
+
34
+ # Type checking
35
+ .mypy_cache/
36
+
37
+ # Jupyter
38
+ .ipynb_checkpoints/
39
+ src/ml4t/backtest/_version.py
40
+
41
+ # Agent-local state
42
+ .claude/
43
+
44
+ # Validation-generated local artifacts
45
+ validation/.zipline/
46
+ validation/CORRECTNESS_RESULTS.md
47
+ validation/BENCHMARK_RESULTS.md
48
+ validation/trade_logs/
49
+ validation/lean/workspace/
50
+ validation/nautilus/.venv-nautilus/
51
+ validation/nautilus/catalog/
52
+ performance-evidence.json
53
+ release-performance-evidence.json
@@ -0,0 +1,348 @@
1
+ # Changelog
2
+
3
+ <!-- Generated from release/changelog.json. Do not edit managed entries. -->
4
+
5
+ ## 0.1.0 - Unreleased
6
+
7
+ ### Added
8
+
9
+ - Versioned compatibility snapshots, beta-artifact migration fixtures, commit-bound release
10
+ candidates, and exact publication verification.
11
+ - Deterministic parity-claim generation and five reproducible performance workloads with behavior
12
+ checksums.
13
+ - Installed-wheel execution checks for the primary installation and quickstart examples.
14
+ - A versioned causal strategy lifecycle and canonical pre-open target intents shared with
15
+ ml4t-live, including child-order lineage, reconciliation evidence, and post-fill position-rule
16
+ activation.
17
+
18
+ ### Changed
19
+
20
+ - Broker state now has explicit account, market, order, risk, and execution-journal owners while
21
+ the Broker remains the public facade.
22
+ - Intraday session enforcement now filters actual exchange intervals, including early closes and
23
+ breaks, using the configured timezone for naive timestamps.
24
+ - DataFeed now rejects a missing resolved reference-price column at construction and documents
25
+ close-only fallbacks explicitly.
26
+ - Stable distribution metadata, release-critical static analysis, and the 250-asset performance
27
+ workload now match the 0.1 release contract.
28
+ - Weekly and month-end rebalance schedules require calendar metadata and use the final scheduled
29
+ exchange session rather than the last available feed bar. Holidays do not move a rebalance
30
+ earlier, and a missing completed period-end session raises a feed-completeness error.
31
+ - Explicit rebalance timestamps match absolute instants across timezone representations and online
32
+ evaluation requires chronological events. A scheduled instant inside the observed feed window
33
+ that has no matching event raises an alignment error instead of being skipped silently.
34
+ - Batch and online session schedules require every complete exchange session to match its required
35
+ close; only an incomplete final session is exempt, and calendar mismatches fail explicitly.
36
+ - Result artifacts retain intent and lifecycle counts by default. Set retain_intent_history or
37
+ retain_lifecycle_history to include the corresponding event histories.
38
+ - Morning-start exchange sessions group pre-market and regular-hours events under the same local
39
+ calendar date; exchange session labels and opens come from cached authoritative calendar
40
+ schedules.
41
+ - Scheduled TargetWeightExecutor.execute calls register completion validation with the Engine, so
42
+ missing required closes and partial event coverage fail the run with distinct diagnostics.
43
+ - Deferred next-open risk exits fill before opening targets are sized. Fractional accounts reject
44
+ largest-remainder residual handling regardless of rounding because its whole-unit allocation
45
+ cannot redistribute fractional remainders; use keep-cash instead.
46
+
47
+ ### Fixed
48
+
49
+ - Financial-accounting, order-rejection, artifact-integrity, quantity-tolerance, and
50
+ parity-comparison defects found during the stable-release audit.
51
+ - Cross-framework validation now fails incomplete runs and requires exact retained comparisons for
52
+ supported scenarios.
53
+ - Batch and online session schedules apply the same daily-close fallback when data frequency and
54
+ timestamp semantics are both omitted. Batch evaluation and flagless online evaluation reject
55
+ repeated dates and intervals under 12 hours as ambiguous intraday data; online events may
56
+ instead carry is_session_close consistently, but mixing explicit and inferred boundaries on one
57
+ date raises.
58
+ - Session-aligned P&L and broker statistics interpret naive timestamps in the configured data
59
+ timezone before applying the authoritative exchange timezone.
60
+
61
+ ### Compatibility
62
+
63
+ - Stable support requires CPython 3.12 through 3.14 on Linux, macOS, and Windows; CPython 3.15
64
+ prereleases are blocking compatibility checks until final release.
65
+ - Manifest-free 0.1.0b22 result artifacts require explicit recovery mode and can then be rewritten
66
+ as schema-versioned stable artifacts.
67
+ - The ambiguous beta-only Broker(account_type=...) constructor spelling was removed; use explicit
68
+ short-selling and leverage policy fields.
69
+ - Engine instances are single-use in 0.1.0; create a new Engine for each independent run.
70
+ - BacktestResult fills, equity_curve, and portfolio_state lists are snapshots instead of aliases
71
+ to mutable Engine or Broker state.
72
+ - The beta-only on_before_risk callback and future-timestamp on_prepare signature are removed.
73
+ Engine construction raises HistoricalStrategyCompatibilityError for strategies that require
74
+ either historical behavior.
75
+ - TargetWeightExecutor.prepare_schedule was removed. Configure calendar, timezone,
76
+ session_start_time, data_frequency, and timestamp_semantics on RebalanceConfig for causal
77
+ schedule evaluation.
78
+ - Custom morning session_start_time values are rejected; morning-start sessions always use the
79
+ local calendar date. Omit the override or restate the configured exchange calendar's standard
80
+ open.
81
+ - Evening session_start_time overrides remain available for calendar-free and evening-start
82
+ sessions, but are rejected for calendars whose authoritative open is in the morning.
83
+ - SessionConfig is immutable; construct and install a replacement instead of mutating calendar,
84
+ timezone, or session_start_time after configuration.
85
+ - ExecutionPolicy.liquidity_fraction now applies only to opening-auction target children.
86
+ Configure Engine execution_limits explicitly to constrain ordinary strategy orders.
87
+
88
+ ### Validation
89
+
90
+ - Release requires compatibility, correctness, coverage, documentation, lint, packaging, parity,
91
+ performance, security, and type-check gates bound to one commit.
92
+ - The exact wheel and source distribution that pass those gates are retained as the release
93
+ candidate and verified after publication.
94
+
95
+ ## 0.1.0b22 - 2026-07-25
96
+
97
+ ### Added
98
+
99
+ - Strategy.on_before_risk(), explicit position-rule clearing, and an opt-in entry-bar
100
+ trailing-watermark mode.
101
+
102
+ ### Compatibility
103
+
104
+ - Strategies that do not override on_before_risk retain their prior behavior. The callback remains
105
+ beta-only and is scheduled for explicit migration rather than inclusion in the stable lifecycle.
106
+
107
+ ## 0.1.0b21 - 2026-06-12
108
+
109
+ ### Added
110
+
111
+ - Broker.equity() as the preferred marked-account-equity accessor.
112
+
113
+ ### Compatibility
114
+
115
+ - Broker.get_account_value() remains available and delegates to equity().
116
+
117
+ ## 0.1.0b20 - 2026-05-17
118
+
119
+ ### Fixed
120
+
121
+ - RiskManager.update(..., broker=...) now applies liquidation actions by flattening positions
122
+ instead of only reporting the breach.
123
+
124
+ ### Compatibility
125
+
126
+ - Liquidation behavior changes only when a portfolio limit returns action='liquidate' and a broker
127
+ is supplied. Omitting the broker retains reporting behavior and emits a warning.
128
+
129
+ ## 0.1.0b19 - 2026-05-17
130
+
131
+ ### Added
132
+
133
+ - Broker.flatten_all_positions() and the typed risk_liquidation exit reason for portfolio-wide
134
+ breaches.
135
+
136
+ ### Compatibility
137
+
138
+ - Existing strategy exits are unchanged; portfolio risk integrations can opt into explicit
139
+ flattening and preserve the liquidation cause.
140
+
141
+ ## 0.1.0b18 - 2026-05-16
142
+
143
+ ### Added
144
+
145
+ - Per-symbol percentage-of-notional margin schedules for price-aware futures margin assumptions.
146
+
147
+ ### Compatibility
148
+
149
+ - Existing global and fixed-dollar margin settings remain valid. Defining the same asset in
150
+ fixed_margin_schedule and margin_pct_schedule is rejected as ambiguous.
151
+
152
+ ## 0.1.0b17 - 2026-05-10
153
+
154
+ ### Changed
155
+
156
+ - `DataFeed` now indexes each timestamp as an `(offset, length)` slice over the original
157
+ prices, signals, and context frames instead of eagerly materializing one child
158
+ `DataFrame` per timestamp.
159
+ - This substantially reduces timestamp-partition memory overhead on large multi-asset
160
+ panels while preserving the same lazy per-bar iteration contract.
161
+ - Added regression coverage for unsorted input alignment and updated the dedicated
162
+ DataFeed memory tests to validate the new slice-index storage model.
163
+
164
+ ### Validation
165
+
166
+ - `uv run pytest tests/ -q`
167
+ - `uv run ruff check src/ml4t/backtest tests`
168
+ - `uv run ty check`
169
+ - `uv run python -m mkdocs build --strict`
170
+
171
+ ## 0.1.0b16 - 2026-05-05
172
+
173
+ ### Added
174
+
175
+ - `SlippageType.SPREAD` with `SpreadSlippage` for bar-based spread-cost modeling.
176
+ - Asset-aware spread configuration via `slippage_spread`, `slippage_spread_by_asset`, and
177
+ `slippage_spread_convention`.
178
+ - Explicit broker assumption helpers via `BacktestConfig.from_assumptions(...)` and
179
+ `BacktestConfig.from_user_config(...)`.
180
+ - The `ibkr_us_stocks_fixed` preset for explicit Interactive Brokers US equities fixed
181
+ commission assumptions.
182
+
183
+ ### Changed
184
+
185
+ - Generic engine defaults are now neutral again: no default commission, no default slippage,
186
+ `min_trade_value=0.0`, and `min_weight_change=0.0`.
187
+ - Integer shares are now the default share mode for the generic and fast profiles, while
188
+ `vectorbt` remains fractional.
189
+ - Integer rebalancing now rounds target-share deltas to the nearest whole share instead of
190
+ truncating toward zero, reducing correction churn and fill amplification.
191
+ - User guides now document neutral defaults, broker assumptions, spread slippage, and the
192
+ updated rebalance behavior.
193
+
194
+ ### Validation
195
+
196
+ - `uv run pytest tests/ -q`
197
+ - `uv run ruff check src/ml4t/backtest tests`
198
+ - `uv run ty check`
199
+ - `uv run python -m mkdocs build --strict`
200
+
201
+ ## 0.1.0b15 - 2026-04-27
202
+
203
+ ### Added
204
+
205
+ - `OrderType.MOC` as a first-class market-on-close order primitive.
206
+ - `Broker.close_position(..., order_type=...)` so positions can be flattened with
207
+ `OrderType.MOC` directly.
208
+
209
+ ### Changed
210
+
211
+ - `MOC` orders now execute at the current bar's close instead of following the standard
212
+ `NEXT_BAR` market-order timing.
213
+ - User docs now describe `MOC` order timing, daily-bar semantics, and position-closing
214
+ usage.
215
+
216
+ ### Validation
217
+
218
+ - `uv run pytest tests/test_order_type_matrix.py tests/test_order_type_moc.py -q`
219
+ - `uv run ruff check src/ml4t/backtest/broker.py src/ml4t/backtest/core/execution_engine.py src/ml4t/backtest/core/fill_engine.py src/ml4t/backtest/core/order_book.py src/ml4t/backtest/engine.py src/ml4t/backtest/types.py tests/test_order_type_matrix.py tests/test_order_type_moc.py`
220
+ - `uv run python -m mkdocs build --strict`
221
+
222
+ ## 0.1.0b13 - 2026-04-01
223
+
224
+ ### Changed
225
+
226
+ - `ml4t-backtest` now depends on `ml4t-specs` for shared market-data artifact contracts
227
+ instead of importing `FeedSpec`, `MarketDataSpec`, and serialization helpers from
228
+ `ml4t-data`.
229
+ - Runtime config, data-feed, result, annualization, and rebalance-schedule code now import
230
+ shared contract types from `ml4t.specs`.
231
+ - `spec_bridge.market_data_spec_to_feed_spec()` now delegates to `FeedSpec.from_any()` so
232
+ spec-to-runtime projection stays aligned with the canonical contract package.
233
+ - Contract, feed, broker, result, rebalancer, schedule, and artifact-spec tests now validate
234
+ the `ml4t-specs` path directly.
235
+ - User docs now show `FeedSpec` imports from `ml4t.specs`.
236
+
237
+ ### Validation
238
+
239
+ - `uv run pytest tests/ -q`
240
+ - `uv run ty check`
241
+ - `uv run python -m mkdocs build --strict`
242
+
243
+ ## 0.1.0b12 - 2026-03-29
244
+
245
+ ### Added
246
+
247
+ - Internal shipped validation helpers under `ml4t.backtest._validation`, including:
248
+ - `lean_runner.py` for shared LEAN CLI orchestration, data export, and artifact parsing
249
+ - `vectorbt_runner.py` for shared VectorBT matrix prep, execution, and result extraction
250
+ - `backtrader_runner.py` for shared Backtrader target-share execution and PyFolio parsing
251
+ - `zipline_runner.py` for shared Zipline bundle orchestration and transaction parsing
252
+
253
+ ### Changed
254
+
255
+ - The library validation harness now uses the shared `_validation` helpers instead of
256
+ carrying duplicate LEAN, VectorBT, Backtrader, and Zipline integration logic inside
257
+ `validation/benchmark_suite.py`.
258
+ - Chapter 16 book parity code can now rely on the released `ml4t-backtest` package for
259
+ shared cross-engine validation machinery instead of vendoring those heavy helpers.
260
+
261
+ ### Validation
262
+
263
+ - `uv run pytest tests/benchmark/test_lean_adapter.py tests/benchmark/test_backtrader_zipline_runners.py tests/test_config_wiring.py -q`
264
+ - `uv run python -m py_compile src/ml4t/backtest/_validation/lean_runner.py src/ml4t/backtest/_validation/vectorbt_runner.py src/ml4t/backtest/_validation/backtrader_runner.py src/ml4t/backtest/_validation/zipline_runner.py validation/benchmark_suite.py`
265
+
266
+ ## 0.1.0b11 - 2026-03-24
267
+
268
+ ### Added
269
+
270
+ - `BacktestResult.predictions` and `BacktestResult.to_predictions_dataframe()` to preserve
271
+ the raw prediction or model-input DataFrame passed into the backtest.
272
+ - `predictions.parquet` export/import support in `BacktestResult.to_parquet()` and
273
+ `BacktestResult.from_parquet()`.
274
+
275
+ ### Changed
276
+
277
+ - Engine results now treat the raw `signals_df` input surface as predictions for downstream
278
+ diagnostics, matching `ml4t-diagnostic`'s current contract.
279
+ - Parquet import falls back from legacy `signals.parquet` to the new predictions surface.
280
+ - User guides and README now document the raw predictions surface for downstream analysis.
281
+
282
+ ### Validation
283
+
284
+ - `uv run ruff check src/ml4t/backtest/result.py src/ml4t/backtest/engine.py tests/test_result.py tests/test_core.py`
285
+ - `uv run pytest tests/test_result.py tests/test_core.py -q`
286
+ - `uv run ty check`
287
+ - `uv run python -m mkdocs build --strict`
288
+
289
+ ## 0.1.0b10 - 2026-03-24
290
+
291
+ ### Added
292
+
293
+ - `BacktestConfig` support for serialized top-level `feed` and passthrough `metadata`
294
+ sections, enabling sparse input presets with generic provenance fields.
295
+ - `BacktestResult.to_spec_dict()` for a resolved runtime snapshot containing the full
296
+ replayable config, library version, and realized run window.
297
+ - `spec.yaml` export alongside `config.yaml` in `BacktestResult.to_parquet()`.
298
+
299
+ ### Changed
300
+
301
+ - `BacktestConfig.to_dict()` now emits plain-data feed metadata that round-trips safely
302
+ through dict, YAML, and Parquet persistence workflows.
303
+ - `BacktestResult.from_parquet()` now falls back to `spec.yaml` when `config.yaml` is absent.
304
+ - User guides now document the config workflow for sparse input, resolved output, `feed`,
305
+ `metadata`, and reproducibility exports.
306
+
307
+ ### Validation
308
+
309
+ - `uv run ruff check src/ml4t/backtest/config.py src/ml4t/backtest/result.py tests/test_broker.py tests/test_result.py`
310
+ - `uv run pytest tests/test_broker.py tests/test_result.py -q`
311
+ - `uv run ty check`
312
+ - `uv run python -m mkdocs build --strict`
313
+
314
+ ## 0.1.0b9 - 2026-03-24
315
+
316
+ ### Added
317
+
318
+ - Quote-aware `DataFeed` support for `price_col`, bid, ask, midpoint, and quote-size caches.
319
+ - New `ExecutionPrice` sources: `price`, `bid`, `ask`, `quote_mid`, and `quote_side`.
320
+ - Separate `mark_price` configuration for open-position marking.
321
+ - `BacktestResult.to_fills_dataframe()` and persisted `fills.parquet` export/import.
322
+ - `BacktestResult.to_portfolio_state_dataframe()` and persisted `portfolio_state.parquet`.
323
+ - Quote context fields on `Fill` and summarized quote context on `Trade`.
324
+ - Activity and exposure metrics: `num_fills`, `num_rebalance_events`, `unique_symbols_traded`,
325
+ `total_filled_notional`, `avg_turnover`, `max_turnover`, `avg_open_positions`,
326
+ and `max_open_positions`.
327
+
328
+ ### Changed
329
+
330
+ - `FeedSpec.price_col` now drives the broker reference price instead of being collapsed back to `close`.
331
+ - Market execution can use side-aware quotes: buys at ask, sells at bid.
332
+ - `QUOTE_SIDE` marking prices long inventory on the bid and short inventory on the ask.
333
+ - Result persistence now includes fills alongside trades, equity, daily P&L, metrics, and config.
334
+ - Result persistence now includes portfolio state alongside trades, fills, equity,
335
+ daily P&L, metrics, and config.
336
+ - User guides and README now document quote-aware feeds, mark pricing, and fill export.
337
+ - User guides and README now document portfolio-state reporting and quote-aware audit fields.
338
+
339
+ ### Performance
340
+
341
+ - Legacy OHLCV hot path remains faster than the pre-optimization baseline.
342
+ - Quote-aware execution adds moderate overhead relative to the optimized OHLCV path, while staying ahead of the legacy baseline in local benchmarks.
343
+
344
+ ### Validation
345
+
346
+ - `uv run ty check`
347
+ - `pre-commit run --all-files`
348
+ - `uv run pytest tests/ -q`
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 Stefan Jansen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.