akquant 0.2.47__tar.gz → 0.2.48__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 (508) hide show
  1. {akquant-0.2.47 → akquant-0.2.48}/CHANGELOG.md +5 -0
  2. {akquant-0.2.47 → akquant-0.2.48}/Cargo.lock +1 -1
  3. {akquant-0.2.47 → akquant-0.2.48}/Cargo.toml +1 -1
  4. {akquant-0.2.47 → akquant-0.2.48}/PKG-INFO +1 -1
  5. {akquant-0.2.47 → akquant-0.2.48}/pyproject.toml +1 -1
  6. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/__init__.py +1 -1
  7. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/backtest/engine.py +8 -0
  8. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/config.py +7 -0
  9. {akquant-0.2.47 → akquant-0.2.48}/src/analysis/result.rs +16 -6
  10. {akquant-0.2.47 → akquant-0.2.48}/src/analysis/tests.rs +94 -0
  11. {akquant-0.2.47 → akquant-0.2.48}/src/engine/core.rs +4 -0
  12. {akquant-0.2.47 → akquant-0.2.48}/src/engine/python.rs +18 -0
  13. {akquant-0.2.47 → akquant-0.2.48}/src/statistics/mod.rs +4 -0
  14. {akquant-0.2.47/tests/golden/current → akquant-0.2.48/tests/golden/baselines}/futures_margin/metrics.json +3 -3
  15. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/baselines/option_basic/metrics.json +3 -3
  16. {akquant-0.2.47/tests/golden/current → akquant-0.2.48/tests/golden/baselines}/stock_t1/metrics.json +3 -3
  17. {akquant-0.2.47/tests/golden/baselines → akquant-0.2.48/tests/golden/current}/futures_margin/metrics.json +3 -3
  18. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/current/option_basic/metrics.json +3 -3
  19. {akquant-0.2.47/tests/golden/baselines → akquant-0.2.48/tests/golden/current}/stock_t1/metrics.json +3 -3
  20. {akquant-0.2.47 → akquant-0.2.48}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  21. {akquant-0.2.47 → akquant-0.2.48}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  22. {akquant-0.2.47 → akquant-0.2.48}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  23. {akquant-0.2.47 → akquant-0.2.48}/.github/workflows/deploy-docs.yml +0 -0
  24. {akquant-0.2.47 → akquant-0.2.48}/.github/workflows/docs-quality.yml +0 -0
  25. {akquant-0.2.47 → akquant-0.2.48}/.github/workflows/release.yml +0 -0
  26. {akquant-0.2.47 → akquant-0.2.48}/.gitignore +0 -0
  27. {akquant-0.2.47 → akquant-0.2.48}/.pre-commit-config.yaml +0 -0
  28. {akquant-0.2.47 → akquant-0.2.48}/CODE_OF_CONDUCT.md +0 -0
  29. {akquant-0.2.47 → akquant-0.2.48}/CONTRIBUTING.md +0 -0
  30. {akquant-0.2.47 → akquant-0.2.48}/LICENSE +0 -0
  31. {akquant-0.2.47 → akquant-0.2.48}/README.md +0 -0
  32. {akquant-0.2.47 → akquant-0.2.48}/assets/dashboard_preview.png +0 -0
  33. {akquant-0.2.47 → akquant-0.2.48}/assets/logo.svg +0 -0
  34. {akquant-0.2.47 → akquant-0.2.48}/assets/social_preview.png +0 -0
  35. {akquant-0.2.47 → akquant-0.2.48}/docs/CNAME +0 -0
  36. {akquant-0.2.47 → akquant-0.2.48}/docs/assets/akquant-icon.svg +0 -0
  37. {akquant-0.2.47 → akquant-0.2.48}/docs/assets/akquant-logo.svg +0 -0
  38. {akquant-0.2.47 → akquant-0.2.48}/docs/assets/reports/akquant_report.html +0 -0
  39. {akquant-0.2.47 → akquant-0.2.48}/docs/en/advanced/analyzer_plugin_spec.md +0 -0
  40. {akquant-0.2.47 → akquant-0.2.48}/docs/en/advanced/broker_capability_matrix.md +0 -0
  41. {akquant-0.2.47 → akquant-0.2.48}/docs/en/advanced/custom_broker_production_checklist.md +0 -0
  42. {akquant-0.2.47 → akquant-0.2.48}/docs/en/advanced/custom_broker_registry.md +0 -0
  43. {akquant-0.2.47 → akquant-0.2.48}/docs/en/advanced/data_feed_adapter_spec.md +0 -0
  44. {akquant-0.2.47 → akquant-0.2.48}/docs/en/advanced/live_functional_quickstart.md +0 -0
  45. {akquant-0.2.47 → akquant-0.2.48}/docs/en/advanced/llm.md +0 -0
  46. {akquant-0.2.47 → akquant-0.2.48}/docs/en/advanced/ml.md +0 -0
  47. {akquant-0.2.47 → akquant-0.2.48}/docs/en/advanced/multi_strategy_guide.md +0 -0
  48. {akquant-0.2.47 → akquant-0.2.48}/docs/en/advanced/multi_timeframe_feed_api.md +0 -0
  49. {akquant-0.2.47 → akquant-0.2.48}/docs/en/advanced/runtime_config.md +0 -0
  50. {akquant-0.2.47 → akquant-0.2.48}/docs/en/advanced/strategy_style_decision.md +0 -0
  51. {akquant-0.2.47 → akquant-0.2.48}/docs/en/advanced/timezone.md +0 -0
  52. {akquant-0.2.47 → akquant-0.2.48}/docs/en/advanced/warm_start.md +0 -0
  53. {akquant-0.2.47 → akquant-0.2.48}/docs/en/guide/analysis.md +0 -0
  54. {akquant-0.2.47 → akquant-0.2.48}/docs/en/guide/cross_section_checklist.md +0 -0
  55. {akquant-0.2.47 → akquant-0.2.48}/docs/en/guide/custom_indicator.md +0 -0
  56. {akquant-0.2.47 → akquant-0.2.48}/docs/en/guide/data.md +0 -0
  57. {akquant-0.2.47 → akquant-0.2.48}/docs/en/guide/examples.md +0 -0
  58. {akquant-0.2.47 → akquant-0.2.48}/docs/en/guide/factor.md +0 -0
  59. {akquant-0.2.47 → akquant-0.2.48}/docs/en/guide/indicator_scenario_quickref.md +0 -0
  60. {akquant-0.2.47 → akquant-0.2.48}/docs/en/guide/optimization.md +0 -0
  61. {akquant-0.2.47 → akquant-0.2.48}/docs/en/guide/python_basics.md +0 -0
  62. {akquant-0.2.47 → akquant-0.2.48}/docs/en/guide/quant_basics.md +0 -0
  63. {akquant-0.2.47 → akquant-0.2.48}/docs/en/guide/rust_indicator_reference.md +0 -0
  64. {akquant-0.2.47 → akquant-0.2.48}/docs/en/guide/strategy.md +0 -0
  65. {akquant-0.2.47 → akquant-0.2.48}/docs/en/guide/talib_indicator_playbook.md +0 -0
  66. {akquant-0.2.47 → akquant-0.2.48}/docs/en/guide/testing.md +0 -0
  67. {akquant-0.2.47 → akquant-0.2.48}/docs/en/guide/visualization.md +0 -0
  68. {akquant-0.2.47 → akquant-0.2.48}/docs/en/index.md +0 -0
  69. {akquant-0.2.47 → akquant-0.2.48}/docs/en/meta/architecture.md +0 -0
  70. {akquant-0.2.47 → akquant-0.2.48}/docs/en/meta/internals.md +0 -0
  71. {akquant-0.2.47 → akquant-0.2.48}/docs/en/reference/api.md +0 -0
  72. {akquant-0.2.47 → akquant-0.2.48}/docs/en/start/first_strategy.md +0 -0
  73. {akquant-0.2.47 → akquant-0.2.48}/docs/en/start/installation.md +0 -0
  74. {akquant-0.2.47 → akquant-0.2.48}/docs/en/start/quickstart.md +0 -0
  75. {akquant-0.2.47 → akquant-0.2.48}/docs/en/start/setup_guide.md +0 -0
  76. {akquant-0.2.47 → akquant-0.2.48}/docs/en/textbook/01_foundations.md +0 -0
  77. {akquant-0.2.47 → akquant-0.2.48}/docs/en/textbook/02_programming.md +0 -0
  78. {akquant-0.2.47 → akquant-0.2.48}/docs/en/textbook/03_data.md +0 -0
  79. {akquant-0.2.47 → akquant-0.2.48}/docs/en/textbook/04_backtest_engine.md +0 -0
  80. {akquant-0.2.47 → akquant-0.2.48}/docs/en/textbook/05_strategy.md +0 -0
  81. {akquant-0.2.47 → akquant-0.2.48}/docs/en/textbook/06_stock_a.md +0 -0
  82. {akquant-0.2.47 → akquant-0.2.48}/docs/en/textbook/07_futures.md +0 -0
  83. {akquant-0.2.47 → akquant-0.2.48}/docs/en/textbook/08_options.md +0 -0
  84. {akquant-0.2.47 → akquant-0.2.48}/docs/en/textbook/09_funds.md +0 -0
  85. {akquant-0.2.47 → akquant-0.2.48}/docs/en/textbook/10_analysis.md +0 -0
  86. {akquant-0.2.47 → akquant-0.2.48}/docs/en/textbook/11_optimization.md +0 -0
  87. {akquant-0.2.47 → akquant-0.2.48}/docs/en/textbook/12_ml.md +0 -0
  88. {akquant-0.2.47 → akquant-0.2.48}/docs/en/textbook/13_visualization.md +0 -0
  89. {akquant-0.2.47 → akquant-0.2.48}/docs/en/textbook/14_factor.md +0 -0
  90. {akquant-0.2.47 → akquant-0.2.48}/docs/en/textbook/15_live_trading.md +0 -0
  91. {akquant-0.2.47 → akquant-0.2.48}/docs/en/textbook/16_rust_indicators.md +0 -0
  92. {akquant-0.2.47 → akquant-0.2.48}/docs/en/textbook/index.md +0 -0
  93. {akquant-0.2.47 → akquant-0.2.48}/docs/javascripts/mathjax.js +0 -0
  94. {akquant-0.2.47 → akquant-0.2.48}/docs/javascripts/search-lang-filter.js +0 -0
  95. {akquant-0.2.47 → akquant-0.2.48}/docs/robots.txt +0 -0
  96. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/advanced/analyzer_plugin_spec.md +0 -0
  97. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/advanced/broker_capability_matrix.md +0 -0
  98. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/advanced/custom_broker_production_checklist.md +0 -0
  99. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/advanced/custom_broker_registry.md +0 -0
  100. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/advanced/data_feed_adapter_spec.md +0 -0
  101. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/advanced/live_functional_quickstart.md +0 -0
  102. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/advanced/llm.md +0 -0
  103. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/advanced/ml.md +0 -0
  104. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/advanced/multi_strategy_guide.md +0 -0
  105. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/advanced/multi_timeframe_feed_api.md +0 -0
  106. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/advanced/runtime_config.md +0 -0
  107. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/advanced/strategy_style_decision.md +0 -0
  108. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/advanced/timezone.md +0 -0
  109. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/advanced/warm_start.md +0 -0
  110. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/guide/analysis.md +0 -0
  111. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/guide/cross_section_checklist.md +0 -0
  112. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/guide/custom_indicator.md +0 -0
  113. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/guide/data.md +0 -0
  114. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/guide/examples.md +0 -0
  115. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/guide/factor.md +0 -0
  116. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/guide/indicator_scenario_quickref.md +0 -0
  117. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/guide/optimization.md +0 -0
  118. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/guide/python_basics.md +0 -0
  119. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/guide/quant_basics.md +0 -0
  120. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/guide/rust_indicator_reference.md +0 -0
  121. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/guide/strategy.md +0 -0
  122. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/guide/talib_indicator_playbook.md +0 -0
  123. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/guide/testing.md +0 -0
  124. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/guide/visualization.md +0 -0
  125. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/index.md +0 -0
  126. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/meta/architecture.md +0 -0
  127. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/meta/internals.md +0 -0
  128. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/reference/api.md +0 -0
  129. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/start/first_strategy.md +0 -0
  130. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/start/installation.md +0 -0
  131. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/start/quickstart.md +0 -0
  132. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/start/setup_guide.md +0 -0
  133. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/00_glossary.md +0 -0
  134. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/01_foundations.md +0 -0
  135. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/02_programming.md +0 -0
  136. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/03_data.md +0 -0
  137. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/04_backtest_engine.md +0 -0
  138. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/05_strategy.md +0 -0
  139. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/06_stock_a.md +0 -0
  140. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/07_futures.md +0 -0
  141. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/08_options.md +0 -0
  142. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/09_funds.md +0 -0
  143. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/10_analysis.md +0 -0
  144. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/11_optimization.md +0 -0
  145. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/12_ml.md +0 -0
  146. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/13_visualization.md +0 -0
  147. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/14_factor.md +0 -0
  148. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/15_live_trading.md +0 -0
  149. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/16_rust_indicators.md +0 -0
  150. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/ROADMAP.md +0 -0
  151. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/appendix_cite.md +0 -0
  152. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/appendix_pitfalls.md +0 -0
  153. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/appendix_setup.md +0 -0
  154. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/capstone.md +0 -0
  155. {akquant-0.2.47 → akquant-0.2.48}/docs/zh/textbook/index.md +0 -0
  156. {akquant-0.2.47 → akquant-0.2.48}/examples/01_quickstart.py +0 -0
  157. {akquant-0.2.47 → akquant-0.2.48}/examples/02_parameter_optimization.py +0 -0
  158. {akquant-0.2.47 → akquant-0.2.48}/examples/03_parameter_optimization_advanced.py +0 -0
  159. {akquant-0.2.47 → akquant-0.2.48}/examples/04_mixed_assets.py +0 -0
  160. {akquant-0.2.47 → akquant-0.2.48}/examples/05_live_trading_ctp.py +0 -0
  161. {akquant-0.2.47 → akquant-0.2.48}/examples/06_complex_orders.py +0 -0
  162. {akquant-0.2.47 → akquant-0.2.48}/examples/07_option_test.py +0 -0
  163. {akquant-0.2.47 → akquant-0.2.48}/examples/08_event_callbacks.py +0 -0
  164. {akquant-0.2.47 → akquant-0.2.48}/examples/09_ml_framework.py +0 -0
  165. {akquant-0.2.47 → akquant-0.2.48}/examples/10_ml_walk_forward.py +0 -0
  166. {akquant-0.2.47 → akquant-0.2.48}/examples/11_plot_visualization.py +0 -0
  167. {akquant-0.2.47 → akquant-0.2.48}/examples/12_wfo_integrated.py +0 -0
  168. {akquant-0.2.47 → akquant-0.2.48}/examples/13_quantstats_report.py +0 -0
  169. {akquant-0.2.47 → akquant-0.2.48}/examples/14_multi_frequency.py +0 -0
  170. {akquant-0.2.47 → akquant-0.2.48}/examples/15_plot_intraday.py +0 -0
  171. {akquant-0.2.47 → akquant-0.2.48}/examples/16_adj_returns_signal.py +0 -0
  172. {akquant-0.2.47 → akquant-0.2.48}/examples/17_readme_demo.py +0 -0
  173. {akquant-0.2.47 → akquant-0.2.48}/examples/18_benchmark_multisymbol.py +0 -0
  174. {akquant-0.2.47 → akquant-0.2.48}/examples/19_factor_expression.py +0 -0
  175. {akquant-0.2.47 → akquant-0.2.48}/examples/20_risk_management_demo.py +0 -0
  176. {akquant-0.2.47 → akquant-0.2.48}/examples/21_warm_start_demo.py +0 -0
  177. {akquant-0.2.47 → akquant-0.2.48}/examples/22_strategy_runtime_config_demo.py +0 -0
  178. {akquant-0.2.47 → akquant-0.2.48}/examples/23_functional_callbacks_demo.py +0 -0
  179. {akquant-0.2.47 → akquant-0.2.48}/examples/24_functional_tick_simulation_demo.py +0 -0
  180. {akquant-0.2.47 → akquant-0.2.48}/examples/25_streaming_backtest_demo.py +0 -0
  181. {akquant-0.2.47 → akquant-0.2.48}/examples/26_streaming_quickstart.py +0 -0
  182. {akquant-0.2.47 → akquant-0.2.48}/examples/27_streaming_monitoring_console.py +0 -0
  183. {akquant-0.2.47 → akquant-0.2.48}/examples/28_streaming_alerts_and_persist.py +0 -0
  184. {akquant-0.2.47 → akquant-0.2.48}/examples/29_streaming_event_report.py +0 -0
  185. {akquant-0.2.47 → akquant-0.2.48}/examples/30_streaming_report_oneclick.py +0 -0
  186. {akquant-0.2.47 → akquant-0.2.48}/examples/31_streaming_live_console.py +0 -0
  187. {akquant-0.2.47 → akquant-0.2.48}/examples/32_streaming_live_web.py +0 -0
  188. {akquant-0.2.47 → akquant-0.2.48}/examples/33_report_and_analysis_outputs.py +0 -0
  189. {akquant-0.2.47 → akquant-0.2.48}/examples/34_multi_strategy_demo.py +0 -0
  190. {akquant-0.2.47 → akquant-0.2.48}/examples/35_custom_broker_registry_demo.py +0 -0
  191. {akquant-0.2.47 → akquant-0.2.48}/examples/36_trailing_orders.py +0 -0
  192. {akquant-0.2.47 → akquant-0.2.48}/examples/37_feed_replay_alignment_demo.py +0 -0
  193. {akquant-0.2.47 → akquant-0.2.48}/examples/38_live_functional_strategy_demo.py +0 -0
  194. {akquant-0.2.47 → akquant-0.2.48}/examples/39_live_broker_submit_order_demo.py +0 -0
  195. {akquant-0.2.47 → akquant-0.2.48}/examples/40_functional_multi_slot_risk_demo.py +0 -0
  196. {akquant-0.2.47 → akquant-0.2.48}/examples/41_live_multi_slot_orchestration_demo.py +0 -0
  197. {akquant-0.2.47 → akquant-0.2.48}/examples/42_live_broker_event_audit_demo.py +0 -0
  198. {akquant-0.2.47 → akquant-0.2.48}/examples/43_target_weights_rebalance.py +0 -0
  199. {akquant-0.2.47 → akquant-0.2.48}/examples/44_strategy_source_loader_demo.py +0 -0
  200. {akquant-0.2.47 → akquant-0.2.48}/examples/45_talib_indicator_playbook_demo.py +0 -0
  201. {akquant-0.2.47 → akquant-0.2.48}/examples/46_broker_profile_demo.py +0 -0
  202. {akquant-0.2.47 → akquant-0.2.48}/examples/47_margin_liquidation_audit_demo.py +0 -0
  203. {akquant-0.2.47 → akquant-0.2.48}/examples/48_margin_liquidation_priority_compare.py +0 -0
  204. {akquant-0.2.47 → akquant-0.2.48}/examples/49_on_expiry_demo.py +0 -0
  205. {akquant-0.2.47 → akquant-0.2.48}/examples/50_framework_hooks_demo.py +0 -0
  206. {akquant-0.2.47 → akquant-0.2.48}/examples/51_class_tick_callbacks_demo.py +0 -0
  207. {akquant-0.2.47 → akquant-0.2.48}/examples/52_pre_open_demo.py +0 -0
  208. {akquant-0.2.47 → akquant-0.2.48}/examples/53_timer_to_pre_open_demo.py +0 -0
  209. {akquant-0.2.47 → akquant-0.2.48}/examples/54_functional_pre_open_demo.py +0 -0
  210. {akquant-0.2.47 → akquant-0.2.48}/examples/55_functional_ml_walk_forward.py +0 -0
  211. {akquant-0.2.47 → akquant-0.2.48}/examples/56_functional_warm_start_demo.py +0 -0
  212. {akquant-0.2.47 → akquant-0.2.48}/examples/57_functional_multi_slot_warm_start_demo.py +0 -0
  213. {akquant-0.2.47 → akquant-0.2.48}/examples/58_incremental_bootstrap_demo.py +0 -0
  214. {akquant-0.2.47 → akquant-0.2.48}/examples/59_akshare_etf_rotation.py +0 -0
  215. {akquant-0.2.47 → akquant-0.2.48}/examples/60_custom_indicator_demo.py +0 -0
  216. {akquant-0.2.47 → akquant-0.2.48}/examples/61_indicator_visualization_export_demo.py +0 -0
  217. {akquant-0.2.47 → akquant-0.2.48}/examples/62_indicator_streaming_demo.py +0 -0
  218. {akquant-0.2.47 → akquant-0.2.48}/examples/63_indicator_ws_bridge_demo.py +0 -0
  219. {akquant-0.2.47 → akquant-0.2.48}/examples/64_indicator_live_web.py +0 -0
  220. {akquant-0.2.47 → akquant-0.2.48}/examples/README.md +0 -0
  221. {akquant-0.2.47 → akquant-0.2.48}/examples/benchmark_utils.py +0 -0
  222. {akquant-0.2.47 → akquant-0.2.48}/examples/pb_mock.py +0 -0
  223. {akquant-0.2.47 → akquant-0.2.48}/examples/strategies/01_stock_dual_moving_average.py +0 -0
  224. {akquant-0.2.47 → akquant-0.2.48}/examples/strategies/02_stock_grid_trading.py +0 -0
  225. {akquant-0.2.47 → akquant-0.2.48}/examples/strategies/03_stock_atr_breakout.py +0 -0
  226. {akquant-0.2.47 → akquant-0.2.48}/examples/strategies/04_stock_momentum_rotation.py +0 -0
  227. {akquant-0.2.47 → akquant-0.2.48}/examples/strategies/05_stock_momentum_rotation_timer.py +0 -0
  228. {akquant-0.2.47 → akquant-0.2.48}/examples/strategies/06_stock_momentum_rotation_bucket.py +0 -0
  229. {akquant-0.2.47 → akquant-0.2.48}/examples/strategies/07_stock_momentum_rotation_on_timer.py +0 -0
  230. {akquant-0.2.47 → akquant-0.2.48}/examples/strategies/08_target_positions_long_short.py +0 -0
  231. {akquant-0.2.47 → akquant-0.2.48}/examples/strategies/09_stock_momentum_rotation_after_bar.py +0 -0
  232. {akquant-0.2.47 → akquant-0.2.48}/examples/strategies/README.md +0 -0
  233. {akquant-0.2.47 → akquant-0.2.48}/examples/textbook/ch01_quickstart.py +0 -0
  234. {akquant-0.2.47 → akquant-0.2.48}/examples/textbook/ch02_programming.py +0 -0
  235. {akquant-0.2.47 → akquant-0.2.48}/examples/textbook/ch03_data.py +0 -0
  236. {akquant-0.2.47 → akquant-0.2.48}/examples/textbook/ch04_comparison.py +0 -0
  237. {akquant-0.2.47 → akquant-0.2.48}/examples/textbook/ch05_strategy.py +0 -0
  238. {akquant-0.2.47 → akquant-0.2.48}/examples/textbook/ch06_stock_a.py +0 -0
  239. {akquant-0.2.47 → akquant-0.2.48}/examples/textbook/ch07_futures.py +0 -0
  240. {akquant-0.2.47 → akquant-0.2.48}/examples/textbook/ch08_options.py +0 -0
  241. {akquant-0.2.47 → akquant-0.2.48}/examples/textbook/ch09_funds.py +0 -0
  242. {akquant-0.2.47 → akquant-0.2.48}/examples/textbook/ch09_portfolio.py +0 -0
  243. {akquant-0.2.47 → akquant-0.2.48}/examples/textbook/ch10_analysis.py +0 -0
  244. {akquant-0.2.47 → akquant-0.2.48}/examples/textbook/ch11_optimization.py +0 -0
  245. {akquant-0.2.47 → akquant-0.2.48}/examples/textbook/ch12_ml.py +0 -0
  246. {akquant-0.2.47 → akquant-0.2.48}/examples/textbook/ch13_visualization.py +0 -0
  247. {akquant-0.2.47 → akquant-0.2.48}/examples/textbook/ch14_factor.py +0 -0
  248. {akquant-0.2.47 → akquant-0.2.48}/examples/textbook/ch15_live_trading.py +0 -0
  249. {akquant-0.2.47 → akquant-0.2.48}/examples/textbook/ch15_strategy_loader.py +0 -0
  250. {akquant-0.2.47 → akquant-0.2.48}/examples/textbook/ch16_indicators.py +0 -0
  251. {akquant-0.2.47 → akquant-0.2.48}/mkdocs.yml +0 -0
  252. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/akquant.pyi +0 -0
  253. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/analysis/__init__.py +0 -0
  254. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/analysis/benchmark.py +0 -0
  255. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/analyzer_plugin.py +0 -0
  256. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/backtest/__init__.py +0 -0
  257. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/backtest/__init__.pyi +0 -0
  258. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/backtest/result.py +0 -0
  259. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/checkpoint.py +0 -0
  260. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/data.py +0 -0
  261. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/factor/__init__.py +0 -0
  262. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/factor/engine.py +0 -0
  263. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/factor/ops.py +0 -0
  264. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/factor/parser.py +0 -0
  265. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/feed_adapter.py +0 -0
  266. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/fund/__init__.py +0 -0
  267. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/futures/__init__.py +0 -0
  268. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/__init__.py +0 -0
  269. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/base.py +0 -0
  270. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/broker_event_bridge.py +0 -0
  271. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/broker_event_mapper.py +0 -0
  272. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/broker_models.py +0 -0
  273. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/broker_recovery.py +0 -0
  274. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/broker_runtime.py +0 -0
  275. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/brokers/__init__.py +0 -0
  276. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/brokers/ctp/__init__.py +0 -0
  277. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/brokers/ctp/adapter.py +0 -0
  278. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/brokers/ctp/native.py +0 -0
  279. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/brokers/miniqmt/__init__.py +0 -0
  280. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/brokers/miniqmt/stub.py +0 -0
  281. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/brokers/ptrade/__init__.py +0 -0
  282. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/brokers/ptrade/stub.py +0 -0
  283. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/ctp_adapter.py +0 -0
  284. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/ctp_native.py +0 -0
  285. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/factory.py +0 -0
  286. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/mapper.py +0 -0
  287. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/miniqmt.py +0 -0
  288. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/models.py +0 -0
  289. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/order_submitter.py +0 -0
  290. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/protocols.py +0 -0
  291. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/ptrade.py +0 -0
  292. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/gateway/registry.py +0 -0
  293. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/indicator.py +0 -0
  294. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/indicator_recording.py +0 -0
  295. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/indicator_stream.py +0 -0
  296. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/live.py +0 -0
  297. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/log.py +0 -0
  298. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/ml/__init__.py +0 -0
  299. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/ml/model.py +0 -0
  300. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/optimize.py +0 -0
  301. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/option/__init__.py +0 -0
  302. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/params.py +0 -0
  303. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/params_adapter.py +0 -0
  304. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/plot/__init__.py +0 -0
  305. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/plot/analysis.py +0 -0
  306. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/plot/dashboard.py +0 -0
  307. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/plot/indicator.py +0 -0
  308. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/plot/report.py +0 -0
  309. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/plot/strategy.py +0 -0
  310. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/plot/utils.py +0 -0
  311. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/py.typed +0 -0
  312. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/risk.py +0 -0
  313. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/sizer.py +0 -0
  314. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/stock/__init__.py +0 -0
  315. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/strategy.py +0 -0
  316. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/strategy_events.py +0 -0
  317. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/strategy_framework_hooks.py +0 -0
  318. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/strategy_history.py +0 -0
  319. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/strategy_loader.py +0 -0
  320. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/strategy_logging.py +0 -0
  321. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/strategy_ml.py +0 -0
  322. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/strategy_order_events.py +0 -0
  323. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/strategy_position.py +0 -0
  324. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/strategy_scheduler.py +0 -0
  325. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/strategy_time.py +0 -0
  326. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/strategy_trading_api.py +0 -0
  327. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/talib/__init__.py +0 -0
  328. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/talib/backend.py +0 -0
  329. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/talib/core.py +0 -0
  330. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/talib/funcs.py +0 -0
  331. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/utils/__init__.py +0 -0
  332. {akquant-0.2.47 → akquant-0.2.48}/python/akquant/utils/inspector.py +0 -0
  333. {akquant-0.2.47 → akquant-0.2.48}/requirements-dev.txt +0 -0
  334. {akquant-0.2.47 → akquant-0.2.48}/scripts/cargo-test.sh +0 -0
  335. {akquant-0.2.47 → akquant-0.2.48}/scripts/check_docs_api_examples.py +0 -0
  336. {akquant-0.2.47 → akquant-0.2.48}/scripts/check_docs_links.py +0 -0
  337. {akquant-0.2.47 → akquant-0.2.48}/scripts/dev-check.sh +0 -0
  338. {akquant-0.2.47 → akquant-0.2.48}/scripts/find_legacy_execution_policy_calls.py +0 -0
  339. {akquant-0.2.47 → akquant-0.2.48}/scripts/golden_baseline_report.py +0 -0
  340. {akquant-0.2.47 → akquant-0.2.48}/src/account.rs +0 -0
  341. {akquant-0.2.47 → akquant-0.2.48}/src/analysis/mod.rs +0 -0
  342. {akquant-0.2.47 → akquant-0.2.48}/src/analysis/python.rs +0 -0
  343. {akquant-0.2.47 → akquant-0.2.48}/src/analysis/tracker.rs +0 -0
  344. {akquant-0.2.47 → akquant-0.2.48}/src/analysis/types.rs +0 -0
  345. {akquant-0.2.47 → akquant-0.2.48}/src/bin/stub_gen.rs +0 -0
  346. {akquant-0.2.47 → akquant-0.2.48}/src/clock.rs +0 -0
  347. {akquant-0.2.47 → akquant-0.2.48}/src/context.rs +0 -0
  348. {akquant-0.2.47 → akquant-0.2.48}/src/data/aggregator.rs +0 -0
  349. {akquant-0.2.47 → akquant-0.2.48}/src/data/batch.rs +0 -0
  350. {akquant-0.2.47 → akquant-0.2.48}/src/data/client.rs +0 -0
  351. {akquant-0.2.47 → akquant-0.2.48}/src/data/feed.rs +0 -0
  352. {akquant-0.2.47 → akquant-0.2.48}/src/data/mod.rs +0 -0
  353. {akquant-0.2.47 → akquant-0.2.48}/src/engine/mod.rs +0 -0
  354. {akquant-0.2.47 → akquant-0.2.48}/src/engine/state.rs +0 -0
  355. {akquant-0.2.47 → akquant-0.2.48}/src/error.rs +0 -0
  356. {akquant-0.2.47 → akquant-0.2.48}/src/event.rs +0 -0
  357. {akquant-0.2.47 → akquant-0.2.48}/src/event_manager.rs +0 -0
  358. {akquant-0.2.47 → akquant-0.2.48}/src/execution/common.rs +0 -0
  359. {akquant-0.2.47 → akquant-0.2.48}/src/execution/crypto.rs +0 -0
  360. {akquant-0.2.47 → akquant-0.2.48}/src/execution/forex.rs +0 -0
  361. {akquant-0.2.47 → akquant-0.2.48}/src/execution/futures.rs +0 -0
  362. {akquant-0.2.47 → akquant-0.2.48}/src/execution/matcher.rs +0 -0
  363. {akquant-0.2.47 → akquant-0.2.48}/src/execution/mod.rs +0 -0
  364. {akquant-0.2.47 → akquant-0.2.48}/src/execution/option.rs +0 -0
  365. {akquant-0.2.47 → akquant-0.2.48}/src/execution/python.rs +0 -0
  366. {akquant-0.2.47 → akquant-0.2.48}/src/execution/realtime.rs +0 -0
  367. {akquant-0.2.47 → akquant-0.2.48}/src/execution/simulated.rs +0 -0
  368. {akquant-0.2.47 → akquant-0.2.48}/src/execution/slippage.rs +0 -0
  369. {akquant-0.2.47 → akquant-0.2.48}/src/execution/stock.rs +0 -0
  370. {akquant-0.2.47 → akquant-0.2.48}/src/history.rs +0 -0
  371. {akquant-0.2.47 → akquant-0.2.48}/src/indicators/momentum.rs +0 -0
  372. {akquant-0.2.47 → akquant-0.2.48}/src/indicators/momentum_oscillators.rs +0 -0
  373. {akquant-0.2.47 → akquant-0.2.48}/src/indicators/momentum_rates.rs +0 -0
  374. {akquant-0.2.47 → akquant-0.2.48}/src/indicators/moving_average.rs +0 -0
  375. {akquant-0.2.47 → akquant-0.2.48}/src/indicators/moving_average_compound.rs +0 -0
  376. {akquant-0.2.47 → akquant-0.2.48}/src/indicators/moving_average_core.rs +0 -0
  377. {akquant-0.2.47 → akquant-0.2.48}/src/indicators/moving_average_transforms.rs +0 -0
  378. {akquant-0.2.47 → akquant-0.2.48}/src/indicators/moving_average_windowed.rs +0 -0
  379. {akquant-0.2.47 → akquant-0.2.48}/src/indicators/trend.rs +0 -0
  380. {akquant-0.2.47 → akquant-0.2.48}/src/indicators/trend_directional.rs +0 -0
  381. {akquant-0.2.47 → akquant-0.2.48}/src/indicators/trend_oscillators.rs +0 -0
  382. {akquant-0.2.47 → akquant-0.2.48}/src/indicators/trend_regression.rs +0 -0
  383. {akquant-0.2.47 → akquant-0.2.48}/src/indicators/volatility.rs +0 -0
  384. {akquant-0.2.47 → akquant-0.2.48}/src/indicators/volatility_price.rs +0 -0
  385. {akquant-0.2.47 → akquant-0.2.48}/src/indicators/volatility_stats.rs +0 -0
  386. {akquant-0.2.47 → akquant-0.2.48}/src/indicators/volume.rs +0 -0
  387. {akquant-0.2.47 → akquant-0.2.48}/src/indicators.rs +0 -0
  388. {akquant-0.2.47 → akquant-0.2.48}/src/lib.rs +0 -0
  389. {akquant-0.2.47 → akquant-0.2.48}/src/log_context.rs +0 -0
  390. {akquant-0.2.47 → akquant-0.2.48}/src/margin/calculator.rs +0 -0
  391. {akquant-0.2.47 → akquant-0.2.48}/src/margin/engine.rs +0 -0
  392. {akquant-0.2.47 → akquant-0.2.48}/src/margin/mod.rs +0 -0
  393. {akquant-0.2.47 → akquant-0.2.48}/src/market/china.rs +0 -0
  394. {akquant-0.2.47 → akquant-0.2.48}/src/market/core.rs +0 -0
  395. {akquant-0.2.47 → akquant-0.2.48}/src/market/corporate_action.rs +0 -0
  396. {akquant-0.2.47 → akquant-0.2.48}/src/market/fund.rs +0 -0
  397. {akquant-0.2.47 → akquant-0.2.48}/src/market/futures.rs +0 -0
  398. {akquant-0.2.47 → akquant-0.2.48}/src/market/manager.rs +0 -0
  399. {akquant-0.2.47 → akquant-0.2.48}/src/market/mod.rs +0 -0
  400. {akquant-0.2.47 → akquant-0.2.48}/src/market/option.rs +0 -0
  401. {akquant-0.2.47 → akquant-0.2.48}/src/market/simple.rs +0 -0
  402. {akquant-0.2.47 → akquant-0.2.48}/src/market/stock.rs +0 -0
  403. {akquant-0.2.47 → akquant-0.2.48}/src/model/corporate_action.rs +0 -0
  404. {akquant-0.2.47 → akquant-0.2.48}/src/model/instrument.rs +0 -0
  405. {akquant-0.2.47 → akquant-0.2.48}/src/model/market_data.rs +0 -0
  406. {akquant-0.2.47 → akquant-0.2.48}/src/model/mod.rs +0 -0
  407. {akquant-0.2.47 → akquant-0.2.48}/src/model/order.rs +0 -0
  408. {akquant-0.2.47 → akquant-0.2.48}/src/model/timer.rs +0 -0
  409. {akquant-0.2.47 → akquant-0.2.48}/src/model/types.rs +0 -0
  410. {akquant-0.2.47 → akquant-0.2.48}/src/order_manager.rs +0 -0
  411. {akquant-0.2.47 → akquant-0.2.48}/src/pipeline/mod.rs +0 -0
  412. {akquant-0.2.47 → akquant-0.2.48}/src/pipeline/processor.rs +0 -0
  413. {akquant-0.2.47 → akquant-0.2.48}/src/pipeline/runner.rs +0 -0
  414. {akquant-0.2.47 → akquant-0.2.48}/src/pipeline/stages/channel.rs +0 -0
  415. {akquant-0.2.47 → akquant-0.2.48}/src/pipeline/stages/cleanup.rs +0 -0
  416. {akquant-0.2.47 → akquant-0.2.48}/src/pipeline/stages/data.rs +0 -0
  417. {akquant-0.2.47 → akquant-0.2.48}/src/pipeline/stages/execution.rs +0 -0
  418. {akquant-0.2.47 → akquant-0.2.48}/src/pipeline/stages/mod.rs +0 -0
  419. {akquant-0.2.47 → akquant-0.2.48}/src/pipeline/stages/shared.rs +0 -0
  420. {akquant-0.2.47 → akquant-0.2.48}/src/pipeline/stages/statistics.rs +0 -0
  421. {akquant-0.2.47 → akquant-0.2.48}/src/pipeline/stages/strategy.rs +0 -0
  422. {akquant-0.2.47 → akquant-0.2.48}/src/portfolio.rs +0 -0
  423. {akquant-0.2.47 → akquant-0.2.48}/src/risk/common.rs +0 -0
  424. {akquant-0.2.47 → akquant-0.2.48}/src/risk/config.rs +0 -0
  425. {akquant-0.2.47 → akquant-0.2.48}/src/risk/futures.rs +0 -0
  426. {akquant-0.2.47 → akquant-0.2.48}/src/risk/manager.rs +0 -0
  427. {akquant-0.2.47 → akquant-0.2.48}/src/risk/mod.rs +0 -0
  428. {akquant-0.2.47 → akquant-0.2.48}/src/risk/option.rs +0 -0
  429. {akquant-0.2.47 → akquant-0.2.48}/src/risk/portfolio.rs +0 -0
  430. {akquant-0.2.47 → akquant-0.2.48}/src/risk/rule.rs +0 -0
  431. {akquant-0.2.47 → akquant-0.2.48}/src/risk/stock.rs +0 -0
  432. {akquant-0.2.47 → akquant-0.2.48}/src/settlement/expiry.rs +0 -0
  433. {akquant-0.2.47 → akquant-0.2.48}/src/settlement/handler.rs +0 -0
  434. {akquant-0.2.47 → akquant-0.2.48}/src/settlement/manager.rs +0 -0
  435. {akquant-0.2.47 → akquant-0.2.48}/src/settlement/mod.rs +0 -0
  436. {akquant-0.2.47 → akquant-0.2.48}/src/settlement/option.rs +0 -0
  437. {akquant-0.2.47 → akquant-0.2.48}/tests/gateway_contract/test_event_bridge_contract.py +0 -0
  438. {akquant-0.2.47 → akquant-0.2.48}/tests/gateway_contract/test_recovery_contract.py +0 -0
  439. {akquant-0.2.47 → akquant-0.2.48}/tests/gateway_contract/test_submitter_contract.py +0 -0
  440. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/BASELINE_REPORT.md +0 -0
  441. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/LEGACY_EXECUTION_CALLS.md +0 -0
  442. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/baselines/futures_margin/equity_curve.parquet +0 -0
  443. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/baselines/futures_margin/orders.parquet +0 -0
  444. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/baselines/option_basic/equity_curve.parquet +0 -0
  445. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/baselines/option_basic/orders.parquet +0 -0
  446. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/baselines/stock_t1/equity_curve.parquet +0 -0
  447. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/baselines/stock_t1/orders.parquet +0 -0
  448. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/baselines/stock_t1/trades.parquet +0 -0
  449. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/current/futures_margin/equity_curve.parquet +0 -0
  450. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/current/futures_margin/orders.parquet +0 -0
  451. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/current/option_basic/equity_curve.parquet +0 -0
  452. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/current/option_basic/orders.parquet +0 -0
  453. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/current/stock_t1/equity_curve.parquet +0 -0
  454. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/current/stock_t1/orders.parquet +0 -0
  455. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/current/stock_t1/trades.parquet +0 -0
  456. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/data/future_margin.parquet +0 -0
  457. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/data/future_margin.parquet.sha256 +0 -0
  458. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/data/option_basic.parquet +0 -0
  459. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/data/option_basic.parquet.sha256 +0 -0
  460. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/data/stock_t1.parquet +0 -0
  461. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/data/stock_t1.parquet.sha256 +0 -0
  462. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/gen_data.py +0 -0
  463. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/runner.py +0 -0
  464. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/strategies/futures_margin.py +0 -0
  465. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/strategies/option_basic.py +0 -0
  466. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/strategies/stock_t1.py +0 -0
  467. {akquant-0.2.47 → akquant-0.2.48}/tests/golden/test_golden.py +0 -0
  468. {akquant-0.2.47 → akquant-0.2.48}/tests/test_account_risk_rules.py +0 -0
  469. {akquant-0.2.47 → akquant-0.2.48}/tests/test_custom_matcher.py +0 -0
  470. {akquant-0.2.47 → akquant-0.2.48}/tests/test_data_catalog.py +0 -0
  471. {akquant-0.2.47 → akquant-0.2.48}/tests/test_docs_api_examples.py +0 -0
  472. {akquant-0.2.47 → akquant-0.2.48}/tests/test_docs_links.py +0 -0
  473. {akquant-0.2.47 → akquant-0.2.48}/tests/test_engine.py +0 -0
  474. {akquant-0.2.47 → akquant-0.2.48}/tests/test_examples_regression.py +0 -0
  475. {akquant-0.2.47 → akquant-0.2.48}/tests/test_factor_engine.py +0 -0
  476. {akquant-0.2.47 → akquant-0.2.48}/tests/test_factor_ops.py +0 -0
  477. {akquant-0.2.47 → akquant-0.2.48}/tests/test_feed_adapter.py +0 -0
  478. {akquant-0.2.47 → akquant-0.2.48}/tests/test_gateway_brokers_paths.py +0 -0
  479. {akquant-0.2.47 → akquant-0.2.48}/tests/test_gateway_callbacks.py +0 -0
  480. {akquant-0.2.47 → akquant-0.2.48}/tests/test_gateway_ctp_adapter.py +0 -0
  481. {akquant-0.2.47 → akquant-0.2.48}/tests/test_gateway_ctp_native.py +0 -0
  482. {akquant-0.2.47 → akquant-0.2.48}/tests/test_gateway_factory.py +0 -0
  483. {akquant-0.2.47 → akquant-0.2.48}/tests/test_gateway_mapper.py +0 -0
  484. {akquant-0.2.47 → akquant-0.2.48}/tests/test_gateway_registry.py +0 -0
  485. {akquant-0.2.47 → akquant-0.2.48}/tests/test_indicator_live_web_example.py +0 -0
  486. {akquant-0.2.47 → akquant-0.2.48}/tests/test_indicator_recording.py +0 -0
  487. {akquant-0.2.47 → akquant-0.2.48}/tests/test_inspector.py +0 -0
  488. {akquant-0.2.47 → akquant-0.2.48}/tests/test_live_runner.py +0 -0
  489. {akquant-0.2.47 → akquant-0.2.48}/tests/test_live_runner_broker_bridge.py +0 -0
  490. {akquant-0.2.47 → akquant-0.2.48}/tests/test_live_runner_broker_recovery.py +0 -0
  491. {akquant-0.2.47 → akquant-0.2.48}/tests/test_live_runner_broker_submitter.py +0 -0
  492. {akquant-0.2.47 → akquant-0.2.48}/tests/test_multisymbol_cross_section_consistency.py +0 -0
  493. {akquant-0.2.47 → akquant-0.2.48}/tests/test_orders_df.py +0 -0
  494. {akquant-0.2.47 → akquant-0.2.48}/tests/test_params_adapter.py +0 -0
  495. {akquant-0.2.47 → akquant-0.2.48}/tests/test_partial_filled_status.py +0 -0
  496. {akquant-0.2.47 → akquant-0.2.48}/tests/test_portfolio.py +0 -0
  497. {akquant-0.2.47 → akquant-0.2.48}/tests/test_quickstart_stream_consistency.py +0 -0
  498. {akquant-0.2.47 → akquant-0.2.48}/tests/test_report_helpers.py +0 -0
  499. {akquant-0.2.47 → akquant-0.2.48}/tests/test_report_plot_extensions.py +0 -0
  500. {akquant-0.2.47 → akquant-0.2.48}/tests/test_result_analysis_extensions.py +0 -0
  501. {akquant-0.2.47 → akquant-0.2.48}/tests/test_stop_orders.py +0 -0
  502. {akquant-0.2.47 → akquant-0.2.48}/tests/test_strategy_extras.py +0 -0
  503. {akquant-0.2.47 → akquant-0.2.48}/tests/test_strategy_timers_indicators.py +0 -0
  504. {akquant-0.2.47 → akquant-0.2.48}/tests/test_t_plus_one.py +0 -0
  505. {akquant-0.2.47 → akquant-0.2.48}/tests/test_talib_backend.py +0 -0
  506. {akquant-0.2.47 → akquant-0.2.48}/tests/test_talib_compat.py +0 -0
  507. {akquant-0.2.47 → akquant-0.2.48}/tests/test_trades_df.py +0 -0
  508. {akquant-0.2.47 → akquant-0.2.48}/tests/test_version.py +0 -0
