akquant 0.2.44__tar.gz → 0.2.45__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.
- {akquant-0.2.44 → akquant-0.2.45}/Cargo.lock +1 -1
- {akquant-0.2.44 → akquant-0.2.45}/Cargo.toml +1 -1
- {akquant-0.2.44 → akquant-0.2.45}/PKG-INFO +1 -1
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/guide/analysis.md +1 -1
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/reference/api.md +2 -1
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/start/quickstart.md +1 -1
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/guide/analysis.md +1 -1
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/reference/api.md +2 -1
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/start/quickstart.md +1 -1
- {akquant-0.2.44 → akquant-0.2.45}/pyproject.toml +1 -1
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/akquant.pyi +2 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/backtest/result.py +91 -2
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/plot/report.py +8 -7
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_engine.py +51 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_report_plot_extensions.py +47 -0
- {akquant-0.2.44 → akquant-0.2.45}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/.github/workflows/deploy-docs.yml +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/.github/workflows/docs-quality.yml +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/.github/workflows/release.yml +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/.gitignore +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/.pre-commit-config.yaml +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/CHANGELOG.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/CODE_OF_CONDUCT.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/CONTRIBUTING.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/LICENSE +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/README.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/assets/dashboard_preview.png +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/assets/logo.svg +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/assets/social_preview.png +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/CNAME +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/assets/akquant-icon.svg +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/assets/akquant-logo.svg +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/assets/reports/akquant_report.html +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/advanced/analyzer_plugin_spec.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/advanced/broker_capability_matrix.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/advanced/custom_broker_production_checklist.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/advanced/custom_broker_registry.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/advanced/data_feed_adapter_spec.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/advanced/live_functional_quickstart.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/advanced/llm.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/advanced/ml.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/advanced/multi_strategy_guide.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/advanced/multi_timeframe_feed_api.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/advanced/runtime_config.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/advanced/strategy_style_decision.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/advanced/timezone.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/advanced/warm_start.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/guide/cross_section_checklist.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/guide/custom_indicator.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/guide/data.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/guide/examples.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/guide/factor.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/guide/indicator_scenario_quickref.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/guide/optimization.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/guide/python_basics.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/guide/quant_basics.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/guide/rust_indicator_reference.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/guide/strategy.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/guide/talib_indicator_playbook.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/guide/testing.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/guide/visualization.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/index.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/meta/architecture.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/meta/internals.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/start/first_strategy.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/start/installation.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/start/setup_guide.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/textbook/01_foundations.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/textbook/02_programming.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/textbook/03_data.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/textbook/04_backtest_engine.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/textbook/05_strategy.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/textbook/06_stock_a.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/textbook/07_futures.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/textbook/08_options.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/textbook/09_funds.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/textbook/10_analysis.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/textbook/11_optimization.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/textbook/12_ml.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/textbook/13_visualization.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/textbook/14_factor.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/textbook/15_live_trading.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/textbook/16_rust_indicators.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/en/textbook/index.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/javascripts/mathjax.js +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/javascripts/search-lang-filter.js +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/robots.txt +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/advanced/analyzer_plugin_spec.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/advanced/broker_capability_matrix.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/advanced/custom_broker_production_checklist.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/advanced/custom_broker_registry.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/advanced/data_feed_adapter_spec.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/advanced/live_functional_quickstart.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/advanced/llm.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/advanced/ml.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/advanced/multi_strategy_guide.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/advanced/multi_timeframe_feed_api.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/advanced/runtime_config.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/advanced/strategy_style_decision.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/advanced/timezone.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/advanced/warm_start.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/guide/cross_section_checklist.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/guide/custom_indicator.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/guide/data.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/guide/examples.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/guide/factor.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/guide/indicator_scenario_quickref.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/guide/optimization.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/guide/python_basics.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/guide/quant_basics.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/guide/rust_indicator_reference.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/guide/strategy.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/guide/talib_indicator_playbook.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/guide/testing.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/guide/visualization.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/index.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/meta/architecture.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/meta/internals.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/start/first_strategy.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/start/installation.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/start/setup_guide.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/textbook/01_foundations.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/textbook/02_programming.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/textbook/03_data.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/textbook/04_backtest_engine.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/textbook/05_strategy.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/textbook/06_stock_a.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/textbook/07_futures.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/textbook/08_options.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/textbook/09_funds.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/textbook/10_analysis.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/textbook/11_optimization.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/textbook/12_ml.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/textbook/13_visualization.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/textbook/14_factor.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/textbook/15_live_trading.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/textbook/16_rust_indicators.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/docs/zh/textbook/index.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/01_quickstart.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/02_parameter_optimization.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/03_parameter_optimization_advanced.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/04_mixed_assets.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/05_live_trading_ctp.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/06_complex_orders.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/07_option_test.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/08_event_callbacks.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/09_ml_framework.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/10_ml_walk_forward.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/11_plot_visualization.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/12_wfo_integrated.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/13_quantstats_report.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/14_multi_frequency.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/15_plot_intraday.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/16_adj_returns_signal.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/17_readme_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/18_benchmark_multisymbol.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/19_factor_expression.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/20_risk_management_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/21_warm_start_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/22_strategy_runtime_config_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/23_functional_callbacks_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/24_functional_tick_simulation_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/25_streaming_backtest_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/26_streaming_quickstart.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/27_streaming_monitoring_console.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/28_streaming_alerts_and_persist.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/29_streaming_event_report.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/30_streaming_report_oneclick.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/31_streaming_live_console.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/32_streaming_live_web.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/33_report_and_analysis_outputs.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/34_multi_strategy_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/35_custom_broker_registry_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/36_trailing_orders.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/37_feed_replay_alignment_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/38_live_functional_strategy_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/39_live_broker_submit_order_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/40_functional_multi_slot_risk_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/41_live_multi_slot_orchestration_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/42_live_broker_event_audit_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/43_target_weights_rebalance.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/44_strategy_source_loader_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/45_talib_indicator_playbook_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/46_broker_profile_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/47_margin_liquidation_audit_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/48_margin_liquidation_priority_compare.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/49_on_expiry_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/50_framework_hooks_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/51_class_tick_callbacks_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/52_pre_open_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/53_timer_to_pre_open_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/54_functional_pre_open_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/55_functional_ml_walk_forward.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/56_functional_warm_start_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/57_functional_multi_slot_warm_start_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/58_incremental_bootstrap_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/59_akshare_etf_rotation.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/60_custom_indicator_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/61_indicator_visualization_export_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/62_indicator_streaming_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/63_indicator_ws_bridge_demo.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/64_indicator_live_web.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/README.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/benchmark_utils.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/pb_mock.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/strategies/01_stock_dual_moving_average.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/strategies/02_stock_grid_trading.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/strategies/03_stock_atr_breakout.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/strategies/04_stock_momentum_rotation.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/strategies/05_stock_momentum_rotation_timer.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/strategies/06_stock_momentum_rotation_bucket.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/strategies/07_stock_momentum_rotation_on_timer.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/strategies/08_target_positions_long_short.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/strategies/09_stock_momentum_rotation_after_bar.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/strategies/README.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/textbook/ch01_quickstart.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/textbook/ch02_programming.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/textbook/ch03_data.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/textbook/ch04_comparison.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/textbook/ch05_strategy.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/textbook/ch06_stock_a.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/textbook/ch07_futures.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/textbook/ch08_options.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/textbook/ch09_funds.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/textbook/ch09_portfolio.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/textbook/ch10_analysis.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/textbook/ch11_optimization.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/textbook/ch12_ml.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/textbook/ch13_visualization.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/textbook/ch14_factor.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/textbook/ch15_live_trading.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/examples/textbook/ch15_strategy_loader.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/mkdocs.yml +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/__init__.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/analysis/__init__.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/analysis/benchmark.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/analyzer_plugin.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/backtest/__init__.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/backtest/__init__.pyi +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/backtest/engine.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/checkpoint.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/config.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/data.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/factor/__init__.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/factor/engine.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/factor/ops.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/factor/parser.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/feed_adapter.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/fund/__init__.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/futures/__init__.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/__init__.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/base.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/broker_event_bridge.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/broker_event_mapper.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/broker_models.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/broker_recovery.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/broker_runtime.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/brokers/__init__.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/brokers/ctp/__init__.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/brokers/ctp/adapter.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/brokers/ctp/native.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/brokers/miniqmt/__init__.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/brokers/miniqmt/stub.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/brokers/ptrade/__init__.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/brokers/ptrade/stub.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/ctp_adapter.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/ctp_native.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/factory.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/mapper.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/miniqmt.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/models.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/order_submitter.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/protocols.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/ptrade.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/gateway/registry.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/indicator.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/indicator_recording.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/indicator_stream.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/live.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/log.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/ml/__init__.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/ml/model.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/optimize.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/option/__init__.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/params.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/params_adapter.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/plot/__init__.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/plot/analysis.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/plot/dashboard.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/plot/indicator.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/plot/strategy.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/plot/utils.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/py.typed +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/risk.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/sizer.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/stock/__init__.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/strategy.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/strategy_events.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/strategy_framework_hooks.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/strategy_history.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/strategy_loader.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/strategy_logging.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/strategy_ml.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/strategy_order_events.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/strategy_position.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/strategy_scheduler.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/strategy_time.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/strategy_trading_api.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/talib/__init__.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/talib/backend.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/talib/core.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/talib/funcs.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/utils/__init__.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/python/akquant/utils/inspector.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/requirements-dev.txt +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/scripts/cargo-test.sh +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/scripts/check_docs_api_examples.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/scripts/check_docs_links.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/scripts/dev-check.sh +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/scripts/find_legacy_execution_policy_calls.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/scripts/golden_baseline_report.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/account.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/analysis/mod.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/analysis/python.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/analysis/result.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/analysis/tests.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/analysis/tracker.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/analysis/types.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/bin/stub_gen.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/clock.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/context.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/data/aggregator.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/data/batch.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/data/client.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/data/feed.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/data/mod.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/engine/core.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/engine/mod.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/engine/python.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/engine/state.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/error.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/event.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/event_manager.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/execution/common.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/execution/crypto.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/execution/forex.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/execution/futures.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/execution/matcher.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/execution/mod.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/execution/option.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/execution/python.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/execution/realtime.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/execution/simulated.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/execution/slippage.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/execution/stock.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/history.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/indicators/momentum.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/indicators/momentum_oscillators.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/indicators/momentum_rates.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/indicators/moving_average.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/indicators/moving_average_compound.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/indicators/moving_average_core.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/indicators/moving_average_transforms.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/indicators/moving_average_windowed.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/indicators/trend.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/indicators/trend_directional.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/indicators/trend_oscillators.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/indicators/trend_regression.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/indicators/volatility.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/indicators/volatility_price.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/indicators/volatility_stats.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/indicators/volume.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/indicators.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/lib.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/log_context.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/margin/calculator.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/margin/engine.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/margin/mod.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/market/china.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/market/core.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/market/corporate_action.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/market/fund.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/market/futures.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/market/manager.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/market/mod.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/market/option.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/market/simple.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/market/stock.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/model/corporate_action.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/model/instrument.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/model/market_data.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/model/mod.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/model/order.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/model/timer.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/model/types.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/order_manager.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/pipeline/mod.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/pipeline/processor.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/pipeline/runner.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/pipeline/stages.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/portfolio.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/risk/common.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/risk/config.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/risk/futures.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/risk/manager.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/risk/mod.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/risk/option.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/risk/portfolio.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/risk/rule.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/risk/stock.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/settlement/expiry.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/settlement/handler.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/settlement/manager.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/settlement/mod.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/settlement/option.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/src/statistics/mod.rs +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/gateway_contract/test_event_bridge_contract.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/gateway_contract/test_recovery_contract.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/gateway_contract/test_submitter_contract.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/BASELINE_REPORT.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/LEGACY_EXECUTION_CALLS.md +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/baselines/futures_margin/equity_curve.parquet +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/baselines/futures_margin/metrics.json +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/baselines/futures_margin/orders.parquet +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/baselines/option_basic/equity_curve.parquet +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/baselines/option_basic/metrics.json +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/baselines/option_basic/orders.parquet +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/baselines/stock_t1/equity_curve.parquet +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/baselines/stock_t1/metrics.json +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/baselines/stock_t1/orders.parquet +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/baselines/stock_t1/trades.parquet +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/current/futures_margin/equity_curve.parquet +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/current/futures_margin/metrics.json +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/current/futures_margin/orders.parquet +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/current/option_basic/equity_curve.parquet +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/current/option_basic/metrics.json +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/current/option_basic/orders.parquet +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/current/stock_t1/equity_curve.parquet +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/current/stock_t1/metrics.json +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/current/stock_t1/orders.parquet +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/current/stock_t1/trades.parquet +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/data/future_margin.parquet +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/data/future_margin.parquet.sha256 +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/data/option_basic.parquet +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/data/option_basic.parquet.sha256 +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/data/stock_t1.parquet +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/data/stock_t1.parquet.sha256 +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/gen_data.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/runner.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/strategies/futures_margin.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/strategies/option_basic.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/strategies/stock_t1.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/golden/test_golden.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_account_risk_rules.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_custom_matcher.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_data_catalog.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_docs_api_examples.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_docs_links.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_examples_regression.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_factor_engine.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_factor_ops.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_feed_adapter.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_gateway_brokers_paths.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_gateway_callbacks.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_gateway_ctp_adapter.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_gateway_ctp_native.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_gateway_factory.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_gateway_mapper.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_gateway_registry.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_indicator_live_web_example.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_indicator_recording.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_inspector.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_live_runner.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_live_runner_broker_bridge.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_live_runner_broker_recovery.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_live_runner_broker_submitter.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_multisymbol_cross_section_consistency.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_orders_df.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_params_adapter.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_partial_filled_status.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_portfolio.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_quickstart_stream_consistency.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_report_helpers.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_result_analysis_extensions.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_stop_orders.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_strategy_extras.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_strategy_timers_indicators.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_t_plus_one.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_talib_backend.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_talib_compat.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_trades_df.py +0 -0
- {akquant-0.2.44 → akquant-0.2.45}/tests/test_version.py +0 -0
|
@@ -17,7 +17,7 @@ result.report(
|
|
|
17
17
|
filename="report.html",
|
|
18
18
|
show=True, # Set to True to open in browser automatically (default is False)
|
|
19
19
|
compact_currency=True, # Format amount columns as K/M/B in report tables
|
|
20
|
-
curve_freq="
|
|
20
|
+
curve_freq="D", # Default uses end-of-day points; "raw" keeps all bars
|
|
21
21
|
)
|
|
22
22
|
```
|
|
23
23
|
|
|
@@ -1113,10 +1113,11 @@ Backtest result object.
|
|
|
1113
1113
|
* `capacity_df(freq="D")`: Capacity proxy metrics (order count, fill rates, turnover).
|
|
1114
1114
|
* `benchmark_analysis(benchmark=None, curve_freq="raw")`: Return a structured benchmark analysis payload for frontends and APIs.
|
|
1115
1115
|
* `export_benchmark_analysis(path, benchmark=None, format="json", curve_freq="raw")`: Persist benchmark analysis as JSON or parquet artifacts.
|
|
1116
|
+
* `top_reject_reason_types(top_n=10)`: Aggregate reject counts by normalized reject type and include a sample detail row.
|
|
1116
1117
|
* `orders_by_strategy()`: Strategy-ownership order aggregation by `owner_strategy_id`.
|
|
1117
1118
|
* `executions_by_strategy()`: Strategy-ownership execution aggregation by `owner_strategy_id`.
|
|
1118
1119
|
* `get_event_stats()`: Unified stream summary stats (for example `processed_events`, `dropped_event_count`, `callback_error_count`, `backpressure_policy`, `stream_mode`).
|
|
1119
|
-
* `report(..., curve_freq="
|
|
1120
|
+
* `report(..., curve_freq="D" | "raw")`: Generate HTML report with daily end-of-day curves by default, or switch back to raw frequency.
|
|
1120
1121
|
|
|
1121
1122
|
```python
|
|
1122
1123
|
orders_by_strategy = result.orders_by_strategy()
|
|
@@ -177,7 +177,7 @@ result.report(
|
|
|
177
177
|
filename="report.html",
|
|
178
178
|
show=True, # 设为 True 以自动在浏览器中打开 (默认为 False)
|
|
179
179
|
compact_currency=True, # 金额列使用 K/M/B 紧凑显示 (默认为 True)
|
|
180
|
-
curve_freq="
|
|
180
|
+
curve_freq="D", # 默认即为 "D","raw" 可保留原始频率
|
|
181
181
|
)
|
|
182
182
|
```
|
|
183
183
|
|
|
@@ -1187,10 +1187,11 @@ class RiskConfig:
|
|
|
1187
1187
|
* `capacity_df(freq="D")`: 容量代理指标(订单数、成交率、换手)。
|
|
1188
1188
|
* `benchmark_analysis(benchmark=None, curve_freq="raw")`: 返回结构化 benchmark analysis,可直接供前端/API 使用。
|
|
1189
1189
|
* `export_benchmark_analysis(path, benchmark=None, format="json", curve_freq="raw")`: 将 benchmark analysis 导出为 JSON 或 parquet 产物。
|
|
1190
|
+
* `top_reject_reason_types(top_n=10)`: 按拒单类型聚合拒单统计,并附带一条示例明细。
|
|
1190
1191
|
* `orders_by_strategy()`: 按 `owner_strategy_id` 聚合订单统计。
|
|
1191
1192
|
* `executions_by_strategy()`: 按 `owner_strategy_id` 聚合成交流水统计。
|
|
1192
1193
|
* `get_event_stats()`: 返回流式事件统计摘要(如 `processed_events`、`dropped_event_count`、`callback_error_count`、`backpressure_policy`、`stream_mode`)。
|
|
1193
|
-
* `report(..., curve_freq="
|
|
1194
|
+
* `report(..., curve_freq="D" | "raw")`: 生成 HTML 报告时,默认使用日频末值曲线,也可切回原始频率。
|
|
1194
1195
|
|
|
1195
1196
|
```python
|
|
1196
1197
|
orders_by_strategy = result.orders_by_strategy()
|
|
@@ -326,6 +326,8 @@ class BacktestResult:
|
|
|
326
326
|
theme: str = ...,
|
|
327
327
|
filename: typing.Optional[str] = ...,
|
|
328
328
|
) -> typing.Any: ...
|
|
329
|
+
def top_reject_reasons(self, top_n: int = ...) -> typing.Any: ...
|
|
330
|
+
def top_reject_reason_types(self, top_n: int = ...) -> typing.Any: ...
|
|
329
331
|
def report(
|
|
330
332
|
self,
|
|
331
333
|
title: str = ...,
|
|
@@ -1167,6 +1167,37 @@ class BacktestResult:
|
|
|
1167
1167
|
"other_risk_reject_count": (~known_mask).astype(int),
|
|
1168
1168
|
}
|
|
1169
1169
|
|
|
1170
|
+
@staticmethod
|
|
1171
|
+
def _classify_reject_reason(reason: Any) -> str:
|
|
1172
|
+
"""Map raw reject messages to stable report-friendly categories."""
|
|
1173
|
+
reason_text = str(reason).strip()
|
|
1174
|
+
if not reason_text:
|
|
1175
|
+
return "Empty Reject Reason"
|
|
1176
|
+
reason_lower = reason_text.lower()
|
|
1177
|
+
if "insufficient margin" in reason_lower:
|
|
1178
|
+
return "Insufficient Margin"
|
|
1179
|
+
if "daily loss" in reason_lower or "stop-loss threshold" in reason_lower:
|
|
1180
|
+
return "Daily Loss Limit"
|
|
1181
|
+
if "drawdown" in reason_lower:
|
|
1182
|
+
return "Drawdown Limit"
|
|
1183
|
+
if "reduce_only mode" in reason_lower or "cooldown" in reason_lower:
|
|
1184
|
+
return "Reduce-Only / Cooldown"
|
|
1185
|
+
if (
|
|
1186
|
+
"projected position" in reason_lower
|
|
1187
|
+
or "available position" in reason_lower
|
|
1188
|
+
or "is restricted" in reason_lower
|
|
1189
|
+
):
|
|
1190
|
+
return "Position Limit"
|
|
1191
|
+
if "order quantity" in reason_lower or "lot size" in reason_lower:
|
|
1192
|
+
return "Order Size Limit"
|
|
1193
|
+
if "order value" in reason_lower:
|
|
1194
|
+
return "Order Value Limit"
|
|
1195
|
+
if "portfolio risk budget" in reason_lower:
|
|
1196
|
+
return "Portfolio Risk Budget"
|
|
1197
|
+
if "risk budget" in reason_lower and "strategy" in reason_lower:
|
|
1198
|
+
return "Strategy Risk Budget"
|
|
1199
|
+
return "Other"
|
|
1200
|
+
|
|
1170
1201
|
def top_reject_reasons(self, top_n: int = 10) -> pd.DataFrame:
|
|
1171
1202
|
"""Get Top-N rejection reasons from orders."""
|
|
1172
1203
|
columns = ["reject_reason", "count", "ratio"]
|
|
@@ -1212,6 +1243,64 @@ class BacktestResult:
|
|
|
1212
1243
|
frame["ratio"] = frame["count"] / float(total)
|
|
1213
1244
|
return cast(pd.DataFrame, frame.reset_index(drop=True))
|
|
1214
1245
|
|
|
1246
|
+
def top_reject_reason_types(self, top_n: int = 10) -> pd.DataFrame:
|
|
1247
|
+
"""Get Top-N rejection categories with a sample raw message."""
|
|
1248
|
+
columns = ["reject_reason_type", "sample_reject_reason", "count", "ratio"]
|
|
1249
|
+
if top_n <= 0:
|
|
1250
|
+
return pd.DataFrame(columns=columns)
|
|
1251
|
+
|
|
1252
|
+
orders = self.orders_df.copy()
|
|
1253
|
+
if orders.empty:
|
|
1254
|
+
return pd.DataFrame(columns=columns)
|
|
1255
|
+
|
|
1256
|
+
if "reject_reason" not in orders.columns:
|
|
1257
|
+
orders["reject_reason"] = ""
|
|
1258
|
+
if "status" not in orders.columns:
|
|
1259
|
+
orders["status"] = ""
|
|
1260
|
+
reject_reason = orders["reject_reason"].fillna("").astype(str)
|
|
1261
|
+
status = orders["status"].fillna("").astype(str)
|
|
1262
|
+
rejected_mask = (reject_reason.str.len() > 0) | status.str.contains(
|
|
1263
|
+
"Rejected", case=False, regex=False
|
|
1264
|
+
)
|
|
1265
|
+
rejected = orders.loc[rejected_mask].copy()
|
|
1266
|
+
if rejected.empty:
|
|
1267
|
+
return pd.DataFrame(columns=columns)
|
|
1268
|
+
|
|
1269
|
+
cleaned_reason = (
|
|
1270
|
+
rejected["reject_reason"]
|
|
1271
|
+
.fillna("")
|
|
1272
|
+
.astype(str)
|
|
1273
|
+
.str.strip()
|
|
1274
|
+
.replace("", "(empty reject reason)")
|
|
1275
|
+
)
|
|
1276
|
+
classified = cleaned_reason.map(self._classify_reject_reason)
|
|
1277
|
+
total = int(len(classified))
|
|
1278
|
+
if total <= 0:
|
|
1279
|
+
return pd.DataFrame(columns=columns)
|
|
1280
|
+
|
|
1281
|
+
frame = pd.DataFrame(
|
|
1282
|
+
{
|
|
1283
|
+
"reject_reason_type": classified.astype(str),
|
|
1284
|
+
"sample_reject_reason": cleaned_reason.astype(str),
|
|
1285
|
+
}
|
|
1286
|
+
)
|
|
1287
|
+
grouped = (
|
|
1288
|
+
frame.groupby("reject_reason_type", sort=False)
|
|
1289
|
+
.agg(
|
|
1290
|
+
count=("reject_reason_type", "size"),
|
|
1291
|
+
sample_reject_reason=(
|
|
1292
|
+
"sample_reject_reason",
|
|
1293
|
+
lambda series: cast(str, series.value_counts().index[0]),
|
|
1294
|
+
),
|
|
1295
|
+
)
|
|
1296
|
+
.reset_index()
|
|
1297
|
+
)
|
|
1298
|
+
grouped = grouped.sort_values(
|
|
1299
|
+
["count", "reject_reason_type"], ascending=[False, True]
|
|
1300
|
+
).head(top_n)
|
|
1301
|
+
grouped["ratio"] = grouped["count"] / float(total)
|
|
1302
|
+
return cast(pd.DataFrame, grouped[columns].reset_index(drop=True))
|
|
1303
|
+
|
|
1215
1304
|
def risk_rejections_by_strategy(self) -> pd.DataFrame:
|
|
1216
1305
|
"""Get strategy-level risk rejection breakdown table."""
|
|
1217
1306
|
orders = self.orders_df.copy()
|
|
@@ -1765,7 +1854,7 @@ class BacktestResult:
|
|
|
1765
1854
|
indicator_symbol: Optional[str] = None,
|
|
1766
1855
|
indicator_include_warmup: bool = True,
|
|
1767
1856
|
benchmark: Optional[Union[str, pd.Series]] = None,
|
|
1768
|
-
curve_freq: str = "
|
|
1857
|
+
curve_freq: str = "D",
|
|
1769
1858
|
) -> None:
|
|
1770
1859
|
"""
|
|
1771
1860
|
生成 HTML 策略回测报告 (便捷方法).
|
|
@@ -1784,7 +1873,7 @@ class BacktestResult:
|
|
|
1784
1873
|
:param indicator_symbol: 可选标的过滤,仅展示指定标的指标
|
|
1785
1874
|
:param indicator_include_warmup: 是否在指标报告区块中保留预热点
|
|
1786
1875
|
:param benchmark: 基准收益序列 (pd.Series) 或基准标识字符串
|
|
1787
|
-
:param curve_freq:
|
|
1876
|
+
:param curve_freq: 曲线频率,默认 "D" 为日频末值,"raw" 为原始频率
|
|
1788
1877
|
"""
|
|
1789
1878
|
# 延迟导入,避免循环引用和非必要的 Plotly 依赖
|
|
1790
1879
|
try:
|
|
@@ -695,7 +695,7 @@ def _build_benchmark_sections(
|
|
|
695
695
|
}
|
|
696
696
|
|
|
697
697
|
|
|
698
|
-
def _build_summary_context(result: Any, curve_freq: str = "
|
|
698
|
+
def _build_summary_context(result: Any, curve_freq: str = "D") -> dict[str, str]:
|
|
699
699
|
"""Build summary text values for report header."""
|
|
700
700
|
equity_curve = _resolve_equity_curve(result, curve_freq)
|
|
701
701
|
start_date = "N/A"
|
|
@@ -979,7 +979,7 @@ def _build_chart_html_sections(
|
|
|
979
979
|
indicator_symbol: Optional[str] = None,
|
|
980
980
|
indicator_include_warmup: bool = True,
|
|
981
981
|
benchmark: Optional[Union[str, pd.Series]] = None,
|
|
982
|
-
curve_freq: str = "
|
|
982
|
+
curve_freq: str = "D",
|
|
983
983
|
) -> dict[str, str]:
|
|
984
984
|
"""Build chart HTML sections from plot figures."""
|
|
985
985
|
config = {"responsive": True}
|
|
@@ -1179,15 +1179,16 @@ def _build_chart_html_sections(
|
|
|
1179
1179
|
else pd.DataFrame()
|
|
1180
1180
|
)
|
|
1181
1181
|
top_reasons_df = (
|
|
1182
|
-
result.
|
|
1183
|
-
if hasattr(result, "
|
|
1182
|
+
result.top_reject_reason_types(top_n=8)
|
|
1183
|
+
if hasattr(result, "top_reject_reason_types")
|
|
1184
1184
|
else pd.DataFrame()
|
|
1185
1185
|
)
|
|
1186
1186
|
if not top_reasons_df.empty:
|
|
1187
1187
|
top_reasons_view = _rename_table_columns(
|
|
1188
1188
|
top_reasons_df,
|
|
1189
1189
|
{
|
|
1190
|
-
"
|
|
1190
|
+
"reject_reason_type": "拒单类型 (Reject Type)",
|
|
1191
|
+
"sample_reject_reason": "示例详情 (Sample Detail)",
|
|
1191
1192
|
"count": "拒单数 (Count)",
|
|
1192
1193
|
"ratio": "占比 (Ratio)",
|
|
1193
1194
|
},
|
|
@@ -1948,7 +1949,7 @@ def plot_report(
|
|
|
1948
1949
|
indicator_symbol: Optional[str] = None,
|
|
1949
1950
|
indicator_include_warmup: bool = True,
|
|
1950
1951
|
benchmark: Optional[Union[str, pd.Series]] = None,
|
|
1951
|
-
curve_freq: str = "
|
|
1952
|
+
curve_freq: str = "D",
|
|
1952
1953
|
) -> None:
|
|
1953
1954
|
"""
|
|
1954
1955
|
生成类似 QuantStats 的整合版 HTML 报告 (中文优化版).
|
|
@@ -1964,7 +1965,7 @@ def plot_report(
|
|
|
1964
1965
|
:param indicator_symbol: 可选标的过滤,仅展示指定标的指标
|
|
1965
1966
|
:param indicator_include_warmup: 是否在指标报告区块中保留预热点
|
|
1966
1967
|
:param benchmark: 基准收益序列 (pd.Series) 或基准标识字符串
|
|
1967
|
-
:param curve_freq:
|
|
1968
|
+
:param curve_freq: 曲线频率,默认 "D" 为日频末值,"raw" 为原始频率
|
|
1968
1969
|
"""
|
|
1969
1970
|
if not check_plotly():
|
|
1970
1971
|
return
|
|
@@ -915,6 +915,57 @@ def test_backtest_result_top_reject_reasons_and_lot_size_category() -> None:
|
|
|
915
915
|
assert int(risk_df["order_size_limit_reject_count"].sum()) >= 1
|
|
916
916
|
|
|
917
917
|
|
|
918
|
+
def test_backtest_result_top_reject_reason_types_normalizes_dynamic_details() -> None:
|
|
919
|
+
"""Reject type view should merge dynamic messages into stable categories."""
|
|
920
|
+
result = akquant.run_backtest(
|
|
921
|
+
data=_build_regression_bars("REJECT_REASON_TYPE"),
|
|
922
|
+
strategy=SingleBuyStrategy,
|
|
923
|
+
symbols="REJECT_REASON_TYPE",
|
|
924
|
+
fill_policy={"price_basis": "close", "temporal": "same_cycle"},
|
|
925
|
+
lot_size=1,
|
|
926
|
+
show_progress=False,
|
|
927
|
+
)
|
|
928
|
+
result.orders_df = pd.DataFrame(
|
|
929
|
+
{
|
|
930
|
+
"reject_reason": [
|
|
931
|
+
(
|
|
932
|
+
"Risk: Insufficient margin at execution. "
|
|
933
|
+
"Required: 35, Available: -330445.517600"
|
|
934
|
+
),
|
|
935
|
+
(
|
|
936
|
+
"Risk: Insufficient margin at execution. "
|
|
937
|
+
"Required: 35, Available: -310706.591600"
|
|
938
|
+
),
|
|
939
|
+
"Order error: Risk: Daily loss 5.46% exceeds limit 5.00%",
|
|
940
|
+
"Order error: Risk: Daily loss 8.79% exceeds limit 5.00%",
|
|
941
|
+
"",
|
|
942
|
+
],
|
|
943
|
+
"status": ["Rejected", "Rejected", "Rejected", "Rejected", "Rejected"],
|
|
944
|
+
}
|
|
945
|
+
)
|
|
946
|
+
|
|
947
|
+
top_reason_types = result.top_reject_reason_types(top_n=5)
|
|
948
|
+
|
|
949
|
+
assert not top_reason_types.empty
|
|
950
|
+
assert "reject_reason_type" in top_reason_types.columns
|
|
951
|
+
assert "sample_reject_reason" in top_reason_types.columns
|
|
952
|
+
assert "count" in top_reason_types.columns
|
|
953
|
+
assert "ratio" in top_reason_types.columns
|
|
954
|
+
counts = dict(
|
|
955
|
+
zip(
|
|
956
|
+
top_reason_types["reject_reason_type"].astype(str),
|
|
957
|
+
top_reason_types["count"].astype(int),
|
|
958
|
+
)
|
|
959
|
+
)
|
|
960
|
+
assert counts["Insufficient Margin"] == 2
|
|
961
|
+
assert counts["Daily Loss Limit"] == 2
|
|
962
|
+
sample_detail = top_reason_types.loc[
|
|
963
|
+
top_reason_types["reject_reason_type"].astype(str) == "Insufficient Margin",
|
|
964
|
+
"sample_reject_reason",
|
|
965
|
+
].iloc[0]
|
|
966
|
+
assert "Required: 35" in str(sample_detail)
|
|
967
|
+
|
|
968
|
+
|
|
918
969
|
def test_policy_resolver_next_close_same_cycle_sets_timer_same_cycle() -> None:
|
|
919
970
|
"""Close + bar_offset=1 + same_cycle should resolve timer policy."""
|
|
920
971
|
resolved = backtest_engine._resolve_execution_policy(
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import importlib.util
|
|
2
|
+
import inspect
|
|
2
3
|
from pathlib import Path
|
|
3
4
|
from typing import cast
|
|
4
5
|
|
|
5
6
|
import pandas as pd
|
|
6
7
|
import pytest
|
|
7
8
|
from akquant import Bar, Strategy, run_backtest
|
|
9
|
+
from akquant.backtest.result import BacktestResult
|
|
8
10
|
from akquant.config import RiskConfig
|
|
9
11
|
from akquant.plot import (
|
|
10
12
|
plot_dashboard,
|
|
@@ -716,6 +718,12 @@ def test_report_accepts_curve_freq_daily(tmp_path: Path) -> None:
|
|
|
716
718
|
assert report_path.exists()
|
|
717
719
|
|
|
718
720
|
|
|
721
|
+
def test_report_defaults_curve_freq_to_daily() -> None:
|
|
722
|
+
"""Report API should default to daily curve frequency for lighter HTML."""
|
|
723
|
+
default_value = inspect.signature(BacktestResult.report)
|
|
724
|
+
assert default_value.parameters["curve_freq"].default == "D"
|
|
725
|
+
|
|
726
|
+
|
|
719
727
|
def test_report_rejects_invalid_curve_freq(tmp_path: Path) -> None:
|
|
720
728
|
"""Report generation should reject unsupported curve frequency values."""
|
|
721
729
|
_skip_if_no_plotly()
|
|
@@ -737,6 +745,45 @@ def test_report_rejects_invalid_curve_freq(tmp_path: Path) -> None:
|
|
|
737
745
|
result.report(filename=str(report_path), show=False, curve_freq="W")
|
|
738
746
|
|
|
739
747
|
|
|
748
|
+
def test_report_displays_normalized_reject_reason_types(tmp_path: Path) -> None:
|
|
749
|
+
"""Report HTML should show reject types and sample details separately."""
|
|
750
|
+
_skip_if_no_plotly()
|
|
751
|
+
result = run_backtest(
|
|
752
|
+
data=_build_intraday_data(),
|
|
753
|
+
strategy=NoTradeStrategy,
|
|
754
|
+
symbols="TEST",
|
|
755
|
+
initial_cash=200000.0,
|
|
756
|
+
commission_rate=0.0,
|
|
757
|
+
stamp_tax_rate=0.0,
|
|
758
|
+
transfer_fee_rate=0.0,
|
|
759
|
+
min_commission=0.0,
|
|
760
|
+
fill_policy={"price_basis": "close", "temporal": "same_cycle"},
|
|
761
|
+
lot_size=1,
|
|
762
|
+
show_progress=False,
|
|
763
|
+
)
|
|
764
|
+
result.orders_df = pd.DataFrame(
|
|
765
|
+
{
|
|
766
|
+
"reject_reason": [
|
|
767
|
+
(
|
|
768
|
+
"Risk: Insufficient margin at execution. "
|
|
769
|
+
"Required: 35, Available: -330445.517600"
|
|
770
|
+
),
|
|
771
|
+
(
|
|
772
|
+
"Risk: Insufficient margin at execution. "
|
|
773
|
+
"Required: 35, Available: -310706.591600"
|
|
774
|
+
),
|
|
775
|
+
],
|
|
776
|
+
"status": ["Rejected", "Rejected"],
|
|
777
|
+
}
|
|
778
|
+
)
|
|
779
|
+
report_path = tmp_path / "report_reject_reason_types.html"
|
|
780
|
+
result.report(filename=str(report_path), show=False)
|
|
781
|
+
html = report_path.read_text(encoding="utf-8")
|
|
782
|
+
assert "拒单类型 (Reject Type)" in html
|
|
783
|
+
assert "示例详情 (Sample Detail)" in html
|
|
784
|
+
assert "Insufficient Margin" in html
|
|
785
|
+
|
|
786
|
+
|
|
740
787
|
def test_report_contains_forced_liquidation_audit_section(tmp_path: Path) -> None:
|
|
741
788
|
"""Report HTML should include forced liquidation audit section and entries."""
|
|
742
789
|
_skip_if_no_plotly()
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|