cnhkmcp 2.1.1__py3-none-any.whl → 2.1.3__py3-none-any.whl

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 (117) hide show
  1. {cnhkmcp-2.1.1.dist-info → cnhkmcp-2.1.3.dist-info}/METADATA +1 -1
  2. cnhkmcp-2.1.3.dist-info/RECORD +6 -0
  3. cnhkmcp-2.1.3.dist-info/top_level.txt +1 -0
  4. cnhkmcp/__init__.py +0 -125
  5. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/README.md +0 -38
  6. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/ace.log +0 -0
  7. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/config.json +0 -6
  8. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/get_knowledgeBase_tool/ace_lib.py +0 -1510
  9. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/get_knowledgeBase_tool/fetch_all_datasets.py +0 -157
  10. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/get_knowledgeBase_tool/fetch_all_documentation.py +0 -132
  11. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/get_knowledgeBase_tool/fetch_all_operators.py +0 -99
  12. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/get_knowledgeBase_tool/helpful_functions.py +0 -180
  13. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/icon.ico +0 -0
  14. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/icon.png +0 -0
  15. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/knowledge/test.txt +0 -1
  16. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/main.py +0 -576
  17. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/process_knowledge_base.py +0 -280
  18. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/rag_engine.py +0 -356
  19. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/requirements.txt +0 -7
  20. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/run.bat +0 -3
  21. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/vector_db/_manifest.json +0 -326
  22. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/vector_db/_meta.json +0 -1
  23. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/vector_db/be5d957c-b724-46e3-91d1-999e9f5f7d28/index_metadata.pickle +0 -0
  24. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/vector_db/chroma.sqlite3 +0 -0
  25. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242//321/211/320/266/320/246/321/206/320/274/320/261/321/210/342/224/220/320/240/321/210/320/261/320/234/321/206/320/231/320/243/321/205/342/225/235/320/220/321/206/320/230/320/241.py +0 -265
  26. cnhkmcp/untracked/APP/.gitignore +0 -32
  27. cnhkmcp/untracked/APP/MODULAR_STRUCTURE.md +0 -112
  28. cnhkmcp/untracked/APP/README.md +0 -309
  29. cnhkmcp/untracked/APP/Tranformer/Transformer.py +0 -4985
  30. cnhkmcp/untracked/APP/Tranformer/ace.log +0 -0
  31. cnhkmcp/untracked/APP/Tranformer/ace_lib.py +0 -1510
  32. cnhkmcp/untracked/APP/Tranformer/helpful_functions.py +0 -180
  33. cnhkmcp/untracked/APP/Tranformer/output/Alpha_candidates.json +0 -2421
  34. cnhkmcp/untracked/APP/Tranformer/output/Alpha_candidates_/321/207/320/264/342/225/221/321/204/342/225/233/320/233.json +0 -654
  35. cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_error.json +0 -1034
  36. cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_success.json +0 -444
  37. cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_/321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/320/237/320/277/321/207/320/253/342/224/244/321/206/320/236/320/265/321/210/342/225/234/342/225/234/321/205/320/225/320/265Machine_lib.json +0 -22
  38. cnhkmcp/untracked/APP/Tranformer/parsetab.py +0 -60
  39. cnhkmcp/untracked/APP/Tranformer/template_summary.txt +0 -3182
  40. cnhkmcp/untracked/APP/Tranformer/transformer_config.json +0 -7
  41. cnhkmcp/untracked/APP/Tranformer/validator.py +0 -889
  42. cnhkmcp/untracked/APP/ace.log +0 -69
  43. cnhkmcp/untracked/APP/ace_lib.py +0 -1510
  44. cnhkmcp/untracked/APP/blueprints/__init__.py +0 -6
  45. cnhkmcp/untracked/APP/blueprints/feature_engineering.py +0 -347
  46. cnhkmcp/untracked/APP/blueprints/idea_house.py +0 -221
  47. cnhkmcp/untracked/APP/blueprints/inspiration_house.py +0 -432
  48. cnhkmcp/untracked/APP/blueprints/paper_analysis.py +0 -570
  49. cnhkmcp/untracked/APP/custom_templates/templates.json +0 -1257
  50. cnhkmcp/untracked/APP/give_me_idea/BRAIN_Alpha_Template_Expert_SystemPrompt.md +0 -400
  51. cnhkmcp/untracked/APP/give_me_idea/ace_lib.py +0 -1510
  52. cnhkmcp/untracked/APP/give_me_idea/alpha_data_specific_template_master.py +0 -252
  53. cnhkmcp/untracked/APP/give_me_idea/fetch_all_datasets.py +0 -157
  54. cnhkmcp/untracked/APP/give_me_idea/fetch_all_operators.py +0 -99
  55. cnhkmcp/untracked/APP/give_me_idea/helpful_functions.py +0 -180
  56. cnhkmcp/untracked/APP/give_me_idea/what_is_Alpha_template.md +0 -11
  57. cnhkmcp/untracked/APP/helpful_functions.py +0 -180
  58. cnhkmcp/untracked/APP/hkSimulator/ace_lib.py +0 -1497
  59. cnhkmcp/untracked/APP/hkSimulator/autosimulator.py +0 -447
  60. cnhkmcp/untracked/APP/hkSimulator/helpful_functions.py +0 -180
  61. cnhkmcp/untracked/APP/mirror_config.txt +0 -20
  62. cnhkmcp/untracked/APP/operaters.csv +0 -129
  63. cnhkmcp/untracked/APP/requirements.txt +0 -53
  64. cnhkmcp/untracked/APP/run_app.bat +0 -28
  65. cnhkmcp/untracked/APP/run_app.sh +0 -34
  66. cnhkmcp/untracked/APP/setup_tsinghua.bat +0 -39
  67. cnhkmcp/untracked/APP/setup_tsinghua.sh +0 -43
  68. cnhkmcp/untracked/APP/simulator/alpha_submitter.py +0 -404
  69. cnhkmcp/untracked/APP/simulator/simulator_wqb.py +0 -618
  70. cnhkmcp/untracked/APP/ssrn-3332513.pdf +6 -109201
  71. cnhkmcp/untracked/APP/static/brain.js +0 -589
  72. cnhkmcp/untracked/APP/static/decoder.js +0 -1540
  73. cnhkmcp/untracked/APP/static/feature_engineering.js +0 -1729
  74. cnhkmcp/untracked/APP/static/idea_house.js +0 -937
  75. cnhkmcp/untracked/APP/static/inspiration.js +0 -465
  76. cnhkmcp/untracked/APP/static/inspiration_house.js +0 -868
  77. cnhkmcp/untracked/APP/static/paper_analysis.js +0 -390
  78. cnhkmcp/untracked/APP/static/script.js +0 -3082
  79. cnhkmcp/untracked/APP/static/simulator.js +0 -597
  80. cnhkmcp/untracked/APP/static/styles.css +0 -3127
  81. cnhkmcp/untracked/APP/static/usage_widget.js +0 -508
  82. cnhkmcp/untracked/APP/templates/alpha_inspector.html +0 -511
  83. cnhkmcp/untracked/APP/templates/feature_engineering.html +0 -960
  84. cnhkmcp/untracked/APP/templates/idea_house.html +0 -564
  85. cnhkmcp/untracked/APP/templates/index.html +0 -932
  86. cnhkmcp/untracked/APP/templates/inspiration_house.html +0 -861
  87. cnhkmcp/untracked/APP/templates/paper_analysis.html +0 -91
  88. cnhkmcp/untracked/APP/templates/simulator.html +0 -343
  89. cnhkmcp/untracked/APP/templates/transformer_web.html +0 -580
  90. cnhkmcp/untracked/APP/usage.md +0 -351
  91. cnhkmcp/untracked/APP//321/207/342/225/235/320/250/321/205/320/230/320/226/321/204/342/225/225/320/220/321/211/320/221/320/243/321/206/320/261/320/265/ace_lib.py +0 -1510
  92. cnhkmcp/untracked/APP//321/207/342/225/235/320/250/321/205/320/230/320/226/321/204/342/225/225/320/220/321/211/320/221/320/243/321/206/320/261/320/265/brain_alpha_inspector.py +0 -712
  93. cnhkmcp/untracked/APP//321/207/342/225/235/320/250/321/205/320/230/320/226/321/204/342/225/225/320/220/321/211/320/221/320/243/321/206/320/261/320/265/helpful_functions.py +0 -180
  94. cnhkmcp/untracked/APP//321/210/342/224/220/320/240/321/210/320/261/320/234/321/206/320/231/320/243/321/205/342/225/235/320/220/321/206/320/230/320/241.py +0 -2456
  95. cnhkmcp/untracked/arXiv_API_Tool_Manual.md +0 -490
  96. cnhkmcp/untracked/arxiv_api.py +0 -229
  97. cnhkmcp/untracked/forum_functions.py +0 -998
  98. cnhkmcp/untracked/mcp/321/206/320/246/320/227/321/204/342/225/227/342/225/242/321/210/320/276/342/225/221/321/205/320/255/320/253/321/207/320/231/320/2302_/321/205/320/266/320/222/321/206/320/256/320/254/321/205/320/236/320/257/321/207/320/231/320/230/321/205/320/240/320/277/321/205/320/232/320/270/321/204/342/225/225/320/235/321/204/342/225/221/320/226/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270/321/205/342/226/221/342/226/222/321/210/320/277/320/245/321/210/342/224/220/320/251/321/204/342/225/225/320/272/forum_functions.py +0 -407
  99. cnhkmcp/untracked/mcp/321/206/320/246/320/227/321/204/342/225/227/342/225/242/321/210/320/276/342/225/221/321/205/320/255/320/253/321/207/320/231/320/2302_/321/205/320/266/320/222/321/206/320/256/320/254/321/205/320/236/320/257/321/207/320/231/320/230/321/205/320/240/320/277/321/205/320/232/320/270/321/204/342/225/225/320/235/321/204/342/225/221/320/226/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270/321/205/342/226/221/342/226/222/321/210/320/277/320/245/321/210/342/224/220/320/251/321/204/342/225/225/320/272/platform_functions.py +0 -2415
  100. cnhkmcp/untracked/mcp/321/206/320/246/320/227/321/204/342/225/227/342/225/242/321/210/320/276/342/225/221/321/205/320/255/320/253/321/207/320/231/320/2302_/321/205/320/266/320/222/321/206/320/256/320/254/321/205/320/236/320/257/321/207/320/231/320/230/321/205/320/240/320/277/321/205/320/232/320/270/321/204/342/225/225/320/235/321/204/342/225/221/320/226/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270/321/205/342/226/221/342/226/222/321/210/320/277/320/245/321/210/342/224/220/320/251/321/204/342/225/225/320/272/user_config.json +0 -31
  101. cnhkmcp/untracked/mcp/321/206/320/246/320/227/321/204/342/225/227/342/225/242/321/210/320/276/342/225/221/321/205/320/255/320/253/321/207/320/231/320/2302_/321/205/320/266/320/222/321/206/320/256/320/254/321/205/320/236/320/257/321/207/320/231/320/230/321/205/320/240/320/277/321/205/320/232/320/270/321/204/342/225/225/320/235/321/204/342/225/221/320/226/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270/321/205/342/226/221/342/226/222/321/210/320/277/320/245/321/210/342/224/220/320/251/321/204/342/225/225/320/272//321/210/320/276/320/271AI/321/210/320/277/342/225/227/321/210/342/224/220/320/251/321/204/342/225/225/320/272/321/206/320/246/320/227/321/206/320/261/320/263/321/206/320/255/320/265/321/205/320/275/320/266/321/204/342/225/235/320/252/321/204/342/225/225/320/233/321/210/342/225/234/342/225/234/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270.md +0 -101
  102. cnhkmcp/untracked/mcp/321/206/320/246/320/227/321/204/342/225/227/342/225/242/321/210/320/276/342/225/221/321/205/320/255/320/253/321/207/320/231/320/2302_/321/205/320/266/320/222/321/206/320/256/320/254/321/205/320/236/320/257/321/207/320/231/320/230/321/205/320/240/320/277/321/205/320/232/320/270/321/204/342/225/225/320/235/321/204/342/225/221/320/226/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270/321/205/342/226/221/342/226/222/321/210/320/277/320/245/321/210/342/224/220/320/251/321/204/342/225/225/320/272//321/211/320/225/320/235/321/207/342/225/234/320/276/321/205/320/231/320/235/321/210/342/224/220/320/240/321/210/320/261/320/234/321/206/320/230/320/241_/321/205/320/276/320/231/321/210/320/263/320/225/321/205/342/224/220/320/225/321/210/320/266/320/221/321/204/342/225/233/320/255/321/210/342/225/241/320/246/321/205/320/234/320/225.py +0 -190
  103. cnhkmcp/untracked/platform_functions.py +0 -2886
  104. cnhkmcp/untracked/sample_mcp_config.json +0 -11
  105. cnhkmcp/untracked/user_config.json +0 -31
  106. cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/320/237/320/222/321/210/320/220/320/223/321/206/320/246/320/227/321/206/320/261/320/263_BRAIN_Alpha_Test_Requirements_and_Tips.md +0 -202
  107. cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/342/225/226/320/265/321/204/342/225/234/320/254/321/206/342/225/241/320/221_Alpha_explaination_workflow.md +0 -56
  108. cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/342/225/226/320/265/321/204/342/225/234/320/254/321/206/342/225/241/320/221_BRAIN_6_Tips_Datafield_Exploration_Guide.md +0 -194
  109. cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/342/225/226/320/265/321/204/342/225/234/320/254/321/206/342/225/241/320/221_BRAIN_Alpha_Improvement_Workflow.md +0 -101
  110. cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/342/225/226/320/265/321/204/342/225/234/320/254/321/206/342/225/241/320/221_Dataset_Exploration_Expert_Manual.md +0 -436
  111. cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/342/225/226/320/265/321/204/342/225/234/320/254/321/206/342/225/241/320/221_daily_report_workflow.md +0 -128
  112. cnhkmcp/untracked//321/211/320/225/320/235/321/207/342/225/234/320/276/321/205/320/231/320/235/321/210/342/224/220/320/240/321/210/320/261/320/234/321/206/320/230/320/241_/321/205/320/276/320/231/321/210/320/263/320/225/321/205/342/224/220/320/225/321/210/320/266/320/221/321/204/342/225/233/320/255/321/210/342/225/241/320/246/321/205/320/234/320/225.py +0 -190
  113. cnhkmcp-2.1.1.dist-info/RECORD +0 -115
  114. cnhkmcp-2.1.1.dist-info/top_level.txt +0 -1
  115. {cnhkmcp-2.1.1.dist-info → cnhkmcp-2.1.3.dist-info}/WHEEL +0 -0
  116. {cnhkmcp-2.1.1.dist-info → cnhkmcp-2.1.3.dist-info}/entry_points.txt +0 -0
  117. {cnhkmcp-2.1.1.dist-info → cnhkmcp-2.1.3.dist-info}/licenses/LICENSE +0 -0