@@ -7,7 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Added
11
+ - `BacktestConfig` 新增 `days_per_year`(年化天数因子,默认 252;数字货币 24/7 市场可设 365)与 `risk_free_rate`(年化无风险利率,默认 0.0)两个字段,用于参数化 Sharpe/Sortino/波动率等风险指标的年化口径。`risk_free_rate` 默认 0 不改变任何现有数值。
12
+
10
13
  ### Changed
14
+ - **回测指标口径变更(破坏性)**:Sharpe / Sortino 比率的分子改为「日收益算术均值 × `days_per_year`」做年化,替代原先的 CAGR(复合年化),与 pyfolio/empyrical/quantstats 等主流实现一致,并与分母 `√days_per_year` 的年化口径匹配。升级后历史报告的 Sharpe/Sortino 数值会变化,不可直接与旧版逐值对比;UPI 与 Calmar 仍沿用 CAGR 口径。
11
15
  - 策略交易日边界回调已硬切改名:`before_trading(trading_date, timestamp)` 更名为 `on_before_trading(trading_date, timestamp)`,`after_trading(trading_date, timestamp)` 更名为 `on_after_trading(trading_date, timestamp)`。
12
16
  - 旧回调名不再保留兼容别名;升级到当前版本后,若策略仍实现 `before_trading` / `after_trading`,将不会再被框架触发,请同步迁移到新名称。
