akquant 0.2.40__tar.gz → 0.2.41__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 (493) hide show
  1. {akquant-0.2.40 → akquant-0.2.41}/Cargo.lock +1 -1
  2. {akquant-0.2.40 → akquant-0.2.41}/Cargo.toml +1 -1
  3. {akquant-0.2.40 → akquant-0.2.41}/PKG-INFO +1 -1
  4. {akquant-0.2.40 → akquant-0.2.41}/docs/en/advanced/llm.md +2 -2
  5. {akquant-0.2.40 → akquant-0.2.41}/docs/en/guide/strategy.md +12 -0
  6. {akquant-0.2.40 → akquant-0.2.41}/docs/en/reference/api.md +7 -1
  7. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/advanced/llm.md +2 -2
  8. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/advanced/timezone.md +1 -1
  9. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/guide/strategy.md +8 -0
  10. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/reference/api.md +5 -1
  11. {akquant-0.2.40 → akquant-0.2.41}/pyproject.toml +1 -1
  12. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/akquant.pyi +17 -0
  13. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/strategy_position.py +14 -1
  14. {akquant-0.2.40 → akquant-0.2.41}/src/context.rs +33 -0
  15. {akquant-0.2.40 → akquant-0.2.41}/src/engine/core.rs +20 -0
  16. {akquant-0.2.40 → akquant-0.2.41}/tests/test_engine.py +102 -0
  17. {akquant-0.2.40 → akquant-0.2.41}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  18. {akquant-0.2.40 → akquant-0.2.41}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  19. {akquant-0.2.40 → akquant-0.2.41}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  20. {akquant-0.2.40 → akquant-0.2.41}/.github/workflows/deploy-docs.yml +0 -0
  21. {akquant-0.2.40 → akquant-0.2.41}/.github/workflows/docs-quality.yml +0 -0
  22. {akquant-0.2.40 → akquant-0.2.41}/.github/workflows/release.yml +0 -0
  23. {akquant-0.2.40 → akquant-0.2.41}/.gitignore +0 -0
  24. {akquant-0.2.40 → akquant-0.2.41}/.pre-commit-config.yaml +0 -0
  25. {akquant-0.2.40 → akquant-0.2.41}/CHANGELOG.md +0 -0
  26. {akquant-0.2.40 → akquant-0.2.41}/CODE_OF_CONDUCT.md +0 -0
  27. {akquant-0.2.40 → akquant-0.2.41}/CONTRIBUTING.md +0 -0
  28. {akquant-0.2.40 → akquant-0.2.41}/LICENSE +0 -0
  29. {akquant-0.2.40 → akquant-0.2.41}/README.md +0 -0
  30. {akquant-0.2.40 → akquant-0.2.41}/assets/dashboard_preview.png +0 -0
  31. {akquant-0.2.40 → akquant-0.2.41}/assets/logo.svg +0 -0
  32. {akquant-0.2.40 → akquant-0.2.41}/assets/social_preview.png +0 -0
  33. {akquant-0.2.40 → akquant-0.2.41}/docs/CNAME +0 -0
  34. {akquant-0.2.40 → akquant-0.2.41}/docs/assets/akquant-icon.svg +0 -0
  35. {akquant-0.2.40 → akquant-0.2.41}/docs/assets/akquant-logo.svg +0 -0
  36. {akquant-0.2.40 → akquant-0.2.41}/docs/assets/reports/akquant_report.html +0 -0
  37. {akquant-0.2.40 → akquant-0.2.41}/docs/en/advanced/analyzer_plugin_spec.md +0 -0
  38. {akquant-0.2.40 → akquant-0.2.41}/docs/en/advanced/broker_capability_matrix.md +0 -0
  39. {akquant-0.2.40 → akquant-0.2.41}/docs/en/advanced/custom_broker_production_checklist.md +0 -0
  40. {akquant-0.2.40 → akquant-0.2.41}/docs/en/advanced/custom_broker_registry.md +0 -0
  41. {akquant-0.2.40 → akquant-0.2.41}/docs/en/advanced/data_feed_adapter_spec.md +0 -0
  42. {akquant-0.2.40 → akquant-0.2.41}/docs/en/advanced/live_functional_quickstart.md +0 -0
  43. {akquant-0.2.40 → akquant-0.2.41}/docs/en/advanced/ml.md +0 -0
  44. {akquant-0.2.40 → akquant-0.2.41}/docs/en/advanced/multi_strategy_guide.md +0 -0
  45. {akquant-0.2.40 → akquant-0.2.41}/docs/en/advanced/multi_timeframe_feed_api.md +0 -0
  46. {akquant-0.2.40 → akquant-0.2.41}/docs/en/advanced/runtime_config.md +0 -0
  47. {akquant-0.2.40 → akquant-0.2.41}/docs/en/advanced/strategy_style_decision.md +0 -0
  48. {akquant-0.2.40 → akquant-0.2.41}/docs/en/advanced/timezone.md +0 -0
  49. {akquant-0.2.40 → akquant-0.2.41}/docs/en/advanced/warm_start.md +0 -0
  50. {akquant-0.2.40 → akquant-0.2.41}/docs/en/guide/analysis.md +0 -0
  51. {akquant-0.2.40 → akquant-0.2.41}/docs/en/guide/cross_section_checklist.md +0 -0
  52. {akquant-0.2.40 → akquant-0.2.41}/docs/en/guide/custom_indicator.md +0 -0
  53. {akquant-0.2.40 → akquant-0.2.41}/docs/en/guide/data.md +0 -0
  54. {akquant-0.2.40 → akquant-0.2.41}/docs/en/guide/examples.md +0 -0
  55. {akquant-0.2.40 → akquant-0.2.41}/docs/en/guide/factor.md +0 -0
  56. {akquant-0.2.40 → akquant-0.2.41}/docs/en/guide/indicator_scenario_quickref.md +0 -0
  57. {akquant-0.2.40 → akquant-0.2.41}/docs/en/guide/optimization.md +0 -0
  58. {akquant-0.2.40 → akquant-0.2.41}/docs/en/guide/python_basics.md +0 -0
  59. {akquant-0.2.40 → akquant-0.2.41}/docs/en/guide/quant_basics.md +0 -0
  60. {akquant-0.2.40 → akquant-0.2.41}/docs/en/guide/rust_indicator_reference.md +0 -0
  61. {akquant-0.2.40 → akquant-0.2.41}/docs/en/guide/talib_indicator_playbook.md +0 -0
  62. {akquant-0.2.40 → akquant-0.2.41}/docs/en/guide/testing.md +0 -0
  63. {akquant-0.2.40 → akquant-0.2.41}/docs/en/guide/visualization.md +0 -0
  64. {akquant-0.2.40 → akquant-0.2.41}/docs/en/index.md +0 -0
  65. {akquant-0.2.40 → akquant-0.2.41}/docs/en/meta/architecture.md +0 -0
  66. {akquant-0.2.40 → akquant-0.2.41}/docs/en/meta/internals.md +0 -0
  67. {akquant-0.2.40 → akquant-0.2.41}/docs/en/start/first_strategy.md +0 -0
  68. {akquant-0.2.40 → akquant-0.2.41}/docs/en/start/installation.md +0 -0
  69. {akquant-0.2.40 → akquant-0.2.41}/docs/en/start/quickstart.md +0 -0
  70. {akquant-0.2.40 → akquant-0.2.41}/docs/en/start/setup_guide.md +0 -0
  71. {akquant-0.2.40 → akquant-0.2.41}/docs/en/textbook/01_foundations.md +0 -0
  72. {akquant-0.2.40 → akquant-0.2.41}/docs/en/textbook/02_programming.md +0 -0
  73. {akquant-0.2.40 → akquant-0.2.41}/docs/en/textbook/03_data.md +0 -0
  74. {akquant-0.2.40 → akquant-0.2.41}/docs/en/textbook/04_backtest_engine.md +0 -0
  75. {akquant-0.2.40 → akquant-0.2.41}/docs/en/textbook/05_strategy.md +0 -0
  76. {akquant-0.2.40 → akquant-0.2.41}/docs/en/textbook/06_stock_a.md +0 -0
  77. {akquant-0.2.40 → akquant-0.2.41}/docs/en/textbook/07_futures.md +0 -0
  78. {akquant-0.2.40 → akquant-0.2.41}/docs/en/textbook/08_options.md +0 -0
  79. {akquant-0.2.40 → akquant-0.2.41}/docs/en/textbook/09_funds.md +0 -0
  80. {akquant-0.2.40 → akquant-0.2.41}/docs/en/textbook/10_analysis.md +0 -0
  81. {akquant-0.2.40 → akquant-0.2.41}/docs/en/textbook/11_optimization.md +0 -0
  82. {akquant-0.2.40 → akquant-0.2.41}/docs/en/textbook/12_ml.md +0 -0
  83. {akquant-0.2.40 → akquant-0.2.41}/docs/en/textbook/13_visualization.md +0 -0
  84. {akquant-0.2.40 → akquant-0.2.41}/docs/en/textbook/14_factor.md +0 -0
  85. {akquant-0.2.40 → akquant-0.2.41}/docs/en/textbook/15_live_trading.md +0 -0
  86. {akquant-0.2.40 → akquant-0.2.41}/docs/en/textbook/16_rust_indicators.md +0 -0
  87. {akquant-0.2.40 → akquant-0.2.41}/docs/en/textbook/index.md +0 -0
  88. {akquant-0.2.40 → akquant-0.2.41}/docs/javascripts/mathjax.js +0 -0
  89. {akquant-0.2.40 → akquant-0.2.41}/docs/javascripts/search-lang-filter.js +0 -0
  90. {akquant-0.2.40 → akquant-0.2.41}/docs/robots.txt +0 -0
  91. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/advanced/analyzer_plugin_spec.md +0 -0
  92. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/advanced/broker_capability_matrix.md +0 -0
  93. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/advanced/custom_broker_production_checklist.md +0 -0
  94. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/advanced/custom_broker_registry.md +0 -0
  95. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/advanced/data_feed_adapter_spec.md +0 -0
  96. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/advanced/live_functional_quickstart.md +0 -0
  97. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/advanced/ml.md +0 -0
  98. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/advanced/multi_strategy_guide.md +0 -0
  99. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/advanced/multi_timeframe_feed_api.md +0 -0
  100. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/advanced/runtime_config.md +0 -0
  101. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/advanced/strategy_style_decision.md +0 -0
  102. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/advanced/warm_start.md +0 -0
  103. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/guide/analysis.md +0 -0
  104. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/guide/cross_section_checklist.md +0 -0
  105. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/guide/custom_indicator.md +0 -0
  106. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/guide/data.md +0 -0
  107. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/guide/examples.md +0 -0
  108. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/guide/factor.md +0 -0
  109. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/guide/indicator_scenario_quickref.md +0 -0
  110. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/guide/optimization.md +0 -0
  111. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/guide/python_basics.md +0 -0
  112. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/guide/quant_basics.md +0 -0
  113. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/guide/rust_indicator_reference.md +0 -0
  114. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/guide/talib_indicator_playbook.md +0 -0
  115. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/guide/testing.md +0 -0
  116. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/guide/visualization.md +0 -0
  117. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/index.md +0 -0
  118. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/meta/architecture.md +0 -0
  119. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/meta/internals.md +0 -0
  120. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/start/first_strategy.md +0 -0
  121. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/start/installation.md +0 -0
  122. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/start/quickstart.md +0 -0
  123. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/start/setup_guide.md +0 -0
  124. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/textbook/01_foundations.md +0 -0
  125. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/textbook/02_programming.md +0 -0
  126. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/textbook/03_data.md +0 -0
  127. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/textbook/04_backtest_engine.md +0 -0
  128. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/textbook/05_strategy.md +0 -0
  129. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/textbook/06_stock_a.md +0 -0
  130. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/textbook/07_futures.md +0 -0
  131. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/textbook/08_options.md +0 -0
  132. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/textbook/09_funds.md +0 -0
  133. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/textbook/10_analysis.md +0 -0
  134. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/textbook/11_optimization.md +0 -0
  135. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/textbook/12_ml.md +0 -0
  136. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/textbook/13_visualization.md +0 -0
  137. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/textbook/14_factor.md +0 -0
  138. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/textbook/15_live_trading.md +0 -0
  139. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/textbook/16_rust_indicators.md +0 -0
  140. {akquant-0.2.40 → akquant-0.2.41}/docs/zh/textbook/index.md +0 -0
  141. {akquant-0.2.40 → akquant-0.2.41}/examples/01_quickstart.py +0 -0
  142. {akquant-0.2.40 → akquant-0.2.41}/examples/02_parameter_optimization.py +0 -0
  143. {akquant-0.2.40 → akquant-0.2.41}/examples/03_parameter_optimization_advanced.py +0 -0
  144. {akquant-0.2.40 → akquant-0.2.41}/examples/04_mixed_assets.py +0 -0
  145. {akquant-0.2.40 → akquant-0.2.41}/examples/05_live_trading_ctp.py +0 -0
  146. {akquant-0.2.40 → akquant-0.2.41}/examples/06_complex_orders.py +0 -0
  147. {akquant-0.2.40 → akquant-0.2.41}/examples/07_option_test.py +0 -0
  148. {akquant-0.2.40 → akquant-0.2.41}/examples/08_event_callbacks.py +0 -0
  149. {akquant-0.2.40 → akquant-0.2.41}/examples/09_ml_framework.py +0 -0
  150. {akquant-0.2.40 → akquant-0.2.41}/examples/10_ml_walk_forward.py +0 -0
  151. {akquant-0.2.40 → akquant-0.2.41}/examples/11_plot_visualization.py +0 -0
  152. {akquant-0.2.40 → akquant-0.2.41}/examples/12_wfo_integrated.py +0 -0
  153. {akquant-0.2.40 → akquant-0.2.41}/examples/13_quantstats_report.py +0 -0
  154. {akquant-0.2.40 → akquant-0.2.41}/examples/14_multi_frequency.py +0 -0
  155. {akquant-0.2.40 → akquant-0.2.41}/examples/15_plot_intraday.py +0 -0
  156. {akquant-0.2.40 → akquant-0.2.41}/examples/16_adj_returns_signal.py +0 -0
  157. {akquant-0.2.40 → akquant-0.2.41}/examples/17_readme_demo.py +0 -0
  158. {akquant-0.2.40 → akquant-0.2.41}/examples/18_benchmark_multisymbol.py +0 -0
  159. {akquant-0.2.40 → akquant-0.2.41}/examples/19_factor_expression.py +0 -0
  160. {akquant-0.2.40 → akquant-0.2.41}/examples/20_risk_management_demo.py +0 -0
  161. {akquant-0.2.40 → akquant-0.2.41}/examples/21_warm_start_demo.py +0 -0
  162. {akquant-0.2.40 → akquant-0.2.41}/examples/22_strategy_runtime_config_demo.py +0 -0
  163. {akquant-0.2.40 → akquant-0.2.41}/examples/23_functional_callbacks_demo.py +0 -0
  164. {akquant-0.2.40 → akquant-0.2.41}/examples/24_functional_tick_simulation_demo.py +0 -0
  165. {akquant-0.2.40 → akquant-0.2.41}/examples/25_streaming_backtest_demo.py +0 -0
  166. {akquant-0.2.40 → akquant-0.2.41}/examples/26_streaming_quickstart.py +0 -0
  167. {akquant-0.2.40 → akquant-0.2.41}/examples/27_streaming_monitoring_console.py +0 -0
  168. {akquant-0.2.40 → akquant-0.2.41}/examples/28_streaming_alerts_and_persist.py +0 -0
  169. {akquant-0.2.40 → akquant-0.2.41}/examples/29_streaming_event_report.py +0 -0
  170. {akquant-0.2.40 → akquant-0.2.41}/examples/30_streaming_report_oneclick.py +0 -0
  171. {akquant-0.2.40 → akquant-0.2.41}/examples/31_streaming_live_console.py +0 -0
  172. {akquant-0.2.40 → akquant-0.2.41}/examples/32_streaming_live_web.py +0 -0
  173. {akquant-0.2.40 → akquant-0.2.41}/examples/33_report_and_analysis_outputs.py +0 -0
  174. {akquant-0.2.40 → akquant-0.2.41}/examples/34_multi_strategy_demo.py +0 -0
  175. {akquant-0.2.40 → akquant-0.2.41}/examples/35_custom_broker_registry_demo.py +0 -0
  176. {akquant-0.2.40 → akquant-0.2.41}/examples/36_trailing_orders.py +0 -0
  177. {akquant-0.2.40 → akquant-0.2.41}/examples/37_feed_replay_alignment_demo.py +0 -0
  178. {akquant-0.2.40 → akquant-0.2.41}/examples/38_live_functional_strategy_demo.py +0 -0
  179. {akquant-0.2.40 → akquant-0.2.41}/examples/39_live_broker_submit_order_demo.py +0 -0
  180. {akquant-0.2.40 → akquant-0.2.41}/examples/40_functional_multi_slot_risk_demo.py +0 -0
  181. {akquant-0.2.40 → akquant-0.2.41}/examples/41_live_multi_slot_orchestration_demo.py +0 -0
  182. {akquant-0.2.40 → akquant-0.2.41}/examples/42_live_broker_event_audit_demo.py +0 -0
  183. {akquant-0.2.40 → akquant-0.2.41}/examples/43_target_weights_rebalance.py +0 -0
  184. {akquant-0.2.40 → akquant-0.2.41}/examples/44_strategy_source_loader_demo.py +0 -0
  185. {akquant-0.2.40 → akquant-0.2.41}/examples/45_talib_indicator_playbook_demo.py +0 -0
  186. {akquant-0.2.40 → akquant-0.2.41}/examples/46_broker_profile_demo.py +0 -0
  187. {akquant-0.2.40 → akquant-0.2.41}/examples/47_margin_liquidation_audit_demo.py +0 -0
  188. {akquant-0.2.40 → akquant-0.2.41}/examples/48_margin_liquidation_priority_compare.py +0 -0
  189. {akquant-0.2.40 → akquant-0.2.41}/examples/49_on_expiry_demo.py +0 -0
  190. {akquant-0.2.40 → akquant-0.2.41}/examples/50_framework_hooks_demo.py +0 -0
  191. {akquant-0.2.40 → akquant-0.2.41}/examples/51_class_tick_callbacks_demo.py +0 -0
  192. {akquant-0.2.40 → akquant-0.2.41}/examples/52_pre_open_demo.py +0 -0
  193. {akquant-0.2.40 → akquant-0.2.41}/examples/53_timer_to_pre_open_demo.py +0 -0
  194. {akquant-0.2.40 → akquant-0.2.41}/examples/54_functional_pre_open_demo.py +0 -0
  195. {akquant-0.2.40 → akquant-0.2.41}/examples/55_functional_ml_walk_forward.py +0 -0
  196. {akquant-0.2.40 → akquant-0.2.41}/examples/56_functional_warm_start_demo.py +0 -0
  197. {akquant-0.2.40 → akquant-0.2.41}/examples/57_functional_multi_slot_warm_start_demo.py +0 -0
  198. {akquant-0.2.40 → akquant-0.2.41}/examples/58_incremental_bootstrap_demo.py +0 -0
  199. {akquant-0.2.40 → akquant-0.2.41}/examples/59_akshare_etf_rotation.py +0 -0
  200. {akquant-0.2.40 → akquant-0.2.41}/examples/60_custom_indicator_demo.py +0 -0
  201. {akquant-0.2.40 → akquant-0.2.41}/examples/61_indicator_visualization_export_demo.py +0 -0
  202. {akquant-0.2.40 → akquant-0.2.41}/examples/62_indicator_streaming_demo.py +0 -0
  203. {akquant-0.2.40 → akquant-0.2.41}/examples/63_indicator_ws_bridge_demo.py +0 -0
  204. {akquant-0.2.40 → akquant-0.2.41}/examples/64_indicator_live_web.py +0 -0
  205. {akquant-0.2.40 → akquant-0.2.41}/examples/README.md +0 -0
  206. {akquant-0.2.40 → akquant-0.2.41}/examples/benchmark_utils.py +0 -0
  207. {akquant-0.2.40 → akquant-0.2.41}/examples/pb_mock.py +0 -0
  208. {akquant-0.2.40 → akquant-0.2.41}/examples/strategies/01_stock_dual_moving_average.py +0 -0
  209. {akquant-0.2.40 → akquant-0.2.41}/examples/strategies/02_stock_grid_trading.py +0 -0
  210. {akquant-0.2.40 → akquant-0.2.41}/examples/strategies/03_stock_atr_breakout.py +0 -0
  211. {akquant-0.2.40 → akquant-0.2.41}/examples/strategies/04_stock_momentum_rotation.py +0 -0
  212. {akquant-0.2.40 → akquant-0.2.41}/examples/strategies/05_stock_momentum_rotation_timer.py +0 -0
  213. {akquant-0.2.40 → akquant-0.2.41}/examples/strategies/06_stock_momentum_rotation_bucket.py +0 -0
  214. {akquant-0.2.40 → akquant-0.2.41}/examples/strategies/07_stock_momentum_rotation_on_timer.py +0 -0
  215. {akquant-0.2.40 → akquant-0.2.41}/examples/strategies/08_target_positions_long_short.py +0 -0
  216. {akquant-0.2.40 → akquant-0.2.41}/examples/strategies/README.md +0 -0
  217. {akquant-0.2.40 → akquant-0.2.41}/examples/textbook/ch01_quickstart.py +0 -0
  218. {akquant-0.2.40 → akquant-0.2.41}/examples/textbook/ch02_programming.py +0 -0
  219. {akquant-0.2.40 → akquant-0.2.41}/examples/textbook/ch03_data.py +0 -0
  220. {akquant-0.2.40 → akquant-0.2.41}/examples/textbook/ch04_comparison.py +0 -0
  221. {akquant-0.2.40 → akquant-0.2.41}/examples/textbook/ch05_strategy.py +0 -0
  222. {akquant-0.2.40 → akquant-0.2.41}/examples/textbook/ch06_stock_a.py +0 -0
  223. {akquant-0.2.40 → akquant-0.2.41}/examples/textbook/ch07_futures.py +0 -0
  224. {akquant-0.2.40 → akquant-0.2.41}/examples/textbook/ch08_options.py +0 -0
  225. {akquant-0.2.40 → akquant-0.2.41}/examples/textbook/ch09_funds.py +0 -0
  226. {akquant-0.2.40 → akquant-0.2.41}/examples/textbook/ch09_portfolio.py +0 -0
  227. {akquant-0.2.40 → akquant-0.2.41}/examples/textbook/ch10_analysis.py +0 -0
  228. {akquant-0.2.40 → akquant-0.2.41}/examples/textbook/ch11_optimization.py +0 -0
  229. {akquant-0.2.40 → akquant-0.2.41}/examples/textbook/ch12_ml.py +0 -0
  230. {akquant-0.2.40 → akquant-0.2.41}/examples/textbook/ch13_visualization.py +0 -0
  231. {akquant-0.2.40 → akquant-0.2.41}/examples/textbook/ch14_factor.py +0 -0
  232. {akquant-0.2.40 → akquant-0.2.41}/examples/textbook/ch15_live_trading.py +0 -0
  233. {akquant-0.2.40 → akquant-0.2.41}/examples/textbook/ch15_strategy_loader.py +0 -0
  234. {akquant-0.2.40 → akquant-0.2.41}/mkdocs.yml +0 -0
  235. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/__init__.py +0 -0
  236. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/analysis/__init__.py +0 -0
  237. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/analysis/benchmark.py +0 -0
  238. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/analyzer_plugin.py +0 -0
  239. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/backtest/__init__.py +0 -0
  240. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/backtest/__init__.pyi +0 -0
  241. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/backtest/engine.py +0 -0
  242. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/backtest/result.py +0 -0
  243. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/checkpoint.py +0 -0
  244. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/config.py +0 -0
  245. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/data.py +0 -0
  246. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/factor/__init__.py +0 -0
  247. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/factor/engine.py +0 -0
  248. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/factor/ops.py +0 -0
  249. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/factor/parser.py +0 -0
  250. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/feed_adapter.py +0 -0
  251. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/fund/__init__.py +0 -0
  252. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/futures/__init__.py +0 -0
  253. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/__init__.py +0 -0
  254. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/base.py +0 -0
  255. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/broker_event_bridge.py +0 -0
  256. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/broker_event_mapper.py +0 -0
  257. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/broker_models.py +0 -0
  258. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/broker_recovery.py +0 -0
  259. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/broker_runtime.py +0 -0
  260. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/brokers/__init__.py +0 -0
  261. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/brokers/ctp/__init__.py +0 -0
  262. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/brokers/ctp/adapter.py +0 -0
  263. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/brokers/ctp/native.py +0 -0
  264. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/brokers/miniqmt/__init__.py +0 -0
  265. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/brokers/miniqmt/stub.py +0 -0
  266. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/brokers/ptrade/__init__.py +0 -0
  267. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/brokers/ptrade/stub.py +0 -0
  268. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/ctp_adapter.py +0 -0
  269. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/ctp_native.py +0 -0
  270. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/factory.py +0 -0
  271. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/mapper.py +0 -0
  272. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/miniqmt.py +0 -0
  273. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/models.py +0 -0
  274. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/order_submitter.py +0 -0
  275. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/protocols.py +0 -0
  276. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/ptrade.py +0 -0
  277. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/gateway/registry.py +0 -0
  278. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/indicator.py +0 -0
  279. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/indicator_recording.py +0 -0
  280. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/indicator_stream.py +0 -0
  281. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/live.py +0 -0
  282. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/log.py +0 -0
  283. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/ml/__init__.py +0 -0
  284. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/ml/model.py +0 -0
  285. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/optimize.py +0 -0
  286. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/option/__init__.py +0 -0
  287. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/params.py +0 -0
  288. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/params_adapter.py +0 -0
  289. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/plot/__init__.py +0 -0
  290. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/plot/analysis.py +0 -0
  291. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/plot/dashboard.py +0 -0
  292. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/plot/indicator.py +0 -0
  293. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/plot/report.py +0 -0
  294. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/plot/strategy.py +0 -0
  295. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/plot/utils.py +0 -0
  296. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/py.typed +0 -0
  297. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/risk.py +0 -0
  298. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/sizer.py +0 -0
  299. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/stock/__init__.py +0 -0
  300. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/strategy.py +0 -0
  301. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/strategy_events.py +0 -0
  302. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/strategy_framework_hooks.py +0 -0
  303. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/strategy_history.py +0 -0
  304. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/strategy_loader.py +0 -0
  305. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/strategy_logging.py +0 -0
  306. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/strategy_ml.py +0 -0
  307. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/strategy_order_events.py +0 -0
  308. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/strategy_scheduler.py +0 -0
  309. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/strategy_time.py +0 -0
  310. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/strategy_trading_api.py +0 -0
  311. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/talib/__init__.py +0 -0
  312. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/talib/backend.py +0 -0
  313. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/talib/core.py +0 -0
  314. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/talib/funcs.py +0 -0
  315. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/utils/__init__.py +0 -0
  316. {akquant-0.2.40 → akquant-0.2.41}/python/akquant/utils/inspector.py +0 -0
  317. {akquant-0.2.40 → akquant-0.2.41}/requirements-dev.txt +0 -0
  318. {akquant-0.2.40 → akquant-0.2.41}/scripts/cargo-test.sh +0 -0
  319. {akquant-0.2.40 → akquant-0.2.41}/scripts/check_docs_api_examples.py +0 -0
  320. {akquant-0.2.40 → akquant-0.2.41}/scripts/check_docs_links.py +0 -0
  321. {akquant-0.2.40 → akquant-0.2.41}/scripts/dev-check.sh +0 -0
  322. {akquant-0.2.40 → akquant-0.2.41}/scripts/find_legacy_execution_policy_calls.py +0 -0
  323. {akquant-0.2.40 → akquant-0.2.41}/scripts/golden_baseline_report.py +0 -0
  324. {akquant-0.2.40 → akquant-0.2.41}/src/account.rs +0 -0
  325. {akquant-0.2.40 → akquant-0.2.41}/src/analysis/mod.rs +0 -0
  326. {akquant-0.2.40 → akquant-0.2.41}/src/analysis/python.rs +0 -0
  327. {akquant-0.2.40 → akquant-0.2.41}/src/analysis/result.rs +0 -0
  328. {akquant-0.2.40 → akquant-0.2.41}/src/analysis/tests.rs +0 -0
  329. {akquant-0.2.40 → akquant-0.2.41}/src/analysis/tracker.rs +0 -0
  330. {akquant-0.2.40 → akquant-0.2.41}/src/analysis/types.rs +0 -0
  331. {akquant-0.2.40 → akquant-0.2.41}/src/bin/stub_gen.rs +0 -0
  332. {akquant-0.2.40 → akquant-0.2.41}/src/clock.rs +0 -0
  333. {akquant-0.2.40 → akquant-0.2.41}/src/data/aggregator.rs +0 -0
  334. {akquant-0.2.40 → akquant-0.2.41}/src/data/batch.rs +0 -0
  335. {akquant-0.2.40 → akquant-0.2.41}/src/data/client.rs +0 -0
  336. {akquant-0.2.40 → akquant-0.2.41}/src/data/feed.rs +0 -0
  337. {akquant-0.2.40 → akquant-0.2.41}/src/data/mod.rs +0 -0
  338. {akquant-0.2.40 → akquant-0.2.41}/src/engine/mod.rs +0 -0
  339. {akquant-0.2.40 → akquant-0.2.41}/src/engine/python.rs +0 -0
  340. {akquant-0.2.40 → akquant-0.2.41}/src/engine/state.rs +0 -0
  341. {akquant-0.2.40 → akquant-0.2.41}/src/error.rs +0 -0
  342. {akquant-0.2.40 → akquant-0.2.41}/src/event.rs +0 -0
  343. {akquant-0.2.40 → akquant-0.2.41}/src/event_manager.rs +0 -0
  344. {akquant-0.2.40 → akquant-0.2.41}/src/execution/common.rs +0 -0
  345. {akquant-0.2.40 → akquant-0.2.41}/src/execution/crypto.rs +0 -0
  346. {akquant-0.2.40 → akquant-0.2.41}/src/execution/forex.rs +0 -0
  347. {akquant-0.2.40 → akquant-0.2.41}/src/execution/futures.rs +0 -0
  348. {akquant-0.2.40 → akquant-0.2.41}/src/execution/matcher.rs +0 -0
  349. {akquant-0.2.40 → akquant-0.2.41}/src/execution/mod.rs +0 -0
  350. {akquant-0.2.40 → akquant-0.2.41}/src/execution/option.rs +0 -0
  351. {akquant-0.2.40 → akquant-0.2.41}/src/execution/python.rs +0 -0
  352. {akquant-0.2.40 → akquant-0.2.41}/src/execution/realtime.rs +0 -0
  353. {akquant-0.2.40 → akquant-0.2.41}/src/execution/simulated.rs +0 -0
  354. {akquant-0.2.40 → akquant-0.2.41}/src/execution/slippage.rs +0 -0
  355. {akquant-0.2.40 → akquant-0.2.41}/src/execution/stock.rs +0 -0
  356. {akquant-0.2.40 → akquant-0.2.41}/src/history.rs +0 -0
  357. {akquant-0.2.40 → akquant-0.2.41}/src/indicators/momentum.rs +0 -0
  358. {akquant-0.2.40 → akquant-0.2.41}/src/indicators/momentum_oscillators.rs +0 -0
  359. {akquant-0.2.40 → akquant-0.2.41}/src/indicators/momentum_rates.rs +0 -0
  360. {akquant-0.2.40 → akquant-0.2.41}/src/indicators/moving_average.rs +0 -0
  361. {akquant-0.2.40 → akquant-0.2.41}/src/indicators/moving_average_compound.rs +0 -0
  362. {akquant-0.2.40 → akquant-0.2.41}/src/indicators/moving_average_core.rs +0 -0
  363. {akquant-0.2.40 → akquant-0.2.41}/src/indicators/moving_average_transforms.rs +0 -0
  364. {akquant-0.2.40 → akquant-0.2.41}/src/indicators/moving_average_windowed.rs +0 -0
  365. {akquant-0.2.40 → akquant-0.2.41}/src/indicators/trend.rs +0 -0
  366. {akquant-0.2.40 → akquant-0.2.41}/src/indicators/trend_directional.rs +0 -0
  367. {akquant-0.2.40 → akquant-0.2.41}/src/indicators/trend_oscillators.rs +0 -0
  368. {akquant-0.2.40 → akquant-0.2.41}/src/indicators/trend_regression.rs +0 -0
  369. {akquant-0.2.40 → akquant-0.2.41}/src/indicators/volatility.rs +0 -0
  370. {akquant-0.2.40 → akquant-0.2.41}/src/indicators/volatility_price.rs +0 -0
  371. {akquant-0.2.40 → akquant-0.2.41}/src/indicators/volatility_stats.rs +0 -0
  372. {akquant-0.2.40 → akquant-0.2.41}/src/indicators/volume.rs +0 -0
  373. {akquant-0.2.40 → akquant-0.2.41}/src/indicators.rs +0 -0
  374. {akquant-0.2.40 → akquant-0.2.41}/src/lib.rs +0 -0
  375. {akquant-0.2.40 → akquant-0.2.41}/src/log_context.rs +0 -0
  376. {akquant-0.2.40 → akquant-0.2.41}/src/margin/calculator.rs +0 -0
  377. {akquant-0.2.40 → akquant-0.2.41}/src/margin/engine.rs +0 -0
  378. {akquant-0.2.40 → akquant-0.2.41}/src/margin/mod.rs +0 -0
  379. {akquant-0.2.40 → akquant-0.2.41}/src/market/china.rs +0 -0
  380. {akquant-0.2.40 → akquant-0.2.41}/src/market/core.rs +0 -0
  381. {akquant-0.2.40 → akquant-0.2.41}/src/market/corporate_action.rs +0 -0
  382. {akquant-0.2.40 → akquant-0.2.41}/src/market/fund.rs +0 -0
  383. {akquant-0.2.40 → akquant-0.2.41}/src/market/futures.rs +0 -0
  384. {akquant-0.2.40 → akquant-0.2.41}/src/market/manager.rs +0 -0
  385. {akquant-0.2.40 → akquant-0.2.41}/src/market/mod.rs +0 -0
  386. {akquant-0.2.40 → akquant-0.2.41}/src/market/option.rs +0 -0
  387. {akquant-0.2.40 → akquant-0.2.41}/src/market/simple.rs +0 -0
  388. {akquant-0.2.40 → akquant-0.2.41}/src/market/stock.rs +0 -0
  389. {akquant-0.2.40 → akquant-0.2.41}/src/model/corporate_action.rs +0 -0
  390. {akquant-0.2.40 → akquant-0.2.41}/src/model/instrument.rs +0 -0
  391. {akquant-0.2.40 → akquant-0.2.41}/src/model/market_data.rs +0 -0
  392. {akquant-0.2.40 → akquant-0.2.41}/src/model/mod.rs +0 -0
  393. {akquant-0.2.40 → akquant-0.2.41}/src/model/order.rs +0 -0
  394. {akquant-0.2.40 → akquant-0.2.41}/src/model/timer.rs +0 -0
  395. {akquant-0.2.40 → akquant-0.2.41}/src/model/types.rs +0 -0
  396. {akquant-0.2.40 → akquant-0.2.41}/src/order_manager.rs +0 -0
  397. {akquant-0.2.40 → akquant-0.2.41}/src/pipeline/mod.rs +0 -0
  398. {akquant-0.2.40 → akquant-0.2.41}/src/pipeline/processor.rs +0 -0
  399. {akquant-0.2.40 → akquant-0.2.41}/src/pipeline/runner.rs +0 -0
  400. {akquant-0.2.40 → akquant-0.2.41}/src/pipeline/stages.rs +0 -0
  401. {akquant-0.2.40 → akquant-0.2.41}/src/portfolio.rs +0 -0
  402. {akquant-0.2.40 → akquant-0.2.41}/src/risk/common.rs +0 -0
  403. {akquant-0.2.40 → akquant-0.2.41}/src/risk/config.rs +0 -0
  404. {akquant-0.2.40 → akquant-0.2.41}/src/risk/futures.rs +0 -0
  405. {akquant-0.2.40 → akquant-0.2.41}/src/risk/manager.rs +0 -0
  406. {akquant-0.2.40 → akquant-0.2.41}/src/risk/mod.rs +0 -0
  407. {akquant-0.2.40 → akquant-0.2.41}/src/risk/option.rs +0 -0
  408. {akquant-0.2.40 → akquant-0.2.41}/src/risk/portfolio.rs +0 -0
  409. {akquant-0.2.40 → akquant-0.2.41}/src/risk/rule.rs +0 -0
  410. {akquant-0.2.40 → akquant-0.2.41}/src/risk/stock.rs +0 -0
  411. {akquant-0.2.40 → akquant-0.2.41}/src/settlement/expiry.rs +0 -0
  412. {akquant-0.2.40 → akquant-0.2.41}/src/settlement/handler.rs +0 -0
  413. {akquant-0.2.40 → akquant-0.2.41}/src/settlement/manager.rs +0 -0
  414. {akquant-0.2.40 → akquant-0.2.41}/src/settlement/mod.rs +0 -0
  415. {akquant-0.2.40 → akquant-0.2.41}/src/settlement/option.rs +0 -0
  416. {akquant-0.2.40 → akquant-0.2.41}/src/statistics/mod.rs +0 -0
  417. {akquant-0.2.40 → akquant-0.2.41}/tests/gateway_contract/test_event_bridge_contract.py +0 -0
  418. {akquant-0.2.40 → akquant-0.2.41}/tests/gateway_contract/test_recovery_contract.py +0 -0
  419. {akquant-0.2.40 → akquant-0.2.41}/tests/gateway_contract/test_submitter_contract.py +0 -0
  420. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/BASELINE_REPORT.md +0 -0
  421. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/LEGACY_EXECUTION_CALLS.md +0 -0
  422. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/baselines/futures_margin/equity_curve.parquet +0 -0
  423. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/baselines/futures_margin/metrics.json +0 -0
  424. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/baselines/futures_margin/orders.parquet +0 -0
  425. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/baselines/option_basic/equity_curve.parquet +0 -0
  426. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/baselines/option_basic/metrics.json +0 -0
  427. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/baselines/option_basic/orders.parquet +0 -0
  428. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/baselines/stock_t1/equity_curve.parquet +0 -0
  429. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/baselines/stock_t1/metrics.json +0 -0
  430. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/baselines/stock_t1/orders.parquet +0 -0
  431. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/baselines/stock_t1/trades.parquet +0 -0
  432. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/current/futures_margin/equity_curve.parquet +0 -0
  433. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/current/futures_margin/metrics.json +0 -0
  434. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/current/futures_margin/orders.parquet +0 -0
  435. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/current/option_basic/equity_curve.parquet +0 -0
  436. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/current/option_basic/metrics.json +0 -0
  437. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/current/option_basic/orders.parquet +0 -0
  438. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/current/stock_t1/equity_curve.parquet +0 -0
  439. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/current/stock_t1/metrics.json +0 -0
  440. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/current/stock_t1/orders.parquet +0 -0
  441. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/current/stock_t1/trades.parquet +0 -0
  442. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/data/future_margin.parquet +0 -0
  443. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/data/future_margin.parquet.sha256 +0 -0
  444. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/data/option_basic.parquet +0 -0
  445. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/data/option_basic.parquet.sha256 +0 -0
  446. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/data/stock_t1.parquet +0 -0
  447. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/data/stock_t1.parquet.sha256 +0 -0
  448. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/gen_data.py +0 -0
  449. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/runner.py +0 -0
  450. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/strategies/futures_margin.py +0 -0
  451. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/strategies/option_basic.py +0 -0
  452. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/strategies/stock_t1.py +0 -0
  453. {akquant-0.2.40 → akquant-0.2.41}/tests/golden/test_golden.py +0 -0
  454. {akquant-0.2.40 → akquant-0.2.41}/tests/test_account_risk_rules.py +0 -0
  455. {akquant-0.2.40 → akquant-0.2.41}/tests/test_custom_matcher.py +0 -0
  456. {akquant-0.2.40 → akquant-0.2.41}/tests/test_data_catalog.py +0 -0
  457. {akquant-0.2.40 → akquant-0.2.41}/tests/test_docs_api_examples.py +0 -0
  458. {akquant-0.2.40 → akquant-0.2.41}/tests/test_docs_links.py +0 -0
  459. {akquant-0.2.40 → akquant-0.2.41}/tests/test_examples_regression.py +0 -0
  460. {akquant-0.2.40 → akquant-0.2.41}/tests/test_factor_engine.py +0 -0
  461. {akquant-0.2.40 → akquant-0.2.41}/tests/test_factor_ops.py +0 -0
  462. {akquant-0.2.40 → akquant-0.2.41}/tests/test_feed_adapter.py +0 -0
  463. {akquant-0.2.40 → akquant-0.2.41}/tests/test_gateway_brokers_paths.py +0 -0
  464. {akquant-0.2.40 → akquant-0.2.41}/tests/test_gateway_callbacks.py +0 -0
  465. {akquant-0.2.40 → akquant-0.2.41}/tests/test_gateway_ctp_adapter.py +0 -0
  466. {akquant-0.2.40 → akquant-0.2.41}/tests/test_gateway_ctp_native.py +0 -0
  467. {akquant-0.2.40 → akquant-0.2.41}/tests/test_gateway_factory.py +0 -0
  468. {akquant-0.2.40 → akquant-0.2.41}/tests/test_gateway_mapper.py +0 -0
  469. {akquant-0.2.40 → akquant-0.2.41}/tests/test_gateway_registry.py +0 -0
  470. {akquant-0.2.40 → akquant-0.2.41}/tests/test_indicator_live_web_example.py +0 -0
  471. {akquant-0.2.40 → akquant-0.2.41}/tests/test_indicator_recording.py +0 -0
  472. {akquant-0.2.40 → akquant-0.2.41}/tests/test_inspector.py +0 -0
  473. {akquant-0.2.40 → akquant-0.2.41}/tests/test_live_runner.py +0 -0
  474. {akquant-0.2.40 → akquant-0.2.41}/tests/test_live_runner_broker_bridge.py +0 -0
  475. {akquant-0.2.40 → akquant-0.2.41}/tests/test_live_runner_broker_recovery.py +0 -0
  476. {akquant-0.2.40 → akquant-0.2.41}/tests/test_live_runner_broker_submitter.py +0 -0
  477. {akquant-0.2.40 → akquant-0.2.41}/tests/test_multisymbol_cross_section_consistency.py +0 -0
  478. {akquant-0.2.40 → akquant-0.2.41}/tests/test_orders_df.py +0 -0
  479. {akquant-0.2.40 → akquant-0.2.41}/tests/test_params_adapter.py +0 -0
  480. {akquant-0.2.40 → akquant-0.2.41}/tests/test_partial_filled_status.py +0 -0
  481. {akquant-0.2.40 → akquant-0.2.41}/tests/test_portfolio.py +0 -0
  482. {akquant-0.2.40 → akquant-0.2.41}/tests/test_quickstart_stream_consistency.py +0 -0
  483. {akquant-0.2.40 → akquant-0.2.41}/tests/test_report_helpers.py +0 -0
  484. {akquant-0.2.40 → akquant-0.2.41}/tests/test_report_plot_extensions.py +0 -0
  485. {akquant-0.2.40 → akquant-0.2.41}/tests/test_result_analysis_extensions.py +0 -0
  486. {akquant-0.2.40 → akquant-0.2.41}/tests/test_stop_orders.py +0 -0
  487. {akquant-0.2.40 → akquant-0.2.41}/tests/test_strategy_extras.py +0 -0
  488. {akquant-0.2.40 → akquant-0.2.41}/tests/test_strategy_timers_indicators.py +0 -0
  489. {akquant-0.2.40 → akquant-0.2.41}/tests/test_t_plus_one.py +0 -0
  490. {akquant-0.2.40 → akquant-0.2.41}/tests/test_talib_backend.py +0 -0
  491. {akquant-0.2.40 → akquant-0.2.41}/tests/test_talib_compat.py +0 -0
  492. {akquant-0.2.40 → akquant-0.2.41}/tests/test_trades_df.py +0 -0
  493. {akquant-0.2.40 → akquant-0.2.41}/tests/test_version.py +0 -0
