cfquant 0.2.48__tar.gz → 0.2.49__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.
- {cfquant-0.2.48 → cfquant-0.2.49}/PKG-INFO +1 -1
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/qmt_strategy_deploy.py +45 -27
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_lite_deployment_paths.py +29 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_qmt_strategy_deploy.py +62 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_qmt_strategy_web.py +2 -2
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/version.py +2 -2
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant.egg-info/PKG-INFO +1 -1
- {cfquant-0.2.48 → cfquant-0.2.49}/pyproject.toml +1 -1
- {cfquant-0.2.48 → cfquant-0.2.49}/qmt_scripts/CFQUANT_LITE.py +1 -1
- {cfquant-0.2.48 → cfquant-0.2.49}/qmt_scripts//345/220/214/350/264/246/345/217/267/347/213/254/347/253/213/345/270/202/345/234/272/CFQUANT_LITE_SH.py +1 -1
- {cfquant-0.2.48 → cfquant-0.2.49}/qmt_scripts//345/220/214/350/264/246/345/217/267/347/213/254/347/253/213/345/270/202/345/234/272/CFQUANT_LITE_SZ.py +1 -1
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/app.js +1 -1
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/index.html +2 -2
- {cfquant-0.2.48 → cfquant-0.2.49}/LICENSE +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/LTtx/__init__.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/LTtx/tx/Config.txt +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/LTtx/tx/LTtx_server.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/LTtx/tx/__init__.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/LTtx/tx/tx.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/MANIFEST.in +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/README.md +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/__init__.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/_editable_install.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/account_routing.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/batch_orders.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/build_info.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/callback_dispatcher.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/cftrader.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/channels.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/cli.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/client.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/config.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/hub.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/level2.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/log_management.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/logging_i18n.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/management.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/normal_bridge.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/order_identity.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/order_meta.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/pipe_bridge.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/pipe_client.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/pipe_hub.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/pipe_transport.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/protocol.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/qmt_bridge.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/qmt_strategy_package.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/qmt_strategy_runtime.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/runtime_report.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/stock_connect.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/10_/345/221/275/344/273/244/350/241/214/346/216/245/345/217/243/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/11_/346/231/256/351/200/232/346/241/245/346/216/245/346/264/276/345/217/221/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/12_/350/256/242/345/215/225/345/244/207/346/263/250/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/13_/347/256/241/351/201/223/344/270/255/345/277/203/350/277/236/346/216/245/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/14_/350/277/220/350/241/214/346/227/266/346/212/245/345/221/212/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/15_/347/275/221/351/241/265/347/212/266/346/200/201/347/274/223/345/255/230/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/16_/345/220/257/345/212/250/345/256/211/350/243/205/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/17_/345/244/247QMT/346/216/245/345/217/243/351/200/202/351/205/215/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/18_/351/253/230/347/272/247/346/250/241/345/274/217/345/256/236/346/234/272/350/201/224/350/260/203.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/19_/345/256/236/346/234/272/350/201/224/350/260/203/345/210/244/345/256/232/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/1_/350/241/214/346/203/205/346/216/245/346/224/266/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/20_/350/201/224/350/260/203/351/227/256/351/242/230/344/277/256/345/244/215/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/21_/345/215/225/350/202/241/350/241/214/346/203/205/350/256/242/351/230/205/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/22_/350/277/236/346/216/245/350/257/212/346/226/255/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/23_/347/244/272/344/276/213/351/205/215/347/275/256/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/24_/350/264/246/346/210/267/347/274/223/345/255/230/346/214/211/351/234/200/345/210/267/346/226/260/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/25_/350/264/246/346/210/267/347/274/223/345/255/230/351/241/265/351/235/242/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/26_/345/205/250/346/216/250/350/256/242/351/230/205/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/27_/345/205/250/346/216/250/350/256/242/351/230/205/351/241/265/351/235/242/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/28_Level2/346/216/245/345/217/243/351/200/202/351/205/215/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/29_Level2/350/241/214/346/203/205/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/2_/346/225/260/346/215/256/350/216/267/345/217/226/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/30_cftrader/346/211/271/351/207/217/344/270/213/345/215/225/346/200/247/350/203/275/345/237/272/345/207/206.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/31_cftrader/346/250/241/346/213/237/350/264/246/345/217/267/346/211/271/351/207/217/344/270/213/345/215/225/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/32_/345/274/202/346/255/245/344/270/213/345/215/225/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/33_/345/220/214/346/255/245/344/270/213/345/215/225/345/233/236/350/260/203/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/3_/346/225/260/346/215/256/344/270/213/350/275/275/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/4_/344/272/244/346/230/223/345/247/224/346/211/230/346/237/245/350/257/242/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/5_/347/234/237/345/256/236/344/270/213/345/215/225/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/6_/345/233/236/350/260/203/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/7_/345/220/214/346/255/245/345/274/202/346/255/245/344/270/213/345/215/225/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/8_/346/210/220/344/272/244/350/256/242/345/215/225/345/222/214/345/247/224/346/211/230/350/256/242/345/215/225/346/237/245/350/257/242/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/9_/345/217/257/346/222/244/350/256/242/345/215/225/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/_helpers.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/log/cftrader/346/250/241/346/213/237/350/264/246/345/217/267/346/211/271/351/207/217/344/270/213/345/215/225/346/265/213/350/257/225_20260911_024617.md" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/log/cftrader/346/250/241/346/213/237/350/264/246/345/217/267/346/211/271/351/207/217/344/270/213/345/215/225/346/265/213/350/257/225_20260921_175732.md" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/readme.md +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_api_tester_browser.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_api_tester_web.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_binding_delete_confirmation.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_callback_requests.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_cftrader.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_cftrader_tutorial.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_cftrader_web.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_credit_compat.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_json_serialization.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_lite_account_routing.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_local_trading_calendar.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_log_management.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_management.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_management_batch.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_market_data_fallback.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_order_identity.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_order_time_callback.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_project_updater.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_python_api_reference.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_qmt_strategy_browser.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_setup_qmt_prompt.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_startup_recovery.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_stock_connect.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_stock_connect_browser.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_trading_dates.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_tutorial_reader.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tests/test_tx_auto_import.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/trading_calendar.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tx.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/tx_trade_bridge.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/xtconstant.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/xtdata.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/xttrader.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant/xttype.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant.egg-info/SOURCES.txt +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant.egg-info/dependency_links.txt +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant.egg-info/entry_points.txt +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant.egg-info/requires.txt +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant.egg-info/top_level.txt +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant_pipe_hub.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/cfquant_web_server.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/qmt_scripts/CFQUANT.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/qmt_scripts/CFQUANT_CTYPE_ALL_LOWLAT.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/qmt_scripts/CFQUANT_TRADE_LOWLAT.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/qmt_scripts/__init__.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/qmt_scripts//345/220/214/350/264/246/345/217/267/347/213/254/347/253/213/345/270/202/345/234/272/CFQUANT_CTYPE_ALL_LOWLAT_SH.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/qmt_scripts//345/220/214/350/264/246/345/217/267/347/213/254/347/253/213/345/270/202/345/234/272/CFQUANT_CTYPE_ALL_LOWLAT_SZ.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/qmt_scripts//345/220/214/350/264/246/345/217/267/347/213/254/347/253/213/345/270/202/345/234/272/CFQUANT_TRADE_LOWLAT_SH.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/qmt_scripts//345/220/214/350/264/246/345/217/267/347/213/254/347/253/213/345/270/202/345/234/272/CFQUANT_TRADE_LOWLAT_SZ.py" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/qmt_scripts//345/220/214/350/264/246/345/217/267/347/213/254/347/253/213/345/270/202/345/234/272/readme.md" +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/requirements.txt +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/setup.cfg +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/__init__.py +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/api-tester.js +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/avatars/amber-pulse.svg +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/avatars/copper-grid.svg +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/avatars/market-blue.svg +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/avatars/rose-circuit.svg +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/avatars/signal-green.svg +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/avatars/slate-wave.svg +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/avatars/teal-orbit.svg +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/avatars/violet-node.svg +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/cftrader-api-data.js +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/docs.js +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/favicon.svg +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/image/qmt_deploy/image-10.png +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/image/qmt_deploy/image-11.png +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/image/qmt_deploy/image-12.png +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/image/qmt_deploy/image-13.png +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/image/qmt_deploy/image-14.png +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/image/qmt_deploy/image-15.png +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/image/qmt_deploy/image-16.png +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/image/qmt_deploy/image-17.png +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/image/qmt_deploy/image-18.png +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/image/qmt_deploy/image-19.png +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/image/qmt_deploy/image-20.png +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/image/qmt_deploy/image-21.png +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/image/qmt_deploy/image-4.png +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/image/qmt_deploy/image-5.png +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/image/qmt_deploy/image-6.png +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/image/qmt_deploy/image-7.png +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/image/qmt_deploy/image-8.png +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/image/qmt_deploy/image-9.png +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/python-api-data.js +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/python-api.js +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/styles.css +0 -0
- {cfquant-0.2.48 → cfquant-0.2.49}/web_dashboard/vendor/mermaid.min.js +0 -0
|
@@ -343,13 +343,23 @@ def managed_source(source_path, identity_path, identity, descriptor):
|
|
|
343
343
|
for start, end, text in sorted(replacements, reverse=True):
|
|
344
344
|
lines[start:end] = [text]
|
|
345
345
|
lines[0] = "# coding: utf-8\n"
|
|
346
|
-
source = "".join(lines)
|
|
347
|
-
ast.parse(source, feature_version=(3, 6))
|
|
348
|
-
helper = Path(__file__).with_name("qmt_strategy_runtime.py").read_text(encoding="utf-8")
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
346
|
+
source = "".join(lines)
|
|
347
|
+
ast.parse(source, feature_version=(3, 6))
|
|
348
|
+
helper = Path(__file__).with_name("qmt_strategy_runtime.py").read_text(encoding="utf-8")
|
|
349
|
+
source_lines = source.splitlines(keepends=True)
|
|
350
|
+
# Adjacent literals compile to the same source string, while keeping every
|
|
351
|
+
# entry line visible in QMT's editor. A single ascii(source) hid thousands
|
|
352
|
+
# of Lite lines behind the same short lease wrapper as the other modes.
|
|
353
|
+
embedded = "\n".join(" " + ascii(line) for line in source_lines)
|
|
354
|
+
header = ("# coding: utf-8\n# cfquant managed strategy\n"
|
|
355
|
+
+ "# Mode: " + ascii(descriptor["mode"]) + "\n"
|
|
356
|
+
+ "# Entry: " + ascii(Path(source_path).name) + "\n"
|
|
357
|
+
+ "# Embedded entry: %d lines, preserved line by line below.\n" % len(source_lines)
|
|
358
|
+
+ "# The lease wrapper is shared by all modes.\n\n")
|
|
359
|
+
generated = (header + helper + "\n_cq_descriptor = " + ascii(descriptor)
|
|
360
|
+
+ "\n_cq_guard = _CqStrategyLease(_cq_descriptor).acquire()\n"
|
|
361
|
+
+ "_cq_guard.namespace = globals()\ntry:\n"
|
|
362
|
+
+ " exec(compile((\n%s\n ), %s, 'exec'), globals())\n" % (embedded, ascii(str(source_path)))
|
|
353
363
|
+ " for _cq_name in ('_cf_bridge', '_normal_bridge', '_trade_bridge'):\n"
|
|
354
364
|
+ " if globals().get(_cq_name) is not None:\n"
|
|
355
365
|
+ " globals()[_cq_name].account_type = %s\n" % ascii(identity["account_type"])
|
|
@@ -408,13 +418,17 @@ class QmtStrategyManager:
|
|
|
408
418
|
job.pop("deploy_retry_count", None)
|
|
409
419
|
job.pop("deploy_retry_after", None)
|
|
410
420
|
|
|
411
|
-
def _clear_generation_transition(self, job):
|
|
412
|
-
changed = False
|
|
413
|
-
for key in ("control_generation", "accepted_generations"):
|
|
414
|
-
if key in job:
|
|
415
|
-
job.pop(key, None)
|
|
416
|
-
changed = True
|
|
417
|
-
|
|
421
|
+
def _clear_generation_transition(self, job):
|
|
422
|
+
changed = False
|
|
423
|
+
for key in ("control_generation", "accepted_generations"):
|
|
424
|
+
if key in job:
|
|
425
|
+
job.pop(key, None)
|
|
426
|
+
changed = True
|
|
427
|
+
for role in job.get("roles", []):
|
|
428
|
+
if "reimport_from_generation" in role:
|
|
429
|
+
role.pop("reimport_from_generation", None)
|
|
430
|
+
changed = True
|
|
431
|
+
return changed
|
|
418
432
|
|
|
419
433
|
def _prepare_generation_transition(self, job, previous=None):
|
|
420
434
|
"""Keep old same-name containers valid until the replacement starts."""
|
|
@@ -467,19 +481,23 @@ class QmtStrategyManager:
|
|
|
467
481
|
)
|
|
468
482
|
job["control_generation"] = legacy
|
|
469
483
|
job["accepted_generations"] = accepted
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
484
|
+
for role in job.get("roles", []):
|
|
485
|
+
if (_runtime_generation(role) == legacy
|
|
486
|
+
and role.get("reimport_from_generation") != legacy):
|
|
487
|
+
# The old report survives QMT shutdown and import. Handle it
|
|
488
|
+
# once per replacement job, including across Web restarts;
|
|
489
|
+
# resetting every poll destroys the prepared/imported model.
|
|
490
|
+
updates = {
|
|
491
|
+
"reimport_from_generation": legacy,
|
|
492
|
+
"reimport_required": True,
|
|
493
|
+
"imported": False,
|
|
494
|
+
"queued": False,
|
|
495
|
+
"model_prepared": False,
|
|
496
|
+
}
|
|
497
|
+
for key, value in updates.items():
|
|
498
|
+
if role.get(key) != value:
|
|
499
|
+
role[key] = value
|
|
500
|
+
changed = True
|
|
483
501
|
if changed and job.get("state") == "error":
|
|
484
502
|
self._state(job, "waiting_exit")
|
|
485
503
|
return changed
|
|
@@ -98,6 +98,35 @@ def test_edit_without_mode_preserves_lite_binding_and_payload(web_deployment):
|
|
|
98
98
|
assert_lite_package(manager, root)
|
|
99
99
|
|
|
100
100
|
|
|
101
|
+
def test_edit_advanced_binding_to_lite_retires_both_advanced_models(web_deployment):
|
|
102
|
+
web, manager, row, infos, root = web_deployment
|
|
103
|
+
trade_root = root.with_name("QMT_trade")
|
|
104
|
+
shutil.copytree(root, trade_root)
|
|
105
|
+
row.update(mode="lttx", qmt_trade_dir=str(trade_root / "bin.x64"))
|
|
106
|
+
row["qmt_strategy"]["autorun"] = True
|
|
107
|
+
trade_info = dict(infos[0], qmt_role="trade", core_dir=str(trade_root / "bin.x64"),
|
|
108
|
+
path=str(trade_root / "bin.x64" / "cfquant_bridge_config.json"))
|
|
109
|
+
manager.configure(row, infos + [trade_info])
|
|
110
|
+
advanced_name = "CFQ_%s_LTTX" % row["account_id"]
|
|
111
|
+
assert models(root)[advanced_name].getAttribute("startupAutorun") == "1"
|
|
112
|
+
assert models(trade_root)[advanced_name].getAttribute("startupAutorun") == "1"
|
|
113
|
+
|
|
114
|
+
body = {key: row[key] for key in ("account_id", "account_type", "bridge_id", "qmt_dir")}
|
|
115
|
+
result = web.save_account_runtime_config(dict(body, mode="lite", qmt_trade_dir=""))
|
|
116
|
+
|
|
117
|
+
assert result["account"]["mode"] == "lite"
|
|
118
|
+
assert result["account"]["qmt_trade_dir"] == ""
|
|
119
|
+
assert not result["qmt_strategy_deploy"].get("error")
|
|
120
|
+
job = assert_lite_package(manager, root)
|
|
121
|
+
assert job["roles"][0]["name"] == "CFQ_%s_LITE" % row["account_id"]
|
|
122
|
+
assert models(root)[job["roles"][0]["name"]].getAttribute("startupAutorun") == "1"
|
|
123
|
+
assert models(root)[advanced_name].getAttribute("startupAutorun") == "0"
|
|
124
|
+
assert models(trade_root)[advanced_name].getAttribute("startupAutorun") == "0"
|
|
125
|
+
trade_job = next(job for job in manager.jobs.values() if job["root"] == str(trade_root))
|
|
126
|
+
assert trade_job["enabled"] is False
|
|
127
|
+
assert trade_job["state"] == "disabled"
|
|
128
|
+
|
|
129
|
+
|
|
101
130
|
@pytest.mark.parametrize("single_account", [False, True])
|
|
102
131
|
def test_shared_qmt_directory_does_not_drop_lite_market_entries(single_account, web_deployment):
|
|
103
132
|
web, _, row, _, root = web_deployment
|
|
@@ -464,6 +464,8 @@ def test_all_managed_entry_variants_compile_without_executing(mode, deployment):
|
|
|
464
464
|
assert document["detail"]["realName"] == role["name"] + ".py"
|
|
465
465
|
assert document["formulaCatalog"][0].encode("utf-8", "surrogateescape").hex() == "ced2b5c4b2dfc2d4"
|
|
466
466
|
ast.parse(document["content"], feature_version=(3, 6))
|
|
467
|
+
assert "# Mode: %r\n" % mode in document["content"]
|
|
468
|
+
assert "# Entry: %r\n" % Path(role["source"]).name in document["content"]
|
|
467
469
|
if mode == "lite":
|
|
468
470
|
embedded = [node.args[0].value for node in ast.walk(ast.parse(document["content"]))
|
|
469
471
|
if isinstance(node, ast.Call) and isinstance(node.func, ast.Name)
|
|
@@ -477,6 +479,8 @@ def test_all_managed_entry_variants_compile_without_executing(mode, deployment):
|
|
|
477
479
|
if isinstance(node, (ast.FunctionDef, ast.ClassDef))}
|
|
478
480
|
assert definitions(actual) == definitions(original)
|
|
479
481
|
assert len(embedded[0].splitlines()) > 7000
|
|
482
|
+
assert len(document["content"].splitlines()) > 7000
|
|
483
|
+
assert max(map(len, document["content"].splitlines())) < 2000
|
|
480
484
|
descriptor = {"mode": mode, "generation": "test", "role": "SH", "control_path": "test", "lease_dir": "test"}
|
|
481
485
|
variants = list((SCRIPTS / "同账号独立市场").glob("*.py")) + [SCRIPTS / "CFQUANT_TRADE_LOWLAT.py"]
|
|
482
486
|
for path in variants:
|
|
@@ -522,6 +526,64 @@ def test_process_once_detects_stale_runtime_generation_and_queues_reimport(deplo
|
|
|
522
526
|
assert (root / "formulas" / (role["name"] + ".rzrk")).is_file()
|
|
523
527
|
|
|
524
528
|
|
|
529
|
+
@pytest.mark.parametrize("report_state", ["running", "stopped"])
|
|
530
|
+
@pytest.mark.parametrize("previous_mode", ["lite", "lttx"])
|
|
531
|
+
def test_old_runtime_report_does_not_reset_prepared_replacement(deployment, report_state, previous_mode):
|
|
532
|
+
manager, row, infos, running, root = deployment
|
|
533
|
+
row["mode"] = "lite"
|
|
534
|
+
manager.configure(row, infos)
|
|
535
|
+
finish_import(manager, root)
|
|
536
|
+
manager.process_once()
|
|
537
|
+
first = copy.deepcopy(next(iter(manager.jobs.values())))
|
|
538
|
+
_write_json(first["roles"][0]["runtime_status_path"], {
|
|
539
|
+
"state": report_state, "generation": first["generation"], "updated_at": time.time() - 120,
|
|
540
|
+
})
|
|
541
|
+
if previous_mode != "lite":
|
|
542
|
+
row["mode"] = previous_mode
|
|
543
|
+
manager.configure(row, infos)
|
|
544
|
+
finish_import(manager, root)
|
|
545
|
+
manager.process_once()
|
|
546
|
+
|
|
547
|
+
row["mode"] = "lite"
|
|
548
|
+
manager.configure(row, infos, force=True)
|
|
549
|
+
job = next(iter(manager.jobs.values()))
|
|
550
|
+
role = job["roles"][0]
|
|
551
|
+
queue = root / "formulas" / (role["name"] + ".rzrk")
|
|
552
|
+
assert queue.is_file()
|
|
553
|
+
assert role["model_prepared"] is True
|
|
554
|
+
|
|
555
|
+
# The old heartbeat remains on disk until QMT has imported and started
|
|
556
|
+
# the new strategy. Repeated polling or a Web restart must not undo it.
|
|
557
|
+
manager = QmtStrategyManager(manager.path, SCRIPTS, lambda root: running[0])
|
|
558
|
+
job = next(iter(manager.jobs.values()))
|
|
559
|
+
role = job["roles"][0]
|
|
560
|
+
running[0] = True
|
|
561
|
+
manager.process_once()
|
|
562
|
+
manager.process_once()
|
|
563
|
+
assert role["reimport_required"] is False
|
|
564
|
+
assert role["model_prepared"] is True
|
|
565
|
+
assert role["queued"] is True
|
|
566
|
+
assert job["state"] == "waiting_manual_start"
|
|
567
|
+
|
|
568
|
+
finish_import(manager, root)
|
|
569
|
+
container = root / "python" / (role["name"] + ".py")
|
|
570
|
+
running[0] = False
|
|
571
|
+
manager.process_once()
|
|
572
|
+
manager.process_once()
|
|
573
|
+
assert container.is_file()
|
|
574
|
+
assert not queue.exists()
|
|
575
|
+
assert role["imported"] is True
|
|
576
|
+
assert job["state"] == "configured"
|
|
577
|
+
|
|
578
|
+
_write_json(role["runtime_status_path"], {
|
|
579
|
+
"state": "running", "generation": job["generation"], "updated_at": time.time(),
|
|
580
|
+
})
|
|
581
|
+
running[0] = True
|
|
582
|
+
manager.process_once()
|
|
583
|
+
assert job["state"] == "running"
|
|
584
|
+
assert not job.get("control_generation")
|
|
585
|
+
|
|
586
|
+
|
|
525
587
|
@pytest.mark.parametrize("encoding", ["utf-8", "gbk", "gb18030"])
|
|
526
588
|
def test_managed_package_executes_after_qmt_encoding_with_chinese_paths(tmp_path, encoding):
|
|
527
589
|
directory = tmp_path / "\u534e\u6cf0\u8bc1\u5238 QMT \u6a21\u62df"
|
|
@@ -304,7 +304,7 @@ def test_save_and_delete_call_deployment_manager(web_config, monkeypatch):
|
|
|
304
304
|
assert calls[-1] == ("reconcile", set())
|
|
305
305
|
|
|
306
306
|
|
|
307
|
-
def test_save_can_start_qmt_auto_login_and_persist_restart_times(web_config, monkeypatch):
|
|
307
|
+
def test_save_can_start_qmt_auto_login_and_persist_restart_times(web_config, monkeypatch, tmp_path):
|
|
308
308
|
web, config = web_config
|
|
309
309
|
calls = []
|
|
310
310
|
monkeypatch.setattr(web, "auto_deploy_qmt_core_for_account", lambda *args, **kwargs: {})
|
|
@@ -325,7 +325,7 @@ def test_save_can_start_qmt_auto_login_and_persist_restart_times(web_config, mon
|
|
|
325
325
|
data = web.save_account_runtime_config({
|
|
326
326
|
"account_id": "8885060548",
|
|
327
327
|
"display_name": "国金证券",
|
|
328
|
-
"qmt_dir":
|
|
328
|
+
"qmt_dir": str(tmp_path / "QMT" / "bin.x64"),
|
|
329
329
|
"qmt_auto_login": {"enabled": True, "restart_times": ["6:30", "06:30", "18:05"]},
|
|
330
330
|
})
|
|
331
331
|
assert data["qmt_auto_login"]["pid"] == 1234
|
|
@@ -562,7 +562,7 @@ def _resolve_batch_order_ids(bridge, account, pending, before_ids):
|
|
|
562
562
|
time.sleep(min(0.05, remaining))
|
|
563
563
|
# END GENERATED CFTRADER BATCH
|
|
564
564
|
|
|
565
|
-
CORE_VERSION = "0.2.
|
|
565
|
+
CORE_VERSION = "0.2.49"
|
|
566
566
|
LITE_ENTRY_VERSION = "lite_20260828_01"
|
|
567
567
|
|
|
568
568
|
_CANCELABLE_ORDER_STATUS_VALUES = set([48, 49, 50, 55])
|
|
@@ -616,7 +616,7 @@ def _resolve_batch_order_ids(bridge, account, pending, before_ids):
|
|
|
616
616
|
time.sleep(min(0.05, remaining))
|
|
617
617
|
# END GENERATED CFTRADER BATCH
|
|
618
618
|
|
|
619
|
-
CORE_VERSION = "0.2.
|
|
619
|
+
CORE_VERSION = "0.2.49"
|
|
620
620
|
LITE_ENTRY_VERSION = "lite_20260828_01"
|
|
621
621
|
|
|
622
622
|
_CANCELABLE_ORDER_STATUS_VALUES = set([48, 49, 50, 55])
|
|
@@ -616,7 +616,7 @@ def _resolve_batch_order_ids(bridge, account, pending, before_ids):
|
|
|
616
616
|
time.sleep(min(0.05, remaining))
|
|
617
617
|
# END GENERATED CFTRADER BATCH
|
|
618
618
|
|
|
619
|
-
CORE_VERSION = "0.2.
|
|
619
|
+
CORE_VERSION = "0.2.49"
|
|
620
620
|
LITE_ENTRY_VERSION = "lite_20260828_01"
|
|
621
621
|
|
|
622
622
|
_CANCELABLE_ORDER_STATUS_VALUES = set([48, 49, 50, 55])
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<title>cfquant 控制台</title>
|
|
7
7
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
|
8
|
-
<link rel="stylesheet" href="/styles.css?v=
|
|
8
|
+
<link rel="stylesheet" href="/styles.css?v=web_20261012_01">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div id="webAuthOverlay" class="auth-overlay hidden" aria-live="polite">
|
|
@@ -3223,6 +3223,6 @@ else:
|
|
|
3223
3223
|
<script src="/api-tester.js?v=20260916_apikey_01"></script>
|
|
3224
3224
|
<script src="/python-api.js?v=20260925_trading_dates_01"></script>
|
|
3225
3225
|
<script src="/docs.js?v=20260925_data_docs_01"></script>
|
|
3226
|
-
<script src="/app.js?v=
|
|
3226
|
+
<script src="/app.js?v=web_20261012_01"></script>
|
|
3227
3227
|
</body>
|
|
3228
3228
|
</html>
|
|
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
|
|
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
|
|
File without changes
|