13
17
  - 新增 `on_pre_open(event)` 框架回调,用于表达“盘前决策,本次 open 成交”;该回调默认下单语义会自动解析为 `price_basis=open, bar_offset=1, temporal=same_cycle`,不再要求用户自行用 `on_timer` 拼装开盘成交时序。
@@ -17,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
17
21
  - 示例体系新增 `examples/52_pre_open_demo.py`,用于演示 `on_pre_open -> on_order/on_trade -> on_bar` 的触发顺序与当日 open 成交语义。
18
22
 
19
23
  ### Fixed
24
+ - 修复短回测区间下 Sharpe/Sortino 因「分子用 CAGR、分母用日波动 × √252」口径不一致而出现异常巨大值(如期货场景 Sharpe 高达数千万)的问题;改用日收益算术均值年化后数值回归合理量级。
20
25
  - 修复 `on_timer` / `add_daily_timer` 场景下,订单级 `fill_policy={"price_basis":"close","bar_offset":0,"temporal":"same_cycle"}` 未在当日 timer 事件内生效的问题;相关卖单现在会按当日 timer 时间与当日 close 成交,不再延后到下一交易日。
21
26
  - 修复 framework 内部 `__framework_rebalance__` / `__framework_boundary__` timer 被误参与 same-cycle 撮合与终态统计的问题,避免出现 `+1ns` 的伪成交、partial fill 被过早补满,以及权益曲线尾部多出额外采样点。