@@ -1,618 +0,0 @@
1
- """
2
- Enhanced Alpha Template Generator Script
3
-
4
- This script generates alpha templates with interactive user input for:
5
- - JSON file path selection
6
- - User authentication
7
- - Simulation parameters
8
- - Multi-simulation mode support
9
- - Real-time log monitoring
10
- """
11
-
12
- import asyncio
13
- import wqb
14
- import json
15
- import os
16
- import getpass
17
- import threading
18
- import time
19
- import sys
20
- import msvcrt # For Windows password input with asterisks
21
- from pathlib import Path
22
-
23
- # FIX: Change working directory to script location to ensure logs are created in the right place
24
- # This prevents the "Permission denied" error when trying to create logs in system directories
25
- # The wqb.wqb_logger() function creates log files relative to the current working directory
26
- script_dir = os.path.dirname(os.path.abspath(__file__))
27
- try:
28
- os.chdir(script_dir)
29
- print(f"📁 工作目录已设置为: {os.getcwd()}")
30
- print(f"📝 日志文件将创建在: {os.getcwd()}")
31
-
32
- # Verify the directory is writable
33
- if not os.access(script_dir, os.W_OK):
34
- print(f"⚠️ 警告: 目录 {script_dir} 不可写,日志可能无法创建")
35
- else:
36
- print(f"✅ 目录 {script_dir} 可写,日志将正常创建")
37
-
38
- except Exception as e:
39
- print(f"⚠️ 警告: 无法更改工作目录到 {script_dir}: {e}")
40
- print(f"📝 日志文件将创建在当前工作目录: {os.getcwd()}")
41
-
42
- def get_password_with_asterisks(prompt):
43
- """Get password input with asterisks shown for each character"""
44
- print(prompt, end='', flush=True)
45
- password = ""
46
-
47
- while True:
48
- char = msvcrt.getch()
49
-
50
- # Handle Enter key (carriage return)
51
- if char == b'\r':
52
- print() # New line
53
- break
54
- # Handle Backspace
55
- elif char == b'\x08':
56
- if len(password) > 0:
57
- password = password[:-1]
58
- # Move cursor back, print space, move cursor back again
59
- print('\b \b', end='', flush=True)
60
- # Handle Ctrl+C
61
- elif char == b'\x03':
62
- print()
63
- raise KeyboardInterrupt
64
- # Handle regular characters
65
- else:
66
- try:
67
- # Convert bytes to string
68
- char_str = char.decode('utf-8')
69
- if char_str.isprintable():
70
- password += char_str
71
- print('*', end='', flush=True)
72
- except UnicodeDecodeError:
73
- pass # Ignore non-printable characters
74
-
75
- return password
76
-
77
- def get_json_filepath():
78
- """Ask user to input the directory/filepath of expressions_with_settings.json"""
79
- while True:
80
- print("\n" + "="*60)
81
- print("JSON 文件配置")
82
- print("="*60)
83
- filepath = input("请复制粘贴 expressions_with_settings.json (即以json格式储存的带有setting的表达式列表)的目录或完整路径: ").strip()
84
-
85
- # Remove quotes if user copied with quotes
86
- filepath = filepath.strip('"').strip("'")
87
-
88
- # Check if it's a directory and try to find the file
89
- if os.path.isdir(filepath):
90
- json_path = os.path.join(filepath, "expressions_with_settings.json")
91
- else:
92
- json_path = filepath
93
-
94
- # Verify file exists
95
- if os.path.exists(json_path):
96
- try:
97
- with open(json_path, 'r') as f:
98
- data = json.load(f)
99
- print(f"✓ 成功加载 JSON 文件: {json_path}")
100
- return json_path, data
101
- except json.JSONDecodeError:
102
- print("❌ 错误: JSON 文件格式无效,请检查文件。")
103
- except Exception as e:
104
- print(f"❌ 读取文件错误: {e}")
105
- else:
106
- print("❌ 错误: 文件未找到,请检查路径后重试。")
107
-
108
- def get_user_credentials():
109
- """Ask user for brain username and password with asterisk password input"""
110
- print("\n" + "="*60)
111
- print("BRAIN 身份验证")
112
- print("="*60)
113
-
114
- username = input("请输入您的 BRAIN 用户名: ").strip()
115
- password = get_password_with_asterisks("请输入您的 BRAIN 密码 (显示为 *): ")
116
-
117
- return username, password
118
-
119
- def test_authentication(username, password):
120
- """Test authentication and return session if successful"""
121
- print("\n" + "="*60)
122
- print("API连通验证")
123
- print("="*60)
124
-
125
- try:
126
- logger = wqb.wqb_logger()
127
- wqbs = wqb.WQBSession((username, password), logger=logger)
128
-
129
- # Test connection
130
- resp = wqbs.locate_field('open')
131
- print(f"连接测试结果: resp.ok = {resp.ok}")
132
-
133
- if resp.ok:
134
- print("✓ 身份验证成功!")
135
- return wqbs, logger
136
- else:
137
- print("❌ 身份验证失败,请检查您的用户名和密码。")
138
- return None, None
139
-
140
- except Exception as e:
141
- print(f"❌ 身份验证错误: {e}")
142
- return None, None
143
-
144
- def get_simulation_parameters(expressions_count, json_path):
145
- """Get simulation parameters from user with validation"""
146
- print("\n" + "="*60)
147
- print("回测参数设置")
148
- print("="*60)
149
- print(f"JSON 中的表达式总数: {expressions_count}")
150
-
151
- # Get starting position
152
- while True:
153
- try:
154
- where_to_start = int(input(f"从列表中第几个表达式开始 (0 到 {expressions_count-1}): "))
155
- if 0 <= where_to_start < expressions_count:
156
- if where_to_start > 0:
157
- print(f"\n⚠️ 警告: 原始 JSON 文件将被直接覆盖!")
158
- print(f"📝 原始文件: {expressions_count} 个表达式")
159
- print(f"🔪 切割后: {expressions_count - where_to_start} 个表达式")
160
- print(f"📂 文件位置: {json_path}")
161
- print(f"\n🚨 重要提示: 如果您不希望覆盖原始文件,请立即关闭终端并手动备份文件!")
162
- print(f"⏰ 5秒后将继续执行覆盖操作...")
163
-
164
- # Give user 5 seconds to think/close terminal
165
- import time
166
- for i in range(5, 0, -1):
167
- print(f"倒计时: {i} 秒...", end='\r')
168
- time.sleep(1)
169
- print(" ") # Clear countdown line
170
-
171
- confirm = input("(继续程序,开始回测y/返回并重选列表起始位置n): ").lower().strip()
172
- if confirm != 'y':
173
- print("请重新选择表达式列表起始位置。")
174
- continue
175
- break
176
- else:
177
- print(f"❌ 起始位置无效,必须在 0 到 {expressions_count-1} 之间")
178
- except ValueError:
179
- print("❌ 请输入有效数字。")
180
-
181
- # Get concurrent count
182
- while True:
183
- try:
184
- concurrent_count = int(input("请输入并发回测数量 (最小值 1): "))
185
- if concurrent_count >= 1:
186
- break
187
- else:
188
- print("❌ 并发数量必须大于等于 1。")
189
- except ValueError:
190
- print("❌ 请输入有效数字。")
191
-
192
- return where_to_start, concurrent_count
193
-
194
- def cut_json_file(json_path, expressions_with_settings, where_to_start):
195
- """Cut the JSON file from the starting point and overwrite the original file"""
196
- if where_to_start == 0:
197
- return expressions_with_settings # No cutting needed
198
-
199
- # Cut the expressions list
200
- cut_expressions = expressions_with_settings[where_to_start:]
201
-
202
- # Overwrite the original JSON file
203
- try:
204
- with open(json_path, 'w', encoding='utf-8') as f:
205
- json.dump(cut_expressions, f, ensure_ascii=False, indent=2)
206
- print(f"✓ 原始 JSON 文件已被覆盖")
207
- print(f"📊 新文件包含 {len(cut_expressions)} 个表达式")
208
- return cut_expressions
209
- except Exception as e:
210
- print(f"❌ 覆盖 JSON 文件失败: {e}")
211
- print(f"⚠️ 将使用原始数据继续运行")
212
- return expressions_with_settings
213
-
214
- def shuffle_json_file(json_path, expressions_with_settings):
215
- """Randomly shuffle the JSON elements and overwrite the file"""
216
- import random
217
-
218
- # Create a copy and shuffle it
219
- shuffled_expressions = expressions_with_settings.copy()
220
- random.shuffle(shuffled_expressions)
221
-
222
- # Overwrite the JSON file with shuffled data
223
- try:
224
- with open(json_path, 'w', encoding='utf-8') as f:
225
- json.dump(shuffled_expressions, f, ensure_ascii=False, indent=2)
226
- print(f"✓ JSON 文件已随机打乱并覆盖")
227
- print(f"🔀 已打乱 {len(shuffled_expressions)} 个表达式的顺序")
228
- return shuffled_expressions
229
- except Exception as e:
230
- print(f"❌ 打乱 JSON 文件失败: {e}")
231
- print(f"⚠️ 将使用原始顺序继续运行")
232
- return expressions_with_settings
233
-
234
- def get_random_shuffle_choice():
235
- """Ask user if they want to randomly shuffle the expressions"""
236
- print("\n" + "="*60)
237
- print("随机模式选择")
238
- print("="*60)
239
- print("是否要随机打乱表达式顺序?")
240
- print("💡 这将改变表达式在文件中的排列顺序,以达到随机回测的目的")
241
-
242
- while True:
243
- choice = input("选择随机模式? (y/n): ").lower().strip()
244
- if choice in ['y', 'n']:
245
- return choice == 'y'
246
- else:
247
- print("❌ 请输入 y 或 n")
248
-
249
- def get_multi_simulation_choice():
250
- """Ask user if they want to use multi-simulation mode"""
251
- print("\n" + "="*60)
252
- print("多重回测(multi-simulatioin)模式选择")
253
- print("="*60)
254
- print("是否要使用多重回测(multi-simulatioin)模式?")
255
- print("💡 多重回测(multi-simulatioin)可以将多个alpha组合在一个回测槽中运行")
256
-
257
- while True:
258
- choice = input("使用多重回测(multi-simulatioin)模式? (y/n): ").lower().strip()
259
- if choice in ['y', 'n']:
260
- return choice == 'y'
261
- else:
262
- print("❌ 请输入 y 或 n")
263
-
264
- def get_alpha_count_per_slot():
265
- """Ask user how many alphas to put in one multi-simulation slot"""
266
- print("\n" + "="*60)
267
- print("多重回测(multi-simulatioin)槽配置")
268
- print("="*60)
269
- print("每个多重回测(multi-simulatioin)槽中放置多少个alpha?")
270
- print("💡 范围: 2-10 个alpha")
271
-
272
- while True:
273
- try:
274
- alpha_count = int(input("每个槽的alpha数量 (2-10): "))
275
- if 2 <= alpha_count <= 10:
276
- return alpha_count
277
- else:
278
- print("❌ 数量必须在 2 到 10 之间")
279
- except ValueError:
280
- print("❌ 请输入有效数字。")
281
-
282
- def monitor_log_file(logger, stop_event, use_multi_sim=False, alpha_count_per_slot=None):
283
- """Monitor log file and print new lines in real-time"""
284
- print("\n📊 开始监控日志文件...")
285
-
286
- # Get current directory to look for log files
287
- current_dir = os.getcwd()
288
- log_file_path = None
289
-
290
- # First, try to find any existing wqb log files (including older ones)
291
- print("🔍 查找 WQB 日志文件...")
292
-
293
- # Look for any wqb*.log files in current directory
294
- wqb_files = []
295
- try:
296
- for file in os.listdir(current_dir):
297
- if file.startswith('wqb') and file.endswith('.log'):
298
- file_path = os.path.join(current_dir, file)
299
- wqb_files.append((file_path, os.path.getmtime(file_path)))
300
- except Exception as e:
301
- print(f"⚠️ 扫描目录失败: {e}")
302
- return
303
-
304
- if wqb_files:
305
- # Sort by modification time, get the newest one
306
- log_file_path = sorted(wqb_files, key=lambda x: x[1], reverse=True)[0][0]
307
- print(f"✓ 监控已找到的最新日志文件: {log_file_path}")
308
- else:
309
- # Wait for new log file to be created
310
- print("等待新的 WQB 日志文件创建...")
311
- start_time = time.time()
312
-
313
- while not stop_event.is_set() and (time.time() - start_time) < 30: # Wait max 30 seconds
314
- try:
315
- for file in os.listdir(current_dir):
316
- if file.startswith('wqb') and file.endswith('.log'):
317
- file_path = os.path.join(current_dir, file)
318
- # Check if file was created recently (within last 120 seconds)
319
- if os.path.getctime(file_path) > (time.time() - 120):
320
- log_file_path = file_path
321
- break
322
- except Exception:
323
- pass
324
-
325
- if log_file_path:
326
- break
327
- time.sleep(1)
328
-
329
- if not log_file_path:
330
- print("⚠️ 未找到 WQB 日志文件,日志监控已禁用。")
331
- print("💡 提示: 日志文件通常在开始回测后才会创建")
332
- return
333
- else:
334
- print(f"✓ 找到新日志文件: {log_file_path}")
335
-
336
- if stop_event.is_set():
337
- return
338
-
339
- print("="*60)
340
-
341
- # Display multi-simulation information if applicable
342
- if use_multi_sim and alpha_count_per_slot:
343
- print("📌 重要提示:")
344
- print(f"以下是multi simulation的记录,你的设计是1个multi simulation中有{alpha_count_per_slot}个alpha,")
345
- print(f"因此需将实际回测数乘以该乘数,才得到实际已完成的Alpha个数。")
346
- print("="*60)
347
-
348
- try:
349
- # Start monitoring from current end of file
350
- with open(log_file_path, 'r', encoding='utf-8') as f:
351
- # Go to end of file
352
- f.seek(0, 2)
353
-
354
- while not stop_event.is_set():
355
- line = f.readline()
356
- if line:
357
- # Clean up the log line and print it
358
- clean_line = line.rstrip()
359
- if clean_line: # Only print non-empty lines
360
- print(f"[日志] {clean_line}")
361
- else:
362
- time.sleep(0.2)
363
- except Exception as e:
364
- print(f"⚠️ 监控日志文件时出错: {e}")
365
-
366
- async def automated_main(json_file_content, username, password, start_position=0, concurrent_count=3,
367
- random_shuffle=False, use_multi_sim=False, alpha_count_per_slot=3):
368
- """Automated main function for web interface - takes all parameters at once"""
369
- try:
370
- print("🧠 BRAIN Alpha 模板回测器 (自动模式)")
371
- print("="*60)
372
-
373
- # Parse JSON content directly
374
- import json
375
- expressions_with_settings = json.loads(json_file_content)
376
- expressions_count = len(expressions_with_settings)
377
-
378
- print(f"📊 已加载 {expressions_count} 个 alpha 配置")
379
-
380
- # Setup logger and session
381
- logger = wqb.wqb_logger()
382
- wqbs = wqb.WQBSession((username, password), logger=logger)
383
-
384
- # Test connection
385
- resp = wqbs.locate_field('open')
386
- print(f"连接测试结果: resp.ok = {resp.ok}")
387
-
388
- if not resp.ok:
389
- print("❌ 身份验证失败")
390
- return {"success": False, "error": "Authentication failed"}
391
-
392
- print("✅ 身份验证成功!")
393
-
394
- # Process expressions based on parameters
395
- if start_position > 0:
396
- expressions_with_settings = expressions_with_settings[start_position:]
397
- print(f"🔪 已从位置 {start_position} 开始切割,剩余 {len(expressions_with_settings)} 个表达式")
398
-
399
- if random_shuffle:
400
- import random
401
- random.shuffle(expressions_with_settings)
402
- print(f"🔀 已随机打乱 {len(expressions_with_settings)} 个表达式的顺序")
403
-
404
- if use_multi_sim:
405
- # Convert to multi-alphas format
406
- original_count = len(expressions_with_settings)
407
- expressions_with_settings = wqb.to_multi_alphas(expressions_with_settings, alpha_count_per_slot)
408
- print(f"✓ 已转换为多重回测(multi-simulatioin)格式")
409
- print(f"📊 原始表达式数: {original_count}")
410
- print(f"🎯 每槽alpha数: {alpha_count_per_slot}")
411
-
412
-
413
- # Write multi-simulation info to log
414
- multi_sim_msg = (f"[MULTI-SIMULATION MODE] 以下是multi simulation的记录,"
415
- f"你的设计是1个multi simulation中有{alpha_count_per_slot}个alpha,"
416
- f"因此需将实际回测数乘以该乘数,才得到实际已完成的Alpha个数。")
417
- logger.info("="*80)
418
- logger.info(multi_sim_msg)
419
- logger.info("="*80)
420
-
421
- print(f"🔄 使用 {concurrent_count} 个并发回测")
422
-
423
- # Start log monitoring in background
424
- stop_log_monitor = threading.Event()
425
- log_thread = threading.Thread(
426
- target=monitor_log_file,
427
- args=(logger, stop_log_monitor, use_multi_sim, alpha_count_per_slot),
428
- daemon=True
429
- )
430
- log_thread.start()
431
-
432
- print("\n" + "="*60)
433
- print("运行回测")
434
- print("="*60)
435
-
436
- if use_multi_sim:
437
- print("开始多重回测(multi-simulatioin)并发回测...")
438
- else:
439
- print("开始并发回测...")
440
-
441
- try:
442
- # Run simulations
443
- resps = await wqbs.concurrent_simulate(
444
- expressions_with_settings,
445
- concurrent_count,
446
- log_gap=10
447
- )
448
- finally:
449
- # Stop log monitoring
450
- stop_log_monitor.set()
451
- # Give the log thread a moment to print remaining logs
452
- time.sleep(0.5)
453
-
454
- # Collect results
455
- alpha_ids = []
456
- successful_count = 0
457
- failed_count = 0
458
-
459
- print("\n" + "="*60)
460
- print("回测结果")
461
- print("="*60)
462
-
463
- if use_multi_sim:
464
- print(f"成功完成 {len(resps)} 个多重回测(multi-simulatioin)槽的回测")
465
- else:
466
- print(f"成功完成 {len(resps)} 个回测")
467
-
468
- print("\nAlpha IDs:")
469
- # for i, resp in enumerate(resps):
470
- # try:
471
- # alpha_id = resp.json()['alpha']
472
- # alpha_ids.append(alpha_id)
473
- # successful_count += 1
474
- # print(f" {i+1:4d}. {alpha_id}")
475
- # except Exception as e:
476
- # failed_count += 1
477
- # print(f" {i+1:4d}. 错误: {e}")
478
-
479
- print("\n✅ 处理完成!")
480
-
481
- return {
482
- "success": True,
483
- "results": {
484
- "total": len(resps),
485
- "successful": successful_count,
486
- "failed": failed_count,
487
- "alphaIds": alpha_ids,
488
- "use_multi_sim": use_multi_sim,
489
- "alpha_count_per_slot": alpha_count_per_slot if use_multi_sim else None
490
- }
491
- }
492
-
493
- except Exception as e:
494
- print(f"\n❌ 错误: {e}")
495
- return {"success": False, "error": str(e)}
496
-
497
- async def main():
498
- """Main function with interactive workflow"""
499
- print("🧠 BRAIN Alpha 模板回测器")
500
- print("="*60)
501
-
502
- # Step 1: Get JSON file and load expressions
503
- json_path, expressions_with_settings = get_json_filepath()
504
- expressions_count = len(expressions_with_settings)
505
-
506
- print(f"\n📊 已从以下位置加载 {expressions_count} 个 alpha 配置:")
507
- print(f" {json_path}")
508
-
509
- # Step 2: Get credentials and test authentication
510
- wqbs = None
511
- logger = None
512
-
513
- while wqbs is None:
514
- username, password = get_user_credentials()
515
- wqbs, logger = test_authentication(username, password)
516
-
517
- if wqbs is None:
518
- retry = input("\n是否要重试? (y/n): ").lower().strip()
519
- if retry != 'y':
520
- print("正在退出...")
521
- return
522
-
523
- # Step 3: Get simulation parameters
524
- where_to_start, concurrent_count = get_simulation_parameters(expressions_count, json_path)
525
-
526
- # Step 3.5: Cut JSON file if needed
527
- if where_to_start > 0:
528
- print(f"\n🔪 正在切割 JSON 文件...")
529
- expressions_with_settings = cut_json_file(json_path, expressions_with_settings, where_to_start)
530
- where_to_start = 0 # Reset to 0 since we cut the file
531
-
532
- # Step 3.6: Ask for random shuffle option
533
- if get_random_shuffle_choice():
534
- print(f"\n🔀 正在随机打乱表达式顺序...")
535
- expressions_with_settings = shuffle_json_file(json_path, expressions_with_settings)
536
-
537
- # Step 3.7: Ask for multi-simulation mode
538
- use_multi_sim = get_multi_simulation_choice()
539
- alpha_count_per_slot = None
540
-
541
- if use_multi_sim:
542
- alpha_count_per_slot = get_alpha_count_per_slot()
543
- # Convert to multi-alphas format
544
- original_count = len(expressions_with_settings)
545
- expressions_with_settings = wqb.to_multi_alphas(expressions_with_settings, alpha_count_per_slot)
546
- print(f"\n✓ 已转换为多重回测(multi-simulatioin)格式")
547
- print(f"📊 原始表达式数: {original_count}")
548
- print(f"🎯 每槽alpha数: {alpha_count_per_slot}")
549
-
550
- # Calculate how many expressions will be processed
551
- print(f"🔄 使用 {concurrent_count} 个并发回测")
552
-
553
- # Step 4: Write multi-simulation info to log if applicable
554
- if use_multi_sim and alpha_count_per_slot and logger:
555
- multi_sim_msg = (f"[MULTI-SIMULATION MODE] 以下是multi simulation的记录,"
556
- f"你的设计是1个multi simulation中有{alpha_count_per_slot}个alpha,"
557
- f"因此需将实际回测数乘以该乘数,才得到实际已完成的Alpha个数。")
558
- logger.info("="*80)
559
- logger.info(multi_sim_msg)
560
- logger.info("="*80)
561
-
562
- # Step 5: Start log monitoring in background
563
- stop_log_monitor = threading.Event()
564
- log_thread = threading.Thread(
565
- target=monitor_log_file,
566
- args=(logger, stop_log_monitor, use_multi_sim, alpha_count_per_slot),
567
- daemon=True
568
- )
569
- log_thread.start()
570
-
571
- # Step 6: Run simulations
572
- print("\n" + "="*60)
573
- print("运行回测")
574
- print("="*60)
575
- if use_multi_sim:
576
- print("开始多重回测(multi-simulatioin)并发回测...")
577
- else:
578
- print("开始并发回测...")
579
-
580
- try:
581
- resps = await wqbs.concurrent_simulate(
582
- expressions_with_settings,
583
- concurrent_count,
584
- log_gap=10
585
- )
586
-
587
- # Stop log monitoring
588
- stop_log_monitor.set()
589
-
590
- # Print results
591
- print("\n" + "="*60)
592
- print("回测结果")
593
- print("="*60)
594
-
595
- if use_multi_sim:
596
- print(f"成功完成 {len(resps)} 个多重回测(multi-simulatioin)槽的回测")
597
- else:
598
- print(f"成功完成 {len(resps)} 个回测")
599
-
600
- # print("\nAlpha IDs:")
601
- # for i, resp in enumerate(resps):
602
- # try:
603
- # alpha_id = resp.json()['alpha']
604
- # print(f" {i+1:4d}. {alpha_id}")
605
- # except Exception as e:
606
- # print(f" {i+1:4d}. 错误: {e}")
607
-
608
- except KeyboardInterrupt:
609
- print("\n\n⚠️ 回测被用户中断")
610
- stop_log_monitor.set()
611
- except Exception as e:
612
- print(f"\n❌ 回测错误: {e}")
613
- stop_log_monitor.set()
614
-
615
- print("\n✅ 处理完成!")
616
-
617
- if __name__ == '__main__':
618
- asyncio.run(main())