cfquant 0.2.43__tar.gz → 0.2.44__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.43 → cfquant-0.2.44}/PKG-INFO +1 -1
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/qmt_strategy_deploy.py +7 -7
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_qmt_strategy_deploy.py +62 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_qmt_strategy_web.py +2 -1
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/version.py +2 -2
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant.egg-info/PKG-INFO +1 -1
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant_web_server.py +3 -1
- {cfquant-0.2.43 → cfquant-0.2.44}/pyproject.toml +1 -1
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/app.js +1 -1
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/index.html +2 -2
- {cfquant-0.2.43 → cfquant-0.2.44}/LICENSE +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/LTtx/__init__.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/LTtx/tx/Config.txt +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/LTtx/tx/LTtx_server.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/LTtx/tx/__init__.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/LTtx/tx/tx.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/MANIFEST.in +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/README.md +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/__init__.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/_editable_install.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/account_routing.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/batch_orders.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/build_info.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/callback_dispatcher.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/cftrader.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/channels.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/cli.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/client.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/config.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/hub.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/level2.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/log_management.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/logging_i18n.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/normal_bridge.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/order_meta.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/pipe_bridge.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/pipe_client.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/pipe_hub.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/pipe_transport.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/protocol.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/qmt_bridge.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/qmt_strategy_package.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/qmt_strategy_runtime.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/runtime_report.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/stock_connect.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/cfquant/tests/29_Level2/350/241/214/346/203/205/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/cfquant/tests/6_/345/233/236/350/260/203/346/265/213/350/257/225.py" +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/cfquant/tests/_helpers.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/cfquant/tests/readme.md +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_api_tester_browser.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_api_tester_web.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_binding_delete_confirmation.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_callback_requests.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_cftrader.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_cftrader_tutorial.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_cftrader_web.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_credit_compat.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_json_serialization.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_log_management.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_management_batch.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_market_data_fallback.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_order_time_callback.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_project_updater.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_python_api_reference.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_qmt_strategy_browser.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_stock_connect.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_stock_connect_browser.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_trading_dates.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_tutorial_reader.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_tx_auto_import.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tx.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tx_trade_bridge.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/xtconstant.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/xtdata.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/xttrader.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/xttype.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant.egg-info/SOURCES.txt +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant.egg-info/dependency_links.txt +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant.egg-info/entry_points.txt +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant.egg-info/requires.txt +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant.egg-info/top_level.txt +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/cfquant_pipe_hub.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/qmt_scripts/CFQUANT.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/qmt_scripts/CFQUANT_CTYPE_ALL_LOWLAT.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/qmt_scripts/CFQUANT_LITE.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/qmt_scripts/CFQUANT_TRADE_LOWLAT.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/qmt_scripts/__init__.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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" +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/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" +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/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.43 → cfquant-0.2.44}/requirements.txt +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/setup.cfg +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/__init__.py +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/api-tester.js +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/avatars/amber-pulse.svg +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/avatars/copper-grid.svg +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/avatars/market-blue.svg +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/avatars/rose-circuit.svg +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/avatars/signal-green.svg +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/avatars/slate-wave.svg +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/avatars/teal-orbit.svg +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/avatars/violet-node.svg +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/cftrader-api-data.js +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/docs.js +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/favicon.svg +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-10.png +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-11.png +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-12.png +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-13.png +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-14.png +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-15.png +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-16.png +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-17.png +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-18.png +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-19.png +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-20.png +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-21.png +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-4.png +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-5.png +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-6.png +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-7.png +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-8.png +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-9.png +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/python-api-data.js +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/python-api.js +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/styles.css +0 -0
- {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/vendor/mermaid.min.js +0 -0
|
@@ -463,7 +463,7 @@ class QmtStrategyManager:
|
|
|
463
463
|
result.update(error=self.load_error, message=self.load_error)
|
|
464
464
|
return result
|
|
465
465
|
|
|
466
|
-
def configure(self, row, identities):
|
|
466
|
+
def configure(self, row, identities, force=False):
|
|
467
467
|
if self.load_error:
|
|
468
468
|
raise ValueError(self.load_error)
|
|
469
469
|
settings = normalize_strategy_settings(row.get("qmt_strategy"))
|
|
@@ -512,7 +512,7 @@ class QmtStrategyManager:
|
|
|
512
512
|
fingerprint = _digest([source_group, mode, [
|
|
513
513
|
hashlib.sha256(Path(__file__).with_name(filename).read_bytes()).hexdigest()
|
|
514
514
|
for filename in ("qmt_strategy_runtime.py", "qmt_strategy_package.py", "qmt_strategy_deploy.py")]])
|
|
515
|
-
if previous.get("fingerprint") == fingerprint and previous.get("enabled"):
|
|
515
|
+
if not force and previous.get("fingerprint") == fingerprint and previous.get("enabled"):
|
|
516
516
|
previous["account_key"] = row["account_key"]
|
|
517
517
|
self._prepare_generation_transition(previous)
|
|
518
518
|
if previous["settings"] != settings:
|
|
@@ -557,11 +557,11 @@ class QmtStrategyManager:
|
|
|
557
557
|
retired=sorted(retired))
|
|
558
558
|
for role in job["roles"]:
|
|
559
559
|
role["name"] = role_names[role["role"]]
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
560
|
+
# Every new generation needs its own imported container.
|
|
561
|
+
# Switching back to a mode can find a same-name container
|
|
562
|
+
# from an earlier job, even though the previous job used
|
|
563
|
+
# a different slot. Its catalog entry proves no freshness.
|
|
564
|
+
role["reimport_required"] = True
|
|
565
565
|
role["identity_path"] = str(directory / (role["name"] + ".json"))
|
|
566
566
|
_write_json(role["identity_path"], role["identity"])
|
|
567
567
|
role["runtime_status_path"] = str(directory / (role["name"] + ".status.json"))
|
|
@@ -281,6 +281,68 @@ def test_switch_and_delete_revoke_old_generation_and_disable_its_model(deploymen
|
|
|
281
281
|
assert not list((root / "formulas").glob("*.rzrk"))
|
|
282
282
|
|
|
283
283
|
|
|
284
|
+
@pytest.mark.parametrize("mode", ["ctypes", "lite", "lttx"])
|
|
285
|
+
def test_force_save_reimports_unchanged_selected_mode(mode, deployment):
|
|
286
|
+
manager, row, infos, running, root = deployment
|
|
287
|
+
row["mode"] = mode
|
|
288
|
+
manager.configure(row, infos)
|
|
289
|
+
finish_import(manager, root)
|
|
290
|
+
manager.process_once()
|
|
291
|
+
original = copy.deepcopy(next(iter(manager.jobs.values())))
|
|
292
|
+
name = original["roles"][0]["name"]
|
|
293
|
+
container = root / "python" / (name + ".py")
|
|
294
|
+
running[0] = True
|
|
295
|
+
manager.configure(row, infos, force=True)
|
|
296
|
+
job = next(iter(manager.jobs.values()))
|
|
297
|
+
assert job["fingerprint"] == original["fingerprint"]
|
|
298
|
+
assert job["generation"] != original["generation"]
|
|
299
|
+
assert job["roles"][0]["name"] == name
|
|
300
|
+
assert job["state"] == "waiting_exit"
|
|
301
|
+
assert container.is_file()
|
|
302
|
+
running[0] = False
|
|
303
|
+
manager.process_once()
|
|
304
|
+
assert not container.exists()
|
|
305
|
+
assert job["state"] == "waiting_import"
|
|
306
|
+
queued = root / "formulas" / (name + ".rzrk")
|
|
307
|
+
assert queued.read_bytes() == Path(job["roles"][0]["package_path"]).read_bytes()
|
|
308
|
+
content = json.loads(_cipher().decrypt(queued.read_bytes()).decode("utf-8", "surrogateescape"))["content"]
|
|
309
|
+
assert job["generation"] in content
|
|
310
|
+
assert original["generation"] not in content
|
|
311
|
+
finish_import(manager, root)
|
|
312
|
+
manager.process_once()
|
|
313
|
+
assert job["state"] == "configured"
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def test_switch_back_to_lite_replaces_previously_imported_container(deployment):
|
|
317
|
+
manager, row, infos, running, root = deployment
|
|
318
|
+
row["mode"] = "lite"
|
|
319
|
+
manager.configure(row, infos)
|
|
320
|
+
finish_import(manager, root)
|
|
321
|
+
manager.process_once()
|
|
322
|
+
lite_name = next(iter(manager.jobs.values()))["roles"][0]["name"]
|
|
323
|
+
old_container = root / "python" / (lite_name + ".py")
|
|
324
|
+
assert old_container.is_file()
|
|
325
|
+
|
|
326
|
+
row["mode"] = "ctypes"
|
|
327
|
+
manager.configure(row, infos)
|
|
328
|
+
finish_import(manager, root)
|
|
329
|
+
manager.process_once()
|
|
330
|
+
assert old_container.is_file()
|
|
331
|
+
|
|
332
|
+
row["mode"] = "lite"
|
|
333
|
+
manager.configure(row, infos)
|
|
334
|
+
job = next(iter(manager.jobs.values()))
|
|
335
|
+
role = job["roles"][0]
|
|
336
|
+
assert role["name"] == lite_name
|
|
337
|
+
assert not old_container.exists()
|
|
338
|
+
assert job["state"] == "waiting_import"
|
|
339
|
+
queued = root / "formulas" / (lite_name + ".rzrk")
|
|
340
|
+
assert queued.read_bytes() == Path(role["package_path"]).read_bytes()
|
|
341
|
+
content = json.loads(_cipher().decrypt(queued.read_bytes()).decode("utf-8", "surrogateescape"))["content"]
|
|
342
|
+
assert job["generation"] in content
|
|
343
|
+
assert "Self-contained ctypes named-pipe entry" in content
|
|
344
|
+
|
|
345
|
+
|
|
284
346
|
def test_historical_generated_name_is_disabled_for_the_same_account(deployment):
|
|
285
347
|
manager, row, infos, running, root = deployment
|
|
286
348
|
document, _ = _read_document(root / "config" / "indexUserConfig.xml")
|
|
@@ -282,7 +282,8 @@ def test_save_and_delete_call_deployment_manager(web_config, monkeypatch):
|
|
|
282
282
|
class Manager:
|
|
283
283
|
def reconcile(self, accounts):
|
|
284
284
|
calls.append(("reconcile", set(accounts)))
|
|
285
|
-
def configure(self, row, identities):
|
|
285
|
+
def configure(self, row, identities, force=False):
|
|
286
|
+
assert force is True
|
|
286
287
|
calls.append(("configure", row["qmt_strategy"], identities))
|
|
287
288
|
return {"enabled": True, "targets": [{"state": "waiting_exit"}]}
|
|
288
289
|
monkeypatch.setattr(web, "QMT_STRATEGIES", Manager())
|
|
@@ -9699,7 +9699,9 @@ def configure_account_qmt_strategies(row, identity):
|
|
|
9699
9699
|
identities.extend(identity.get("market_identities") or [])
|
|
9700
9700
|
try:
|
|
9701
9701
|
QMT_STRATEGIES.reconcile(WEB_CONFIG.account_configs())
|
|
9702
|
-
|
|
9702
|
+
# Explicit binding saves and updates must replace even an unchanged
|
|
9703
|
+
# managed slot with a newly built package for the selected mode.
|
|
9704
|
+
return QMT_STRATEGIES.configure(row, identities, force=True)
|
|
9703
9705
|
except Exception as error:
|
|
9704
9706
|
detail = str(error or "").strip()
|
|
9705
9707
|
if not detail or detail in ("策略部署失败", "error"):
|
|
@@ -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_20260926_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_20260926_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
|