22
27
  - 修复 `on_pre_open` 首个交易日可能因延迟注册 timer 而不触发的问题;相关 framework timer 现会在回测事件循环开始前直接注入引擎,从而保证首日也能按预期开盘语义执行。
@@ -30,7 +30,7 @@ dependencies = [
30
30
 
31
31
  [[package]]
32
32
  name = "akquant"
33
- version = "0.2.47"
33
+ version = "0.2.48"
34
34
  dependencies = [
35
35
  "anyhow",
36
36
  "chrono",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "akquant"
3
- version = "0.2.47"
3
+ version = "0.2.48"
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.47
3
+ Version: 0.2.48
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: Implementation :: PyPy
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "akquant"
7
- version = "0.2.47"
7
+ version = "0.2.48"
8
8
  description = "High-performance quantitative trading framework based on Rust and Python"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT License"}
@@ -8,7 +8,7 @@ try:
8
8
  except metadata.PackageNotFoundError:
9
9
  __version__ = "0.0.0+unknown"
10
10
 
11
- __engine_rule_version__ = "1.0.0" # Increment on behavior-changing updates
11
+ __engine_rule_version__ = "1.1.0" # Increment on behavior-changing updates
12
12
 
13
13
  from . import akquant as _akquant
14
14
  from . import log as _log
@@ -3313,6 +3313,14 @@ def run_backtest(
3313
3313
  raise ValueError(f"Invalid timezone: {timezone}")
3314
3314
  offset = int(offset_delta.total_seconds())
3315
3315
  engine.set_timezone(offset)
3316
+ if hasattr(engine, "set_days_per_year"):
3317
+ cast(Any, engine).set_days_per_year(
3318
+ getattr(config, "days_per_year", 252.0) if config else 252.0
3319
+ )
3320
+ if hasattr(engine, "set_risk_free_rate"):
3321
+ cast(Any, engine).set_risk_free_rate(
3322
+ getattr(config, "risk_free_rate", 0.0) if config else 0.0
3323
+ )
3316
3324
  engine.set_cash(initial_cash)
3317
3325
  if hasattr(engine, "set_default_strategy_id"):
3318
3326
  cast(Any, engine).set_default_strategy_id(effective_strategy_id)
@@ -631,6 +631,11 @@ class BacktestConfig:
631
631
  **Environment:**
632
632
  :param benchmark: Benchmark symbol for performance comparison.
633
633
  :param timezone: Exchange timezone. Default "Asia/Shanghai".
634
+ :param days_per_year: Annualization factor for risk metrics (Sharpe/Sortino/
635
+ volatility). Traditional markets use 252; crypto 24/7
636
+ markets use 365. Default 252.0.
637
+ :param risk_free_rate: Annualized risk-free rate subtracted from annualized
638
+ return in Sharpe/Sortino/UPI. Default 0.0.
634
639
  :param show_progress: Show progress bar. Default True.
635
640
  :param history_depth: Auto-load N bars of history before strategy starts.
636
641
 
@@ -654,6 +659,8 @@ class BacktestConfig:
654
659
 
655
660
  benchmark: Optional[str] = None
656
661
  timezone: str = "Asia/Shanghai"
662
+ days_per_year: float = 252.0
663
+ risk_free_rate: float = 0.0
657
664
  show_progress: bool = True
658
665
  history_depth: int = 0
659
666
 
@@ -22,6 +22,10 @@ pub struct CalculatorInput {
22
22
  pub orders: Vec<Order>,
23
23
  pub executions: Vec<Trade>,
24
24
  pub liquidation_audits: Vec<LiquidationAudit>,
25
+ /// 年化天数因子。A 股等传统市场用 252,数字货币 24/7 市场用 365。
26
+ pub days_per_year: f64,
27
+ /// 年化无风险利率,默认 0.0。直接从年化收益分子里扣除。
28
+ pub risk_free_rate: f64,
25
29
  }
26
30
 
27
31
  #[gen_stub_pyclass]
@@ -250,12 +254,18 @@ impl BacktestResult {
250
254
  };
251
255
 
252
256
  let std_dev = variance.sqrt();
253
- let annualized_volatility = std_dev * (252.0f64).sqrt();
257
+ let dpy = input.days_per_year;
258
+ let annualized_volatility = std_dev * dpy.sqrt();
259
+
260
+ // 口径说明:Sharpe / Sortino 的分子使用「日收益算术均值 × days_per_year」做年化,
261
+ // 与 pyfolio/empyrical/quantstats 等行业实现一致;与分母 √days_per_year 的算术年化口径匹配。
262
+ // 注意:UPI 与 Calmar 刻意沿用 CAGR(annualized_return),不要改成算术均值。
263
+ let annualized_mean_return = mean_return * dpy;
264
+ let risk_free_rate = input.risk_free_rate; // 年化无风险利率,默认 0.0
254
265
 
255
266
  // 5. Sharpe Ratio
256
- let risk_free_rate = 0.0; // Assume 0 for simplicity or pass config
257
267
  let sharpe_ratio = if annualized_volatility != 0.0 {
258
- (annualized_return - risk_free_rate) / annualized_volatility
268
+ (annualized_mean_return - risk_free_rate) / annualized_volatility
259
269
  } else {
260
270
  0.0
261
271
  };
@@ -268,15 +278,15 @@ impl BacktestResult {
268
278
  0.0
269
279
  };
270
280
  let downside_std_dev = downside_variance.sqrt();
271
- let annualized_downside_volatility = downside_std_dev * (252.0f64).sqrt();
281
+ let annualized_downside_volatility = downside_std_dev * dpy.sqrt();
272
282
 
273
283
  let sortino_ratio = if annualized_downside_volatility != 0.0 {
274
- (annualized_return - risk_free_rate) / annualized_downside_volatility
284
+ (annualized_mean_return - risk_free_rate) / annualized_downside_volatility
275
285
  } else {
276
286
  0.0
277
287
  };
278
288
 
279
- // 7. UPI
289
+ // 7. UPI (Ulcer Performance Index) —— 沿用 CAGR 口径(与 quantstats 一致)
280
290
  let upi = if ulcer_index != 0.0 {
281
291
  (annualized_return - risk_free_rate) / ulcer_index
282
292
  } else {
@@ -229,6 +229,8 @@ fn test_max_drawdown_logic() {
229
229
  orders: vec![],
230
230
  executions: vec![],
231
231
  liquidation_audits: vec![],
232
+ days_per_year: 252.0,
233
+ risk_free_rate: 0.0,
232
234
  });
233
235
  assert_eq!(result.metrics.max_drawdown, 0.25);
234
236
 
@@ -252,6 +254,8 @@ fn test_max_drawdown_logic() {
252
254
  orders: vec![],
253
255
  executions: vec![],
254
256
  liquidation_audits: vec![],
257
+ days_per_year: 252.0,
258
+ risk_free_rate: 0.0,
255
259
  });
256
260
  assert_eq!(result_2.metrics.max_drawdown, 0.0);
257
261
 
@@ -275,6 +279,8 @@ fn test_max_drawdown_logic() {
275
279
  orders: vec![],
276
280
  executions: vec![],
277
281
  liquidation_audits: vec![],
282
+ days_per_year: 252.0,
283
+ risk_free_rate: 0.0,
278
284
  });
279
285
  assert_eq!(result_3.metrics.max_drawdown, 0.2);
280
286
 
@@ -301,6 +307,8 @@ fn test_max_drawdown_logic() {
301
307
  orders: vec![],
302
308
  executions: vec![],
303
309
  liquidation_audits: vec![],
310
+ days_per_year: 252.0,
311
+ risk_free_rate: 0.0,
304
312
  });
305
313
  assert_eq!(result_4.metrics.max_drawdown, 0.5);
306
314
  }
@@ -337,6 +345,8 @@ fn test_ulcer_index_logic() {
337
345
  orders: vec![],
338
346
  executions: vec![],
339
347
  liquidation_audits: vec![],
348
+ days_per_year: 252.0,
349
+ risk_free_rate: 0.0,
340
350
  });
341
351
  let expected_ui = 0.004f64.sqrt();
342
352
  assert!((result.metrics.ulcer_index - expected_ui).abs() < 1e-9);
@@ -364,6 +374,8 @@ fn test_calmar_uses_raw_drawdown_ratio_not_pct() {
364
374
  orders: vec![],
365
375
  executions: vec![],
366
376
  liquidation_audits: vec![],
377
+ days_per_year: 252.0,
378
+ risk_free_rate: 0.0,
367
379
  });
368
380
 
369
381
  let expected_raw_calmar = result.metrics.annualized_return / result.metrics.max_drawdown;
@@ -409,6 +421,8 @@ fn test_daily_metrics_resample_by_local_timezone_day() {
409
421
  orders: vec![],
410
422
  executions: vec![],
411
423
  liquidation_audits: vec![],
424
+ days_per_year: 252.0,
425
+ risk_free_rate: 0.0,
412
426
  });