@@ -30,7 +30,7 @@ dependencies = [
30
30
 
31
31
  [[package]]
32
32
  name = "akquant"
33
- version = "0.2.40"
33
+ version = "0.2.41"
34
34
  dependencies = [
35
35
  "anyhow",
36
36
  "chrono",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "akquant"
3
- version = "0.2.40"
3
+ version = "0.2.41"
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.40
3
+ Version: 0.2.41
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: Implementation :: PyPy
@@ -17,7 +17,7 @@ Your task is to write trading strategies or backtest scripts based on user requi
17
17
  * **Initialization**: Define parameters in `__init__`. Calling `super().__init__()` is optional but recommended.
18
18
  * **Subscription**: Call `self.subscribe(symbol)` in `on_start` to explicitly declare interest. In backtest, it's optional if data is provided.
19
19
  * **Logic**: Implement trading logic in `on_bar(self, bar: Bar)`.
20
- * **Position Helper**: You can use `self.get_position(symbol)` or the `Position` helper class (e.g., `pos = Position(self.ctx, symbol)`).
20
+ * **Position Helper**: You can use `self.get_position(symbol)` for numeric quantity, or the `Position` helper class (e.g., `pos = Position(self.ctx, symbol)`) when you also need `size`, `available`, or `entry_price`.
21
21
 
22
22
  2. **Data Access**:
23
23
  * **Warmup Period**:
@@ -35,7 +35,7 @@ Your task is to write trading strategies or backtest scripts based on user requi
35
35
  * `self.sell(symbol, quantity, price=None)`: Sell.
36
36
  * `self.order_target_percent(target, symbol)`: Adjust position to target percentage.
37
37
  * `self.order_target_value(target, symbol)`: Adjust position to target value.
38
- * **Position**: `self.get_position(symbol)` returns current holding (float).
38
+ * **Position**: `self.get_position(symbol)` returns current holding (float). `self.position.entry_price` or `self.ctx.get_position_entry_price(symbol)` returns runtime average entry price.
39
39
  * **Account**: `self.ctx.cash`, `self.get_portfolio_value()`, `self.get_account()`.
40
40
 
41
41
  4. **Indicators**:
@@ -617,6 +617,18 @@ In addition to `get_position`, you can query more account information:
617
617
  * **`self.get_trades()`**: Get all historical closed trades.
618
618
  * **`self.get_open_orders()`**: Get current open orders.
619
619
  * **`self.get_available_position(symbol)`**: Get available position (considering T+1 rule).
620
+ * **`self.position.entry_price`**: Get the current symbol's average entry price from the `Position` helper.
621
+ * **`self.position.avg_price`**: Alias of `entry_price`.
622
+ * **`self.ctx.get_position_entry_price(symbol)`**: Get average entry price for a specific symbol.
623
+
624
+ `self.get_position(symbol)` still returns a numeric quantity. If you need average entry price, use the `Position` helper or `self.ctx.get_position_entry_price(symbol)`.
625
+
626
+ ```python
627
+ def on_bar(self, bar):
628
+ pos = self.position
629
+ if pos.size > 0 and pos.entry_price > 0:
630
+ pnl_pct = (bar.close - pos.entry_price) / pos.entry_price
631
+ ```
620
632
 
621
633
  ### 5.6 Instrument Static Metadata Query (Recommended)
622
634
 
@@ -848,7 +848,13 @@ Note: if you do not pass an explicit `fill_policy` here, the framework defaults
848
848
 
849
849
  * `get_history(count, symbol, field="close") -> np.ndarray`: Get history data array (Zero-Copy). Supports `open/high/low/close/volume` and any numeric extra fields (e.g., `adj_close`, `adj_factor`).
850
850
  * `get_history_df(count, symbol) -> pd.DataFrame`: Get history data DataFrame (OHLCV).
851
- * `get_position(symbol) -> float`: Get current position size.
851
+ * `get_position(symbol) -> float`: Get current position size. This still returns a numeric quantity, not an object.
852
+ * `get_available_position(symbol) -> float`: Get available position size.
853
+ * `get_positions() -> Dict[str, float]`: Get all positions by symbol.
854
+ * `self.position.entry_price -> float`: Get the current symbol's average entry price via the `Position` helper.
855
+ * `self.position.avg_price -> float`: Alias of `entry_price`.
856
+ * `ctx.get_position_entry_price(symbol) -> float`: Get the current average entry price for one symbol.
857
+ * `ctx.get_position_entry_prices() -> Dict[str, float]`: Get current average entry prices for all symbols.
852
858
  * `get_cash() -> float`: Get current available cash.
853
859
  * `get_account() -> Dict[str, float]`: Get an account snapshot. Common fields include `cash`, `equity`, `market_value`, `notional_value`, `frozen_cash`, `margin`, `used_margin`, `unrealized_pnl`, `borrowed_cash`, `short_market_value`, `maintenance_ratio`, `account_mode`, `accrued_interest`, and `daily_interest`.
854
860
  * In cash / spot-style accounts, `market_value` usually represents marked position value.
@@ -17,7 +17,7 @@ Your task is to write trading strategies or backtest scripts based on user requi
17
17
  * **Initialization**: Define parameters in `__init__`. Calling `super().__init__()` is optional but recommended.
18
18
  * **Subscription**: Call `self.subscribe(symbol)` in `on_start` to explicitly declare interest. In backtest, it's optional if data is provided.
19
19
  * **Logic**: Implement trading logic in `on_bar(self, bar: Bar)`.
20
- * **Position Helper**: You can use `self.get_position(symbol)` or the `Position` helper class (e.g., `pos = Position(self.ctx, symbol)`).
20
+ * **Position Helper**: You can use `self.get_position(symbol)` for numeric quantity, or the `Position` helper class (e.g., `pos = Position(self.ctx, symbol)`) when you also need `size`, `available`, or `entry_price`.
21
21
 
22
22
  2. **Data Access**:
23
23
  * **Warmup Period**:
@@ -36,7 +36,7 @@ Your task is to write trading strategies or backtest scripts based on user requi
36
36
  * `self.order_target_percent(target, symbol)`: Adjust position to target percentage.
37
37
  * `self.order_target_value(target, symbol)`: Adjust position to target value.
38
38
  * 在 `fill_policy={"price_basis":"close","bar_offset":0}` 下,同一事件周期中若同时存在卖单与买单,撮合采用先卖后买语义:先处理卖单成交并结算资金,再进行买单风控与下单数量计算。
39
- * **Position**: `self.get_position(symbol)` returns current holding (float).
39
+ * **Position**: `self.get_position(symbol)` returns current holding (float). `self.position.entry_price` or `self.ctx.get_position_entry_price(symbol)` returns runtime average entry price.
40
40
  * **Account**: `self.ctx.cash`, `self.get_portfolio_value()`, `self.get_account()`.
41
41
 
42
42
  4. **Indicators**:
@@ -161,7 +161,7 @@ A: 因为这些字段现在统一表示 UTC 时间。北京时间 09:31 对应 U
161
161
  A: 请检查你的输入数据是否是 Naive Datetime(无时区)。如果是 Naive 的,AKQuant 会默认当作北京时间处理,导致转换到 UTC 时出错。请在传入数据前使用 `.tz_localize("US/Eastern")` 处理数据索引。
162
162
 
163
163
  **Q: `AttributeError: 'float' object has no attribute 'quantity'` 是什么?**
164
- A: 这通常是在访问持仓时发生的错误。`self.ctx.get_position(symbol)` 返回的是持仓数量(float),而不是一个对象。请直接使用返回值作为数量。
164
+ A: 这通常是在访问持仓时发生的错误。`self.ctx.get_position(symbol)` 返回的是持仓数量(float),而不是一个对象。请直接使用返回值作为数量。如果你需要持仓均价,请改用 `self.position.entry_price` 或 `self.ctx.get_position_entry_price(symbol)`。
165
165
 
166
166
  **Q: 混合频率回测时,日线和分钟线怎么对齐?**
167
167
  A: AKQuant 是事件驱动的,按时间戳顺序处理 Bar。
@@ -869,7 +869,11 @@ akquant.run_backtest(
869
869
  > pos = self.position # 获取当前 symbol 的 Position 对象
870
870
  > print(pos.size) # 总持仓
871
871
  > print(pos.available) # 可用持仓
872
+ > print(pos.entry_price) # 持仓均价
873
+ > print(pos.avg_price) # entry_price 的别名
872
874
  > ```
875
+ >
876
+ > `self.get_position(symbol)` 的返回值仍然是 `float` 数量;如果你需要持仓均价,请使用 `Position` helper 或 `self.ctx.get_position_entry_price(symbol)`。
873
877
 
874
878
  **示例代码**:
875
879
 
@@ -881,6 +885,10 @@ def on_bar(self, bar: Bar):
881
885
  # 卖出逻辑:必须检查可用持仓
882
886
  if signal_sell and pos.available > 0:
883
887
  self.sell(bar.symbol, pos.available)
888
+
889
+ # 成本线判断:直接读取运行态持仓均价
890
+ if pos.size > 0 and pos.entry_price > 0:
891
+ pnl_pct = (bar.close - pos.entry_price) / pos.entry_price
884
892
  ```
885
893
 
886
894
  > **注意**:如果你在 T+1 模式下尝试卖出超过 `available` 的数量,订单会被风控模块(Risk Manager)**拒绝 (Rejected)**,并提示 "Insufficient available position"。
@@ -871,9 +871,13 @@ def on_pre_open(self, event: Dict[str, Any]) -> None:
871
871
  * `get_history_map(count, symbols, field="close") -> Dict[str, np.ndarray]`: 批量获取多个标的历史数据。
872
872
  * `rebalance_to_topn(scores, top_n, weight_mode="equal", ...) -> List[str]`: 根据打分选取 TopN 并执行调仓,支持等权或按分数归一化。
873
873
  * `get_history_df(count, symbol) -> pd.DataFrame`: 获取历史数据 DataFrame (OHLCV)。
874
- * `get_position(symbol) -> float`: 获取当前持仓量。
874
+ * `get_position(symbol) -> float`: 获取当前持仓量。返回值仍为数量,不返回对象。
875
875
  * `get_available_position(symbol) -> float`: 获取可用持仓量。
876
876
  * `get_positions() -> Dict[str, float]`: 获取所有标的持仓。
877
+ * `self.position.entry_price -> float`: 通过 `Position` helper 获取当前标的持仓均价。
878
+ * `self.position.avg_price -> float`: `entry_price` 的别名。
879
+ * `ctx.get_position_entry_price(symbol) -> float`: 获取指定标的当前持仓均价。
880
+ * `ctx.get_position_entry_prices() -> Dict[str, float]`: 获取所有标的当前持仓均价。
877
881
  * `hold_bar(symbol) -> int`: 获取当前持仓持有的 Bar 数量。
878
882
  * `get_cash() -> float`: 获取当前可用资金。
879
883
  * `get_account() -> Dict[str, float]`: 获取账户详情快照。常见字段包括 `cash`、`equity`、`market_value`、`notional_value`、`frozen_cash`、`margin`、`used_margin`、`unrealized_pnl`、`borrowed_cash`、`short_market_value`、`maintenance_ratio`、`account_mode`、`accrued_interest`、`daily_interest`。
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "akquant"
7
- version = "0.2.40"
7
+ version = "0.2.41"
8
8
  description = "High-performance quantitative trading framework based on Rust and Python"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT License"}
@@ -2703,6 +2703,23 @@ class StrategyContext:
2703
2703
  """
2704
2704
  ...
2705
2705
 
2706
+ def get_position_entry_prices(self) -> dict[str, float]:
2707
+ r"""
2708
+ 获取当前所有持仓均价.
2709
+
2710
+ :return: 持仓均价字典 {symbol: entry_price}
2711
+ """
2712
+ ...
2713
+
2714
+ def get_position_entry_price(self, symbol: str) -> float:
2715
+ r"""
2716
+ 获取当前持仓均价.
2717
+
2718
+ :param symbol: 标的代码
2719
+ :return: 持仓均价
2720
+ """
2721
+ ...
2722
+
2706
2723
  class ExpiryEvent:
2707
2724
  symbol: str
2708
2725
  asset_type: akquant.AssetType
@@ -28,6 +28,19 @@ class Position:
28
28
  """可用持仓数量."""
29
29
  return self._ctx.get_available_position(self._symbol)
30
30
 
31
+ @property
32
+ def entry_price(self) -> float:
33
+ """持仓均价."""
34
+ return self._ctx.get_position_entry_price(self._symbol)
35
+
36
+ @property
37
+ def avg_price(self) -> float:
38
+ """持仓均价别名."""
39
+ return self.entry_price
40
+
31
41
  def __repr__(self) -> str:
32
42
  """返回持仓信息的字符串表示."""
33
- return f"Position(symbol={self._symbol}, size={self.size})"
43
+ return (
44
+ f"Position(symbol={self._symbol}, size={self.size}, "
45
+ f"available={self.available}, entry_price={self.entry_price})"
46
+ )
@@ -43,6 +43,7 @@ pub struct ContextInit {
43
43
  pub previous_cash: Decimal,
44
44
  pub positions: Arc<HashMap<String, Decimal>>,
45
45
  pub available_positions: Arc<HashMap<String, Decimal>>,
46
+ pub position_entry_prices: Arc<HashMap<String, Decimal>>,
46
47
  pub session: TradingSession,
47
48
  pub current_time: i64,
48
49
  pub active_orders: Arc<Vec<Order>>,
@@ -75,6 +76,7 @@ pub struct ContextUpdate {
75
76
  pub previous_cash: Decimal,
76
77
  pub positions: Arc<HashMap<String, Decimal>>,
77
78
  pub available_positions: Arc<HashMap<String, Decimal>>,
79
+ pub position_entry_prices: Arc<HashMap<String, Decimal>>,
78
80
  pub session: TradingSession,
79
81
  pub current_time: i64,
80
82
  pub active_orders: Arc<Vec<Order>>,
@@ -287,6 +289,7 @@ impl StrategyContext {
287
289
  self.previous_cash = update.previous_cash;
288
290
  self.positions = update.positions;
289
291
  self.available_positions = update.available_positions;
292
+ self.position_entry_prices = update.position_entry_prices;
290
293
  self.session = update.session;
291
294
  self.current_time = update.current_time;
292
295
  self.active_orders_arc = update.active_orders.clone();
@@ -375,6 +378,7 @@ pub struct StrategyContext {
375
378
  pub previous_cash: Decimal,
376
379
  pub positions: Arc<HashMap<String, Decimal>>,
377
380
  pub available_positions: Arc<HashMap<String, Decimal>>,
381
+ pub position_entry_prices: Arc<HashMap<String, Decimal>>,
378
382
  #[pyo3(get)]
379
383
  pub session: TradingSession,
380
384
  #[pyo3(get)]
@@ -443,6 +447,7 @@ impl StrategyContext {
443
447
  previous_cash: init.previous_cash,
444
448
  positions: init.positions,
445
449
  available_positions: init.available_positions,
450
+ position_entry_prices: init.position_entry_prices,
446
451
  session: init.session,
447
452
  current_time: init.current_time,
448
453
  closed_trades: init.closed_trades,
@@ -479,6 +484,7 @@ impl StrategyContext {
479
484
  /// :param cash: 初始资金
480
485
  /// :param positions: 初始持仓 {symbol: quantity}
481
486
  /// :param available_positions: 初始可用持仓 {symbol: quantity}
487
+ /// :param position_entry_prices: 初始持仓均价 {symbol: entry_price}
482
488
  /// :param session: 当前交易时段
483
489
  /// :param current_time: 当前时间戳 (纳秒)
484
490
  /// :param active_orders: 当前活跃订单列表
@@ -493,6 +499,7 @@ impl StrategyContext {
493
499
  previous_cash: Option<&Bound<'_, PyAny>>,
494
500
  positions: HashMap<String, f64>,
495
501
  available_positions: HashMap<String, f64>,
502
+ position_entry_prices: Option<HashMap<String, f64>>,
496
503
  session: Option<TradingSession>,
497
504
  current_time: Option<i64>,
498
505
  active_orders: Option<Vec<Order>>,
@@ -524,6 +531,11 @@ impl StrategyContext {
524
531
  .into_iter()
525
532
  .map(|(k, v)| (k, Decimal::from_f64(v).unwrap_or(Decimal::ZERO)))
526
533
  .collect();
534
+ let entry_price_dec: HashMap<String, Decimal> = position_entry_prices
535
+ .unwrap_or_default()
536
+ .into_iter()
537
+ .map(|(k, v)| (k, Decimal::from_f64(v).unwrap_or(Decimal::ZERO)))
538
+ .collect();
527
539
 
528
540
  Ok(StrategyContext {
529
541
  orders: Vec::new(),
@@ -538,6 +550,7 @@ impl StrategyContext {
538
550
  previous_cash: extract_decimal(previous_cash.unwrap_or(cash))?,
539
551
  positions: Arc::new(pos_dec),
540
552
  available_positions: Arc::new(avail_dec),
553
+ position_entry_prices: Arc::new(entry_price_dec),
541
554
  session: session.unwrap_or(TradingSession::Continuous),
542
555
  current_time: current_time.unwrap_or(0),
543
556
  closed_trades: Arc::new(closed_trades.unwrap_or_default()),
@@ -672,6 +685,14 @@ impl StrategyContext {
672
685
  .collect()
673
686
  }
674
687
 
688
+ #[getter]
689
+ fn get_position_entry_prices(&self) -> HashMap<String, f64> {
690
+ self.position_entry_prices
691
+ .iter()
692
+ .map(|(k, v)| (k.clone(), v.to_f64().unwrap_or_default()))
693
+ .collect()
694
+ }
695
+
675
696
  /// 注册定时器.
676
697
  ///
677
698
  /// :param timestamp: 触发时间戳 (纳秒)
@@ -950,4 +971,16 @@ impl StrategyContext {
950
971
  .to_f64()
951
972
  .unwrap_or_default()
952
973
  }
974
+
975
+ /// 获取当前持仓均价.
976
+ ///
977
+ /// :param symbol: 标的代码
978
+ /// :return: 持仓均价
979
+ fn get_position_entry_price(&self, symbol: String) -> f64 {
980
+ self.position_entry_prices
981
+ .get(&symbol)
982
+ .unwrap_or(&Decimal::ZERO)
983
+ .to_f64()
984
+ .unwrap_or_default()
985
+ }
953
986
  }
@@ -146,6 +146,22 @@ impl Engine {
146
146
  )
147
147
  }
148
148
 
149
+ fn build_position_entry_prices(&self) -> Arc<HashMap<String, Decimal>> {
150
+ let mut entry_prices = HashMap::new();
151
+ for (symbol, quantity) in self.state.portfolio.positions.iter() {
152
+ if quantity.is_zero() {
153
+ continue;
154
+ }
155
+ let average_price = self
156
+ .state
157
+ .order_manager
158
+ .trade_tracker
159
+ .get_average_price(symbol);
160
+ entry_prices.insert(symbol.clone(), average_price);
161
+ }
162
+ Arc::new(entry_prices)
163
+ }
164
+
149
165
  pub(crate) fn is_active_timestamp(&self, timestamp: i64) -> bool {
150
166
  self.active_start_time_ns
151
167
  .is_none_or(|start_ns| timestamp >= start_ns)
@@ -602,6 +618,7 @@ impl Engine {
602
618
  ) -> PyResult<Py<StrategyContext>> {
603
619
  self.ensure_strategy_context_capacity();
604
620
  let account_metrics = self.current_account_metrics();
621
+ let position_entry_prices = self.build_position_entry_prices();
605
622
  if let Some(existing_ctx) = self
606
623
  .strategy_contexts
607
624
  .get(slot_index)
@@ -616,6 +633,7 @@ impl Engine {
616
633
  previous_cash,
617
634
  positions: self.state.portfolio.positions.clone(),
618
635
  available_positions: self.state.portfolio.available_positions.clone(),
636
+ position_entry_prices,
619
637
  session: self.clock.session,
620
638
  current_time: self.clock.timestamp().unwrap_or(0),
621
639
  active_orders,
@@ -999,12 +1017,14 @@ impl Engine {
999
1017
  previous_account_metrics: AccountMetrics,
1000
1018
  ) -> StrategyContext {
1001
1019
  let account_metrics = self.current_account_metrics();
1020
+ let position_entry_prices = self.build_position_entry_prices();
1002
1021
  // Create a temporary context for the strategy to use
1003
1022
  StrategyContext::new(crate::context::ContextInit {
1004
1023
  cash: self.state.portfolio.cash,
1005
1024
  previous_cash,
1006
1025
  positions: self.state.portfolio.positions.clone(),
1007
1026
  available_positions: self.state.portfolio.available_positions.clone(),
1027
+ position_entry_prices,
1008
1028
  session: self.clock.session,
1009
1029
  current_time: self.clock.timestamp().unwrap_or(0),
1010
1030
  active_orders,
@@ -159,6 +159,42 @@ class BuyBuySellBuyStrategy(akquant.Strategy):
159
159
  self._step += 1
160
160
 
161
161
 
162
+ class PositionEntryPriceCaptureStrategy(akquant.Strategy):
163
+ """Capture runtime position helper state across buy/sell transitions."""
164
+
165
+ def __init__(self) -> None:
166
+ """Initialize step counter and capture buffer."""
167
+ super().__init__()
168
+ self._step = 0
169
+ self.snapshots: list[dict[str, float | str]] = []
170
+
171
+ def on_bar(self, bar: akquant.Bar) -> None:
172
+ """Record helper values before submitting deterministic orders."""
173
+ pos = self.position
174
+ ctx_entry_price = 0.0
175
+ if self.ctx is not None:
176
+ ctx_entry_price = float(self.ctx.get_position_entry_price(bar.symbol))
177
+ self.snapshots.append(
178
+ {
179
+ "size": float(pos.size),
180
+ "available": float(pos.available),
181
+ "entry_price": float(pos.entry_price),
182
+ "avg_price": float(pos.avg_price),
183
+ "ctx_entry_price": ctx_entry_price,
184
+ "repr": repr(pos),
185
+ }
186
+ )
187
+ if self._step == 0:
188
+ self.buy(symbol=bar.symbol, quantity=10)
189
+ elif self._step == 1:
190
+ self.buy(symbol=bar.symbol, quantity=10)
191
+ elif self._step == 2:
192
+ self.sell(symbol=bar.symbol, quantity=5)
193
+ elif self._step == 3:
194
+ self.sell(symbol=bar.symbol, quantity=15)
195
+ self._step += 1
196
+
197
+
162
198
  class ContinuousBuyStrategy(akquant.Strategy):
163
199
  """Submit a buy order on every bar."""
164
200
 
@@ -384,6 +420,22 @@ def _build_daily_loss_bars(symbol: str) -> list[akquant.Bar]:
384
420
  ]
385
421
 
386
422
 
423
+ def _build_position_entry_price_bars(symbol: str) -> list[akquant.Bar]:
424
+ """Build bars for weighted-average position entry price checks."""
425
+ day1 = _ns(datetime(2023, 2, 1, 15, 0, tzinfo=timezone.utc))
426
+ day2 = _ns(datetime(2023, 2, 2, 15, 0, tzinfo=timezone.utc))
427
+ day3 = _ns(datetime(2023, 2, 3, 15, 0, tzinfo=timezone.utc))
428
+ day4 = _ns(datetime(2023, 2, 4, 15, 0, tzinfo=timezone.utc))
429
+ day5 = _ns(datetime(2023, 2, 5, 15, 0, tzinfo=timezone.utc))
430
+ return [
431
+ akquant.Bar(day1, 10.0, 10.0, 10.0, 10.0, 1000.0, symbol),
432
+ akquant.Bar(day2, 12.0, 12.0, 12.0, 12.0, 1000.0, symbol),
433
+ akquant.Bar(day3, 11.0, 11.0, 11.0, 11.0, 1000.0, symbol),
434
+ akquant.Bar(day4, 11.0, 11.0, 11.0, 11.0, 1000.0, symbol),
435
+ akquant.Bar(day5, 11.0, 11.0, 11.0, 11.0, 1000.0, symbol),
436
+ ]
437
+
438
+
387
439
  def _build_reduce_only_bars(symbol: str) -> list[akquant.Bar]:
388
440
  """Build 4 bars used to validate reduce-only fallback behavior."""
389
441
  day1 = _ns(datetime(2023, 1, 2, 15, 0, tzinfo=timezone.utc))
@@ -1783,6 +1835,56 @@ def test_engine_set_fill_policy_roundtrip() -> None:
1783
1835
  assert temporal == "next_event"
1784
1836
 
1785
1837
 
1838
+ def test_position_helper_exposes_runtime_entry_price() -> None:
1839
+ """Position helper should expose weighted-average runtime entry price."""
1840
+ symbol = "POS_HELPER"
1841
+ engine = akquant.Engine()
1842
+ engine.use_simple_market(0.0)
1843
+ engine.set_force_session_continuous(True)
1844
+ cast(Any, engine).set_fill_policy("close", 0, "same_cycle")
1845
+ engine.set_cash(100000.0)
1846
+ engine.set_stock_fee_rules(0.0, 0.0, 0.0, 0.0)
1847
+ engine.set_t_plus_one(False)
1848
+
1849
+ instr = akquant.Instrument(
1850
+ symbol=symbol,
1851
+ asset_type=akquant.AssetType.Stock,
1852
+ multiplier=1.0,
1853
+ margin_ratio=1.0,
1854
+ tick_size=0.01,
1855
+ option_type=None,
1856
+ strike_price=None,
1857
+ expiry_date=None,
1858
+ lot_size=1.0,
1859
+ )
1860
+ engine.add_instrument(instr)
1861
+ engine.add_bars(_build_position_entry_price_bars(symbol))
1862
+
1863
+ strategy = PositionEntryPriceCaptureStrategy()
1864
+ engine.run(strategy, show_progress=False)
1865
+
1866
+ assert len(strategy.snapshots) == 5
1867
+ assert strategy.snapshots[0]["size"] == pytest.approx(0.0, rel=1e-9)
1868
+ assert strategy.snapshots[0]["entry_price"] == pytest.approx(0.0, rel=1e-9)
1869
+ assert strategy.snapshots[1]["size"] == pytest.approx(10.0, rel=1e-9)
1870
+ assert strategy.snapshots[1]["available"] == pytest.approx(10.0, rel=1e-9)
1871
+ assert strategy.snapshots[1]["entry_price"] == pytest.approx(10.0, rel=1e-9)
1872
+ assert strategy.snapshots[1]["avg_price"] == pytest.approx(10.0, rel=1e-9)
1873
+ assert strategy.snapshots[1]["ctx_entry_price"] == pytest.approx(10.0, rel=1e-9)
1874
+ assert strategy.snapshots[2]["size"] == pytest.approx(20.0, rel=1e-9)
1875
+ assert strategy.snapshots[2]["entry_price"] == pytest.approx(11.0, rel=1e-9)
1876
+ assert strategy.snapshots[3]["size"] == pytest.approx(15.0, rel=1e-9)
1877
+ assert strategy.snapshots[3]["entry_price"] == pytest.approx(34.0 / 3.0, rel=1e-9)
1878
+ assert strategy.snapshots[3]["avg_price"] == pytest.approx(34.0 / 3.0, rel=1e-9)
1879
+ assert strategy.snapshots[3]["ctx_entry_price"] == pytest.approx(
1880
+ 34.0 / 3.0, rel=1e-9
1881
+ )
1882
+ assert strategy.snapshots[4]["size"] == pytest.approx(0.0, rel=1e-9)
1883
+ assert strategy.snapshots[4]["available"] == pytest.approx(0.0, rel=1e-9)
1884
+ assert strategy.snapshots[4]["entry_price"] == pytest.approx(0.0, rel=1e-9)
1885
+ assert "entry_price=0.0" in cast(str, strategy.snapshots[4]["repr"])
1886
+
1887
+
1786
1888
  def test_engine_set_fill_policy_invalid_combo() -> None:
1787
1889
  """Engine fill policy should reject invalid basis/offset combos."""
1788
1890
  engine = akquant.Engine()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes