akquant 0.3.1__tar.gz → 0.3.2__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 (583) hide show
  1. {akquant-0.3.1 → akquant-0.3.2}/CHANGELOG.md +1 -0
  2. {akquant-0.3.1 → akquant-0.3.2}/Cargo.lock +1 -1
  3. {akquant-0.3.1 → akquant-0.3.2}/Cargo.toml +1 -1
  4. {akquant-0.3.1 → akquant-0.3.2}/PKG-INFO +1 -1
  5. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/guide/strategy.md +36 -0
  6. {akquant-0.3.1 → akquant-0.3.2}/examples/36_trailing_orders.py +6 -2
  7. {akquant-0.3.1 → akquant-0.3.2}/pyproject.toml +1 -1
  8. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/__init__.py +5 -0
  9. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/akquant.pyi +1 -1
  10. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/execution/sim.py +3 -2
  11. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/broker_event_adapter.py +8 -2
  12. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/broker_execution.py +27 -8
  13. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/broker_models.py +3 -0
  14. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/broker_runtime.py +6 -0
  15. akquant-0.3.2/python/akquant/gateway/order_receipt.py +60 -0
  16. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/order_submitter.py +127 -23
  17. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/live.py +43 -0
  18. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/strategy.py +51 -18
  19. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/strategy_trading_api.py +58 -27
  20. {akquant-0.3.1 → akquant-0.3.2}/tests/gateway_contract/test_submitter_contract.py +2 -2
  21. {akquant-0.3.1 → akquant-0.3.2}/tests/test_broker_event_adapter.py +45 -0
  22. {akquant-0.3.1 → akquant-0.3.2}/tests/test_broker_execution_local_stops.py +10 -5
  23. {akquant-0.3.1 → akquant-0.3.2}/tests/test_broker_execution_read_path_parity.py +2 -2
  24. {akquant-0.3.1 → akquant-0.3.2}/tests/test_broker_execution_stop_requeue.py +6 -3
  25. {akquant-0.3.1 → akquant-0.3.2}/tests/test_execution_broker.py +64 -3
  26. {akquant-0.3.1 → akquant-0.3.2}/tests/test_gateway_broker_live_cancel.py +69 -0
  27. {akquant-0.3.1 → akquant-0.3.2}/tests/test_gateway_broker_models_ext.py +40 -0
  28. {akquant-0.3.1 → akquant-0.3.2}/tests/test_gateway_broker_submitter_readiness.py +1 -1
  29. {akquant-0.3.1 → akquant-0.3.2}/tests/test_gateway_broker_submitter_signature.py +21 -5
  30. akquant-0.3.2/tests/test_gateway_order_submitter_extra.py +216 -0
  31. akquant-0.3.2/tests/test_gateway_tif_mapping.py +25 -0
  32. {akquant-0.3.1 → akquant-0.3.2}/tests/test_live_runner_broker_bridge.py +138 -8
  33. {akquant-0.3.1 → akquant-0.3.2}/tests/test_live_runner_broker_submitter.py +7 -7
  34. {akquant-0.3.1 → akquant-0.3.2}/tests/test_live_runner_order_request_cache.py +1 -0
  35. {akquant-0.3.1 → akquant-0.3.2}/tests/test_live_runner_stop_remap.py +1 -0
  36. {akquant-0.3.1 → akquant-0.3.2}/tests/test_local_stop_scenario.py +11 -3
  37. {akquant-0.3.1 → akquant-0.3.2}/tests/test_oco_bracket_broker_live_scenario.py +11 -3
  38. akquant-0.3.2/tests/test_order_receipt.py +66 -0
  39. akquant-0.3.2/tests/test_order_receipt_backtest.py +39 -0
  40. {akquant-0.3.1 → akquant-0.3.2}/tests/test_stop_id_remap_scenario.py +10 -6
  41. {akquant-0.3.1 → akquant-0.3.2}/tests/test_strategy_extras.py +25 -17
  42. akquant-0.3.1/tests/test_gateway_order_submitter_extra.py +0 -69
  43. {akquant-0.3.1 → akquant-0.3.2}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  44. {akquant-0.3.1 → akquant-0.3.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  45. {akquant-0.3.1 → akquant-0.3.2}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  46. {akquant-0.3.1 → akquant-0.3.2}/.github/workflows/deploy-docs.yml +0 -0
  47. {akquant-0.3.1 → akquant-0.3.2}/.github/workflows/docs-quality.yml +0 -0
  48. {akquant-0.3.1 → akquant-0.3.2}/.github/workflows/release.yml +0 -0
  49. {akquant-0.3.1 → akquant-0.3.2}/.gitignore +0 -0
  50. {akquant-0.3.1 → akquant-0.3.2}/.pre-commit-config.yaml +0 -0
  51. {akquant-0.3.1 → akquant-0.3.2}/CODE_OF_CONDUCT.md +0 -0
  52. {akquant-0.3.1 → akquant-0.3.2}/CONTRIBUTING.md +0 -0
  53. {akquant-0.3.1 → akquant-0.3.2}/LICENSE +0 -0
  54. {akquant-0.3.1 → akquant-0.3.2}/README.md +0 -0
  55. {akquant-0.3.1 → akquant-0.3.2}/assets/dashboard_preview.png +0 -0
  56. {akquant-0.3.1 → akquant-0.3.2}/assets/logo.svg +0 -0
  57. {akquant-0.3.1 → akquant-0.3.2}/assets/social_preview.png +0 -0
  58. {akquant-0.3.1 → akquant-0.3.2}/docs/CNAME +0 -0
  59. {akquant-0.3.1 → akquant-0.3.2}/docs/assets/akquant-icon.svg +0 -0
  60. {akquant-0.3.1 → akquant-0.3.2}/docs/assets/akquant-logo.svg +0 -0
  61. {akquant-0.3.1 → akquant-0.3.2}/docs/assets/reports/akquant_report.html +0 -0
  62. {akquant-0.3.1 → akquant-0.3.2}/docs/en/advanced/analyzer_plugin_spec.md +0 -0
  63. {akquant-0.3.1 → akquant-0.3.2}/docs/en/advanced/broker_capability_matrix.md +0 -0
  64. {akquant-0.3.1 → akquant-0.3.2}/docs/en/advanced/custom_broker_production_checklist.md +0 -0
  65. {akquant-0.3.1 → akquant-0.3.2}/docs/en/advanced/custom_broker_registry.md +0 -0
  66. {akquant-0.3.1 → akquant-0.3.2}/docs/en/advanced/data_feed_adapter_spec.md +0 -0
  67. {akquant-0.3.1 → akquant-0.3.2}/docs/en/advanced/live_functional_quickstart.md +0 -0
  68. {akquant-0.3.1 → akquant-0.3.2}/docs/en/advanced/llm.md +0 -0
  69. {akquant-0.3.1 → akquant-0.3.2}/docs/en/advanced/ml.md +0 -0
  70. {akquant-0.3.1 → akquant-0.3.2}/docs/en/advanced/multi_strategy_guide.md +0 -0
  71. {akquant-0.3.1 → akquant-0.3.2}/docs/en/advanced/multi_timeframe_feed_api.md +0 -0
  72. {akquant-0.3.1 → akquant-0.3.2}/docs/en/advanced/runtime_config.md +0 -0
  73. {akquant-0.3.1 → akquant-0.3.2}/docs/en/advanced/strategy_style_decision.md +0 -0
  74. {akquant-0.3.1 → akquant-0.3.2}/docs/en/advanced/timezone.md +0 -0
  75. {akquant-0.3.1 → akquant-0.3.2}/docs/en/advanced/warm_start.md +0 -0
  76. {akquant-0.3.1 → akquant-0.3.2}/docs/en/guide/analysis.md +0 -0
  77. {akquant-0.3.1 → akquant-0.3.2}/docs/en/guide/cross_section_checklist.md +0 -0
  78. {akquant-0.3.1 → akquant-0.3.2}/docs/en/guide/custom_indicator.md +0 -0
  79. {akquant-0.3.1 → akquant-0.3.2}/docs/en/guide/data.md +0 -0
  80. {akquant-0.3.1 → akquant-0.3.2}/docs/en/guide/examples.md +0 -0
  81. {akquant-0.3.1 → akquant-0.3.2}/docs/en/guide/factor.md +0 -0
  82. {akquant-0.3.1 → akquant-0.3.2}/docs/en/guide/indicator_scenario_quickref.md +0 -0
  83. {akquant-0.3.1 → akquant-0.3.2}/docs/en/guide/optimization.md +0 -0
  84. {akquant-0.3.1 → akquant-0.3.2}/docs/en/guide/python_basics.md +0 -0
  85. {akquant-0.3.1 → akquant-0.3.2}/docs/en/guide/quant_basics.md +0 -0
  86. {akquant-0.3.1 → akquant-0.3.2}/docs/en/guide/rust_indicator_reference.md +0 -0
  87. {akquant-0.3.1 → akquant-0.3.2}/docs/en/guide/strategy.md +0 -0
  88. {akquant-0.3.1 → akquant-0.3.2}/docs/en/guide/talib_indicator_playbook.md +0 -0
  89. {akquant-0.3.1 → akquant-0.3.2}/docs/en/guide/testing.md +0 -0
  90. {akquant-0.3.1 → akquant-0.3.2}/docs/en/guide/visualization.md +0 -0
  91. {akquant-0.3.1 → akquant-0.3.2}/docs/en/index.md +0 -0
  92. {akquant-0.3.1 → akquant-0.3.2}/docs/en/meta/architecture.md +0 -0
  93. {akquant-0.3.1 → akquant-0.3.2}/docs/en/meta/internals.md +0 -0
  94. {akquant-0.3.1 → akquant-0.3.2}/docs/en/reference/api.md +0 -0
  95. {akquant-0.3.1 → akquant-0.3.2}/docs/en/start/first_strategy.md +0 -0
  96. {akquant-0.3.1 → akquant-0.3.2}/docs/en/start/installation.md +0 -0
  97. {akquant-0.3.1 → akquant-0.3.2}/docs/en/start/quickstart.md +0 -0
  98. {akquant-0.3.1 → akquant-0.3.2}/docs/en/start/setup_guide.md +0 -0
  99. {akquant-0.3.1 → akquant-0.3.2}/docs/en/textbook/01_foundations.md +0 -0
  100. {akquant-0.3.1 → akquant-0.3.2}/docs/en/textbook/02_programming.md +0 -0
  101. {akquant-0.3.1 → akquant-0.3.2}/docs/en/textbook/03_data.md +0 -0
  102. {akquant-0.3.1 → akquant-0.3.2}/docs/en/textbook/04_backtest_engine.md +0 -0
  103. {akquant-0.3.1 → akquant-0.3.2}/docs/en/textbook/05_strategy.md +0 -0
  104. {akquant-0.3.1 → akquant-0.3.2}/docs/en/textbook/06_stock_a.md +0 -0
  105. {akquant-0.3.1 → akquant-0.3.2}/docs/en/textbook/07_futures.md +0 -0
  106. {akquant-0.3.1 → akquant-0.3.2}/docs/en/textbook/08_options.md +0 -0
  107. {akquant-0.3.1 → akquant-0.3.2}/docs/en/textbook/09_funds.md +0 -0
  108. {akquant-0.3.1 → akquant-0.3.2}/docs/en/textbook/10_analysis.md +0 -0
  109. {akquant-0.3.1 → akquant-0.3.2}/docs/en/textbook/11_optimization.md +0 -0
  110. {akquant-0.3.1 → akquant-0.3.2}/docs/en/textbook/12_ml.md +0 -0
  111. {akquant-0.3.1 → akquant-0.3.2}/docs/en/textbook/13_visualization.md +0 -0
  112. {akquant-0.3.1 → akquant-0.3.2}/docs/en/textbook/14_factor.md +0 -0
  113. {akquant-0.3.1 → akquant-0.3.2}/docs/en/textbook/15_live_trading.md +0 -0
  114. {akquant-0.3.1 → akquant-0.3.2}/docs/en/textbook/16_rust_indicators.md +0 -0
  115. {akquant-0.3.1 → akquant-0.3.2}/docs/en/textbook/index.md +0 -0
  116. {akquant-0.3.1 → akquant-0.3.2}/docs/javascripts/mathjax.js +0 -0
  117. {akquant-0.3.1 → akquant-0.3.2}/docs/javascripts/search-lang-filter.js +0 -0
  118. {akquant-0.3.1 → akquant-0.3.2}/docs/robots.txt +0 -0
  119. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/advanced/adding_a_broker.md +0 -0
  120. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/advanced/analyzer_plugin_spec.md +0 -0
  121. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/advanced/broker_capability_matrix.md +0 -0
  122. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/advanced/custom_broker_production_checklist.md +0 -0
  123. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/advanced/custom_broker_registry.md +0 -0
  124. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/advanced/data_feed_adapter_spec.md +0 -0
  125. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/advanced/live_functional_quickstart.md +0 -0
  126. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/advanced/llm.md +0 -0
  127. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/advanced/ml.md +0 -0
  128. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/advanced/multi_strategy_guide.md +0 -0
  129. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/advanced/multi_timeframe_feed_api.md +0 -0
  130. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/advanced/runtime_config.md +0 -0
  131. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/advanced/strategy_style_decision.md +0 -0
  132. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/advanced/timezone.md +0 -0
  133. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/advanced/warm_start.md +0 -0
  134. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/guide/analysis.md +0 -0
  135. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/guide/cross_section_checklist.md +0 -0
  136. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/guide/custom_indicator.md +0 -0
  137. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/guide/data.md +0 -0
  138. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/guide/examples.md +0 -0
  139. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/guide/factor.md +0 -0
  140. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/guide/indicator_scenario_quickref.md +0 -0
  141. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/guide/optimization.md +0 -0
  142. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/guide/python_basics.md +0 -0
  143. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/guide/quant_basics.md +0 -0
  144. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/guide/rust_indicator_reference.md +0 -0
  145. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/guide/talib_indicator_playbook.md +0 -0
  146. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/guide/testing.md +0 -0
  147. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/guide/visualization.md +0 -0
  148. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/index.md +0 -0
  149. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/meta/architecture.md +0 -0
  150. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/meta/internals.md +0 -0
  151. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/reference/api.md +0 -0
  152. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/start/first_strategy.md +0 -0
  153. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/start/installation.md +0 -0
  154. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/start/quickstart.md +0 -0
  155. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/start/setup_guide.md +0 -0
  156. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/00_glossary.md +0 -0
  157. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/01_foundations.md +0 -0
  158. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/02_programming.md +0 -0
  159. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/03_data.md +0 -0
  160. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/04_backtest_engine.md +0 -0
  161. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/05_strategy.md +0 -0
  162. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/06_stock_a.md +0 -0
  163. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/07_futures.md +0 -0
  164. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/08_options.md +0 -0
  165. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/09_funds.md +0 -0
  166. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/10_analysis.md +0 -0
  167. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/11_optimization.md +0 -0
  168. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/12_ml.md +0 -0
  169. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/13_visualization.md +0 -0
  170. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/14_factor.md +0 -0
  171. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/15_live_trading.md +0 -0
  172. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/16_rust_indicators.md +0 -0
  173. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/ROADMAP.md +0 -0
  174. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/appendix_cite.md +0 -0
  175. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/appendix_pitfalls.md +0 -0
  176. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/appendix_setup.md +0 -0
  177. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/capstone.md +0 -0
  178. {akquant-0.3.1 → akquant-0.3.2}/docs/zh/textbook/index.md +0 -0
  179. {akquant-0.3.1 → akquant-0.3.2}/examples/01_quickstart.py +0 -0
  180. {akquant-0.3.1 → akquant-0.3.2}/examples/02_parameter_optimization.py +0 -0
  181. {akquant-0.3.1 → akquant-0.3.2}/examples/03_parameter_optimization_advanced.py +0 -0
  182. {akquant-0.3.1 → akquant-0.3.2}/examples/04_mixed_assets.py +0 -0
  183. {akquant-0.3.1 → akquant-0.3.2}/examples/05_live_trading_ctp.py +0 -0
  184. {akquant-0.3.1 → akquant-0.3.2}/examples/06_complex_orders.py +0 -0
  185. {akquant-0.3.1 → akquant-0.3.2}/examples/07_option_test.py +0 -0
  186. {akquant-0.3.1 → akquant-0.3.2}/examples/08_event_callbacks.py +0 -0
  187. {akquant-0.3.1 → akquant-0.3.2}/examples/09_ml_framework.py +0 -0
  188. {akquant-0.3.1 → akquant-0.3.2}/examples/10_ml_walk_forward.py +0 -0
  189. {akquant-0.3.1 → akquant-0.3.2}/examples/11_plot_visualization.py +0 -0
  190. {akquant-0.3.1 → akquant-0.3.2}/examples/12_wfo_integrated.py +0 -0
  191. {akquant-0.3.1 → akquant-0.3.2}/examples/13_quantstats_report.py +0 -0
  192. {akquant-0.3.1 → akquant-0.3.2}/examples/14_multi_frequency.py +0 -0
  193. {akquant-0.3.1 → akquant-0.3.2}/examples/15_plot_intraday.py +0 -0
  194. {akquant-0.3.1 → akquant-0.3.2}/examples/16_adj_returns_signal.py +0 -0
  195. {akquant-0.3.1 → akquant-0.3.2}/examples/17_readme_demo.py +0 -0
  196. {akquant-0.3.1 → akquant-0.3.2}/examples/18_benchmark_multisymbol.py +0 -0
  197. {akquant-0.3.1 → akquant-0.3.2}/examples/19_factor_expression.py +0 -0
  198. {akquant-0.3.1 → akquant-0.3.2}/examples/20_risk_management_demo.py +0 -0
  199. {akquant-0.3.1 → akquant-0.3.2}/examples/21_warm_start_demo.py +0 -0
  200. {akquant-0.3.1 → akquant-0.3.2}/examples/22_strategy_runtime_config_demo.py +0 -0
  201. {akquant-0.3.1 → akquant-0.3.2}/examples/23_functional_callbacks_demo.py +0 -0
  202. {akquant-0.3.1 → akquant-0.3.2}/examples/24_functional_tick_simulation_demo.py +0 -0
  203. {akquant-0.3.1 → akquant-0.3.2}/examples/25_streaming_backtest_demo.py +0 -0
  204. {akquant-0.3.1 → akquant-0.3.2}/examples/26_streaming_quickstart.py +0 -0
  205. {akquant-0.3.1 → akquant-0.3.2}/examples/27_streaming_monitoring_console.py +0 -0
  206. {akquant-0.3.1 → akquant-0.3.2}/examples/28_streaming_alerts_and_persist.py +0 -0
  207. {akquant-0.3.1 → akquant-0.3.2}/examples/29_streaming_event_report.py +0 -0
  208. {akquant-0.3.1 → akquant-0.3.2}/examples/30_streaming_report_oneclick.py +0 -0
  209. {akquant-0.3.1 → akquant-0.3.2}/examples/31_streaming_live_console.py +0 -0
  210. {akquant-0.3.1 → akquant-0.3.2}/examples/32_streaming_live_web.py +0 -0
  211. {akquant-0.3.1 → akquant-0.3.2}/examples/33_report_and_analysis_outputs.py +0 -0
  212. {akquant-0.3.1 → akquant-0.3.2}/examples/34_multi_strategy_demo.py +0 -0
  213. {akquant-0.3.1 → akquant-0.3.2}/examples/35_custom_broker_registry_demo.py +0 -0
  214. {akquant-0.3.1 → akquant-0.3.2}/examples/37_feed_replay_alignment_demo.py +0 -0
  215. {akquant-0.3.1 → akquant-0.3.2}/examples/38_live_functional_strategy_demo.py +0 -0
  216. {akquant-0.3.1 → akquant-0.3.2}/examples/39_live_broker_submit_order_demo.py +0 -0
  217. {akquant-0.3.1 → akquant-0.3.2}/examples/40_functional_multi_slot_risk_demo.py +0 -0
  218. {akquant-0.3.1 → akquant-0.3.2}/examples/41_live_multi_slot_orchestration_demo.py +0 -0
  219. {akquant-0.3.1 → akquant-0.3.2}/examples/42_live_broker_event_audit_demo.py +0 -0
  220. {akquant-0.3.1 → akquant-0.3.2}/examples/43_target_weights_rebalance.py +0 -0
  221. {akquant-0.3.1 → akquant-0.3.2}/examples/44_strategy_source_loader_demo.py +0 -0
  222. {akquant-0.3.1 → akquant-0.3.2}/examples/45_talib_indicator_playbook_demo.py +0 -0
  223. {akquant-0.3.1 → akquant-0.3.2}/examples/46_broker_profile_demo.py +0 -0
  224. {akquant-0.3.1 → akquant-0.3.2}/examples/47_margin_liquidation_audit_demo.py +0 -0
  225. {akquant-0.3.1 → akquant-0.3.2}/examples/48_margin_liquidation_priority_compare.py +0 -0
  226. {akquant-0.3.1 → akquant-0.3.2}/examples/49_on_expiry_demo.py +0 -0
  227. {akquant-0.3.1 → akquant-0.3.2}/examples/50_framework_hooks_demo.py +0 -0
  228. {akquant-0.3.1 → akquant-0.3.2}/examples/51_class_tick_callbacks_demo.py +0 -0
  229. {akquant-0.3.1 → akquant-0.3.2}/examples/52_pre_open_demo.py +0 -0
  230. {akquant-0.3.1 → akquant-0.3.2}/examples/53_timer_to_pre_open_demo.py +0 -0
  231. {akquant-0.3.1 → akquant-0.3.2}/examples/54_functional_pre_open_demo.py +0 -0
  232. {akquant-0.3.1 → akquant-0.3.2}/examples/55_functional_ml_walk_forward.py +0 -0
  233. {akquant-0.3.1 → akquant-0.3.2}/examples/56_functional_warm_start_demo.py +0 -0
  234. {akquant-0.3.1 → akquant-0.3.2}/examples/57_functional_multi_slot_warm_start_demo.py +0 -0
  235. {akquant-0.3.1 → akquant-0.3.2}/examples/58_incremental_bootstrap_demo.py +0 -0
  236. {akquant-0.3.1 → akquant-0.3.2}/examples/59_akshare_etf_rotation.py +0 -0
  237. {akquant-0.3.1 → akquant-0.3.2}/examples/60_custom_indicator_demo.py +0 -0
  238. {akquant-0.3.1 → akquant-0.3.2}/examples/61_indicator_visualization_export_demo.py +0 -0
  239. {akquant-0.3.1 → akquant-0.3.2}/examples/62_indicator_streaming_demo.py +0 -0
  240. {akquant-0.3.1 → akquant-0.3.2}/examples/63_indicator_ws_bridge_demo.py +0 -0
  241. {akquant-0.3.1 → akquant-0.3.2}/examples/64_indicator_live_web.py +0 -0
  242. {akquant-0.3.1 → akquant-0.3.2}/examples/65_bar_generator.py +0 -0
  243. {akquant-0.3.1 → akquant-0.3.2}/examples/README.md +0 -0
  244. {akquant-0.3.1 → akquant-0.3.2}/examples/benchmark_utils.py +0 -0
  245. {akquant-0.3.1 → akquant-0.3.2}/examples/pb_mock.py +0 -0
  246. {akquant-0.3.1 → akquant-0.3.2}/examples/strategies/01_stock_dual_moving_average.py +0 -0
  247. {akquant-0.3.1 → akquant-0.3.2}/examples/strategies/02_stock_grid_trading.py +0 -0
  248. {akquant-0.3.1 → akquant-0.3.2}/examples/strategies/03_stock_atr_breakout.py +0 -0
  249. {akquant-0.3.1 → akquant-0.3.2}/examples/strategies/04_stock_momentum_rotation.py +0 -0
  250. {akquant-0.3.1 → akquant-0.3.2}/examples/strategies/05_stock_momentum_rotation_timer.py +0 -0
  251. {akquant-0.3.1 → akquant-0.3.2}/examples/strategies/06_stock_momentum_rotation_bucket.py +0 -0
  252. {akquant-0.3.1 → akquant-0.3.2}/examples/strategies/07_stock_momentum_rotation_on_timer.py +0 -0
  253. {akquant-0.3.1 → akquant-0.3.2}/examples/strategies/08_target_positions_long_short.py +0 -0
  254. {akquant-0.3.1 → akquant-0.3.2}/examples/strategies/09_stock_momentum_rotation_after_bar.py +0 -0
  255. {akquant-0.3.1 → akquant-0.3.2}/examples/strategies/README.md +0 -0
  256. {akquant-0.3.1 → akquant-0.3.2}/examples/textbook/ch01_quickstart.py +0 -0
  257. {akquant-0.3.1 → akquant-0.3.2}/examples/textbook/ch02_programming.py +0 -0
  258. {akquant-0.3.1 → akquant-0.3.2}/examples/textbook/ch03_data.py +0 -0
  259. {akquant-0.3.1 → akquant-0.3.2}/examples/textbook/ch04_comparison.py +0 -0
  260. {akquant-0.3.1 → akquant-0.3.2}/examples/textbook/ch05_strategy.py +0 -0
  261. {akquant-0.3.1 → akquant-0.3.2}/examples/textbook/ch06_stock_a.py +0 -0
  262. {akquant-0.3.1 → akquant-0.3.2}/examples/textbook/ch07_futures.py +0 -0
  263. {akquant-0.3.1 → akquant-0.3.2}/examples/textbook/ch08_options.py +0 -0
  264. {akquant-0.3.1 → akquant-0.3.2}/examples/textbook/ch09_funds.py +0 -0
  265. {akquant-0.3.1 → akquant-0.3.2}/examples/textbook/ch09_portfolio.py +0 -0
  266. {akquant-0.3.1 → akquant-0.3.2}/examples/textbook/ch10_analysis.py +0 -0
  267. {akquant-0.3.1 → akquant-0.3.2}/examples/textbook/ch11_optimization.py +0 -0
  268. {akquant-0.3.1 → akquant-0.3.2}/examples/textbook/ch12_ml.py +0 -0
  269. {akquant-0.3.1 → akquant-0.3.2}/examples/textbook/ch13_visualization.py +0 -0
  270. {akquant-0.3.1 → akquant-0.3.2}/examples/textbook/ch14_factor.py +0 -0
  271. {akquant-0.3.1 → akquant-0.3.2}/examples/textbook/ch15_live_trading.py +0 -0
  272. {akquant-0.3.1 → akquant-0.3.2}/examples/textbook/ch15_strategy_loader.py +0 -0
  273. {akquant-0.3.1 → akquant-0.3.2}/examples/textbook/ch16_indicators.py +0 -0
  274. {akquant-0.3.1 → akquant-0.3.2}/mkdocs.yml +0 -0
  275. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/analysis/__init__.py +0 -0
  276. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/analysis/benchmark.py +0 -0
  277. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/analyzer_plugin.py +0 -0
  278. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/backtest/__init__.py +0 -0
  279. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/backtest/__init__.pyi +0 -0
  280. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/backtest/engine.py +0 -0
  281. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/backtest/result.py +0 -0
  282. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/bar_generator.py +0 -0
  283. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/checkpoint.py +0 -0
  284. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/config.py +0 -0
  285. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/data.py +0 -0
  286. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/execution/__init__.py +0 -0
  287. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/execution/base.py +0 -0
  288. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/factor/__init__.py +0 -0
  289. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/factor/engine.py +0 -0
  290. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/factor/ops.py +0 -0
  291. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/factor/parser.py +0 -0
  292. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/feed_adapter.py +0 -0
  293. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/fund/__init__.py +0 -0
  294. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/futures/__init__.py +0 -0
  295. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/__init__.py +0 -0
  296. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/base.py +0 -0
  297. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/broker_event_bridge.py +0 -0
  298. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/broker_event_mapper.py +0 -0
  299. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/broker_recovery.py +0 -0
  300. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/broker_state_cache.py +0 -0
  301. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/broker_strategy_api.py +0 -0
  302. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/brokers/__init__.py +0 -0
  303. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/brokers/builtins.py +0 -0
  304. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/brokers/ctp/__init__.py +0 -0
  305. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/brokers/ctp/adapter.py +0 -0
  306. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/brokers/ctp/native.py +0 -0
  307. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/brokers/miniqmt/__init__.py +0 -0
  308. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/brokers/miniqmt/stub.py +0 -0
  309. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/brokers/plugins.py +0 -0
  310. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/brokers/ptrade/__init__.py +0 -0
  311. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/brokers/ptrade/stub.py +0 -0
  312. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/ctp_adapter.py +0 -0
  313. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/ctp_native.py +0 -0
  314. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/factory.py +0 -0
  315. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/local_stop_book.py +0 -0
  316. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/mapper.py +0 -0
  317. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/miniqmt.py +0 -0
  318. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/models.py +0 -0
  319. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/protocols.py +0 -0
  320. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/ptrade.py +0 -0
  321. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/registry.py +0 -0
  322. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/gateway/trader_base.py +0 -0
  323. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/indicator.py +0 -0
  324. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/indicator_recording.py +0 -0
  325. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/indicator_stream.py +0 -0
  326. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/log.py +0 -0
  327. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/ml/__init__.py +0 -0
  328. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/ml/model.py +0 -0
  329. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/optimize.py +0 -0
  330. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/option/__init__.py +0 -0
  331. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/params.py +0 -0
  332. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/params_adapter.py +0 -0
  333. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/plot/__init__.py +0 -0
  334. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/plot/analysis.py +0 -0
  335. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/plot/dashboard.py +0 -0
  336. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/plot/indicator.py +0 -0
  337. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/plot/report.py +0 -0
  338. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/plot/strategy.py +0 -0
  339. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/plot/utils.py +0 -0
  340. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/py.typed +0 -0
  341. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/risk.py +0 -0
  342. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/sizer.py +0 -0
  343. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/stock/__init__.py +0 -0
  344. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/strategy_events.py +0 -0
  345. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/strategy_framework_hooks.py +0 -0
  346. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/strategy_history.py +0 -0
  347. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/strategy_loader.py +0 -0
  348. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/strategy_logging.py +0 -0
  349. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/strategy_ml.py +0 -0
  350. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/strategy_order_events.py +0 -0
  351. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/strategy_position.py +0 -0
  352. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/strategy_scheduler.py +0 -0
  353. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/strategy_time.py +0 -0
  354. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/talib/__init__.py +0 -0
  355. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/talib/backend.py +0 -0
  356. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/talib/core.py +0 -0
  357. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/talib/funcs.py +0 -0
  358. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/utils/__init__.py +0 -0
  359. {akquant-0.3.1 → akquant-0.3.2}/python/akquant/utils/inspector.py +0 -0
  360. {akquant-0.3.1 → akquant-0.3.2}/requirements-dev.txt +0 -0
  361. {akquant-0.3.1 → akquant-0.3.2}/scripts/cargo-test.sh +0 -0
  362. {akquant-0.3.1 → akquant-0.3.2}/scripts/check_docs_api_examples.py +0 -0
  363. {akquant-0.3.1 → akquant-0.3.2}/scripts/check_docs_links.py +0 -0
  364. {akquant-0.3.1 → akquant-0.3.2}/scripts/dev-check.sh +0 -0
  365. {akquant-0.3.1 → akquant-0.3.2}/scripts/find_legacy_execution_policy_calls.py +0 -0
  366. {akquant-0.3.1 → akquant-0.3.2}/scripts/golden_baseline_report.py +0 -0
  367. {akquant-0.3.1 → akquant-0.3.2}/src/account.rs +0 -0
  368. {akquant-0.3.1 → akquant-0.3.2}/src/analysis/mod.rs +0 -0
  369. {akquant-0.3.1 → akquant-0.3.2}/src/analysis/python.rs +0 -0
  370. {akquant-0.3.1 → akquant-0.3.2}/src/analysis/result.rs +0 -0
  371. {akquant-0.3.1 → akquant-0.3.2}/src/analysis/tests.rs +0 -0
  372. {akquant-0.3.1 → akquant-0.3.2}/src/analysis/tracker.rs +0 -0
  373. {akquant-0.3.1 → akquant-0.3.2}/src/analysis/types.rs +0 -0
  374. {akquant-0.3.1 → akquant-0.3.2}/src/bin/stub_gen.rs +0 -0
  375. {akquant-0.3.1 → akquant-0.3.2}/src/clock.rs +0 -0
  376. {akquant-0.3.1 → akquant-0.3.2}/src/context.rs +0 -0
  377. {akquant-0.3.1 → akquant-0.3.2}/src/data/aggregator.rs +0 -0
  378. {akquant-0.3.1 → akquant-0.3.2}/src/data/batch.rs +0 -0
  379. {akquant-0.3.1 → akquant-0.3.2}/src/data/client.rs +0 -0
  380. {akquant-0.3.1 → akquant-0.3.2}/src/data/feed.rs +0 -0
  381. {akquant-0.3.1 → akquant-0.3.2}/src/data/mod.rs +0 -0
  382. {akquant-0.3.1 → akquant-0.3.2}/src/engine/core.rs +0 -0
  383. {akquant-0.3.1 → akquant-0.3.2}/src/engine/mod.rs +0 -0
  384. {akquant-0.3.1 → akquant-0.3.2}/src/engine/python.rs +0 -0
  385. {akquant-0.3.1 → akquant-0.3.2}/src/engine/state.rs +0 -0
  386. {akquant-0.3.1 → akquant-0.3.2}/src/error.rs +0 -0
  387. {akquant-0.3.1 → akquant-0.3.2}/src/event.rs +0 -0
  388. {akquant-0.3.1 → akquant-0.3.2}/src/event_manager.rs +0 -0
  389. {akquant-0.3.1 → akquant-0.3.2}/src/execution/common.rs +0 -0
  390. {akquant-0.3.1 → akquant-0.3.2}/src/execution/crypto.rs +0 -0
  391. {akquant-0.3.1 → akquant-0.3.2}/src/execution/forex.rs +0 -0
  392. {akquant-0.3.1 → akquant-0.3.2}/src/execution/futures.rs +0 -0
  393. {akquant-0.3.1 → akquant-0.3.2}/src/execution/matcher.rs +0 -0
  394. {akquant-0.3.1 → akquant-0.3.2}/src/execution/mod.rs +0 -0
  395. {akquant-0.3.1 → akquant-0.3.2}/src/execution/option.rs +0 -0
  396. {akquant-0.3.1 → akquant-0.3.2}/src/execution/python.rs +0 -0
  397. {akquant-0.3.1 → akquant-0.3.2}/src/execution/realtime.rs +0 -0
  398. {akquant-0.3.1 → akquant-0.3.2}/src/execution/simulated.rs +0 -0
  399. {akquant-0.3.1 → akquant-0.3.2}/src/execution/slippage.rs +0 -0
  400. {akquant-0.3.1 → akquant-0.3.2}/src/execution/stock.rs +0 -0
  401. {akquant-0.3.1 → akquant-0.3.2}/src/history.rs +0 -0
  402. {akquant-0.3.1 → akquant-0.3.2}/src/indicators/momentum.rs +0 -0
  403. {akquant-0.3.1 → akquant-0.3.2}/src/indicators/momentum_oscillators.rs +0 -0
  404. {akquant-0.3.1 → akquant-0.3.2}/src/indicators/momentum_rates.rs +0 -0
  405. {akquant-0.3.1 → akquant-0.3.2}/src/indicators/moving_average.rs +0 -0
  406. {akquant-0.3.1 → akquant-0.3.2}/src/indicators/moving_average_compound.rs +0 -0
  407. {akquant-0.3.1 → akquant-0.3.2}/src/indicators/moving_average_core.rs +0 -0
  408. {akquant-0.3.1 → akquant-0.3.2}/src/indicators/moving_average_transforms.rs +0 -0
  409. {akquant-0.3.1 → akquant-0.3.2}/src/indicators/moving_average_windowed.rs +0 -0
  410. {akquant-0.3.1 → akquant-0.3.2}/src/indicators/trend.rs +0 -0
  411. {akquant-0.3.1 → akquant-0.3.2}/src/indicators/trend_directional.rs +0 -0
  412. {akquant-0.3.1 → akquant-0.3.2}/src/indicators/trend_oscillators.rs +0 -0
  413. {akquant-0.3.1 → akquant-0.3.2}/src/indicators/trend_regression.rs +0 -0
  414. {akquant-0.3.1 → akquant-0.3.2}/src/indicators/volatility.rs +0 -0
  415. {akquant-0.3.1 → akquant-0.3.2}/src/indicators/volatility_price.rs +0 -0
  416. {akquant-0.3.1 → akquant-0.3.2}/src/indicators/volatility_stats.rs +0 -0
  417. {akquant-0.3.1 → akquant-0.3.2}/src/indicators/volume.rs +0 -0
  418. {akquant-0.3.1 → akquant-0.3.2}/src/indicators.rs +0 -0
  419. {akquant-0.3.1 → akquant-0.3.2}/src/lib.rs +0 -0
  420. {akquant-0.3.1 → akquant-0.3.2}/src/log_context.rs +0 -0
  421. {akquant-0.3.1 → akquant-0.3.2}/src/margin/calculator.rs +0 -0
  422. {akquant-0.3.1 → akquant-0.3.2}/src/margin/engine.rs +0 -0
  423. {akquant-0.3.1 → akquant-0.3.2}/src/margin/mod.rs +0 -0
  424. {akquant-0.3.1 → akquant-0.3.2}/src/market/china.rs +0 -0
  425. {akquant-0.3.1 → akquant-0.3.2}/src/market/core.rs +0 -0
  426. {akquant-0.3.1 → akquant-0.3.2}/src/market/corporate_action.rs +0 -0
  427. {akquant-0.3.1 → akquant-0.3.2}/src/market/fund.rs +0 -0
  428. {akquant-0.3.1 → akquant-0.3.2}/src/market/futures.rs +0 -0
  429. {akquant-0.3.1 → akquant-0.3.2}/src/market/manager.rs +0 -0
  430. {akquant-0.3.1 → akquant-0.3.2}/src/market/mod.rs +0 -0
  431. {akquant-0.3.1 → akquant-0.3.2}/src/market/option.rs +0 -0
  432. {akquant-0.3.1 → akquant-0.3.2}/src/market/simple.rs +0 -0
  433. {akquant-0.3.1 → akquant-0.3.2}/src/market/stock.rs +0 -0
  434. {akquant-0.3.1 → akquant-0.3.2}/src/model/corporate_action.rs +0 -0
  435. {akquant-0.3.1 → akquant-0.3.2}/src/model/instrument.rs +0 -0
  436. {akquant-0.3.1 → akquant-0.3.2}/src/model/market_data.rs +0 -0
  437. {akquant-0.3.1 → akquant-0.3.2}/src/model/mod.rs +0 -0
  438. {akquant-0.3.1 → akquant-0.3.2}/src/model/order.rs +0 -0
  439. {akquant-0.3.1 → akquant-0.3.2}/src/model/timer.rs +0 -0
  440. {akquant-0.3.1 → akquant-0.3.2}/src/model/types.rs +0 -0
  441. {akquant-0.3.1 → akquant-0.3.2}/src/order_manager.rs +0 -0
  442. {akquant-0.3.1 → akquant-0.3.2}/src/pipeline/mod.rs +0 -0
  443. {akquant-0.3.1 → akquant-0.3.2}/src/pipeline/processor.rs +0 -0
  444. {akquant-0.3.1 → akquant-0.3.2}/src/pipeline/runner.rs +0 -0
  445. {akquant-0.3.1 → akquant-0.3.2}/src/pipeline/stages/channel.rs +0 -0
  446. {akquant-0.3.1 → akquant-0.3.2}/src/pipeline/stages/cleanup.rs +0 -0
  447. {akquant-0.3.1 → akquant-0.3.2}/src/pipeline/stages/data.rs +0 -0
  448. {akquant-0.3.1 → akquant-0.3.2}/src/pipeline/stages/execution.rs +0 -0
  449. {akquant-0.3.1 → akquant-0.3.2}/src/pipeline/stages/mod.rs +0 -0
  450. {akquant-0.3.1 → akquant-0.3.2}/src/pipeline/stages/shared.rs +0 -0
  451. {akquant-0.3.1 → akquant-0.3.2}/src/pipeline/stages/statistics.rs +0 -0
  452. {akquant-0.3.1 → akquant-0.3.2}/src/pipeline/stages/strategy.rs +0 -0
  453. {akquant-0.3.1 → akquant-0.3.2}/src/portfolio.rs +0 -0
  454. {akquant-0.3.1 → akquant-0.3.2}/src/risk/common.rs +0 -0
  455. {akquant-0.3.1 → akquant-0.3.2}/src/risk/config.rs +0 -0
  456. {akquant-0.3.1 → akquant-0.3.2}/src/risk/futures.rs +0 -0
  457. {akquant-0.3.1 → akquant-0.3.2}/src/risk/manager.rs +0 -0
  458. {akquant-0.3.1 → akquant-0.3.2}/src/risk/mod.rs +0 -0
  459. {akquant-0.3.1 → akquant-0.3.2}/src/risk/option.rs +0 -0
  460. {akquant-0.3.1 → akquant-0.3.2}/src/risk/portfolio.rs +0 -0
  461. {akquant-0.3.1 → akquant-0.3.2}/src/risk/rule.rs +0 -0
  462. {akquant-0.3.1 → akquant-0.3.2}/src/risk/stock.rs +0 -0
  463. {akquant-0.3.1 → akquant-0.3.2}/src/settlement/expiry.rs +0 -0
  464. {akquant-0.3.1 → akquant-0.3.2}/src/settlement/handler.rs +0 -0
  465. {akquant-0.3.1 → akquant-0.3.2}/src/settlement/manager.rs +0 -0
  466. {akquant-0.3.1 → akquant-0.3.2}/src/settlement/mod.rs +0 -0
  467. {akquant-0.3.1 → akquant-0.3.2}/src/settlement/option.rs +0 -0
  468. {akquant-0.3.1 → akquant-0.3.2}/src/statistics/mod.rs +0 -0
  469. {akquant-0.3.1 → akquant-0.3.2}/tests/gateway_contract/test_event_bridge_contract.py +0 -0
  470. {akquant-0.3.1 → akquant-0.3.2}/tests/gateway_contract/test_recovery_contract.py +0 -0
  471. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/BASELINE_REPORT.md +0 -0
  472. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/LEGACY_EXECUTION_CALLS.md +0 -0
  473. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/baselines/futures_margin/equity_curve.parquet +0 -0
  474. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/baselines/futures_margin/metrics.json +0 -0
  475. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/baselines/futures_margin/orders.parquet +0 -0
  476. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/baselines/option_basic/equity_curve.parquet +0 -0
  477. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/baselines/option_basic/metrics.json +0 -0
  478. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/baselines/option_basic/orders.parquet +0 -0
  479. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/baselines/stock_t1/equity_curve.parquet +0 -0
  480. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/baselines/stock_t1/metrics.json +0 -0
  481. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/baselines/stock_t1/orders.parquet +0 -0
  482. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/baselines/stock_t1/trades.parquet +0 -0
  483. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/current/futures_margin/equity_curve.parquet +0 -0
  484. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/current/futures_margin/metrics.json +0 -0
  485. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/current/futures_margin/orders.parquet +0 -0
  486. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/current/option_basic/equity_curve.parquet +0 -0
  487. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/current/option_basic/metrics.json +0 -0
  488. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/current/option_basic/orders.parquet +0 -0
  489. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/current/stock_t1/equity_curve.parquet +0 -0
  490. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/current/stock_t1/metrics.json +0 -0
  491. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/current/stock_t1/orders.parquet +0 -0
  492. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/current/stock_t1/trades.parquet +0 -0
  493. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/data/future_margin.parquet +0 -0
  494. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/data/future_margin.parquet.sha256 +0 -0
  495. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/data/option_basic.parquet +0 -0
  496. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/data/option_basic.parquet.sha256 +0 -0
  497. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/data/stock_t1.parquet +0 -0
  498. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/data/stock_t1.parquet.sha256 +0 -0
  499. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/gen_data.py +0 -0
  500. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/runner.py +0 -0
  501. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/strategies/futures_margin.py +0 -0
  502. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/strategies/option_basic.py +0 -0
  503. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/strategies/stock_t1.py +0 -0
  504. {akquant-0.3.1 → akquant-0.3.2}/tests/golden/test_golden.py +0 -0
  505. {akquant-0.3.1 → akquant-0.3.2}/tests/test_account_risk_rules.py +0 -0
  506. {akquant-0.3.1 → akquant-0.3.2}/tests/test_api_rename_cash.py +0 -0
  507. {akquant-0.3.1 → akquant-0.3.2}/tests/test_api_rename_composites.py +0 -0
  508. {akquant-0.3.1 → akquant-0.3.2}/tests/test_api_rename_equity.py +0 -0
  509. {akquant-0.3.1 → akquant-0.3.2}/tests/test_api_rename_holding_bars.py +0 -0
  510. {akquant-0.3.1 → akquant-0.3.2}/tests/test_api_rename_positions.py +0 -0
  511. {akquant-0.3.1 → akquant-0.3.2}/tests/test_api_rename_rebalance.py +0 -0
  512. {akquant-0.3.1 → akquant-0.3.2}/tests/test_bar_generator.py +0 -0
  513. {akquant-0.3.1 → akquant-0.3.2}/tests/test_broker_bridge_adapts_events.py +0 -0
  514. {akquant-0.3.1 → akquant-0.3.2}/tests/test_broker_bridge_drives_order_groups.py +0 -0
  515. {akquant-0.3.1 → akquant-0.3.2}/tests/test_broker_event_adapter_local_id.py +0 -0
  516. {akquant-0.3.1 → akquant-0.3.2}/tests/test_broker_plugins.py +0 -0
  517. {akquant-0.3.1 → akquant-0.3.2}/tests/test_broker_position_sync.py +0 -0
  518. {akquant-0.3.1 → akquant-0.3.2}/tests/test_broker_seed_baseline.py +0 -0
  519. {akquant-0.3.1 → akquant-0.3.2}/tests/test_broker_trade_redelivery_dedup.py +0 -0
  520. {akquant-0.3.1 → akquant-0.3.2}/tests/test_close_position_delegate.py +0 -0
  521. {akquant-0.3.1 → akquant-0.3.2}/tests/test_composed_ctx_not_ready.py +0 -0
  522. {akquant-0.3.1 → akquant-0.3.2}/tests/test_cost_config_consolidation.py +0 -0
  523. {akquant-0.3.1 → akquant-0.3.2}/tests/test_custom_matcher.py +0 -0
  524. {akquant-0.3.1 → akquant-0.3.2}/tests/test_data_catalog.py +0 -0
  525. {akquant-0.3.1 → akquant-0.3.2}/tests/test_docs_api_examples.py +0 -0
  526. {akquant-0.3.1 → akquant-0.3.2}/tests/test_docs_links.py +0 -0
  527. {akquant-0.3.1 → akquant-0.3.2}/tests/test_engine.py +0 -0
  528. {akquant-0.3.1 → akquant-0.3.2}/tests/test_event_model_parity.py +0 -0
  529. {akquant-0.3.1 → akquant-0.3.2}/tests/test_examples_regression.py +0 -0
  530. {akquant-0.3.1 → akquant-0.3.2}/tests/test_execution_binding.py +0 -0
  531. {akquant-0.3.1 → akquant-0.3.2}/tests/test_execution_broker_reads_routed.py +0 -0
  532. {akquant-0.3.1 → akquant-0.3.2}/tests/test_execution_composed_parity.py +0 -0
  533. {akquant-0.3.1 → akquant-0.3.2}/tests/test_execution_read_delegation.py +0 -0
  534. {akquant-0.3.1 → akquant-0.3.2}/tests/test_execution_sim.py +0 -0
  535. {akquant-0.3.1 → akquant-0.3.2}/tests/test_execution_write_delegation.py +0 -0
  536. {akquant-0.3.1 → akquant-0.3.2}/tests/test_factor_engine.py +0 -0
  537. {akquant-0.3.1 → akquant-0.3.2}/tests/test_factor_ops.py +0 -0
  538. {akquant-0.3.1 → akquant-0.3.2}/tests/test_feed_adapter.py +0 -0
  539. {akquant-0.3.1 → akquant-0.3.2}/tests/test_gateway_broker_live_reads.py +0 -0
  540. {akquant-0.3.1 → akquant-0.3.2}/tests/test_gateway_broker_state_cache.py +0 -0
  541. {akquant-0.3.1 → akquant-0.3.2}/tests/test_gateway_broker_state_invalidation.py +0 -0
  542. {akquant-0.3.1 → akquant-0.3.2}/tests/test_gateway_brokers_paths.py +0 -0
  543. {akquant-0.3.1 → akquant-0.3.2}/tests/test_gateway_builtins_registry.py +0 -0
  544. {akquant-0.3.1 → akquant-0.3.2}/tests/test_gateway_callbacks.py +0 -0
  545. {akquant-0.3.1 → akquant-0.3.2}/tests/test_gateway_ctp_adapter.py +0 -0
  546. {akquant-0.3.1 → akquant-0.3.2}/tests/test_gateway_ctp_native.py +0 -0
  547. {akquant-0.3.1 → akquant-0.3.2}/tests/test_gateway_factory.py +0 -0
  548. {akquant-0.3.1 → akquant-0.3.2}/tests/test_gateway_mapper.py +0 -0
  549. {akquant-0.3.1 → akquant-0.3.2}/tests/test_gateway_optional_market.py +0 -0
  550. {akquant-0.3.1 → akquant-0.3.2}/tests/test_gateway_registry.py +0 -0
  551. {akquant-0.3.1 → akquant-0.3.2}/tests/test_gateway_sim_submit_guard.py +0 -0
  552. {akquant-0.3.1 → akquant-0.3.2}/tests/test_gateway_trader_base.py +0 -0
  553. {akquant-0.3.1 → akquant-0.3.2}/tests/test_indicator_live_web_example.py +0 -0
  554. {akquant-0.3.1 → akquant-0.3.2}/tests/test_indicator_recording.py +0 -0
  555. {akquant-0.3.1 → akquant-0.3.2}/tests/test_inspector.py +0 -0
  556. {akquant-0.3.1 → akquant-0.3.2}/tests/test_live_runner.py +0 -0
  557. {akquant-0.3.1 → akquant-0.3.2}/tests/test_live_runner_broker_readiness.py +0 -0
  558. {akquant-0.3.1 → akquant-0.3.2}/tests/test_live_runner_broker_recovery.py +0 -0
  559. {akquant-0.3.1 → akquant-0.3.2}/tests/test_local_stop_book.py +0 -0
  560. {akquant-0.3.1 → akquant-0.3.2}/tests/test_local_stop_book_threadsafe.py +0 -0
  561. {akquant-0.3.1 → akquant-0.3.2}/tests/test_multisymbol_cross_section_consistency.py +0 -0
  562. {akquant-0.3.1 → akquant-0.3.2}/tests/test_on_execution_report_noop.py +0 -0
  563. {akquant-0.3.1 → akquant-0.3.2}/tests/test_orders_df.py +0 -0
  564. {akquant-0.3.1 → akquant-0.3.2}/tests/test_params_adapter.py +0 -0
  565. {akquant-0.3.1 → akquant-0.3.2}/tests/test_partial_filled_status.py +0 -0
  566. {akquant-0.3.1 → akquant-0.3.2}/tests/test_portfolio.py +0 -0
  567. {akquant-0.3.1 → akquant-0.3.2}/tests/test_quickstart_stream_consistency.py +0 -0
  568. {akquant-0.3.1 → akquant-0.3.2}/tests/test_removed_wrappers.py +0 -0
  569. {akquant-0.3.1 → akquant-0.3.2}/tests/test_report_helpers.py +0 -0
  570. {akquant-0.3.1 → akquant-0.3.2}/tests/test_report_plot_extensions.py +0 -0
  571. {akquant-0.3.1 → akquant-0.3.2}/tests/test_result_analysis_extensions.py +0 -0
  572. {akquant-0.3.1 → akquant-0.3.2}/tests/test_review_minors_cleanup.py +0 -0
  573. {akquant-0.3.1 → akquant-0.3.2}/tests/test_stop_orders.py +0 -0
  574. {akquant-0.3.1 → akquant-0.3.2}/tests/test_strategy_events_stop_hook.py +0 -0
  575. {akquant-0.3.1 → akquant-0.3.2}/tests/test_strategy_order_group_lock.py +0 -0
  576. {akquant-0.3.1 → akquant-0.3.2}/tests/test_strategy_sizing_broker_live_guard.py +0 -0
  577. {akquant-0.3.1 → akquant-0.3.2}/tests/test_strategy_timers_indicators.py +0 -0
  578. {akquant-0.3.1 → akquant-0.3.2}/tests/test_t_plus_one.py +0 -0
  579. {akquant-0.3.1 → akquant-0.3.2}/tests/test_talib_backend.py +0 -0
  580. {akquant-0.3.1 → akquant-0.3.2}/tests/test_talib_compat.py +0 -0
  581. {akquant-0.3.1 → akquant-0.3.2}/tests/test_target_orders_core.py +0 -0
  582. {akquant-0.3.1 → akquant-0.3.2}/tests/test_trades_df.py +0 -0
  583. {akquant-0.3.1 → akquant-0.3.2}/tests/test_version.py +0 -0
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
12
12
  - `BacktestConfig` 新增 `days_per_year`(年化天数因子,默认 252;数字货币 24/7 市场可设 365)与 `risk_free_rate`(年化无风险利率,默认 0.0)两个字段,用于参数化 Sharpe/Sortino/波动率等风险指标的年化口径。`risk_free_rate` 默认 0 不改变任何现有数值。
13
13
 
14
14
  ### Changed
15
+ - **`buy`/`sell`/`submit_order` 返回类型变更(破坏性)**:三者现统一返回 `OrderReceipt`(原为 `str` 订单号),回测与实盘(`broker_live`)两种模式返回类型一致;实盘 `submit_order` 此前会将多腿委托(如反手拆分的平仓+开仓、开平分离)收窄为单一 id 字符串,现已修复为返回携带全部腿 id 的完整 `OrderReceipt`。取单个订单 id 用 `receipt.primary`(首腿 broker_order_id,兼容旧用法),取全部腿 id 用 `receipt.order_ids`;`str(receipt)` 取 `group_id`(逻辑委托的客户端订单号),关联成交请用 `trade.group_id` 而非逐个 order_id 比对;新增 `cancel_group(group_id)` 用于一次性撤销一个逻辑委托的全部腿。
15
16
  - **回测指标口径变更(破坏性)**:Sharpe / Sortino 比率的分子改为「日收益算术均值 × `days_per_year`」做年化,替代原先的 CAGR(复合年化),与 pyfolio/empyrical/quantstats 等主流实现一致,并与分母 `√days_per_year` 的年化口径匹配。升级后历史报告的 Sharpe/Sortino 数值会变化,不可直接与旧版逐值对比;UPI 与 Calmar 仍沿用 CAGR 口径。
16
17
  - 策略交易日边界回调已硬切改名:`before_trading(trading_date, timestamp)` 更名为 `on_before_trading(trading_date, timestamp)`,`after_trading(trading_date, timestamp)` 更名为 `on_after_trading(trading_date, timestamp)`。
17
18
  - 旧回调名不再保留兼容别名;升级到当前版本后,若策略仍实现 `before_trading` / `after_trading`,将不会再被框架触发,请同步迁移到新名称。
@@ -30,7 +30,7 @@ dependencies = [
30
30
 
31
31
  [[package]]
32
32
  name = "akquant"
33
- version = "0.3.1"
33
+ version = "0.3.2"
34
34
  dependencies = [
35
35
  "anyhow",
36
36
  "chrono",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "akquant"
3
- version = "0.3.1"
3
+ version = "0.3.2"
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.3.1
3
+ Version: 0.3.2
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: Implementation :: PyPy
@@ -774,8 +774,44 @@ AKQuant 当前的订单语义已经不再是单纯的 `side`,而是 `side + po
774
774
 
775
775
  * **撤单 (Cancel Order)**:
776
776
  * `self.cancel_order(order_id)`: 撤销指定订单。
777
+ * `self.cancel_group(group_id)`: 按 `group_id` 撤销一个逻辑委托拆出的全部腿。
777
778
  * `self.cancel_all_orders()`: 撤销当前所有未成交订单。
778
779
 
780
+ ### 7.2.2 OrderReceipt:下单回执与 group_id
781
+
782
+ `buy()` / `sell()` / `submit_order()` 统一返回 `OrderReceipt`(回测与
783
+ `broker_live` 实盘两种模式返回类型一致,不再是裸 `str` 订单号):
784
+
785
+ * `receipt.primary`:首腿的订单 id(`broker_order_id`),多数场景下当作
786
+ "这笔下单的订单号" 使用,等价于旧版直接拿到的 `str`。
787
+ * `receipt.order_ids`:全部腿的订单 id 元组。一次 `side + position_effect="auto"`
788
+ 调用在持有反向仓位时会被自动拆成 `close` + `open` 两腿(或期货 `close_today`
789
+ / `close_yesterday` 两腿),此时 `order_ids` 长度 > 1,`primary` 只是其中一腿。
790
+ * `str(receipt)`:逻辑委托的 `group_id`(客户端订单号),用于把拆出的多腿关联为
791
+ "同一次下单";与 `receipt.primary` 是两个不同的 id 空间,不要混用。
792
+ * 关联成交回报时优先用 `trade.group_id` 而不是逐个 `order_id` 比对,这样无论
793
+ 该笔委托是否被拆腿都能正确聚合。
794
+
795
+ 跨 `close + open` 的反手示例(先平后开,两腿在同一次 `buy()`/`sell()` 调用里发出):
796
+
797
+ ```python
798
+ def on_bar(self, bar):
799
+ # 当前持有空头仓位,买入 300 手:自动拆成「平空 200 手」+「开多 100 手」两腿
800
+ receipt = self.buy(bar.symbol, quantity=300) # position_effect 默认 "auto"
801
+
802
+ print(receipt.primary) # 首腿(平仓腿)的订单 id,兼容旧版单一 str 用法
803
+ print(receipt.order_ids) # (平仓腿 id, 开仓腿 id) —— 全部腿
804
+ print(str(receipt)) # group_id:这次逻辑委托的客户端订单号
805
+
806
+ # 想整单撤销(两腿都撤):
807
+ self.cancel_group(receipt) # 等价于 self.cancel_group(str(receipt))
808
+
809
+ def on_trade(self, trade):
810
+ # 用 group_id 聚合同一次逻辑委托拆出的多腿成交,而不是比较单个 order_id
811
+ if trade.group_id == self._entry_group_id:
812
+ ...
813
+ ```
814
+
779
815
  ### 7.3 OCO 与 Bracket 助手
780
816
 
781
817
  AKQuant 提供了两组交易助手,减少策略中手写订单联动逻辑:
@@ -23,7 +23,8 @@ class TrailingOrderStrategy(Strategy):
23
23
  and not self.entry_order_id
24
24
  and not self.trailing_order_id
25
25
  ):
26
- self.entry_order_id = self.buy(bar.symbol, 100, tag="trail-entry")
26
+ entry_receipt = self.buy(bar.symbol, 100, tag="trail-entry")
27
+ self.entry_order_id = str(getattr(entry_receipt, "primary", entry_receipt))
27
28
  print(
28
29
  f"[{bar.timestamp_iso}] 提交进场单: {bar.symbol}, close={bar.close:.2f}"
29
30
  )
@@ -37,7 +38,7 @@ class TrailingOrderStrategy(Strategy):
37
38
  if trade.order_id == self.entry_order_id:
38
39
  self.entry_order_id = ""
39
40
  ref_price = self.last_close.get(trade.symbol, float(trade.price))
40
- self.trailing_order_id = self.place_trailing_stop(
41
+ trailing_receipt = self.place_trailing_stop(
41
42
  symbol=trade.symbol,
42
43
  quantity=float(trade.quantity),
43
44
  trail_offset=self.trail_offset,
@@ -45,6 +46,9 @@ class TrailingOrderStrategy(Strategy):
45
46
  trail_reference_price=ref_price,
46
47
  tag="trail-stop",
47
48
  )
49
+ self.trailing_order_id = str(
50
+ getattr(trailing_receipt, "primary", trailing_receipt)
51
+ )
48
52
  print(
49
53
  f"[{trade.timestamp}] 提交 trailing stop: symbol={trade.symbol}, "
50
54
  f"offset={self.trail_offset:.2f}, ref={ref_price:.2f}"
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "akquant"
7
- version = "0.3.1"
7
+ version = "0.3.2"
8
8
  description = "High-performance quantitative trading framework based on Rust and Python"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT License"}
@@ -52,6 +52,7 @@ from .feed_adapter import (
52
52
  ReplayFeedAdapter,
53
53
  ResampledFeedAdapter,
54
54
  )
55
+ from .gateway.order_receipt import OrderLeg, OrderReceipt
55
56
  from .indicator import Indicator, IndicatorSet
56
57
  from .indicator_stream import (
57
58
  is_indicator_stream_event,
@@ -181,6 +182,8 @@ if hasattr(_akquant, "__all__"): # noqa: F405
181
182
  "validate_strategy_params",
182
183
  "extract_runtime_kwargs",
183
184
  "build_param_grid_from_search_space",
185
+ "OrderLeg",
186
+ "OrderReceipt",
184
187
  "talib",
185
188
  ]
186
189
  else:
@@ -259,6 +262,8 @@ else:
259
262
  "validate_strategy_params",
260
263
  "extract_runtime_kwargs",
261
264
  "build_param_grid_from_search_space",
265
+ "OrderLeg",
266
+ "OrderReceipt",
262
267
  "talib",
263
268
  ]
264
269
 
@@ -112,7 +112,7 @@ class TimeInForce:
112
112
  GTC: typing.ClassVar["TimeInForce"]
113
113
  IOC: typing.ClassVar["TimeInForce"]
114
114
  FOK: typing.ClassVar["TimeInForce"]
115
- GTD: typing.ClassVar["TimeInForce"]
115
+ Day: typing.ClassVar["TimeInForce"]
116
116
 
117
117
  class TradingSession:
118
118
  Normal: typing.ClassVar["TradingSession"]
@@ -5,6 +5,7 @@ from __future__ import annotations
5
5
  from typing import Any
6
6
 
7
7
  from .. import strategy_trading_api as api
8
+ from ..gateway.order_receipt import OrderReceipt
8
9
 
9
10
 
10
11
  class SimExecution:
@@ -50,8 +51,8 @@ class SimExecution:
50
51
  """获取现金."""
51
52
  return api._sim_get_cash(self._s)
52
53
 
53
- def submit_order(self, **kwargs: Any) -> str:
54
- """提交订单,返回订单号."""
54
+ def submit_order(self, **kwargs: Any) -> OrderReceipt:
55
+ """提交订单,返回 OrderReceipt(携带回测拆腿产生的全部订单 id)."""
55
56
  return api._sim_submit_order(self._s, **kwargs)
56
57
 
57
58
  def cancel_order(self, order_id: str) -> None:
@@ -44,6 +44,7 @@ class StrategyOrder:
44
44
  client_order_id: str = ""
45
45
  broker_order_id: str = ""
46
46
  owner_strategy_id: Optional[str] = None
47
+ group_id: str = ""
47
48
 
48
49
 
49
50
  @dataclass
@@ -62,6 +63,7 @@ class StrategyTrade:
62
63
  client_order_id: str = ""
63
64
  broker_order_id: str = ""
64
65
  owner_strategy_id: Optional[str] = None
66
+ group_id: str = ""
65
67
 
66
68
 
67
69
  _STATUS_MAP = {
@@ -138,8 +140,8 @@ def _to_tif(value: Any) -> Optional[Any]:
138
140
  "GTC": TimeInForce.GTC,
139
141
  "IOC": TimeInForce.IOC,
140
142
  "FOK": TimeInForce.FOK,
141
- "GTD": TimeInForce.GTD,
142
- "DAY": TimeInForce.GTD,
143
+ "GTD": TimeInForce.Day,
144
+ "DAY": TimeInForce.Day,
143
145
  }
144
146
  return mapping.get(text)
145
147
 
@@ -149,6 +151,7 @@ def map_order_snapshot(
149
151
  request: Any = None,
150
152
  owner_strategy_id: Optional[str] = None,
151
153
  local_id: Optional[str] = None,
154
+ group_id: str = "",
152
155
  ) -> StrategyOrder:
153
156
  """把 UnifiedOrderSnapshot 映射成与回测 Order 同形状的 StrategyOrder."""
154
157
  broker_order_id = str(_get(snapshot, "broker_order_id", "") or "")
@@ -186,6 +189,7 @@ def map_order_snapshot(
186
189
  client_order_id=str(_get(snapshot, "client_order_id", "") or ""),
187
190
  broker_order_id=broker_order_id,
188
191
  owner_strategy_id=owner_strategy_id,
192
+ group_id=group_id,
189
193
  )
190
194
 
191
195
 
@@ -236,6 +240,7 @@ def map_trade(
236
240
  request: Any = None,
237
241
  owner_strategy_id: Optional[str] = None,
238
242
  local_id: Optional[str] = None,
243
+ group_id: str = "",
239
244
  ) -> StrategyTrade:
240
245
  """把 UnifiedTrade 映射成与回测 Trade 同形状的 StrategyTrade."""
241
246
  return StrategyTrade(
@@ -251,4 +256,5 @@ def map_trade(
251
256
  client_order_id=str(_get(trade, "client_order_id", "") or ""),
252
257
  broker_order_id=str(_get(trade, "broker_order_id", "") or ""),
253
258
  owner_strategy_id=owner_strategy_id,
259
+ group_id=group_id,
254
260
  )
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Any
5
+ from typing import Any, cast
6
6
 
7
7
  from ..log import get_logger
8
8
  from .broker_event_adapter import map_local_stop, map_order_snapshot
@@ -14,6 +14,7 @@ from .local_stop_book import (
14
14
  is_stop_order_type,
15
15
  underlying_order_type,
16
16
  )
17
+ from .order_receipt import OrderReceipt
17
18
 
18
19
  logger = get_logger("gateway.live")
19
20
 
@@ -30,13 +31,15 @@ class BrokerExecution:
30
31
  state_cache: BrokerStateCache,
31
32
  submitter: Any,
32
33
  record_stop_remap: Any = None,
34
+ group_broker_ids: Any = None,
33
35
  ) -> None:
34
- """绑定策略实例、柜台网关、状态缓存、下单器与止损 remap 回调."""
36
+ """绑定策略实例、柜台网关、状态缓存、下单器、止损 remap 与 group 反查回调."""
35
37
  self._s = strategy
36
38
  self._gw = trader_gateway
37
39
  self._cache = state_cache
38
40
  self._submitter = submitter
39
41
  self._record_stop_remap = record_stop_remap
42
+ self._group_broker_ids = group_broker_ids
40
43
  self._stop_book = LocalStopBook()
41
44
  self._stop_seq = 0
42
45
  self._warned_hold_bar = False
@@ -126,11 +129,12 @@ class BrokerExecution:
126
129
  """获取现金."""
127
130
  return float(getattr(self._cache.account(), "cash", 0.0) or 0.0)
128
131
 
129
- def submit_order(self, **kwargs: Any) -> str:
130
- """提交订单,返回订单号.
132
+ def submit_order(self, **kwargs: Any) -> OrderReceipt:
133
+ """提交订单,返回下单回执(OrderReceipt,含全部腿 id).
131
134
 
132
135
  条件/止损单(trigger_price/trail_offset 或止损类 order_type)拦截入
133
- 本地簿,不下发柜台;柜台不支持这类原生条件单。
136
+ 本地簿,不下发柜台;柜台不支持这类原生条件单——本地止损单只有单一
137
+ 本地 id,封装为单腿 OrderReceipt 以保持返回类型与柜台下单一致。
134
138
 
135
139
  time_in_force=None(Strategy.submit_order 的缺省值)会显式覆盖
136
140
  submitter.submit_order 签名默认值 "GTC";这里丢弃 None,
@@ -141,10 +145,16 @@ class BrokerExecution:
141
145
  or kwargs.get("trail_offset") is not None
142
146
  or is_stop_order_type(kwargs.get("order_type"))
143
147
  ):
144
- return self._register_local_stop(**kwargs)
148
+ local_id = self._register_local_stop(**kwargs)
149
+ return OrderReceipt.single(
150
+ group_id=local_id,
151
+ broker_order_id=local_id,
152
+ position_effect=str(kwargs.get("position_effect") or "auto"),
153
+ client_order_id=local_id,
154
+ )
145
155
  if kwargs.get("time_in_force") is None:
146
156
  kwargs.pop("time_in_force", None)
147
- return str(self._submitter.submit_order(**kwargs))
157
+ return cast(OrderReceipt, self._submitter.submit_order(**kwargs))
148
158
 
149
159
  def _next_local_stop_id(self) -> str:
150
160
  self._stop_seq += 1
@@ -205,7 +215,7 @@ class BrokerExecution:
205
215
  if order.time_in_force is not None:
206
216
  kwargs["time_in_force"] = order.time_in_force
207
217
  try:
208
- broker_order_id = str(self._submitter.submit_order(**kwargs))
218
+ broker_order_id = str(self._submitter.submit_order(**kwargs).primary)
209
219
  except Exception as exc: # noqa: BLE001
210
220
  order.submit_attempts += 1
211
221
  if order.submit_attempts < MAX_STOP_SUBMIT_ATTEMPTS:
@@ -233,6 +243,15 @@ class BrokerExecution:
233
243
  return
234
244
  self._gw.cancel_order(str(order_id))
235
245
 
246
+ def cancel_group(self, group_id: str) -> None:
247
+ """撤销一个逻辑委托的全部腿(按 group_id)."""
248
+ gid = str(group_id)
249
+ if self._group_broker_ids is None:
250
+ return
251
+ for broker_order_id in self._group_broker_ids(gid):
252
+ if broker_order_id:
253
+ self.cancel_order(str(broker_order_id))
254
+
236
255
  def cancel_all_orders(self, symbol: str | None = None) -> None:
237
256
  """取消所有未完成订单(含本地止损)."""
238
257
  for order in self._stop_book.open_orders(symbol):
@@ -195,6 +195,7 @@ class UnifiedOrderSnapshot:
195
195
  reject_reason: str = ""
196
196
  timestamp_ns: int = 0
197
197
  position_effect: str = "auto"
198
+ group_id: str = ""
198
199
 
199
200
 
200
201
  @dataclass
@@ -210,6 +211,7 @@ class UnifiedTrade:
210
211
  price: float
211
212
  timestamp_ns: int
212
213
  position_effect: str = "auto"
214
+ group_id: str = ""
213
215
 
214
216
 
215
217
  @dataclass
@@ -225,6 +227,7 @@ class UnifiedExecutionReport:
225
227
  reject_reason: str = ""
226
228
  timestamp_ns: int = 0
227
229
  position_effect: str = "auto"
230
+ group_id: str = ""
228
231
 
229
232
 
230
233
  @dataclass
@@ -38,6 +38,8 @@ class BrokerRuntime:
38
38
  adapt_strategy_payload: Callable[[str, Any], Any],
39
39
  record_stop_remap: Any = None,
40
40
  should_replay_trades: Callable[[], bool] | None = None,
41
+ sync_group_mapping: Callable[[str, str], None] = lambda _c, _g: None,
42
+ group_broker_ids: Callable[[str], list[str]] | None = None,
41
43
  ) -> None:
42
44
  """Assemble broker submitter, event bridge and recovery coordinators."""
43
45
  self._broker_state_caches: list[Any] = []
@@ -76,6 +78,8 @@ class BrokerRuntime:
76
78
  self._get_execution_capabilities = get_execution_capabilities
77
79
  self._record_order_request = record_order_request
78
80
  self._record_stop_remap = record_stop_remap
81
+ self._sync_group_mapping = sync_group_mapping
82
+ self._group_broker_ids = group_broker_ids
79
83
  self._submitter: BrokerOrderSubmitter | None = None
80
84
 
81
85
  @property
@@ -114,6 +118,7 @@ class BrokerRuntime:
114
118
  payload_field=self._payload_field,
115
119
  get_execution_capabilities=self._get_execution_capabilities,
116
120
  record_order_request=self._record_order_request,
121
+ sync_group_mapping=self._sync_group_mapping,
117
122
  )
118
123
  self._submitter.install()
119
124
 
@@ -130,6 +135,7 @@ class BrokerRuntime:
130
135
  cache,
131
136
  self._submitter,
132
137
  record_stop_remap=self._record_stop_remap,
138
+ group_broker_ids=self._group_broker_ids,
133
139
  )
134
140
 
135
141
  return self._submitter
@@ -0,0 +1,60 @@
1
+ """OrderReceipt: 逻辑委托的返回句柄,携带跨边界拆出的全部腿 id 与语义."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import Iterator
7
+
8
+
9
+ @dataclass(frozen=True)
10
+ class OrderLeg:
11
+ """单腿委托:语义 + client/broker id."""
12
+
13
+ position_effect: str
14
+ quantity: float
15
+ client_order_id: str
16
+ broker_order_id: str
17
+
18
+
19
+ @dataclass(frozen=True)
20
+ class OrderReceipt:
21
+ """一次下单调用的结果:一个逻辑委托可拆成多腿分别报单."""
22
+
23
+ group_id: str
24
+ order_ids: tuple[str, ...]
25
+ legs: tuple[OrderLeg, ...]
26
+
27
+ def __str__(self) -> str:
28
+ """Return group_id as string representation."""
29
+ return self.group_id
30
+
31
+ def __iter__(self) -> Iterator[str]:
32
+ """Iterate over order_ids."""
33
+ return iter(self.order_ids)
34
+
35
+ def __len__(self) -> int:
36
+ """Return count of order_ids."""
37
+ return len(self.order_ids)
38
+
39
+ @property
40
+ def primary(self) -> str:
41
+ """Return first order_id or empty string if no ids."""
42
+ return self.order_ids[0] if self.order_ids else ""
43
+
44
+ @classmethod
45
+ def single(
46
+ cls,
47
+ group_id: str,
48
+ broker_order_id: str,
49
+ position_effect: str = "auto",
50
+ quantity: float = 0.0,
51
+ client_order_id: str = "",
52
+ ) -> "OrderReceipt":
53
+ """Create a single-leg receipt for convenience."""
54
+ leg = OrderLeg(
55
+ position_effect=position_effect,
56
+ quantity=quantity,
57
+ client_order_id=client_order_id or group_id,
58
+ broker_order_id=broker_order_id,
59
+ )
60
+ return cls(group_id=group_id, order_ids=(broker_order_id,), legs=(leg,))
@@ -8,6 +8,7 @@ from .broker_models import (
8
8
  validate_broker_extra,
9
9
  validate_execution_semantics,
10
10
  )
11
+ from .order_receipt import OrderLeg, OrderReceipt
11
12
 
12
13
  logger = get_logger("gateway.live")
13
14
 
@@ -38,49 +39,38 @@ def find_live_close_position(
38
39
  return None
39
40
 
40
41
 
41
- def resolve_live_order_legs(
42
+ def _split_close_legs(
42
43
  trader_gateway: Any,
43
44
  capability: BrokerCapability,
44
45
  symbol: str,
45
46
  side: str,
46
47
  quantity: float,
47
- position_effect: str,
48
- reduce_only: bool,
48
+ supported_effects: set[str],
49
49
  payload_field: Callable[[Any, str], Any],
50
50
  ) -> list[tuple[str, float]]:
51
- """Resolve close orders into close_today/close_yesterday legs when supported."""
52
- normalized_effect = str(position_effect).strip().lower()
53
- if quantity <= 0 or reduce_only or normalized_effect != "close":
54
- return [(normalized_effect, quantity)]
55
- supported_effects = {
56
- str(item).strip().lower() for item in capability.supported_position_effects
57
- }
51
+ """把一段平仓量拆成 close_today/close_yesterday;能力不足则整段 close."""
58
52
  if not capability.position_details:
59
- return [(normalized_effect, quantity)]
53
+ return [("close", quantity)]
60
54
  if (
61
55
  "close_today" not in supported_effects
62
56
  or "close_yesterday" not in supported_effects
63
57
  ):
64
- return [(normalized_effect, quantity)]
65
-
58
+ return [("close", quantity)]
66
59
  query_positions = getattr(trader_gateway, "query_positions", None)
67
60
  if not callable(query_positions):
68
- return [(normalized_effect, quantity)]
61
+ return [("close", quantity)]
69
62
  try:
70
63
  positions = query_positions()
71
64
  except Exception:
72
- return [(normalized_effect, quantity)]
73
-
65
+ return [("close", quantity)]
74
66
  target_position = find_live_close_position(positions, symbol, side, payload_field)
75
67
  if target_position is None:
76
- return [(normalized_effect, quantity)]
77
-
68
+ return [("close", quantity)]
78
69
  available_today = max(
79
70
  0.0, float(getattr(target_position, "available_today_quantity", 0.0) or 0.0)
80
71
  )
81
72
  available_yesterday = max(
82
- 0.0,
83
- float(getattr(target_position, "available_yesterday_quantity", 0.0) or 0.0),
73
+ 0.0, float(getattr(target_position, "available_yesterday_quantity", 0.0) or 0.0)
84
74
  )
85
75
  split_quantity = min(quantity, available_today + available_yesterday)
86
76
  legs: list[tuple[str, float]] = []
@@ -99,6 +89,95 @@ def resolve_live_order_legs(
99
89
  return legs
100
90
 
101
91
 
92
+ def resolve_live_order_legs(
93
+ trader_gateway: Any,
94
+ capability: BrokerCapability,
95
+ symbol: str,
96
+ side: str,
97
+ quantity: float,
98
+ position_effect: str,
99
+ reduce_only: bool,
100
+ payload_field: Callable[[Any, str], Any],
101
+ ) -> list[tuple[str, float]]:
102
+ """Resolve close orders into close_today/close_yesterday legs when supported.
103
+
104
+ Also resolves `auto` reversal orders (sell/buy quantity exceeding the opposite
105
+ position) into close leg(s) plus a trailing `open` leg, unless the broker
106
+ declares it handles reversal itself via `"auto_reverse" in capability.features`.
107
+ """
108
+ normalized_effect = str(position_effect).strip().lower()
109
+ if quantity <= 0 or reduce_only:
110
+ return [(normalized_effect, quantity)]
111
+
112
+ supported_effects = {
113
+ str(item).strip().lower() for item in capability.supported_position_effects
114
+ }
115
+
116
+ # 反手:auto 单卖出量超过反向持仓可用量时,核心拆成 平仓 + 开仓。
117
+ # broker 若声明自身会反手(auto_reverse),则不拆。
118
+ if normalized_effect == "auto":
119
+ if "auto_reverse" in capability.features:
120
+ return [(normalized_effect, quantity)]
121
+ if "open" not in supported_effects or "close" not in supported_effects:
122
+ return [(normalized_effect, quantity)]
123
+ query_positions = getattr(trader_gateway, "query_positions", None)
124
+ if not callable(query_positions):
125
+ return [(normalized_effect, quantity)]
126
+ try:
127
+ positions = query_positions()
128
+ except Exception:
129
+ return [(normalized_effect, quantity)]
130
+ target = find_live_close_position(positions, symbol, side, payload_field)
131
+ if target is None:
132
+ return [(normalized_effect, quantity)]
133
+ raw_today = payload_field(target, "available_today_quantity")
134
+ raw_yesterday = payload_field(target, "available_yesterday_quantity")
135
+ raw_available = payload_field(target, "available_quantity")
136
+ has_availability = any(
137
+ value is not None for value in (raw_today, raw_yesterday, raw_available)
138
+ )
139
+ available_split = max(0.0, float(raw_today or 0.0)) + max(
140
+ 0.0, float(raw_yesterday or 0.0)
141
+ )
142
+ available_quantity = max(0.0, float(raw_available or 0.0))
143
+ raw_quantity = abs(float(payload_field(target, "quantity") or 0.0))
144
+ # 可平口径与 _split_close_legs 一致: broker 报可用量时优先用今昨可用量,
145
+ # 其次 available_quantity(即便为 0 也不回退——全冻结应交由下方 closable<=0
146
+ # 门槛退回单腿 auto); 仅当 broker 完全不提供可用量字段时才退回原始持仓。
147
+ if has_availability:
148
+ closable = available_split if available_split > 0 else available_quantity
149
+ else:
150
+ closable = raw_quantity
151
+ if closable <= 0 or quantity <= closable:
152
+ return [(normalized_effect, quantity)]
153
+ close_qty = closable
154
+ open_qty = quantity - closable
155
+ legs = _split_close_legs(
156
+ trader_gateway,
157
+ capability,
158
+ symbol,
159
+ side,
160
+ close_qty,
161
+ supported_effects,
162
+ payload_field,
163
+ )
164
+ legs.append(("open", open_qty))
165
+ return legs
166
+
167
+ if normalized_effect != "close":
168
+ return [(normalized_effect, quantity)]
169
+
170
+ return _split_close_legs(
171
+ trader_gateway,
172
+ capability,
173
+ symbol,
174
+ side,
175
+ quantity,
176
+ supported_effects,
177
+ payload_field,
178
+ )
179
+
180
+
102
181
  def build_live_order_client_ids(
103
182
  request_client_order_id: str, order_legs: list[tuple[str, float]]
104
183
  ) -> list[str]:
@@ -169,6 +248,7 @@ class BrokerOrderSubmitter:
169
248
  payload_field: Callable[[Any, str], Any],
170
249
  get_execution_capabilities: Callable[[], dict[str, Any]],
171
250
  record_order_request: Callable[[str, Any], None],
251
+ sync_group_mapping: Callable[[str, str], None] = lambda _c, _g: None,
172
252
  ) -> None:
173
253
  """Bind strategy injection hooks, id mapping and capability callbacks."""
174
254
  self._trader_gateway = trader_gateway
@@ -182,6 +262,7 @@ class BrokerOrderSubmitter:
182
262
  self._payload_field = payload_field
183
263
  self._get_execution_capabilities = get_execution_capabilities
184
264
  self._record_order_request = record_order_request
265
+ self._sync_group_mapping = sync_group_mapping
185
266
  self._warned_ignored_params: set[str] = set()
186
267
 
187
268
  def install(self) -> None:
@@ -213,8 +294,17 @@ class BrokerOrderSubmitter:
213
294
  trail_offset: float | None = None,
214
295
  trail_reference_price: float | None = None,
215
296
  broker_options: dict[str, Any] | None = None,
216
- ) -> str:
217
- """Submit a live broker order using the unified strategy-facing signature."""
297
+ ) -> OrderReceipt:
298
+ """Submit a live broker order using the unified strategy-facing signature.
299
+
300
+ Returns an `OrderReceipt`, not a single id string: a logical order can be
301
+ split into multiple legs (e.g. close_today/close_yesterday, or a reversal's
302
+ close+open legs), each with its own client/broker order id. `receipt.primary`
303
+ is the *first leg's* `broker_order_id` (the value production call sites use
304
+ as "the" order id); `str(receipt)` is the `group_id` (client order id) and is
305
+ a *different* id space in production brokers — do not use them
306
+ interchangeably.
307
+ """
218
308
  if not getattr(self._strategy, "broker_ready", True):
219
309
  raise RuntimeError(
220
310
  "broker 尚未就绪,请在 broker_ready=True"
@@ -279,6 +369,7 @@ class BrokerOrderSubmitter:
279
369
  notify_strategy_error=self._notify_strategy_error,
280
370
  )
281
371
  broker_order_ids: list[str] = []
372
+ legs: list[OrderLeg] = []
282
373
  for leg_index, (leg_position_effect, leg_quantity) in enumerate(order_legs):
283
374
  request = UnifiedOrderRequest(
284
375
  client_order_id=client_order_ids[leg_index],
@@ -300,4 +391,17 @@ class BrokerOrderSubmitter:
300
391
  self._bind_order_owner(
301
392
  request.client_order_id, broker_order_id, owner_strategy_id
302
393
  )
303
- return broker_order_ids[0]
394
+ self._sync_group_mapping(request.client_order_id, request_client_order_id)
395
+ legs.append(
396
+ OrderLeg(
397
+ position_effect=leg_position_effect,
398
+ quantity=leg_quantity,
399
+ client_order_id=request.client_order_id,
400
+ broker_order_id=broker_order_id,
401
+ )
402
+ )
403
+ return OrderReceipt(
404
+ group_id=request_client_order_id,
405
+ order_ids=tuple(broker_order_ids),
406
+ legs=tuple(legs),
407
+ )