413
427
 
414
428
  let expected_returns = [0.21_f64, 0.10_f64];
@@ -422,3 +436,83 @@ fn test_daily_metrics_resample_by_local_timezone_day() {
422
436
 
423
437
  assert!((result.metrics.volatility - expected_volatility).abs() < 1e-12);
424
438
  }
439
+
440
+ /// 构造一段每日权益曲线(日收益 [0.21, 0.10]),用指定的 days_per_year / risk_free_rate 计算结果。
441
+ fn build_sharpe_fixture(days_per_year: f64, risk_free_rate: f64) -> BacktestResult {
442
+ let empty_pnl = TradeTracker::new().calculate_pnl(None);
443
+ let day_ns = 86_400_000_000_000_i64;
444
+ let equity_curve = vec![
445
+ (0, Decimal::from(100)),
446
+ (day_ns, Decimal::from(121)),
447
+ (2 * day_ns, Decimal::from_str_exact("133.1").unwrap()),
448
+ ];
449
+
450
+ BacktestResult::calculate(crate::analysis::CalculatorInput {
451
+ equity_curve_decimal: equity_curve,
452
+ cash_curve_decimal: vec![],
453
+ margin_curve_decimal: vec![],
454
+ snapshots: vec![],
455
+ timezone_name: Some("UTC".to_string()),
456
+ timezone_offset: 0,
457
+ trade_pnl: empty_pnl,
458
+ trades: vec![],
459
+ initial_cash: Decimal::from(100),
460
+ orders: vec![],
461
+ executions: vec![],
462
+ liquidation_audits: vec![],
463
+ days_per_year,
464
+ risk_free_rate,
465
+ })
466
+ }
467
+
468
+ #[test]
469
+ fn test_sharpe_uses_arithmetic_mean_not_cagr() {
470
+ let dpy = 252.0_f64;
471
+ let result = build_sharpe_fixture(dpy, 0.0);
472
+
473
+ // 期望:分子为日收益算术均值年化 (mean * dpy),与分母 std * sqrt(dpy) 口径匹配。
474
+ let returns = [0.21_f64, 0.10_f64];
475
+ let mean = returns.iter().sum::<f64>() / returns.len() as f64;
476
+ let variance =
477
+ returns.iter().map(|r| (r - mean).powi(2)).sum::<f64>() / (returns.len() - 1) as f64;
478
+ let std = variance.sqrt();
479
+ let expected_sharpe = (mean * dpy) / (std * dpy.sqrt());
480
+
481
+ assert!((result.metrics.sharpe_ratio - expected_sharpe).abs() < 1e-9);
482
+
483
+ // 反向断言:旧的 CAGR 口径 (annualized_return / volatility) 在这种短回测下会爆炸,
484
+ // 新口径必须显著不同于它,以防回归到 PR #305 修复前的行为。
485
+ let old_cagr_sharpe = result.metrics.annualized_return / result.metrics.volatility;
486
+ assert!((result.metrics.sharpe_ratio - old_cagr_sharpe).abs() > 1.0);
487
+ }
488
+
489
+ #[test]
490
+ fn test_days_per_year_scales_annualization() {
491
+ let sharpe_252 = build_sharpe_fixture(252.0, 0.0).metrics.sharpe_ratio;
492
+ let sharpe_365 = build_sharpe_fixture(365.0, 0.0).metrics.sharpe_ratio;
493
+
494
+ // sharpe = mean * sqrt(dpy) / std,故比值应为 sqrt(365/252)。
495
+ let expected_ratio = (365.0_f64 / 252.0_f64).sqrt();
496
+ assert!((sharpe_365 / sharpe_252 - expected_ratio).abs() < 1e-9);
497
+ }
498
+
499
+ #[test]
500
+ fn test_risk_free_rate_lowers_sharpe() {
501
+ let dpy = 252.0_f64;
502
+ let rf = 0.5_f64; // 年化无风险利率
503
+ let base = build_sharpe_fixture(dpy, 0.0);
504
+ let with_rf = build_sharpe_fixture(dpy, rf);
505
+
506
+ // rf=0 与默认行为一致,保证基线不动。
507
+ let returns = [0.21_f64, 0.10_f64];
508
+ let mean = returns.iter().sum::<f64>() / returns.len() as f64;
509
+ let variance =
510
+ returns.iter().map(|r| (r - mean).powi(2)).sum::<f64>() / (returns.len() - 1) as f64;
511
+ let annualized_vol = variance.sqrt() * dpy.sqrt();
512
+
513
+ // Sharpe 下降量应恰为 rf / annualized_volatility。
514
+ let expected_drop = rf / annualized_vol;
515
+ assert!(
516
+ (base.metrics.sharpe_ratio - with_rf.metrics.sharpe_ratio - expected_drop).abs() < 1e-9
517
+ );
518
+ }
@@ -63,6 +63,10 @@ pub struct Engine {
63
63
  pub risk_manager: RiskManager,
64
64
  pub(crate) timezone_offset: i32,
65
65
  pub(crate) timezone_name: Option<String>,
66
+ /// 年化天数因子。传统市场 252,数字货币 24/7 用 365。
67
+ pub(crate) days_per_year: f64,
68
+ /// 年化无风险利率,默认 0.0。
69
+ pub(crate) risk_free_rate: f64,
66
70
  pub(crate) history_buffer: Arc<RwLock<HistoryBuffer>>,
67
71
  pub(crate) initial_cash: Decimal,
68
72
  #[pyo3(get, set)]
@@ -519,6 +519,8 @@ impl Engine {
519
519
  risk_manager: RiskManager::new(),
520
520
  timezone_offset: 28800, // Default UTC+8
521
521
  timezone_name: Some("Asia/Shanghai".to_string()),
522
+ days_per_year: 252.0,
523
+ risk_free_rate: 0.0,
522
524
  history_buffer: Arc::new(RwLock::new(HistoryBuffer::new(10000))), // Default large capacity for MAE/MFE
523
525
  initial_cash,
524
526
  active_start_time_ns: None,
@@ -742,6 +744,20 @@ impl Engine {
742
744
  Ok(())
743
745
  }
744
746
 
747
+ /// 设置年化天数因子.
748
+ ///
749
+ /// :param days: 年化使用的天数。A 股等传统市场用 252,数字货币 24/7 市场用 365。
750
+ pub fn set_days_per_year(&mut self, days: f64) {
751
+ self.days_per_year = days;
752
+ }
753
+
754
+ /// 设置年化无风险利率.
755
+ ///
756
+ /// :param rate: 年化无风险利率 (例如 0.02 表示 2%)。默认 0.0。
757
+ pub fn set_risk_free_rate(&mut self, rate: f64) {
758
+ self.risk_free_rate = rate;
759
+ }
760
+
745
761
  /// 启用模拟执行 (回测模式)
746
762
  ///
747
763
  /// 默认模式。在内存中撮合订单。
@@ -1235,6 +1251,8 @@ impl Engine {
1235
1251
  self.terminal_result_timestamp(),
1236
1252
  self.timezone_name.clone(),
1237
1253
  self.timezone_offset,
1254
+ self.days_per_year,
1255
+ self.risk_free_rate,
1238
1256
  )
1239
1257
  }
1240
1258
  }
