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