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.
Files changed (164) hide show
  1. {cfquant-0.2.43 → cfquant-0.2.44}/PKG-INFO +1 -1
  2. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/qmt_strategy_deploy.py +7 -7
  3. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_qmt_strategy_deploy.py +62 -0
  4. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_qmt_strategy_web.py +2 -1
  5. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/version.py +2 -2
  6. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant.egg-info/PKG-INFO +1 -1
  7. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant_web_server.py +3 -1
  8. {cfquant-0.2.43 → cfquant-0.2.44}/pyproject.toml +1 -1
  9. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/app.js +1 -1
  10. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/index.html +2 -2
  11. {cfquant-0.2.43 → cfquant-0.2.44}/LICENSE +0 -0
  12. {cfquant-0.2.43 → cfquant-0.2.44}/LTtx/__init__.py +0 -0
  13. {cfquant-0.2.43 → cfquant-0.2.44}/LTtx/tx/Config.txt +0 -0
  14. {cfquant-0.2.43 → cfquant-0.2.44}/LTtx/tx/LTtx_server.py +0 -0
  15. {cfquant-0.2.43 → cfquant-0.2.44}/LTtx/tx/__init__.py +0 -0
  16. {cfquant-0.2.43 → cfquant-0.2.44}/LTtx/tx/tx.py +0 -0
  17. {cfquant-0.2.43 → cfquant-0.2.44}/MANIFEST.in +0 -0
  18. {cfquant-0.2.43 → cfquant-0.2.44}/README.md +0 -0
  19. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/__init__.py +0 -0
  20. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/_editable_install.py +0 -0
  21. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/account_routing.py +0 -0
  22. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/batch_orders.py +0 -0
  23. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/build_info.py +0 -0
  24. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/callback_dispatcher.py +0 -0
  25. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/cftrader.py +0 -0
  26. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/channels.py +0 -0
  27. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/cli.py +0 -0
  28. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/client.py +0 -0
  29. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/config.py +0 -0
  30. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/hub.py +0 -0
  31. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/level2.py +0 -0
  32. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/log_management.py +0 -0
  33. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/logging_i18n.py +0 -0
  34. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/normal_bridge.py +0 -0
  35. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/order_meta.py +0 -0
  36. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/pipe_bridge.py +0 -0
  37. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/pipe_client.py +0 -0
  38. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/pipe_hub.py +0 -0
  39. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/pipe_transport.py +0 -0
  40. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/protocol.py +0 -0
  41. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/qmt_bridge.py +0 -0
  42. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/qmt_strategy_package.py +0 -0
  43. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/qmt_strategy_runtime.py +0 -0
  44. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/runtime_report.py +0 -0
  45. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/stock_connect.py +0 -0
  46. {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
  47. {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
  48. {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
  49. {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
  50. {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
  51. {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
  52. {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
  53. {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
  54. {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
  55. {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
  56. {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
  57. {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
  58. {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
  59. {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
  60. {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
  61. {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
  62. {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
  63. {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
  64. {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
  65. {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
  66. {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
  67. {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
  68. {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
  69. {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
  70. {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
  71. {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
  72. {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
  73. {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
  74. {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
  75. {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
  76. {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
  77. {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
  78. {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
  79. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/_helpers.py +0 -0
  80. {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
  81. {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
  82. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/readme.md +0 -0
  83. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_api_tester_browser.py +0 -0
  84. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_api_tester_web.py +0 -0
  85. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_binding_delete_confirmation.py +0 -0
  86. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_callback_requests.py +0 -0
  87. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_cftrader.py +0 -0
  88. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_cftrader_tutorial.py +0 -0
  89. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_cftrader_web.py +0 -0
  90. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_credit_compat.py +0 -0
  91. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_json_serialization.py +0 -0
  92. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_log_management.py +0 -0
  93. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_management_batch.py +0 -0
  94. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_market_data_fallback.py +0 -0
  95. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_order_time_callback.py +0 -0
  96. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_project_updater.py +0 -0
  97. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_python_api_reference.py +0 -0
  98. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_qmt_strategy_browser.py +0 -0
  99. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_stock_connect.py +0 -0
  100. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_stock_connect_browser.py +0 -0
  101. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_trading_dates.py +0 -0
  102. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_tutorial_reader.py +0 -0
  103. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tests/test_tx_auto_import.py +0 -0
  104. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tx.py +0 -0
  105. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/tx_trade_bridge.py +0 -0
  106. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/xtconstant.py +0 -0
  107. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/xtdata.py +0 -0
  108. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/xttrader.py +0 -0
  109. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant/xttype.py +0 -0
  110. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant.egg-info/SOURCES.txt +0 -0
  111. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant.egg-info/dependency_links.txt +0 -0
  112. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant.egg-info/entry_points.txt +0 -0
  113. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant.egg-info/requires.txt +0 -0
  114. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant.egg-info/top_level.txt +0 -0
  115. {cfquant-0.2.43 → cfquant-0.2.44}/cfquant_pipe_hub.py +0 -0
  116. {cfquant-0.2.43 → cfquant-0.2.44}/qmt_scripts/CFQUANT.py +0 -0
  117. {cfquant-0.2.43 → cfquant-0.2.44}/qmt_scripts/CFQUANT_CTYPE_ALL_LOWLAT.py +0 -0
  118. {cfquant-0.2.43 → cfquant-0.2.44}/qmt_scripts/CFQUANT_LITE.py +0 -0
  119. {cfquant-0.2.43 → cfquant-0.2.44}/qmt_scripts/CFQUANT_TRADE_LOWLAT.py +0 -0
  120. {cfquant-0.2.43 → cfquant-0.2.44}/qmt_scripts/__init__.py +0 -0
  121. {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
  122. {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
  123. {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
  124. {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
  125. {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
  126. {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
  127. {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
  128. {cfquant-0.2.43 → cfquant-0.2.44}/requirements.txt +0 -0
  129. {cfquant-0.2.43 → cfquant-0.2.44}/setup.cfg +0 -0
  130. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/__init__.py +0 -0
  131. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/api-tester.js +0 -0
  132. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/avatars/amber-pulse.svg +0 -0
  133. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/avatars/copper-grid.svg +0 -0
  134. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/avatars/market-blue.svg +0 -0
  135. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/avatars/rose-circuit.svg +0 -0
  136. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/avatars/signal-green.svg +0 -0
  137. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/avatars/slate-wave.svg +0 -0
  138. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/avatars/teal-orbit.svg +0 -0
  139. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/avatars/violet-node.svg +0 -0
  140. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/cftrader-api-data.js +0 -0
  141. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/docs.js +0 -0
  142. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/favicon.svg +0 -0
  143. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-10.png +0 -0
  144. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-11.png +0 -0
  145. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-12.png +0 -0
  146. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-13.png +0 -0
  147. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-14.png +0 -0
  148. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-15.png +0 -0
  149. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-16.png +0 -0
  150. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-17.png +0 -0
  151. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-18.png +0 -0
  152. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-19.png +0 -0
  153. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-20.png +0 -0
  154. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-21.png +0 -0
  155. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-4.png +0 -0
  156. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-5.png +0 -0
  157. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-6.png +0 -0
  158. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-7.png +0 -0
  159. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-8.png +0 -0
  160. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/image/qmt_deploy/image-9.png +0 -0
  161. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/python-api-data.js +0 -0
  162. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/python-api.js +0 -0
  163. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/styles.css +0 -0
  164. {cfquant-0.2.43 → cfquant-0.2.44}/web_dashboard/vendor/mermaid.min.js +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cfquant
3
- Version: 0.2.43
3
+ Version: 0.2.44
4
4
  Summary: QMT local bridge and xtquant-compatible Python client.
5
5
  License: MIT
6
6
  Requires-Python: >=3.8
@@ -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
- role["reimport_required"] = bool(
561
- previous.get("fingerprint")
562
- and isinstance(previous_roles.get(role["role"]), dict)
563
- and previous_roles[role["role"]].get("name") == role["name"]
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())
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """cfquant core version metadata."""
3
3
 
4
- __version__ = "0.2.43"
5
- WEB_VERSION = "web_20260925_02"
4
+ __version__ = "0.2.44"
5
+ WEB_VERSION = "web_20260926_01"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cfquant
3
- Version: 0.2.43
3
+ Version: 0.2.44
4
4
  Summary: QMT local bridge and xtquant-compatible Python client.
5
5
  License: MIT
6
6
  Requires-Python: >=3.8
@@ -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
- return QMT_STRATEGIES.configure(row, identities)
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"):
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "cfquant"
7
- version = "0.2.43"
7
+ version = "0.2.44"
8
8
  description = "QMT local bridge and xtquant-compatible Python client."
9
9
  license = {text = "MIT"}
10
10
  readme = "README.md"
@@ -1,4 +1,4 @@
1
- const FRONTEND_VERSION = 'web_20260925_02';
1
+ const FRONTEND_VERSION = 'web_20260926_01';
2
2
 
3
3
  const state = {
4
4
  accountId: '',
@@ -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=web_20260925_02">
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=web_20260925_02"></script>
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