@@ -165,6 +165,8 @@ impl StatisticsManager {
165
165
  now_ns: Option<i64>,
166
166
  timezone_name: Option<String>,
167
167
  timezone_offset: i32,
168
+ days_per_year: f64,
169
+ risk_free_rate: f64,
168
170
  ) -> BacktestResult {
169
171
  // Calculate final PnL
170
172
  let trade_pnl = order_manager
@@ -217,6 +219,8 @@ impl StatisticsManager {
217
219
  orders: order_manager.get_all_orders(),
218
220
  executions: order_manager.trades.clone(),
219
221
  liquidation_audits: self.liquidation_audits.clone(),
222
+ days_per_year,
223
+ risk_free_rate,
220
224
  })
221
225
  }
222
226
 
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "total_return_pct": 22.44825,
3
- "sharpe_ratio": 49116247.924969286,
3
+ "sharpe_ratio": 6.79796016372159,
4
4
  "max_drawdown_pct": 7.55175,
5
5
  "total_commission": 103.5,
6
6
  "net_pnl": -103.5,
7
7
  "end_market_value": 244896.5,
8
- "engine_rule_version": "1.0.0",
9
- "akquant_version": "0.2.45"
8
+ "engine_rule_version": "1.1.0",
9
+ "akquant_version": "0.2.47"
10
10
  }
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "total_return_pct": -40.0,
3
- "sharpe_ratio": -0.3149703941743559,
3
+ "sharpe_ratio": -7.93725393319377,
4
4
  "max_drawdown_pct": 40.0,
