akquant 0.2.30__tar.gz → 0.2.32__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 (458) hide show
  1. {akquant-0.2.30 → akquant-0.2.32}/Cargo.lock +1 -1
  2. {akquant-0.2.30 → akquant-0.2.32}/Cargo.toml +1 -1
  3. {akquant-0.2.30 → akquant-0.2.32}/PKG-INFO +1 -1
  4. {akquant-0.2.30 → akquant-0.2.32}/docs/en/guide/strategy.md +6 -5
  5. {akquant-0.2.30 → akquant-0.2.32}/docs/en/reference/api.md +4 -3
  6. akquant-0.2.32/docs/javascripts/search-lang-filter.js +142 -0
  7. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/guide/strategy.md +4 -3
  8. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/reference/api.md +4 -4
  9. {akquant-0.2.30 → akquant-0.2.32}/mkdocs.yml +1 -4
  10. {akquant-0.2.30 → akquant-0.2.32}/pyproject.toml +1 -1
  11. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/strategy.py +10 -0
  12. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/strategy_events.py +9 -7
  13. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/strategy_framework_hooks.py +141 -38
  14. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/strategy_history.py +13 -2
  15. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/strategy_order_events.py +6 -1
  16. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/strategy_trading_api.py +58 -22
  17. {akquant-0.2.30 → akquant-0.2.32}/src/context.rs +82 -2
  18. {akquant-0.2.30 → akquant-0.2.32}/src/engine/core.rs +68 -0
  19. {akquant-0.2.30 → akquant-0.2.32}/src/history.rs +16 -1
  20. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/current/futures_margin/metrics.json +1 -1
  21. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/current/futures_margin/orders.parquet +0 -0
  22. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/current/option_basic/metrics.json +1 -1
  23. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/current/option_basic/orders.parquet +0 -0
  24. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/current/stock_t1/metrics.json +1 -1
  25. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/current/stock_t1/orders.parquet +0 -0
  26. {akquant-0.2.30 → akquant-0.2.32}/tests/test_strategy_extras.py +303 -1
  27. {akquant-0.2.30 → akquant-0.2.32}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  28. {akquant-0.2.30 → akquant-0.2.32}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  29. {akquant-0.2.30 → akquant-0.2.32}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  30. {akquant-0.2.30 → akquant-0.2.32}/.github/workflows/deploy-docs.yml +0 -0
  31. {akquant-0.2.30 → akquant-0.2.32}/.github/workflows/docs-quality.yml +0 -0
  32. {akquant-0.2.30 → akquant-0.2.32}/.github/workflows/release.yml +0 -0
  33. {akquant-0.2.30 → akquant-0.2.32}/.gitignore +0 -0
  34. {akquant-0.2.30 → akquant-0.2.32}/.pre-commit-config.yaml +0 -0
  35. {akquant-0.2.30 → akquant-0.2.32}/CHANGELOG.md +0 -0
  36. {akquant-0.2.30 → akquant-0.2.32}/CODE_OF_CONDUCT.md +0 -0
  37. {akquant-0.2.30 → akquant-0.2.32}/CONTRIBUTING.md +0 -0
  38. {akquant-0.2.30 → akquant-0.2.32}/LICENSE +0 -0
  39. {akquant-0.2.30 → akquant-0.2.32}/README.md +0 -0
  40. {akquant-0.2.30 → akquant-0.2.32}/assets/dashboard_preview.png +0 -0
  41. {akquant-0.2.30 → akquant-0.2.32}/assets/logo.svg +0 -0
  42. {akquant-0.2.30 → akquant-0.2.32}/assets/social_preview.png +0 -0
  43. {akquant-0.2.30 → akquant-0.2.32}/docs/CNAME +0 -0
  44. {akquant-0.2.30 → akquant-0.2.32}/docs/assets/akquant-icon.svg +0 -0
  45. {akquant-0.2.30 → akquant-0.2.32}/docs/assets/akquant-logo.svg +0 -0
  46. {akquant-0.2.30 → akquant-0.2.32}/docs/assets/reports/akquant_report.html +0 -0
  47. {akquant-0.2.30 → akquant-0.2.32}/docs/en/advanced/analyzer_plugin_spec.md +0 -0
  48. {akquant-0.2.30 → akquant-0.2.32}/docs/en/advanced/broker_capability_matrix.md +0 -0
  49. {akquant-0.2.30 → akquant-0.2.32}/docs/en/advanced/custom_broker_production_checklist.md +0 -0
  50. {akquant-0.2.30 → akquant-0.2.32}/docs/en/advanced/custom_broker_registry.md +0 -0
  51. {akquant-0.2.30 → akquant-0.2.32}/docs/en/advanced/data_feed_adapter_spec.md +0 -0
  52. {akquant-0.2.30 → akquant-0.2.32}/docs/en/advanced/live_functional_quickstart.md +0 -0
  53. {akquant-0.2.30 → akquant-0.2.32}/docs/en/advanced/llm.md +0 -0
  54. {akquant-0.2.30 → akquant-0.2.32}/docs/en/advanced/ml.md +0 -0
  55. {akquant-0.2.30 → akquant-0.2.32}/docs/en/advanced/multi_strategy_guide.md +0 -0
  56. {akquant-0.2.30 → akquant-0.2.32}/docs/en/advanced/multi_timeframe_feed_api.md +0 -0
  57. {akquant-0.2.30 → akquant-0.2.32}/docs/en/advanced/runtime_config.md +0 -0
  58. {akquant-0.2.30 → akquant-0.2.32}/docs/en/advanced/strategy_style_decision.md +0 -0
  59. {akquant-0.2.30 → akquant-0.2.32}/docs/en/advanced/timezone.md +0 -0
  60. {akquant-0.2.30 → akquant-0.2.32}/docs/en/advanced/warm_start.md +0 -0
  61. {akquant-0.2.30 → akquant-0.2.32}/docs/en/guide/analysis.md +0 -0
  62. {akquant-0.2.30 → akquant-0.2.32}/docs/en/guide/cross_section_checklist.md +0 -0
  63. {akquant-0.2.30 → akquant-0.2.32}/docs/en/guide/custom_indicator.md +0 -0
  64. {akquant-0.2.30 → akquant-0.2.32}/docs/en/guide/data.md +0 -0
  65. {akquant-0.2.30 → akquant-0.2.32}/docs/en/guide/examples.md +0 -0
  66. {akquant-0.2.30 → akquant-0.2.32}/docs/en/guide/factor.md +0 -0
  67. {akquant-0.2.30 → akquant-0.2.32}/docs/en/guide/indicator_scenario_quickref.md +0 -0
  68. {akquant-0.2.30 → akquant-0.2.32}/docs/en/guide/optimization.md +0 -0
  69. {akquant-0.2.30 → akquant-0.2.32}/docs/en/guide/python_basics.md +0 -0
  70. {akquant-0.2.30 → akquant-0.2.32}/docs/en/guide/quant_basics.md +0 -0
  71. {akquant-0.2.30 → akquant-0.2.32}/docs/en/guide/rust_indicator_reference.md +0 -0
  72. {akquant-0.2.30 → akquant-0.2.32}/docs/en/guide/talib_indicator_playbook.md +0 -0
  73. {akquant-0.2.30 → akquant-0.2.32}/docs/en/guide/testing.md +0 -0
  74. {akquant-0.2.30 → akquant-0.2.32}/docs/en/guide/visualization.md +0 -0
  75. {akquant-0.2.30 → akquant-0.2.32}/docs/en/index.md +0 -0
  76. {akquant-0.2.30 → akquant-0.2.32}/docs/en/meta/architecture.md +0 -0
  77. {akquant-0.2.30 → akquant-0.2.32}/docs/en/meta/internals.md +0 -0
  78. {akquant-0.2.30 → akquant-0.2.32}/docs/en/start/first_strategy.md +0 -0
  79. {akquant-0.2.30 → akquant-0.2.32}/docs/en/start/installation.md +0 -0
  80. {akquant-0.2.30 → akquant-0.2.32}/docs/en/start/quickstart.md +0 -0
  81. {akquant-0.2.30 → akquant-0.2.32}/docs/en/start/setup_guide.md +0 -0
  82. {akquant-0.2.30 → akquant-0.2.32}/docs/en/textbook/01_foundations.md +0 -0
  83. {akquant-0.2.30 → akquant-0.2.32}/docs/en/textbook/02_programming.md +0 -0
  84. {akquant-0.2.30 → akquant-0.2.32}/docs/en/textbook/03_data.md +0 -0
  85. {akquant-0.2.30 → akquant-0.2.32}/docs/en/textbook/04_backtest_engine.md +0 -0
  86. {akquant-0.2.30 → akquant-0.2.32}/docs/en/textbook/05_strategy.md +0 -0
  87. {akquant-0.2.30 → akquant-0.2.32}/docs/en/textbook/06_stock_a.md +0 -0
  88. {akquant-0.2.30 → akquant-0.2.32}/docs/en/textbook/07_futures.md +0 -0
  89. {akquant-0.2.30 → akquant-0.2.32}/docs/en/textbook/08_options.md +0 -0
  90. {akquant-0.2.30 → akquant-0.2.32}/docs/en/textbook/09_funds.md +0 -0
  91. {akquant-0.2.30 → akquant-0.2.32}/docs/en/textbook/10_analysis.md +0 -0
  92. {akquant-0.2.30 → akquant-0.2.32}/docs/en/textbook/11_optimization.md +0 -0
  93. {akquant-0.2.30 → akquant-0.2.32}/docs/en/textbook/12_ml.md +0 -0
  94. {akquant-0.2.30 → akquant-0.2.32}/docs/en/textbook/13_visualization.md +0 -0
  95. {akquant-0.2.30 → akquant-0.2.32}/docs/en/textbook/14_factor.md +0 -0
  96. {akquant-0.2.30 → akquant-0.2.32}/docs/en/textbook/15_live_trading.md +0 -0
  97. {akquant-0.2.30 → akquant-0.2.32}/docs/en/textbook/16_rust_indicators.md +0 -0
  98. {akquant-0.2.30 → akquant-0.2.32}/docs/en/textbook/index.md +0 -0
  99. {akquant-0.2.30 → akquant-0.2.32}/docs/javascripts/mathjax.js +0 -0
  100. {akquant-0.2.30 → akquant-0.2.32}/docs/robots.txt +0 -0
  101. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/advanced/analyzer_plugin_spec.md +0 -0
  102. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/advanced/broker_capability_matrix.md +0 -0
  103. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/advanced/custom_broker_production_checklist.md +0 -0
  104. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/advanced/custom_broker_registry.md +0 -0
  105. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/advanced/data_feed_adapter_spec.md +0 -0
  106. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/advanced/live_functional_quickstart.md +0 -0
  107. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/advanced/llm.md +0 -0
  108. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/advanced/ml.md +0 -0
  109. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/advanced/multi_strategy_guide.md +0 -0
  110. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/advanced/multi_timeframe_feed_api.md +0 -0
  111. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/advanced/runtime_config.md +0 -0
  112. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/advanced/strategy_style_decision.md +0 -0
  113. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/advanced/timezone.md +0 -0
  114. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/advanced/warm_start.md +0 -0
  115. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/guide/analysis.md +0 -0
  116. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/guide/cross_section_checklist.md +0 -0
  117. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/guide/custom_indicator.md +0 -0
  118. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/guide/data.md +0 -0
  119. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/guide/examples.md +0 -0
  120. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/guide/factor.md +0 -0
  121. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/guide/indicator_scenario_quickref.md +0 -0
  122. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/guide/optimization.md +0 -0
  123. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/guide/python_basics.md +0 -0
  124. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/guide/quant_basics.md +0 -0
  125. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/guide/rust_indicator_reference.md +0 -0
  126. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/guide/talib_indicator_playbook.md +0 -0
  127. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/guide/testing.md +0 -0
  128. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/guide/visualization.md +0 -0
  129. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/index.md +0 -0
  130. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/meta/architecture.md +0 -0
  131. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/meta/internals.md +0 -0
  132. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/start/first_strategy.md +0 -0
  133. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/start/installation.md +0 -0
  134. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/start/quickstart.md +0 -0
  135. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/start/setup_guide.md +0 -0
  136. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/textbook/01_foundations.md +0 -0
  137. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/textbook/02_programming.md +0 -0
  138. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/textbook/03_data.md +0 -0
  139. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/textbook/04_backtest_engine.md +0 -0
  140. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/textbook/05_strategy.md +0 -0
  141. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/textbook/06_stock_a.md +0 -0
  142. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/textbook/07_futures.md +0 -0
  143. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/textbook/08_options.md +0 -0
  144. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/textbook/09_funds.md +0 -0
  145. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/textbook/10_analysis.md +0 -0
  146. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/textbook/11_optimization.md +0 -0
  147. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/textbook/12_ml.md +0 -0
  148. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/textbook/13_visualization.md +0 -0
  149. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/textbook/14_factor.md +0 -0
  150. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/textbook/15_live_trading.md +0 -0
  151. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/textbook/16_rust_indicators.md +0 -0
  152. {akquant-0.2.30 → akquant-0.2.32}/docs/zh/textbook/index.md +0 -0
  153. {akquant-0.2.30 → akquant-0.2.32}/examples/01_quickstart.py +0 -0
  154. {akquant-0.2.30 → akquant-0.2.32}/examples/02_parameter_optimization.py +0 -0
  155. {akquant-0.2.30 → akquant-0.2.32}/examples/03_parameter_optimization_advanced.py +0 -0
  156. {akquant-0.2.30 → akquant-0.2.32}/examples/04_mixed_assets.py +0 -0
  157. {akquant-0.2.30 → akquant-0.2.32}/examples/05_live_trading_ctp.py +0 -0
  158. {akquant-0.2.30 → akquant-0.2.32}/examples/06_complex_orders.py +0 -0
  159. {akquant-0.2.30 → akquant-0.2.32}/examples/07_option_test.py +0 -0
  160. {akquant-0.2.30 → akquant-0.2.32}/examples/08_event_callbacks.py +0 -0
  161. {akquant-0.2.30 → akquant-0.2.32}/examples/09_ml_framework.py +0 -0
  162. {akquant-0.2.30 → akquant-0.2.32}/examples/10_ml_walk_forward.py +0 -0
  163. {akquant-0.2.30 → akquant-0.2.32}/examples/11_plot_visualization.py +0 -0
  164. {akquant-0.2.30 → akquant-0.2.32}/examples/12_wfo_integrated.py +0 -0
  165. {akquant-0.2.30 → akquant-0.2.32}/examples/13_quantstats_report.py +0 -0
  166. {akquant-0.2.30 → akquant-0.2.32}/examples/14_multi_frequency.py +0 -0
  167. {akquant-0.2.30 → akquant-0.2.32}/examples/15_plot_intraday.py +0 -0
  168. {akquant-0.2.30 → akquant-0.2.32}/examples/16_adj_returns_signal.py +0 -0
  169. {akquant-0.2.30 → akquant-0.2.32}/examples/17_readme_demo.py +0 -0
  170. {akquant-0.2.30 → akquant-0.2.32}/examples/18_benchmark_multisymbol.py +0 -0
  171. {akquant-0.2.30 → akquant-0.2.32}/examples/19_factor_expression.py +0 -0
  172. {akquant-0.2.30 → akquant-0.2.32}/examples/20_risk_management_demo.py +0 -0
  173. {akquant-0.2.30 → akquant-0.2.32}/examples/21_warm_start_demo.py +0 -0
  174. {akquant-0.2.30 → akquant-0.2.32}/examples/22_strategy_runtime_config_demo.py +0 -0
  175. {akquant-0.2.30 → akquant-0.2.32}/examples/23_functional_callbacks_demo.py +0 -0
  176. {akquant-0.2.30 → akquant-0.2.32}/examples/24_functional_tick_simulation_demo.py +0 -0
  177. {akquant-0.2.30 → akquant-0.2.32}/examples/25_streaming_backtest_demo.py +0 -0
  178. {akquant-0.2.30 → akquant-0.2.32}/examples/26_streaming_quickstart.py +0 -0
  179. {akquant-0.2.30 → akquant-0.2.32}/examples/27_streaming_monitoring_console.py +0 -0
  180. {akquant-0.2.30 → akquant-0.2.32}/examples/28_streaming_alerts_and_persist.py +0 -0
  181. {akquant-0.2.30 → akquant-0.2.32}/examples/29_streaming_event_report.py +0 -0
  182. {akquant-0.2.30 → akquant-0.2.32}/examples/30_streaming_report_oneclick.py +0 -0
  183. {akquant-0.2.30 → akquant-0.2.32}/examples/31_streaming_live_console.py +0 -0
  184. {akquant-0.2.30 → akquant-0.2.32}/examples/32_streaming_live_web.py +0 -0
  185. {akquant-0.2.30 → akquant-0.2.32}/examples/33_report_and_analysis_outputs.py +0 -0
  186. {akquant-0.2.30 → akquant-0.2.32}/examples/34_multi_strategy_demo.py +0 -0
  187. {akquant-0.2.30 → akquant-0.2.32}/examples/35_custom_broker_registry_demo.py +0 -0
  188. {akquant-0.2.30 → akquant-0.2.32}/examples/36_trailing_orders.py +0 -0
  189. {akquant-0.2.30 → akquant-0.2.32}/examples/37_feed_replay_alignment_demo.py +0 -0
  190. {akquant-0.2.30 → akquant-0.2.32}/examples/38_live_functional_strategy_demo.py +0 -0
  191. {akquant-0.2.30 → akquant-0.2.32}/examples/39_live_broker_submit_order_demo.py +0 -0
  192. {akquant-0.2.30 → akquant-0.2.32}/examples/40_functional_multi_slot_risk_demo.py +0 -0
  193. {akquant-0.2.30 → akquant-0.2.32}/examples/41_live_multi_slot_orchestration_demo.py +0 -0
  194. {akquant-0.2.30 → akquant-0.2.32}/examples/42_live_broker_event_audit_demo.py +0 -0
  195. {akquant-0.2.30 → akquant-0.2.32}/examples/43_target_weights_rebalance.py +0 -0
  196. {akquant-0.2.30 → akquant-0.2.32}/examples/44_strategy_source_loader_demo.py +0 -0
  197. {akquant-0.2.30 → akquant-0.2.32}/examples/45_talib_indicator_playbook_demo.py +0 -0
  198. {akquant-0.2.30 → akquant-0.2.32}/examples/46_broker_profile_demo.py +0 -0
  199. {akquant-0.2.30 → akquant-0.2.32}/examples/47_margin_liquidation_audit_demo.py +0 -0
  200. {akquant-0.2.30 → akquant-0.2.32}/examples/48_margin_liquidation_priority_compare.py +0 -0
  201. {akquant-0.2.30 → akquant-0.2.32}/examples/49_on_expiry_demo.py +0 -0
  202. {akquant-0.2.30 → akquant-0.2.32}/examples/50_framework_hooks_demo.py +0 -0
  203. {akquant-0.2.30 → akquant-0.2.32}/examples/51_class_tick_callbacks_demo.py +0 -0
  204. {akquant-0.2.30 → akquant-0.2.32}/examples/52_pre_open_demo.py +0 -0
  205. {akquant-0.2.30 → akquant-0.2.32}/examples/53_timer_to_pre_open_demo.py +0 -0
  206. {akquant-0.2.30 → akquant-0.2.32}/examples/54_functional_pre_open_demo.py +0 -0
  207. {akquant-0.2.30 → akquant-0.2.32}/examples/55_functional_ml_walk_forward.py +0 -0
  208. {akquant-0.2.30 → akquant-0.2.32}/examples/56_functional_warm_start_demo.py +0 -0
  209. {akquant-0.2.30 → akquant-0.2.32}/examples/57_functional_multi_slot_warm_start_demo.py +0 -0
  210. {akquant-0.2.30 → akquant-0.2.32}/examples/58_incremental_bootstrap_demo.py +0 -0
  211. {akquant-0.2.30 → akquant-0.2.32}/examples/59_akshare_etf_rotation.py +0 -0
  212. {akquant-0.2.30 → akquant-0.2.32}/examples/60_custom_indicator_demo.py +0 -0
  213. {akquant-0.2.30 → akquant-0.2.32}/examples/README.md +0 -0
  214. {akquant-0.2.30 → akquant-0.2.32}/examples/benchmark_utils.py +0 -0
  215. {akquant-0.2.30 → akquant-0.2.32}/examples/pb_mock.py +0 -0
  216. {akquant-0.2.30 → akquant-0.2.32}/examples/strategies/01_stock_dual_moving_average.py +0 -0
  217. {akquant-0.2.30 → akquant-0.2.32}/examples/strategies/02_stock_grid_trading.py +0 -0
  218. {akquant-0.2.30 → akquant-0.2.32}/examples/strategies/03_stock_atr_breakout.py +0 -0
  219. {akquant-0.2.30 → akquant-0.2.32}/examples/strategies/04_stock_momentum_rotation.py +0 -0
  220. {akquant-0.2.30 → akquant-0.2.32}/examples/strategies/05_stock_momentum_rotation_timer.py +0 -0
  221. {akquant-0.2.30 → akquant-0.2.32}/examples/strategies/06_stock_momentum_rotation_bucket.py +0 -0
  222. {akquant-0.2.30 → akquant-0.2.32}/examples/strategies/07_stock_momentum_rotation_on_timer.py +0 -0
  223. {akquant-0.2.30 → akquant-0.2.32}/examples/strategies/08_target_positions_long_short.py +0 -0
  224. {akquant-0.2.30 → akquant-0.2.32}/examples/strategies/README.md +0 -0
  225. {akquant-0.2.30 → akquant-0.2.32}/examples/textbook/ch01_quickstart.py +0 -0
  226. {akquant-0.2.30 → akquant-0.2.32}/examples/textbook/ch02_programming.py +0 -0
  227. {akquant-0.2.30 → akquant-0.2.32}/examples/textbook/ch03_data.py +0 -0
  228. {akquant-0.2.30 → akquant-0.2.32}/examples/textbook/ch04_comparison.py +0 -0
  229. {akquant-0.2.30 → akquant-0.2.32}/examples/textbook/ch05_strategy.py +0 -0
  230. {akquant-0.2.30 → akquant-0.2.32}/examples/textbook/ch06_stock_a.py +0 -0
  231. {akquant-0.2.30 → akquant-0.2.32}/examples/textbook/ch07_futures.py +0 -0
  232. {akquant-0.2.30 → akquant-0.2.32}/examples/textbook/ch08_options.py +0 -0
  233. {akquant-0.2.30 → akquant-0.2.32}/examples/textbook/ch09_funds.py +0 -0
  234. {akquant-0.2.30 → akquant-0.2.32}/examples/textbook/ch09_portfolio.py +0 -0
  235. {akquant-0.2.30 → akquant-0.2.32}/examples/textbook/ch10_analysis.py +0 -0
  236. {akquant-0.2.30 → akquant-0.2.32}/examples/textbook/ch11_optimization.py +0 -0
  237. {akquant-0.2.30 → akquant-0.2.32}/examples/textbook/ch12_ml.py +0 -0
  238. {akquant-0.2.30 → akquant-0.2.32}/examples/textbook/ch13_visualization.py +0 -0
  239. {akquant-0.2.30 → akquant-0.2.32}/examples/textbook/ch14_factor.py +0 -0
  240. {akquant-0.2.30 → akquant-0.2.32}/examples/textbook/ch15_live_trading.py +0 -0
  241. {akquant-0.2.30 → akquant-0.2.32}/examples/textbook/ch15_strategy_loader.py +0 -0
  242. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/__init__.py +0 -0
  243. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/akquant.pyi +0 -0
  244. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/analyzer_plugin.py +0 -0
  245. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/backtest/__init__.py +0 -0
  246. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/backtest/__init__.pyi +0 -0
  247. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/backtest/engine.py +0 -0
  248. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/backtest/result.py +0 -0
  249. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/checkpoint.py +0 -0
  250. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/config.py +0 -0
  251. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/data.py +0 -0
  252. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/factor/__init__.py +0 -0
  253. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/factor/engine.py +0 -0
  254. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/factor/ops.py +0 -0
  255. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/factor/parser.py +0 -0
  256. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/feed_adapter.py +0 -0
  257. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/fund/__init__.py +0 -0
  258. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/futures/__init__.py +0 -0
  259. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/gateway/__init__.py +0 -0
  260. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/gateway/base.py +0 -0
  261. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/gateway/ctp_adapter.py +0 -0
  262. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/gateway/ctp_native.py +0 -0
  263. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/gateway/factory.py +0 -0
  264. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/gateway/mapper.py +0 -0
  265. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/gateway/miniqmt.py +0 -0
  266. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/gateway/models.py +0 -0
  267. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/gateway/ptrade.py +0 -0
  268. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/gateway/registry.py +0 -0
  269. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/indicator.py +0 -0
  270. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/live.py +0 -0
  271. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/log.py +0 -0
  272. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/ml/__init__.py +0 -0
  273. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/ml/model.py +0 -0
  274. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/optimize.py +0 -0
  275. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/option/__init__.py +0 -0
  276. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/params.py +0 -0
  277. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/params_adapter.py +0 -0
  278. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/plot/__init__.py +0 -0
  279. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/plot/analysis.py +0 -0
  280. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/plot/dashboard.py +0 -0
  281. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/plot/report.py +0 -0
  282. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/plot/strategy.py +0 -0
  283. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/plot/utils.py +0 -0
  284. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/py.typed +0 -0
  285. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/risk.py +0 -0
  286. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/sizer.py +0 -0
  287. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/stock/__init__.py +0 -0
  288. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/strategy_loader.py +0 -0
  289. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/strategy_logging.py +0 -0
  290. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/strategy_ml.py +0 -0
  291. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/strategy_position.py +0 -0
  292. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/strategy_scheduler.py +0 -0
  293. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/strategy_time.py +0 -0
  294. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/talib/__init__.py +0 -0
  295. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/talib/backend.py +0 -0
  296. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/talib/core.py +0 -0
  297. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/talib/funcs.py +0 -0
  298. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/utils/__init__.py +0 -0
  299. {akquant-0.2.30 → akquant-0.2.32}/python/akquant/utils/inspector.py +0 -0
  300. {akquant-0.2.30 → akquant-0.2.32}/requirements-dev.txt +0 -0
  301. {akquant-0.2.30 → akquant-0.2.32}/scripts/cargo-test.sh +0 -0
  302. {akquant-0.2.30 → akquant-0.2.32}/scripts/check_docs_api_examples.py +0 -0
  303. {akquant-0.2.30 → akquant-0.2.32}/scripts/check_docs_links.py +0 -0
  304. {akquant-0.2.30 → akquant-0.2.32}/scripts/dev-check.sh +0 -0
  305. {akquant-0.2.30 → akquant-0.2.32}/scripts/find_legacy_execution_policy_calls.py +0 -0
  306. {akquant-0.2.30 → akquant-0.2.32}/scripts/golden_baseline_report.py +0 -0
  307. {akquant-0.2.30 → akquant-0.2.32}/src/account.rs +0 -0
  308. {akquant-0.2.30 → akquant-0.2.32}/src/analysis/mod.rs +0 -0
  309. {akquant-0.2.30 → akquant-0.2.32}/src/analysis/python.rs +0 -0
  310. {akquant-0.2.30 → akquant-0.2.32}/src/analysis/result.rs +0 -0
  311. {akquant-0.2.30 → akquant-0.2.32}/src/analysis/tests.rs +0 -0
  312. {akquant-0.2.30 → akquant-0.2.32}/src/analysis/tracker.rs +0 -0
  313. {akquant-0.2.30 → akquant-0.2.32}/src/analysis/types.rs +0 -0
  314. {akquant-0.2.30 → akquant-0.2.32}/src/bin/stub_gen.rs +0 -0
  315. {akquant-0.2.30 → akquant-0.2.32}/src/clock.rs +0 -0
  316. {akquant-0.2.30 → akquant-0.2.32}/src/data/aggregator.rs +0 -0
  317. {akquant-0.2.30 → akquant-0.2.32}/src/data/batch.rs +0 -0
  318. {akquant-0.2.30 → akquant-0.2.32}/src/data/client.rs +0 -0
  319. {akquant-0.2.30 → akquant-0.2.32}/src/data/feed.rs +0 -0
  320. {akquant-0.2.30 → akquant-0.2.32}/src/data/mod.rs +0 -0
  321. {akquant-0.2.30 → akquant-0.2.32}/src/engine/mod.rs +0 -0
  322. {akquant-0.2.30 → akquant-0.2.32}/src/engine/python.rs +0 -0
  323. {akquant-0.2.30 → akquant-0.2.32}/src/engine/state.rs +0 -0
  324. {akquant-0.2.30 → akquant-0.2.32}/src/error.rs +0 -0
  325. {akquant-0.2.30 → akquant-0.2.32}/src/event.rs +0 -0
  326. {akquant-0.2.30 → akquant-0.2.32}/src/event_manager.rs +0 -0
  327. {akquant-0.2.30 → akquant-0.2.32}/src/execution/common.rs +0 -0
  328. {akquant-0.2.30 → akquant-0.2.32}/src/execution/crypto.rs +0 -0
  329. {akquant-0.2.30 → akquant-0.2.32}/src/execution/forex.rs +0 -0
  330. {akquant-0.2.30 → akquant-0.2.32}/src/execution/futures.rs +0 -0
  331. {akquant-0.2.30 → akquant-0.2.32}/src/execution/matcher.rs +0 -0
  332. {akquant-0.2.30 → akquant-0.2.32}/src/execution/mod.rs +0 -0
  333. {akquant-0.2.30 → akquant-0.2.32}/src/execution/option.rs +0 -0
  334. {akquant-0.2.30 → akquant-0.2.32}/src/execution/python.rs +0 -0
  335. {akquant-0.2.30 → akquant-0.2.32}/src/execution/realtime.rs +0 -0
  336. {akquant-0.2.30 → akquant-0.2.32}/src/execution/simulated.rs +0 -0
  337. {akquant-0.2.30 → akquant-0.2.32}/src/execution/slippage.rs +0 -0
  338. {akquant-0.2.30 → akquant-0.2.32}/src/execution/stock.rs +0 -0
  339. {akquant-0.2.30 → akquant-0.2.32}/src/indicators/momentum.rs +0 -0
  340. {akquant-0.2.30 → akquant-0.2.32}/src/indicators/momentum_oscillators.rs +0 -0
  341. {akquant-0.2.30 → akquant-0.2.32}/src/indicators/momentum_rates.rs +0 -0
  342. {akquant-0.2.30 → akquant-0.2.32}/src/indicators/moving_average.rs +0 -0
  343. {akquant-0.2.30 → akquant-0.2.32}/src/indicators/moving_average_compound.rs +0 -0
  344. {akquant-0.2.30 → akquant-0.2.32}/src/indicators/moving_average_core.rs +0 -0
  345. {akquant-0.2.30 → akquant-0.2.32}/src/indicators/moving_average_transforms.rs +0 -0
  346. {akquant-0.2.30 → akquant-0.2.32}/src/indicators/moving_average_windowed.rs +0 -0
  347. {akquant-0.2.30 → akquant-0.2.32}/src/indicators/trend.rs +0 -0
  348. {akquant-0.2.30 → akquant-0.2.32}/src/indicators/trend_directional.rs +0 -0
  349. {akquant-0.2.30 → akquant-0.2.32}/src/indicators/trend_oscillators.rs +0 -0
  350. {akquant-0.2.30 → akquant-0.2.32}/src/indicators/trend_regression.rs +0 -0
  351. {akquant-0.2.30 → akquant-0.2.32}/src/indicators/volatility.rs +0 -0
  352. {akquant-0.2.30 → akquant-0.2.32}/src/indicators/volatility_price.rs +0 -0
  353. {akquant-0.2.30 → akquant-0.2.32}/src/indicators/volatility_stats.rs +0 -0
  354. {akquant-0.2.30 → akquant-0.2.32}/src/indicators/volume.rs +0 -0
  355. {akquant-0.2.30 → akquant-0.2.32}/src/indicators.rs +0 -0
  356. {akquant-0.2.30 → akquant-0.2.32}/src/lib.rs +0 -0
  357. {akquant-0.2.30 → akquant-0.2.32}/src/margin/calculator.rs +0 -0
  358. {akquant-0.2.30 → akquant-0.2.32}/src/margin/engine.rs +0 -0
  359. {akquant-0.2.30 → akquant-0.2.32}/src/margin/mod.rs +0 -0
  360. {akquant-0.2.30 → akquant-0.2.32}/src/market/china.rs +0 -0
  361. {akquant-0.2.30 → akquant-0.2.32}/src/market/core.rs +0 -0
  362. {akquant-0.2.30 → akquant-0.2.32}/src/market/corporate_action.rs +0 -0
  363. {akquant-0.2.30 → akquant-0.2.32}/src/market/fund.rs +0 -0
  364. {akquant-0.2.30 → akquant-0.2.32}/src/market/futures.rs +0 -0
  365. {akquant-0.2.30 → akquant-0.2.32}/src/market/manager.rs +0 -0
  366. {akquant-0.2.30 → akquant-0.2.32}/src/market/mod.rs +0 -0
  367. {akquant-0.2.30 → akquant-0.2.32}/src/market/option.rs +0 -0
  368. {akquant-0.2.30 → akquant-0.2.32}/src/market/simple.rs +0 -0
  369. {akquant-0.2.30 → akquant-0.2.32}/src/market/stock.rs +0 -0
  370. {akquant-0.2.30 → akquant-0.2.32}/src/model/corporate_action.rs +0 -0
  371. {akquant-0.2.30 → akquant-0.2.32}/src/model/instrument.rs +0 -0
  372. {akquant-0.2.30 → akquant-0.2.32}/src/model/market_data.rs +0 -0
  373. {akquant-0.2.30 → akquant-0.2.32}/src/model/mod.rs +0 -0
  374. {akquant-0.2.30 → akquant-0.2.32}/src/model/order.rs +0 -0
  375. {akquant-0.2.30 → akquant-0.2.32}/src/model/timer.rs +0 -0
  376. {akquant-0.2.30 → akquant-0.2.32}/src/model/types.rs +0 -0
  377. {akquant-0.2.30 → akquant-0.2.32}/src/order_manager.rs +0 -0
  378. {akquant-0.2.30 → akquant-0.2.32}/src/pipeline/mod.rs +0 -0
  379. {akquant-0.2.30 → akquant-0.2.32}/src/pipeline/processor.rs +0 -0
  380. {akquant-0.2.30 → akquant-0.2.32}/src/pipeline/runner.rs +0 -0
  381. {akquant-0.2.30 → akquant-0.2.32}/src/pipeline/stages.rs +0 -0
  382. {akquant-0.2.30 → akquant-0.2.32}/src/portfolio.rs +0 -0
  383. {akquant-0.2.30 → akquant-0.2.32}/src/risk/common.rs +0 -0
  384. {akquant-0.2.30 → akquant-0.2.32}/src/risk/config.rs +0 -0
  385. {akquant-0.2.30 → akquant-0.2.32}/src/risk/futures.rs +0 -0
  386. {akquant-0.2.30 → akquant-0.2.32}/src/risk/manager.rs +0 -0
  387. {akquant-0.2.30 → akquant-0.2.32}/src/risk/mod.rs +0 -0
  388. {akquant-0.2.30 → akquant-0.2.32}/src/risk/option.rs +0 -0
  389. {akquant-0.2.30 → akquant-0.2.32}/src/risk/portfolio.rs +0 -0
  390. {akquant-0.2.30 → akquant-0.2.32}/src/risk/rule.rs +0 -0
  391. {akquant-0.2.30 → akquant-0.2.32}/src/risk/stock.rs +0 -0
  392. {akquant-0.2.30 → akquant-0.2.32}/src/settlement/expiry.rs +0 -0
  393. {akquant-0.2.30 → akquant-0.2.32}/src/settlement/handler.rs +0 -0
  394. {akquant-0.2.30 → akquant-0.2.32}/src/settlement/manager.rs +0 -0
  395. {akquant-0.2.30 → akquant-0.2.32}/src/settlement/mod.rs +0 -0
  396. {akquant-0.2.30 → akquant-0.2.32}/src/settlement/option.rs +0 -0
  397. {akquant-0.2.30 → akquant-0.2.32}/src/statistics/mod.rs +0 -0
  398. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/BASELINE_REPORT.md +0 -0
  399. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/LEGACY_EXECUTION_CALLS.md +0 -0
  400. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/baselines/futures_margin/equity_curve.parquet +0 -0
  401. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/baselines/futures_margin/metrics.json +0 -0
  402. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/baselines/futures_margin/orders.parquet +0 -0
  403. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/baselines/option_basic/equity_curve.parquet +0 -0
  404. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/baselines/option_basic/metrics.json +0 -0
  405. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/baselines/option_basic/orders.parquet +0 -0
  406. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/baselines/stock_t1/equity_curve.parquet +0 -0
  407. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/baselines/stock_t1/metrics.json +0 -0
  408. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/baselines/stock_t1/orders.parquet +0 -0
  409. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/baselines/stock_t1/trades.parquet +0 -0
  410. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/current/futures_margin/equity_curve.parquet +0 -0
  411. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/current/option_basic/equity_curve.parquet +0 -0
  412. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/current/stock_t1/equity_curve.parquet +0 -0
  413. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/current/stock_t1/trades.parquet +0 -0
  414. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/data/future_margin.parquet +0 -0
  415. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/data/future_margin.parquet.sha256 +0 -0
  416. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/data/option_basic.parquet +0 -0
  417. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/data/option_basic.parquet.sha256 +0 -0
  418. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/data/stock_t1.parquet +0 -0
  419. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/data/stock_t1.parquet.sha256 +0 -0
  420. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/gen_data.py +0 -0
  421. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/runner.py +0 -0
  422. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/strategies/futures_margin.py +0 -0
  423. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/strategies/option_basic.py +0 -0
  424. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/strategies/stock_t1.py +0 -0
  425. {akquant-0.2.30 → akquant-0.2.32}/tests/golden/test_golden.py +0 -0
  426. {akquant-0.2.30 → akquant-0.2.32}/tests/test_account_risk_rules.py +0 -0
  427. {akquant-0.2.30 → akquant-0.2.32}/tests/test_custom_matcher.py +0 -0
  428. {akquant-0.2.30 → akquant-0.2.32}/tests/test_docs_api_examples.py +0 -0
  429. {akquant-0.2.30 → akquant-0.2.32}/tests/test_docs_links.py +0 -0
  430. {akquant-0.2.30 → akquant-0.2.32}/tests/test_engine.py +0 -0
  431. {akquant-0.2.30 → akquant-0.2.32}/tests/test_examples_regression.py +0 -0
  432. {akquant-0.2.30 → akquant-0.2.32}/tests/test_factor_engine.py +0 -0
  433. {akquant-0.2.30 → akquant-0.2.32}/tests/test_factor_ops.py +0 -0
  434. {akquant-0.2.30 → akquant-0.2.32}/tests/test_feed_adapter.py +0 -0
  435. {akquant-0.2.30 → akquant-0.2.32}/tests/test_gateway_callbacks.py +0 -0
  436. {akquant-0.2.30 → akquant-0.2.32}/tests/test_gateway_ctp_adapter.py +0 -0
  437. {akquant-0.2.30 → akquant-0.2.32}/tests/test_gateway_ctp_native.py +0 -0
  438. {akquant-0.2.30 → akquant-0.2.32}/tests/test_gateway_factory.py +0 -0
  439. {akquant-0.2.30 → akquant-0.2.32}/tests/test_gateway_mapper.py +0 -0
  440. {akquant-0.2.30 → akquant-0.2.32}/tests/test_gateway_registry.py +0 -0
  441. {akquant-0.2.30 → akquant-0.2.32}/tests/test_inspector.py +0 -0
  442. {akquant-0.2.30 → akquant-0.2.32}/tests/test_live_runner_broker_bridge.py +0 -0
  443. {akquant-0.2.30 → akquant-0.2.32}/tests/test_multisymbol_cross_section_consistency.py +0 -0
  444. {akquant-0.2.30 → akquant-0.2.32}/tests/test_orders_df.py +0 -0
  445. {akquant-0.2.30 → akquant-0.2.32}/tests/test_params_adapter.py +0 -0
  446. {akquant-0.2.30 → akquant-0.2.32}/tests/test_partial_filled_status.py +0 -0
  447. {akquant-0.2.30 → akquant-0.2.32}/tests/test_portfolio.py +0 -0
  448. {akquant-0.2.30 → akquant-0.2.32}/tests/test_quickstart_stream_consistency.py +0 -0
  449. {akquant-0.2.30 → akquant-0.2.32}/tests/test_report_helpers.py +0 -0
  450. {akquant-0.2.30 → akquant-0.2.32}/tests/test_report_plot_extensions.py +0 -0
  451. {akquant-0.2.30 → akquant-0.2.32}/tests/test_result_analysis_extensions.py +0 -0
  452. {akquant-0.2.30 → akquant-0.2.32}/tests/test_stop_orders.py +0 -0
  453. {akquant-0.2.30 → akquant-0.2.32}/tests/test_strategy_timers_indicators.py +0 -0
  454. {akquant-0.2.30 → akquant-0.2.32}/tests/test_t_plus_one.py +0 -0
  455. {akquant-0.2.30 → akquant-0.2.32}/tests/test_talib_backend.py +0 -0
  456. {akquant-0.2.30 → akquant-0.2.32}/tests/test_talib_compat.py +0 -0
  457. {akquant-0.2.30 → akquant-0.2.32}/tests/test_trades_df.py +0 -0
  458. {akquant-0.2.30 → akquant-0.2.32}/tests/test_version.py +0 -0