5
5
  "total_commission": 0.0,
6
6
  "net_pnl": 0.0,
7
7
  "end_market_value": 6000.0,
8
- "engine_rule_version": "1.0.0",
9
- "akquant_version": "0.1.52"
8
+ "engine_rule_version": "1.1.0",
9
+ "akquant_version": "0.2.47"
10
10
  }
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "total_return_pct": -0.05811444,
3
- "sharpe_ratio": -4.8254367091354355,
3
+ "sharpe_ratio": -3.416410456188606,
4
4
  "max_drawdown_pct": 0.11702244,
5
5
  "total_commission": 16.11444,
6
6
  "net_pnl": -88.11444,
7
7
  "end_market_value": 99941.88556,
8
- "engine_rule_version": "1.0.0",
9
- "akquant_version": "0.2.45"
8
+ "engine_rule_version": "1.1.0",
9
+ "akquant_version": "0.2.47"
10
10
  }
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "total_return_pct": 22.44825,
3
- "sharpe_ratio": 49116247.924969286,
3
+ "sharpe_ratio": 6.79796016372159,
4
4
  "max_drawdown_pct": 7.55175,
5
5
  "total_commission": 103.5,
6
6
  "net_pnl": -103.5,
7
7
  "end_market_value": 244896.5,
8
- "engine_rule_version": "1.0.0",
9
- "akquant_version": "0.1.52"
8
+ "engine_rule_version": "1.1.0",
9
+ "akquant_version": "0.2.47"
10
10
  }
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "total_return_pct": -40.0,
3
- "sharpe_ratio": -0.3149703941743559,
3
+ "sharpe_ratio": -7.93725393319377,
4
4
  "max_drawdown_pct": 40.0,
5
5
  "total_commission": 0.0,
6
6
  "net_pnl": 0.0,
7
7
  "end_market_value": 6000.0,
8
- "engine_rule_version": "1.0.0",
9
- "akquant_version": "0.2.45"
8
+ "engine_rule_version": "1.1.0",
9
+ "akquant_version": "0.2.47"
10
10
  }
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "total_return_pct": -0.05811444,
3
- "sharpe_ratio": -4.8254367091354355,
3
+ "sharpe_ratio": -3.416410456188606,
4
4
  "max_drawdown_pct": 0.11702244,
5
5
  "total_commission": 16.11444,
6
6
  "net_pnl": -88.11444,
7
7
  "end_market_value": 99941.88556,
8
- "engine_rule_version": "1.0.0",
9
- "akquant_version": "0.1.52"
8
+ "engine_rule_version": "1.1.0",
9
+ "akquant_version": "0.2.47"
10
10
  }
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