@@ -30,7 +30,7 @@ dependencies = [
30
30
 
31
31
  [[package]]
32
32
  name = "akquant"
33
- version = "0.2.30"
33
+ version = "0.2.32"
34
34
  dependencies = [
35
35
  "anyhow",
36
36
  "chrono",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "akquant"
3
- version = "0.2.30"
3
+ version = "0.2.32"
4
4
  edition = "2024"
5
5
  description = "High-performance quantitative trading framework based on Rust and Python"
6
6
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: akquant
3
- Version: 0.2.30
3
+ Version: 0.2.32
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: Implementation :: PyPy
@@ -54,7 +54,7 @@ A strategy goes through the following stages from start to finish:
54
54
  | `on_before_trading` | First entry into `Normal` session each local trading day | Pre-market checks, trading-date level signal preparation | `examples/50_framework_hooks_demo.py` |
55
55
  | `on_pre_open` | Triggered by a framework timer before the first regular event of each trading day | Auction/pre-open signal generation with default next-open order semantics | `examples/52_pre_open_demo.py` |
56
56
  | `on_daily_rebalance` | At most once per trading day, same phase as `on_before_trading` | Cross-sectional ranking and one-shot rebalance | `examples/strategies/05_stock_momentum_rotation_timer.py` |
57
- | `on_after_trading` | When leaving `Normal`, or replayed on the next event if needed | End-of-day summaries, post-close cleanup, archiving | `examples/50_framework_hooks_demo.py` |
57
+ | `on_after_trading` | When leaving the regular trading session, or replayed on the next event if needed | End-of-day summaries, post-close cleanup, archiving | `examples/50_framework_hooks_demo.py` |
58
58
  | `on_portfolio_update` | Incrementally when portfolio snapshot changes | Monitor cash/equity changes, push UI or alerts | `examples/50_framework_hooks_demo.py` |
59
59
  | `on_error` | When any user callback raises | Record callback source and choose continue vs fail-fast | `examples/22_strategy_runtime_config_demo.py` |
60
60
  | `on_timer` | When a registered timer fires | Scheduled rebalance, pre-market tasks, cadence checks | `examples/strategies/07_stock_momentum_rotation_on_timer.py` |
@@ -79,10 +79,11 @@ Notes:
79
79
 
80
80
  * `on_reject` is emitted once per order id when the order first becomes `Rejected`.
81
81
  * `on_pre_open` is emitted once per trading day before the first regular bar/tick callback of that day.
82
- * `on_before_trading` is emitted once per local trading date when session enters `Normal`.
83
- * `on_after_trading` is emitted once per local trading date when leaving `Normal`, or on next event if day rollover occurs first.
82
+ * `on_before_trading` is emitted once per local trading date when the regular trading session starts; on the default backtest path this session is usually exposed as `Continuous`.
83
+ * `on_before_trading` / `on_daily_rebalance` always use a "previous trading day / previous snapshot only" visibility model; inside these callbacks, `get_history()`, `get_account()`, and `get_portfolio_value()` must not expose the current day's new bar or the current day's updated account view.
84
+ * `on_after_trading` is emitted once per local trading date when leaving the regular trading session, or on the next event if day rollover occurs first.
84
85
  * Inside `on_pre_open`, plain `buy/sell/order_target_*` calls automatically resolve to `price_basis=open, bar_offset=1, temporal=same_cycle` unless an explicit `fill_policy` is provided.
85
- * Set `self.enable_precise_day_boundary_hooks = True` to enable boundary-timer based precise day hooks.
86
+ * Set `self.enable_precise_day_boundary_hooks = True` to enable boundary-timer based precise day hooks; this switch changes trigger precision only, not the history/account visibility window seen inside day-boundary callbacks.
86
87
  * `on_portfolio_update` is incremental: emitted once at initialization, then only on order/trade or position-relevant price changes.
87
88
  * Use `self.portfolio_update_eps` to filter tiny equity/cash changes (default `0.0`).
88
89
  * During stop phase, pending `on_session_end` / `on_after_trading` are flushed before `on_stop`.
@@ -188,7 +189,7 @@ Practical tips:
188
189
  Timing note:
189
190
 
190
191
  * Do not treat `on_before_trading` as a stable same-day preparation stage that always runs before `on_pre_open`.
191
- * On the default path, `on_pre_open` runs before the first regular event, while `on_before_trading` is usually emitted on that first regular event after the session enters `Normal`.
192
+ * On the default path, `on_pre_open` runs before the first regular event, while `on_before_trading` is usually emitted on that first regular event after the regular trading session begins.
192
193
  * Even with `enable_precise_day_boundary_hooks`, the boundary-timer version of `on_before_trading` should not be used as a deterministic same-day predecessor for `on_pre_open`.
193
194
  * For a true two-stage pattern, prepare in a later callback from the previous trading day and execute in the next trading day's `on_pre_open`, for example via a previous-day `on_timer` or `on_after_trading`.
194
195
  * See `examples/53_timer_to_pre_open_demo.py`.
@@ -687,9 +687,10 @@ Strategy base class. Users should inherit from this class and override callback
687
687
  * `on_expiry(event: Dict[str, Any])`: Triggered after an `expiry_date` driven settlement/removal is actually executed. Portfolio state is already updated when the callback runs. See `examples/49_on_expiry_demo.py` for a runnable example.
688
688
  * `on_session_start(session, timestamp)`: Triggered on session transition start.
689
689
  * `on_session_end(session, timestamp)`: Triggered on session transition end.
690
- * `on_before_trading(trading_date, timestamp)`: Triggered once when entering Normal session each local day.
690
+ * `on_before_trading(trading_date, timestamp)`: Triggered once when the regular trading session starts each local day; on the default backtest path this session is usually exposed as `Continuous`. This callback follows a "previous trading day / previous snapshot only" visibility model.
691
691
  * `on_pre_open(event: Dict[str, Any])`: Triggered once before the first regular event of each trading day. Use it for "pre-open decision, current open fill" workflows; default order semantics resolve to `price_basis=open, bar_offset=1, temporal=same_cycle`. See `examples/52_pre_open_demo.py`.
692
- * `on_after_trading(trading_date, timestamp)`: Triggered when leaving Normal session, or replayed on next event after day rollover.
692
+ * `on_daily_rebalance(trading_date, timestamp)`: Daily rebalance hook, triggered at most once per trading day and in the same phase as `on_before_trading`. It also exposes only previous-trading-day / previous-snapshot information.
693
+ * `on_after_trading(trading_date, timestamp)`: Triggered when leaving the regular trading session, or replayed on next event after day rollover.
693
694
  * `on_portfolio_update(snapshot)`: Triggered when cash/equity/position snapshot changes.
694
695
  * `on_error(error, source, payload=None)`: Triggered when user callback raises, then exception is re-raised by default.
695
696
  * `on_timer(payload: str)`: Triggered by timer.
@@ -714,7 +715,7 @@ Note: if you do not pass an explicit `fill_policy` here, the framework defaults
714
715
  * `self.position`: Position object for current symbol, with `size` and `available` properties.
715
716
  * `self.now`: Current backtest time (`pd.Timestamp`).
716
717
  * `self.runtime_config`: Runtime behavior config object (`StrategyRuntimeConfig`).
717
- * `self.enable_precise_day_boundary_hooks`: Enable boundary timer based precise day hooks (default `False`).
718
+ * `self.enable_precise_day_boundary_hooks`: Enable boundary timer based precise day hooks (default `False`). This switch changes trigger precision only; it does not change the visibility window of `get_history()`, `get_account()`, or `get_portfolio_value()` inside `on_before_trading` / `on_daily_rebalance`.
718
719
  * `self.portfolio_update_eps`: Snapshot threshold; changes below it skip `on_portfolio_update` (default `0.0`).
719
720
  * `self.error_mode`: Error handling mode, `"raise"` or `"continue"` (default `"raise"`).
720
721
  * `self.re_raise_on_error`: Whether to re-raise user callback exception after `on_error` (default `True`).
@@ -0,0 +1,142 @@
1
+ (function () {
2
+ "use strict";
3
+
4
+ var ENGLISH_PREFIX = /^\/en(?:\/|$)/;
5
+ var RESULT_LIST_SELECTOR = ".md-search-result__list";
6
+ var RESULT_ITEM_SELECTOR = ".md-search-result__item";
7
+ var RESULT_LINK_SELECTOR = ".md-search-result__link";
8
+ var SEARCH_QUERY_SELECTOR = 'input[data-md-component="search-query"]';
9
+ var EMPTY_STATE_ATTR = "data-akquant-locale-empty";
10
+ var rafId = null;
11
+
12
+ function getCurrentLocale() {
13
+ return ENGLISH_PREFIX.test(window.location.pathname) ? "en" : "zh";
14
+ }
15
+
16
+ function getResultPath(href) {
17
+ try {
18
+ return new URL(href, window.location.origin).pathname;
19
+ } catch (error) {
20
+ return "";
21
+ }
22
+ }
23
+
24
+ function matchesCurrentLocale(pathname, locale) {
25
+ if (!pathname) {
26
+ return true;
27
+ }
28
+ return locale === "en"
29
+ ? ENGLISH_PREFIX.test(pathname)
30
+ : !ENGLISH_PREFIX.test(pathname);
31
+ }
32
+
33
+ function getQueryText() {
34
+ var input = document.querySelector(SEARCH_QUERY_SELECTOR);
35
+ return input ? input.value.trim() : "";
36
+ }
37
+
38
+ function getEmptyMessage(locale) {
39
+ return locale === "en"
40
+ ? "No results in the current language. Switch language to search the translated page."
41
+ : "当前语言暂无匹配结果,可切换语言后重试。";
42
+ }
43
+
44
+ function ensureEmptyState(list, locale, shouldShow) {
45
+ var existing = list.querySelector("[" + EMPTY_STATE_ATTR + "]");
46
+
47
+ if (!shouldShow) {
48
+ if (existing) {
49
+ existing.remove();
50
+ }
51
+ return;
52
+ }
53
+
54
+ if (existing) {
55
+ existing.querySelector("p").textContent = getEmptyMessage(locale);
56
+ return;
57
+ }
58
+
59
+ var item = document.createElement("li");
60
+ item.className = "md-search-result__item";
61
+ item.setAttribute(EMPTY_STATE_ATTR, "true");
62
+
63
+ var article = document.createElement("article");
64
+ article.className = "md-search-result__article md-typeset";
65
+
66
+ var paragraph = document.createElement("p");
67
+ paragraph.textContent = getEmptyMessage(locale);
68
+
69
+ article.appendChild(paragraph);
70
+ item.appendChild(article);
71
+ list.appendChild(item);
72
+ }
73
+
74
+ function filterList(list) {
75
+ var locale = getCurrentLocale();
76
+ var items = Array.prototype.filter.call(
77
+ list.querySelectorAll(RESULT_ITEM_SELECTOR),
78
+ function (item) {
79
+ return !item.hasAttribute(EMPTY_STATE_ATTR);
80
+ }
81
+ );
82
+
83
+ if (!items.length) {
84
+ ensureEmptyState(list, locale, false);
85
+ return;
86
+ }
87
+
88
+ var visibleCount = 0;
89
+
90
+ items.forEach(function (item) {
91
+ var links = item.querySelectorAll(RESULT_LINK_SELECTOR);
92
+ var keep = Array.prototype.some.call(links, function (link) {
93
+ var href = link.getAttribute("href") || "";
94
+ return matchesCurrentLocale(getResultPath(href), locale);
95
+ });
96
+
97
+ item.hidden = !keep;
98
+ if (keep) {
99
+ visibleCount += 1;
100
+ }
101
+ });
102
+
103
+ ensureEmptyState(
104
+ list,
105
+ locale,
106
+ visibleCount === 0 && items.length > 0 && getQueryText().length > 0
107
+ );
108
+ }
109
+
110
+ function filterAllSearchResults() {
111
+ document.querySelectorAll(RESULT_LIST_SELECTOR).forEach(filterList);
112
+ }
113
+
114
+ function scheduleFilter() {
115
+ if (rafId !== null) {
116
+ window.cancelAnimationFrame(rafId);
117
+ }
118
+ rafId = window.requestAnimationFrame(function () {
119
+ rafId = null;
120
+ filterAllSearchResults();
121
+ });
122
+ }
123
+
124
+ document.addEventListener("input", function (event) {
125
+ if (event.target && event.target.matches(SEARCH_QUERY_SELECTOR)) {
126
+ scheduleFilter();
127
+ }
128
+ });
129
+
130
+ window.addEventListener("hashchange", scheduleFilter);
131
+ window.addEventListener("pageshow", scheduleFilter);
132
+ document.addEventListener("DOMContentLoaded", scheduleFilter);
133
+
134
+ var observer = new MutationObserver(function () {
135
+ scheduleFilter();
136
+ });
137
+
138
+ observer.observe(document.body, {
139
+ childList: true,
140
+ subtree: true,
141
+ });
142
+ })();
@@ -80,14 +80,15 @@
80
80
 
81
81
  * `on_reject` 对同一订单 id 只触发一次。
82
82
  * 回测中已终态拒单会通过上下文快照 `recent_rejected_orders` 在下一次事件分发时补发,避免因清理活跃订单导致漏触发。
83
- * `on_before_trading` 在本地交易日首次进入 Normal 会话时触发一次。
83
+ * `on_before_trading` 在本地交易日首次进入常规交易会话时触发一次;默认回测路径下该会话通常表现为 `Continuous`。
84
84
  * `on_pre_open` 在每个交易日的首个常规行情事件前,由框架预注册 timer 先触发一次。
85
85
  * `on_daily_rebalance` 与 `on_before_trading` 同一阶段触发,每个交易日最多触发一次。
86
- * `on_after_trading` 在离开 Normal 会话时触发;若先跨日再收到事件,会在下一事件补发上一交易日的 `on_after_trading`。
86
+ * `on_before_trading` / `on_daily_rebalance` 始终按“前一交易日/前一时点信息可见”的语义工作;在这些回调里,`get_history()`、`get_account()`、`get_portfolio_value()` 不应看到当日新 bar 或当日更新后的账户视图。
87
+ * `on_after_trading` 在离开常规交易会话时触发;若先跨日再收到事件,会在下一事件补发上一交易日的 `on_after_trading`。
87
88
  * `on_pre_open` 内若直接调用 `buy/sell/order_target_*` 且未显式传 `fill_policy`,框架会自动解析为 `price_basis=open, bar_offset=1, temporal=same_cycle`。
88
89
  * 这里表达的是框架侧“盘前决策,本次 open 成交”的时序语义,不等同于交易所或券商柜台已经实现了集合竞价专用报单、撤单窗口控制或专有价格类型。
89
90
  * 新股/新债打新不属于 `on_pre_open` 或当前统一 `submit_order(...)` 的默认承诺范围;若要支持,通常需要补齐 broker 专有字段与业务路由。
90
- * 若需要更精确的交易日边界触发,可在策略中设置 `self.enable_precise_day_boundary_hooks = True`。
91
+ * 若需要更精确的交易日边界触发,可在策略中设置 `self.enable_precise_day_boundary_hooks = True`;该开关只影响 `on_before_trading` / `on_daily_rebalance` / `on_after_trading` 的触发精度,不改变这些日边界回调中的历史数据与账户快照可见窗口。
91
92
  * `on_portfolio_update` 采用增量触发:初始化时触发一次,后续仅在订单/成交或持仓相关价格变化时触发。
92
93
  * 可通过 `self.portfolio_update_eps` 过滤微小资产波动(默认 `0.0`,即不过滤)。
93
94
  * 停止阶段会在 `on_stop` 之前补发待触发的 `on_session_end` / `on_after_trading`。
@@ -711,10 +711,10 @@ result = run_backtest(
711
711
  * `on_expiry(event: Dict[str, Any])`: 到期结算回调。仅当引擎实际执行 `expiry_date` 驱动的到期结算/移除后触发;回调时账户状态已更新。示例见:`examples/49_on_expiry_demo.py`。
712
712
  * `on_session_start(session, timestamp)`: 会话切换开始时触发。
713
713
  * `on_session_end(session, timestamp)`: 会话切换结束时触发。
714
- * `on_before_trading(trading_date, timestamp)`: 每个本地交易日首次进入 Normal 会话时触发一次。
714
+ * `on_before_trading(trading_date, timestamp)`: 每个本地交易日首次进入常规交易会话时触发一次;默认回测路径下该会话通常表现为 `Continuous`。该回调按“前一交易日/前一时点信息可见”的语义工作。
715
715
  * `on_pre_open(event: Dict[str, Any])`: 每个交易日首个常规行情事件前触发一次。适合“盘前决策,本次 open 成交”;默认下单语义会自动解析为 `price_basis=open, bar_offset=1, temporal=same_cycle`。示例见:`examples/52_pre_open_demo.py`。
716
- * `on_daily_rebalance(trading_date, timestamp)`: 交易日调仓钩子,每个交易日最多触发一次。
717
- * `on_after_trading(trading_date, timestamp)`: 离开 Normal 会话时触发;若先跨日则在下一事件补发。
716
+ * `on_daily_rebalance(trading_date, timestamp)`: 交易日调仓钩子,每个交易日最多触发一次,与 `on_before_trading` 同阶段;该回调同样只暴露前一交易日/前一时点信息。
717
+ * `on_after_trading(trading_date, timestamp)`: 离开常规交易会话时触发;若先跨日则在下一事件补发。
718
718
  * `on_portfolio_update(snapshot)`: 账户快照变化时触发。
719
719
  * `on_error(error, source, payload=None)`: 用户回调抛异常时触发,默认触发后继续抛出。
720
720
  * `on_timer(payload: str)`: 定时器触发。
@@ -739,7 +739,7 @@ def on_pre_open(self, event: Dict[str, Any]) -> None:
739
739
  * `self.position`: 当前标的持仓辅助对象 (`Position`),包含 `size` 和 `available` 属性。
740
740
  * `self.now`: 当前回测时间 (`pd.Timestamp`)。
741
741
  * `self.runtime_config`: 运行时行为配置对象 (`StrategyRuntimeConfig`)。
742
- * `self.enable_precise_day_boundary_hooks`: 是否启用边界定时器精确交易日钩子(默认 `False`)。
742
+ * `self.enable_precise_day_boundary_hooks`: 是否启用边界定时器精确交易日钩子(默认 `False`)。该开关只影响日边界 hooks 的触发精度,不改变 `on_before_trading` / `on_daily_rebalance` 中 `get_history()`、`get_account()`、`get_portfolio_value()` 等接口的可见数据窗口。
743
743
  * `self.portfolio_update_eps`: 账户快照更新阈值,低于该变化量不触发 `on_portfolio_update`(默认 `0.0`)。
744
744
  * `self.error_mode`: 错误处理模式,`"raise"` 或 `"continue"`(默认 `"raise"`)。
745
745
  * `self.re_raise_on_error`: 用户回调异常后是否继续抛出(默认 `True`)。
@@ -49,10 +49,6 @@ markdown_extensions:
49
49
  - pymdownx.snippets
50
50
  - pymdownx.superfences
51
51
 
52
- extra_javascript:
53
- - javascripts/mathjax.js
54
- - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
55
-
56
52
  plugins:
57
53
  - search
58
54
  - i18n:
@@ -304,6 +300,7 @@ extra:
304
300
 
305
301
  extra_javascript:
306
302
  - javascripts/mathjax.js
303
+ - javascripts/search-lang-filter.js
307
304
  - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
308
305
 
309
306
  copyright: Copyright © 2026 AKQuant Contributors
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "akquant"
7
- version = "0.2.30"
7
+ version = "0.2.32"
8
8
  description = "High-performance quantitative trading framework based on Rust and Python"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT License"}
@@ -338,6 +338,11 @@ class Strategy:
338
338
  _framework_boundary_timers_registered: bool
339
339
  _framework_pre_open_timers_registered: bool
340
340
  _framework_in_pre_open_phase: bool
341
+ _framework_phase: Optional[str]
342
+ _framework_history_cutoff_ns: Optional[int]
343
+ _framework_use_previous_account_snapshot: bool
344
+ _framework_previous_account_details: Optional[Dict[str, float]]
345
+ _framework_emit_previous_portfolio_snapshot: bool
341
346
  _trading_day_bounds: Dict[str, Tuple[int, int]]
342
347
  _oco_groups: Dict[str, set[str]]
343
348
  _oco_order_to_group: Dict[str, str]
@@ -468,6 +473,11 @@ class Strategy:
468
473
  instance._framework_boundary_timers_registered = False
469
474
  instance._framework_pre_open_timers_registered = False
470
475
  instance._framework_in_pre_open_phase = False
476
+ instance._framework_phase = None
477
+ instance._framework_history_cutoff_ns = None
478
+ instance._framework_use_previous_account_snapshot = False
479
+ instance._framework_previous_account_details = None
480
+ instance._framework_emit_previous_portfolio_snapshot = False
471
481
  instance._trading_day_bounds = {}
472
482
  instance._oco_groups = {}
473
483
  instance._oco_order_to_group = {}
@@ -66,12 +66,8 @@ def on_bar_event(strategy: Any, bar: Bar, ctx: StrategyContext) -> None:
66
66
  strategy._auto_configure_model()
67
67
 
68
68
  previous_price = strategy._last_prices.get(bar.symbol)
69
- strategy.current_bar = bar
69
+ strategy.current_bar = None
70
70
  strategy.current_tick = None
71
- if hasattr(strategy, "_update_incremental_indicators"):
72
- strategy._update_incremental_indicators(bar)
73
- strategy._last_prices[bar.symbol] = bar.close
74
- strategy._bar_count += 1
75
71
 
76
72
  if _is_before_active_start(strategy, int(bar.timestamp)):
77
73
  return
@@ -79,6 +75,11 @@ def on_bar_event(strategy: Any, bar: Bar, ctx: StrategyContext) -> None:
79
75
  if current_pos != 0 and previous_price is not None and previous_price != bar.close:
80
76
  mark_portfolio_dirty(strategy)
81
77
  dispatch_time_hooks(strategy)
78
+ strategy.current_bar = bar
79
+ if hasattr(strategy, "_update_incremental_indicators"):
80
+ strategy._update_incremental_indicators(bar)
81
+ strategy._last_prices[bar.symbol] = bar.close
82
+ strategy._bar_count += 1
82
83
  dispatch_portfolio_update(strategy)
83
84
 
84
85
  if strategy._bar_count < strategy.warmup_period:
@@ -125,9 +126,8 @@ def on_tick_event(strategy: Any, tick: Tick, ctx: StrategyContext) -> None:
125
126
  strategy._check_order_events()
126
127
  check_expiry_events(strategy)
127
128
  previous_price = strategy._last_prices.get(tick.symbol)
128
- strategy.current_tick = tick
129
129
  strategy.current_bar = None
130
- strategy._last_prices[tick.symbol] = tick.price
130
+ strategy.current_tick = None
131
131
 
132
132
  if _is_before_active_start(strategy, int(tick.timestamp)):
133
133
  return
@@ -136,6 +136,8 @@ def on_tick_event(strategy: Any, tick: Tick, ctx: StrategyContext) -> None:
136
136
  if current_pos != 0 and previous_price is not None and previous_price != tick.price:
137
137
  mark_portfolio_dirty(strategy)
138
138
  dispatch_time_hooks(strategy)
139
+ strategy.current_tick = tick
140
+ strategy._last_prices[tick.symbol] = tick.price
139
141
  dispatch_portfolio_update(strategy)
140
142
  call_user_callback(strategy, "on_tick", tick, payload=tick)
141
143
 
@@ -44,10 +44,18 @@ def _use_precise_day_boundary_hooks(strategy: Any) -> bool:
44
44
 
45
45
  def _is_normal_session(session: Any) -> bool:
46
46
  normal = getattr(TradingSession, "Normal", None)
47
- if normal is not None:
48
- return bool(session == normal)
47
+ continuous = getattr(TradingSession, "Continuous", None)
49
48
  text = str(session).lower()
50
- return text == "normal" or text.endswith(".normal")
49
+ if (
50
+ text == "normal"
51
+ or text.endswith(".normal")
52
+ or text == "continuous"
53
+ or text.endswith(".continuous")
54
+ ):
55
+ return True
56
+ if normal is not None or continuous is not None:
57
+ return bool(session == normal or session == continuous)
58
+ return False
51
59
 
52
60
 
53
61
  def _is_pre_open_session(session: Any) -> bool:
@@ -138,27 +146,81 @@ def _should_reraise_on_error(strategy: Any) -> bool:
138
146
  return bool(_runtime_option(strategy, "re_raise_on_error"))
139
147
 
140
148
 
149
+ def _snapshot_previous_account_details(strategy: Any) -> Optional[Dict[str, float]]:
150
+ """Capture previous-snapshot derived account fields for framework phases."""
151
+ if strategy.ctx is None:
152
+ return None
153
+ from .strategy_trading_api import _calc_frozen_cash, _resolve_mark_price
154
+
155
+ short_market_value = 0.0
156
+ for sym, qty in strategy.ctx.positions.items():
157
+ qty_f = float(qty)
158
+ if qty_f >= 0.0:
159
+ continue
160
+ short_market_value += abs(qty_f) * _resolve_mark_price(strategy, str(sym))
161
+ return {
162
+ "frozen_cash": float(_calc_frozen_cash(strategy)),
163
+ "short_market_value": float(short_market_value),
164
+ "margin_accrued_interest": float(
165
+ getattr(strategy.ctx, "margin_accrued_interest", 0.0)
166
+ ),
167
+ "margin_daily_interest": float(
168
+ getattr(strategy.ctx, "margin_daily_interest", 0.0)
169
+ ),
170
+ }
171
+
172
+
173
+ def _run_in_framework_phase(
174
+ strategy: Any,
175
+ phase: str,
176
+ timestamp: int,
177
+ callback_name: str,
178
+ *args: Any,
179
+ payload: Optional[Any] = None,
180
+ ) -> Any:
181
+ """Run a callback with a framework phase and history visibility cutoff."""
182
+ previous_phase = getattr(strategy, "_framework_phase", None)
183
+ previous_cutoff = getattr(strategy, "_framework_history_cutoff_ns", None)
184
+ previous_pre_open = bool(getattr(strategy, "_framework_in_pre_open_phase", False))
185
+ previous_bar = getattr(strategy, "current_bar", None)
186
+ previous_tick = getattr(strategy, "current_tick", None)
187
+ previous_account_snapshot = bool(
188
+ getattr(strategy, "_framework_use_previous_account_snapshot", False)
189
+ )
190
+ previous_account_details = getattr(
191
+ strategy, "_framework_previous_account_details", None
192
+ )
193
+ strategy._framework_phase = phase
194
+ strategy._framework_history_cutoff_ns = int(timestamp)
195
+ strategy._framework_previous_account_details = _snapshot_previous_account_details(
196
+ strategy
197
+ )
198
+ strategy._framework_use_previous_account_snapshot = True
199
+ strategy.current_bar = None
200
+ strategy.current_tick = None
201
+ if phase == "pre_open":
202
+ strategy._framework_in_pre_open_phase = True
203
+ try:
204
+ return call_user_callback(strategy, callback_name, *args, payload=payload)
205
+ finally:
206
+ strategy._framework_phase = previous_phase
207
+ strategy._framework_history_cutoff_ns = previous_cutoff
208
+ strategy._framework_in_pre_open_phase = previous_pre_open
209
+ strategy._framework_use_previous_account_snapshot = previous_account_snapshot
210
+ strategy._framework_previous_account_details = previous_account_details
211
+ strategy.current_bar = previous_bar
212
+ strategy.current_tick = previous_tick
213
+
214
+
141
215
  def _dispatch_daily_rebalance_if_needed(
142
216
  strategy: Any, trading_date: Any, timestamp: int
143
217
  ) -> None:
144
218
  if getattr(strategy, "_framework_daily_rebalance_done_date", None) == trading_date:
145
219
  return
146
- event_type = getattr(strategy, "_last_event_type", None)
147
- if event_type == "bar" and strategy.ctx is not None:
148
- pending_date = getattr(
149
- strategy,
150
- "_framework_daily_rebalance_pending_date",
151
- None,
152
- )
153
- if pending_date == trading_date:
154
- return
155
- schedule_ts = int(timestamp) + 1
156
- payload = f"__framework_rebalance__|{trading_date}|{int(timestamp)}"
157
- strategy.ctx.schedule(schedule_ts, payload)
158
- strategy._framework_daily_rebalance_pending_date = trading_date
159
- return
160
- call_user_callback(
220
+ _run_in_framework_phase(
161
221
  strategy,
222
+ "daily_rebalance",
223
+ timestamp,
162
224
  "on_daily_rebalance",
163
225
  trading_date,
164
226
  timestamp,
@@ -201,12 +263,6 @@ def dispatch_time_hooks(strategy: Any) -> None:
201
263
  current_date = ts.date()
202
264
  current_session = getattr(strategy.ctx, "session", None)
203
265
  use_precise_boundaries = _use_precise_day_boundary_hooks(strategy)
204
- if (
205
- not use_precise_boundaries
206
- and getattr(strategy, "_framework_daily_rebalance_done_date", None)
207
- != current_date
208
- ):
209
- _dispatch_daily_rebalance_if_needed(strategy, current_date, current_time)
210
266
 
211
267
  last_date = getattr(strategy, "_framework_last_local_date", None)
212
268
  before_done_date = getattr(strategy, "_framework_before_trading_done_date", None)
@@ -253,14 +309,23 @@ def dispatch_time_hooks(strategy: Any) -> None:
253
309
  and getattr(strategy, "_framework_before_trading_done_date", None)
254
310
  != current_date
255
311
  ):
256
- call_user_callback(
312
+ _run_in_framework_phase(
257
313
  strategy,
314
+ "before_trading",
315
+ current_time,
258
316
  "on_before_trading",
259
317
  current_date,
260
318
  current_time,
261
319
  payload={"trading_date": current_date, "timestamp": current_time},
262
320
  )
263
321
  strategy._framework_before_trading_done_date = current_date
322
+ if (
323
+ not use_precise_boundaries
324
+ and _is_normal_session(current_session)
325
+ and getattr(strategy, "_framework_daily_rebalance_done_date", None)
326
+ != current_date
327
+ ):
328
+ _dispatch_daily_rebalance_if_needed(strategy, current_date, current_time)
264
329
 
265
330
  if (
266
331
  not use_precise_boundaries
@@ -343,8 +408,10 @@ def dispatch_boundary_timer(strategy: Any, payload: str) -> bool:
343
408
  current_time = int(getattr(strategy.ctx, "current_time", 0))
344
409
  if phase == "before":
345
410
  if getattr(strategy, "_framework_before_trading_done_date", None) != day:
346
- call_user_callback(
411
+ _run_in_framework_phase(
347
412
  strategy,
413
+ "before_trading",
414
+ current_time,
348
415
  "on_before_trading",
349
416
  day,
350
417
  current_time,
@@ -352,8 +419,10 @@ def dispatch_boundary_timer(strategy: Any, payload: str) -> bool:
352
419
  )
353
420
  strategy._framework_before_trading_done_date = day
354
421
  if getattr(strategy, "_framework_daily_rebalance_done_date", None) != day:
355
- call_user_callback(
422
+ _run_in_framework_phase(
356
423
  strategy,
424
+ "daily_rebalance",
425
+ current_time,
357
426
  "on_daily_rebalance",
358
427
  day,
359
428
  current_time,
@@ -403,11 +472,14 @@ def dispatch_pre_open_timer(strategy: Any, payload: str) -> bool:
403
472
  return True
404
473
 
405
474
  event = _build_pre_open_event(strategy, trading_date, source_timestamp)
406
- strategy._framework_in_pre_open_phase = True
407
- try:
408
- call_user_callback(strategy, "on_pre_open", event, payload=event)
409
- finally:
410
- strategy._framework_in_pre_open_phase = False
475
+ _run_in_framework_phase(
476
+ strategy,
477
+ "pre_open",
478
+ source_timestamp,
479
+ "on_pre_open",
480
+ event,
481
+ payload=event,
482
+ )
411
483
  strategy._framework_pre_open_done_date = trading_date
412
484
  return True
413
485
 
@@ -434,8 +506,10 @@ def dispatch_daily_rebalance_timer(strategy: Any, payload: str) -> bool:
434
506
 
435
507
  done_date = getattr(strategy, "_framework_daily_rebalance_done_date", None)
436
508
  if done_date != trading_date:
437
- call_user_callback(
509
+ _run_in_framework_phase(
438
510
  strategy,
511
+ "daily_rebalance",
512
+ source_timestamp,
439
513
  "on_daily_rebalance",
440
514
  trading_date,
441
515
  source_timestamp,
@@ -468,8 +542,21 @@ def dispatch_portfolio_update(strategy: Any) -> None:
468
542
  available_positions = {
469
543
  k: float(v) for k, v in dict(strategy.ctx.available_positions).items()
470
544
  }
471
- equity = float(strategy.get_portfolio_value())
472
- market_value = float(equity - cash)
545
+ use_previous_snapshot = bool(
546
+ getattr(strategy, "_framework_emit_previous_portfolio_snapshot", False)
547
+ )
548
+ previous_override = bool(
549
+ getattr(strategy, "_framework_use_previous_account_snapshot", False)
550
+ )
551
+ strategy._framework_use_previous_account_snapshot = use_previous_snapshot
552
+ try:
553
+ equity = float(strategy.get_portfolio_value())
554
+ market_value = float(equity - cash)
555
+ account_snapshot = strategy.get_account()
556
+ finally:
557
+ strategy._framework_use_previous_account_snapshot = previous_override
558
+ if use_previous_snapshot:
559
+ strategy._framework_emit_previous_portfolio_snapshot = False
473
560
 
474
561
  state_key: Tuple[Any, ...] = (
475
562
  round(cash, 8),
@@ -497,7 +584,6 @@ def dispatch_portfolio_update(strategy: Any) -> None:
497
584
  return
498
585
 
499
586
  strategy._framework_last_portfolio_state = state_key
500
- account_snapshot = strategy.get_account()
501
587
  snapshot: Dict[str, Any] = {
502
588
  "timestamp": current_time,
503
589
  "session": session,
@@ -509,8 +595,15 @@ def dispatch_portfolio_update(strategy: Any) -> None:
509
595
  "margin": float(account_snapshot.get("margin", 0.0)),
510
596
  "frozen_cash": float(account_snapshot.get("frozen_cash", 0.0)),
511
597
  }
512
- call_user_callback(strategy, "on_portfolio_update", snapshot, payload=snapshot)
513
- strategy._framework_portfolio_dirty = False
598
+ callback_override = bool(
599
+ getattr(strategy, "_framework_use_previous_account_snapshot", False)
600
+ )
601
+ strategy._framework_use_previous_account_snapshot = use_previous_snapshot
602
+ try:
603
+ call_user_callback(strategy, "on_portfolio_update", snapshot, payload=snapshot)
604
+ strategy._framework_portfolio_dirty = False
605
+ finally:
606
+ strategy._framework_use_previous_account_snapshot = callback_override
514
607
 
515
608
 
516
609
  def dispatch_shutdown_hooks(strategy: Any) -> None:
@@ -567,6 +660,16 @@ def ensure_framework_state(strategy: Any) -> None:
567
660
  strategy._framework_pre_open_timers_registered = False
568
661
  if not hasattr(strategy, "_framework_in_pre_open_phase"):
569
662
  strategy._framework_in_pre_open_phase = False
663
+ if not hasattr(strategy, "_framework_phase"):
664
+ strategy._framework_phase = None
665
+ if not hasattr(strategy, "_framework_history_cutoff_ns"):
666
+ strategy._framework_history_cutoff_ns = None
667
+ if not hasattr(strategy, "_framework_use_previous_account_snapshot"):
668
+ strategy._framework_use_previous_account_snapshot = False
669
+ if not hasattr(strategy, "_framework_previous_account_details"):
670
+ strategy._framework_previous_account_details = None
671
+ if not hasattr(strategy, "_framework_emit_previous_portfolio_snapshot"):
672
+ strategy._framework_emit_previous_portfolio_snapshot = False
570
673
  if not hasattr(strategy, "_framework_last_portfolio_state"):
571
674
  strategy._framework_last_portfolio_state = None
572
675
  if not hasattr(strategy, "_framework_portfolio_dirty"):