cnhkmcp 2.1.2__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 (113) hide show
  1. {cnhkmcp-2.1.2.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 -281
  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 -408
  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//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
  22. cnhkmcp/untracked/APP/.gitignore +0 -32
  23. cnhkmcp/untracked/APP/MODULAR_STRUCTURE.md +0 -112
  24. cnhkmcp/untracked/APP/README.md +0 -309
  25. cnhkmcp/untracked/APP/Tranformer/Transformer.py +0 -4985
  26. cnhkmcp/untracked/APP/Tranformer/ace.log +0 -0
  27. cnhkmcp/untracked/APP/Tranformer/ace_lib.py +0 -1510
  28. cnhkmcp/untracked/APP/Tranformer/helpful_functions.py +0 -180
  29. cnhkmcp/untracked/APP/Tranformer/output/Alpha_candidates.json +0 -2421
  30. cnhkmcp/untracked/APP/Tranformer/output/Alpha_candidates_/321/207/320/264/342/225/221/321/204/342/225/233/320/233.json +0 -654
  31. cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_error.json +0 -1034
  32. cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_success.json +0 -444
  33. 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
  34. cnhkmcp/untracked/APP/Tranformer/parsetab.py +0 -60
  35. cnhkmcp/untracked/APP/Tranformer/template_summary.txt +0 -3182
  36. cnhkmcp/untracked/APP/Tranformer/transformer_config.json +0 -7
  37. cnhkmcp/untracked/APP/Tranformer/validator.py +0 -889
  38. cnhkmcp/untracked/APP/ace.log +0 -69
  39. cnhkmcp/untracked/APP/ace_lib.py +0 -1510
  40. cnhkmcp/untracked/APP/blueprints/__init__.py +0 -6
  41. cnhkmcp/untracked/APP/blueprints/feature_engineering.py +0 -347
  42. cnhkmcp/untracked/APP/blueprints/idea_house.py +0 -221
  43. cnhkmcp/untracked/APP/blueprints/inspiration_house.py +0 -432
  44. cnhkmcp/untracked/APP/blueprints/paper_analysis.py +0 -570
  45. cnhkmcp/untracked/APP/custom_templates/templates.json +0 -1257
  46. cnhkmcp/untracked/APP/give_me_idea/BRAIN_Alpha_Template_Expert_SystemPrompt.md +0 -400
  47. cnhkmcp/untracked/APP/give_me_idea/ace_lib.py +0 -1510
  48. cnhkmcp/untracked/APP/give_me_idea/alpha_data_specific_template_master.py +0 -252
  49. cnhkmcp/untracked/APP/give_me_idea/fetch_all_datasets.py +0 -157
  50. cnhkmcp/untracked/APP/give_me_idea/fetch_all_operators.py +0 -99
  51. cnhkmcp/untracked/APP/give_me_idea/helpful_functions.py +0 -180
  52. cnhkmcp/untracked/APP/give_me_idea/what_is_Alpha_template.md +0 -11
  53. cnhkmcp/untracked/APP/helpful_functions.py +0 -180
  54. cnhkmcp/untracked/APP/hkSimulator/ace_lib.py +0 -1497
  55. cnhkmcp/untracked/APP/hkSimulator/autosimulator.py +0 -447
  56. cnhkmcp/untracked/APP/hkSimulator/helpful_functions.py +0 -180
  57. cnhkmcp/untracked/APP/mirror_config.txt +0 -20
  58. cnhkmcp/untracked/APP/operaters.csv +0 -129
  59. cnhkmcp/untracked/APP/requirements.txt +0 -53
  60. cnhkmcp/untracked/APP/run_app.bat +0 -28
  61. cnhkmcp/untracked/APP/run_app.sh +0 -34
  62. cnhkmcp/untracked/APP/setup_tsinghua.bat +0 -39
  63. cnhkmcp/untracked/APP/setup_tsinghua.sh +0 -43
  64. cnhkmcp/untracked/APP/simulator/alpha_submitter.py +0 -404
  65. cnhkmcp/untracked/APP/simulator/simulator_wqb.py +0 -618
  66. cnhkmcp/untracked/APP/ssrn-3332513.pdf +6 -109201
  67. cnhkmcp/untracked/APP/static/brain.js +0 -589
  68. cnhkmcp/untracked/APP/static/decoder.js +0 -1540
  69. cnhkmcp/untracked/APP/static/feature_engineering.js +0 -1729
  70. cnhkmcp/untracked/APP/static/idea_house.js +0 -937
  71. cnhkmcp/untracked/APP/static/inspiration.js +0 -465
  72. cnhkmcp/untracked/APP/static/inspiration_house.js +0 -868
  73. cnhkmcp/untracked/APP/static/paper_analysis.js +0 -390
  74. cnhkmcp/untracked/APP/static/script.js +0 -3082
  75. cnhkmcp/untracked/APP/static/simulator.js +0 -597
  76. cnhkmcp/untracked/APP/static/styles.css +0 -3127
  77. cnhkmcp/untracked/APP/static/usage_widget.js +0 -508
  78. cnhkmcp/untracked/APP/templates/alpha_inspector.html +0 -511
  79. cnhkmcp/untracked/APP/templates/feature_engineering.html +0 -960
  80. cnhkmcp/untracked/APP/templates/idea_house.html +0 -564
  81. cnhkmcp/untracked/APP/templates/index.html +0 -932
  82. cnhkmcp/untracked/APP/templates/inspiration_house.html +0 -861
  83. cnhkmcp/untracked/APP/templates/paper_analysis.html +0 -91
  84. cnhkmcp/untracked/APP/templates/simulator.html +0 -343
  85. cnhkmcp/untracked/APP/templates/transformer_web.html +0 -580
  86. cnhkmcp/untracked/APP/usage.md +0 -351
  87. 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
  88. 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
  89. 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
  90. 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
  91. cnhkmcp/untracked/arXiv_API_Tool_Manual.md +0 -490
  92. cnhkmcp/untracked/arxiv_api.py +0 -229
  93. cnhkmcp/untracked/forum_functions.py +0 -998
  94. 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
  95. 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
  96. 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
  97. 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
  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//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
  99. cnhkmcp/untracked/platform_functions.py +0 -2886
  100. cnhkmcp/untracked/sample_mcp_config.json +0 -11
  101. cnhkmcp/untracked/user_config.json +0 -31
  102. 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
  103. 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
  104. 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
  105. 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
  106. 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
  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_daily_report_workflow.md +0 -128
  108. 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
  109. cnhkmcp-2.1.2.dist-info/RECORD +0 -111
  110. cnhkmcp-2.1.2.dist-info/top_level.txt +0 -1
  111. {cnhkmcp-2.1.2.dist-info → cnhkmcp-2.1.3.dist-info}/WHEEL +0 -0
  112. {cnhkmcp-2.1.2.dist-info → cnhkmcp-2.1.3.dist-info}/entry_points.txt +0 -0
  113. {cnhkmcp-2.1.2.dist-info → cnhkmcp-2.1.3.dist-info}/licenses/LICENSE +0 -0
@@ -1,511 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="zh-CN">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>BRAIN Alpha 跨界连锁 - 缘分一道桥</title>
7
- <link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
8
- <style>
9
- .inspector-container {
10
- max-width: 1200px;
11
- margin: 0 auto;
12
- padding: 20px;
13
- }
14
- .login-section, .filter-section, .results-section {
15
- background: white;
16
- padding: 20px;
17
- border-radius: 8px;
18
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
19
- margin-bottom: 20px;
20
- }
21
- .form-group {
22
- margin-bottom: 15px;
23
- }
24
- .form-group label {
25
- display: block;
26
- margin-bottom: 5px;
27
- font-weight: bold;
28
- }
29
- .form-group input {
30
- width: 100%;
31
- padding: 8px;
32
- border: 1px solid #ddd;
33
- border-radius: 4px;
34
- }
35
- .alpha-item {
36
- border: 1px solid #eee;
37
- margin-bottom: 10px;
38
- border-radius: 4px;
39
- overflow: hidden;
40
- }
41
- .alpha-header {
42
- background: #f8f9fa;
43
- padding: 10px 15px;
44
- cursor: pointer;
45
- display: flex;
46
- justify-content: space-between;
47
- align-items: center;
48
- }
49
- .alpha-header:hover {
50
- background: #e9ecef;
51
- }
52
- .alpha-details {
53
- padding: 15px;
54
- display: none;
55
- border-top: 1px solid #eee;
56
- }
57
- .alpha-details.active {
58
- display: block;
59
- }
60
- .variant-btn {
61
- margin: 5px;
62
- padding: 8px 12px;
63
- background: #fff;
64
- border: 1px solid #007bff;
65
- color: #007bff;
66
- border-radius: 4px;
67
- cursor: pointer;
68
- transition: all 0.2s;
69
- }
70
- .variant-btn:hover {
71
- background: #007bff;
72
- color: white;
73
- }
74
- .variant-btn.simulating {
75
- background: #ffc107;
76
- border-color: #ffc107;
77
- color: #000;
78
- cursor: wait;
79
- }
80
- .variant-btn.success {
81
- background: #28a745;
82
- border-color: #28a745;
83
- color: white;
84
- }
85
- .variant-btn.sharpe-low {
86
- background: #ffc107;
87
- border-color: #ffc107;
88
- color: #000;
89
- }
90
- .variant-btn.sharpe-high {
91
- background: #6f42c1;
92
- border-color: #6f42c1;
93
- color: white;
94
- }
95
- .variant-btn.error {
96
- background: #dc3545;
97
- border-color: #dc3545;
98
- color: white;
99
- }
100
- .btn-warning {
101
- background-color: #ffc107;
102
- color: #212529;
103
- border: 1px solid #ffc107;
104
- padding: 8px 16px;
105
- border-radius: 4px;
106
- cursor: pointer;
107
- font-size: 14px;
108
- }
109
- .btn-warning:hover {
110
- background-color: #e0a800;
111
- border-color: #d39e00;
112
- }
113
- .btn-warning:disabled {
114
- background-color: #ffeeba;
115
- border-color: #ffeeba;
116
- cursor: not-allowed;
117
- opacity: 0.65;
118
- }
119
- .loading {
120
- display: none;
121
- text-align: center;
122
- padding: 20px;
123
- }
124
- .hidden {
125
- display: none;
126
- }
127
- </style>
128
- </head>
129
- <body>
130
- <div class="inspector-container">
131
- <header style="margin-bottom: 20px; display: flex; justify-content: space-between; align-items: center;">
132
- <h1>🌉 缘分一道桥 (Alpha 跨区连锁)</h1>
133
- <a href="/" class="btn btn-secondary">返回主页</a>
134
- </header>
135
-
136
- <div class="instructions-section" style="background: #e9ecef; padding: 15px; border-radius: 8px; margin-bottom: 20px;">
137
- <h3 style="margin-top: 0;">📖 使用说明</h3>
138
- <ol style="padding-left: 20px; margin-bottom: 0; line-height: 1.6;">
139
- <li>获取一段时间内的Alpha列表</li>
140
- <li>分析每个Alpha里的数据字段并进行强替换,查看是否在其他Region/Universe/Delay有同样字段</li>
141
- <li>生成新的Alpha</li>
142
- <li>本页面的回测方式为排队回测,一个完成后才会发送另一个,因此中途退出页面会中断回测</li>
143
- <li>过长的回测队列有时会因为账号超时登出而出现连续失败,因此不建议选择过长时间跨度</li>
144
- <li>如想批量回测,请下载所有待回测的Alpha并选择首页回测器进行回测</li>
145
- <li>如果你想,你可以输入个很大的时间范围,下载所有表达式,慢慢进行批量回测。</li>
146
- <li>出现‘Field 'maxPercent' has no availability or not found. Intersection is empty’这类报错无需担心</li>
147
- <li>如果您一个都桥不出来,说明您使用了太多model data</li>
148
- <li>关于使用AI以跨区搭桥,我们已在72变里更新,跨区变换,最好还是使用72变功能</li>
149
- <li>对了,我们还有Alpha ID模式,您把差点可以提交的AlphaID放进来,说不定会在其他地方找到缘分</li>
150
- </ol>
151
- </div>
152
-
153
- <!-- Login Section -->
154
- <div id="loginSection" class="login-section">
155
- <h2>登录 BRAIN</h2>
156
- <div class="form-group">
157
- <label>用户名 (邮箱)</label>
158
- <input type="text" id="username" placeholder="请输入您的邮箱">
159
- </div>
160
- <div class="form-group">
161
- <label>密码</label>
162
- <input type="password" id="password" placeholder="请输入您的密码">
163
- </div>
164
- <button onclick="handleLogin()" class="btn btn-primary">登录</button>
165
- <div id="loginStatus" style="margin-top: 10px;"></div>
166
- </div>
167
-
168
- <!-- Main Content (Hidden until login) -->
169
- <div id="mainContent" class="hidden">
170
- <!-- Filter Section -->
171
- <div class="filter-section">
172
- <h2>选择模式</h2>
173
- <div style="margin-bottom: 15px;">
174
- <label><input type="radio" name="fetchMode" value="date" checked onclick="toggleMode()"> 按日期范围</label>
175
- <label style="margin-left: 20px;"><input type="radio" name="fetchMode" value="id" onclick="toggleMode()"> 指定 Alpha ID</label>
176
- </div>
177
-
178
- <div id="dateModeInputs">
179
- <h3>选择Alpha提交的日期范围(不建议超过30天)</h3>
180
- <div style="display: flex; gap: 20px;">
181
- <div class="form-group" style="flex: 1;">
182
- <label>开始日期</label>
183
- <input type="date" id="startDate">
184
- </div>
185
- <div class="form-group" style="flex: 1;">
186
- <label>结束日期</label>
187
- <input type="date" id="endDate">
188
- </div>
189
- </div>
190
- </div>
191
-
192
- <div id="idModeInputs" class="hidden">
193
- <h3>输入 Alpha ID (用逗号、空格或换行分隔)</h3>
194
- <div class="form-group">
195
- <textarea id="alphaIds" rows="5" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px;" placeholder="例如: QPdZrdQG, abc12345"></textarea>
196
- </div>
197
- </div>
198
-
199
- <button onclick="fetchAlphas()" class="btn btn-primary">获取 Alpha 并分析</button>
200
- <button onclick="downloadResults()" class="btn btn-secondary" id="downloadBtn" disabled>下载所有待回测Alpha</button>
201
- <button onclick="queueAllSimulations()" class="btn btn-warning" id="queueBtn" disabled>一键全部排队回测</button>
202
- </div>
203
-
204
- <!-- Results Section -->
205
- <div class="results-section">
206
- <h2>Alpha 列表 <span id="alphaCount"></span></h2>
207
- <div id="loadingIndicator" class="loading">
208
- 正在分析 Alpha... 请耐心等待...
209
- </div>
210
- <div id="alphasList"></div>
211
- </div>
212
- </div>
213
- </div>
214
-
215
- <script>
216
- let currentSessionId = null;
217
- let analyzedAlphas = [];
218
-
219
- async function handleLogin() {
220
- const username = document.getElementById('username').value;
221
- const password = document.getElementById('password').value;
222
- const statusDiv = document.getElementById('loginStatus');
223
-
224
- statusDiv.textContent = '正在登录...';
225
-
226
- try {
227
- const response = await fetch('/api/yuanfen/login', {
228
- method: 'POST',
229
- headers: {'Content-Type': 'application/json'},
230
- body: JSON.stringify({username, password})
231
- });
232
-
233
- const data = await response.json();
234
-
235
- if (data.success) {
236
- statusDiv.textContent = '登录成功!';
237
- statusDiv.style.color = 'green';
238
- currentSessionId = data.session_id;
239
- document.getElementById('loginSection').classList.add('hidden');
240
- document.getElementById('mainContent').classList.remove('hidden');
241
- } else {
242
- statusDiv.textContent = '登录失败:' + data.message;
243
- statusDiv.style.color = 'red';
244
- }
245
- } catch (e) {
246
- statusDiv.textContent = '错误:' + e.message;
247
- statusDiv.style.color = 'red';
248
- }
249
- }
250
-
251
- function toggleMode() {
252
- const mode = document.querySelector('input[name="fetchMode"]:checked').value;
253
- if (mode === 'date') {
254
- document.getElementById('dateModeInputs').classList.remove('hidden');
255
- document.getElementById('idModeInputs').classList.add('hidden');
256
- } else {
257
- document.getElementById('dateModeInputs').classList.add('hidden');
258
- document.getElementById('idModeInputs').classList.remove('hidden');
259
- }
260
- }
261
-
262
- async function fetchAlphas() {
263
- const mode = document.querySelector('input[name="fetchMode"]:checked').value;
264
- let payload = {
265
- session_id: currentSessionId,
266
- mode: mode === 'date' ? 'date_range' : 'ids'
267
- };
268
-
269
- if (mode === 'date') {
270
- const startDate = document.getElementById('startDate').value;
271
- const endDate = document.getElementById('endDate').value;
272
- if (!startDate || !endDate) {
273
- alert('请选择开始和结束日期');
274
- return;
275
- }
276
- payload.start_date = startDate;
277
- payload.end_date = endDate;
278
- } else {
279
- const alphaIds = document.getElementById('alphaIds').value;
280
- if (!alphaIds.trim()) {
281
- alert('请输入 Alpha ID');
282
- return;
283
- }
284
- payload.alpha_ids = alphaIds;
285
- }
286
-
287
- const loadingIndicator = document.getElementById('loadingIndicator');
288
- loadingIndicator.style.display = 'block';
289
- loadingIndicator.textContent = '正在初始化请求...';
290
- document.getElementById('alphasList').innerHTML = '';
291
-
292
- try {
293
- const response = await fetch('/api/yuanfen/fetch_alphas', {
294
- method: 'POST',
295
- headers: {'Content-Type': 'application/json'},
296
- body: JSON.stringify(payload)
297
- });
298
-
299
- const reader = response.body.getReader();
300
- const decoder = new TextDecoder();
301
- let buffer = '';
302
-
303
- while (true) {
304
- const { done, value } = await reader.read();
305
- if (done) break;
306
-
307
- buffer += decoder.decode(value, { stream: true });
308
- const lines = buffer.split('\n');
309
- buffer = lines.pop(); // Keep the last incomplete line
310
-
311
- for (const line of lines) {
312
- if (!line.trim()) continue;
313
- try {
314
- const msg = JSON.parse(line);
315
- if (msg.type === 'progress') {
316
- loadingIndicator.textContent = msg.message;
317
- } else if (msg.type === 'result') {
318
- if (msg.success) {
319
- analyzedAlphas = msg.alphas;
320
- document.getElementById('alphaCount').textContent = `(${analyzedAlphas.length})`;
321
- document.getElementById('downloadBtn').disabled = false;
322
- document.getElementById('queueBtn').disabled = false;
323
- renderAlphas(analyzedAlphas);
324
- } else {
325
- throw new Error(msg.message || 'Unknown error');
326
- }
327
- } else if (msg.type === 'error') {
328
- throw new Error(msg.message);
329
- }
330
- } catch (e) {
331
- console.error("Error parsing stream:", e);
332
- }
333
- }
334
- }
335
- } catch (e) {
336
- alert('获取 Alpha 失败:' + e.message);
337
- } finally {
338
- loadingIndicator.style.display = 'none';
339
- }
340
- }
341
-
342
- function renderAlphas(alphas) {
343
- const container = document.getElementById('alphasList');
344
- container.innerHTML = '';
345
-
346
- alphas.forEach((alpha, index) => {
347
- const div = document.createElement('div');
348
- div.className = 'alpha-item';
349
-
350
- const variantsHtml = alpha.variants.map(v => {
351
- const s = v.diff_settings;
352
- const label = `${s.region}/${s.universe}/delay_${s.delay}`;
353
- // Encode payload to pass to simulate function
354
- const payloadEncoded = encodeURIComponent(JSON.stringify(v.simulation_payload));
355
- return `<button class="variant-btn" onclick="simulateVariant(this, '${payloadEncoded}')">${label}</button>`;
356
- }).join('');
357
-
358
- div.innerHTML = `
359
- <div class="alpha-header" onclick="toggleDetails(${index})">
360
- <span>${alpha.id}${alpha.dateSubmitted ? ' - ' + alpha.dateSubmitted : ''}</span>
361
- <span>${alpha.variants.length} 个可用变体</span>
362
- </div>
363
- <div class="alpha-details" id="details-${index}">
364
- <p><strong>表达式:</strong> <code>${alpha.expression}</code></p>
365
- <div class="variants-list">
366
- ${variantsHtml || '未找到有效变体。'}
367
- </div>
368
- </div>
369
- `;
370
- container.appendChild(div);
371
- });
372
- }
373
-
374
- function toggleDetails(index) {
375
- const details = document.getElementById(`details-${index}`);
376
- details.classList.toggle('active');
377
- }
378
-
379
- async function simulateVariant(btn, payloadEncoded) {
380
- // Allow retry if it was error, but prevent double click if simulating
381
- if (btn.classList.contains('simulating')) return;
382
-
383
- // Reset state for retry
384
- btn.classList.remove('error');
385
- btn.classList.remove('success');
386
- btn.classList.remove('sharpe-low');
387
- btn.classList.remove('sharpe-high');
388
- const originalText = btn.textContent; // Keep original label if needed, but we overwrite it
389
-
390
- const payload = JSON.parse(decodeURIComponent(payloadEncoded));
391
-
392
- btn.textContent = '回测中...';
393
- btn.classList.add('simulating');
394
-
395
- try {
396
- const response = await fetch('/api/yuanfen/simulate', {
397
- method: 'POST',
398
- headers: {'Content-Type': 'application/json'},
399
- body: JSON.stringify({
400
- session_id: currentSessionId,
401
- payload: payload
402
- })
403
- });
404
-
405
- const data = await response.json();
406
-
407
- if (data.success) {
408
- btn.classList.remove('simulating');
409
-
410
- const res = data.result.is;
411
- const sharpe = res.sharpe;
412
-
413
- if (sharpe > 1.5) {
414
- btn.classList.add('sharpe-high');
415
- } else if (sharpe > 1.0) {
416
- btn.classList.add('success');
417
- } else {
418
- btn.classList.add('sharpe-low');
419
- }
420
-
421
- const alphaId = data.result.id;
422
- const alphaUrl = `https://platform.worldquantbrain.com/alpha/${alphaId}`;
423
-
424
- // Determine text color for link based on background
425
- const linkColor = (sharpe <= 1.0) ? 'black' : 'white';
426
-
427
- btn.innerHTML = `夏普: ${res.sharpe.toFixed(2)} | 收益: ${(res.returns * 100).toFixed(1)}% | <a href="${alphaUrl}" target="_blank" style="color: ${linkColor}; text-decoration: underline;" onclick="event.stopPropagation()">${alphaId}</a>`;
428
- btn.title = `ID: ${alphaId}\n换手率: ${res.turnover}`;
429
-
430
- // Remove onclick to prevent re-simulation
431
- btn.removeAttribute('onclick');
432
- btn.style.cursor = 'default';
433
- } else {
434
- throw new Error(data.message);
435
- }
436
- } catch (e) {
437
- btn.classList.remove('simulating');
438
- btn.classList.add('error');
439
- btn.textContent = '错误';
440
- btn.title = e.message;
441
- console.error("Simulation Error Details:", e);
442
- alert('回测失败: ' + e.message);
443
- }
444
- }
445
-
446
- function downloadResults() {
447
- // Flatten the list to get all simulatable payloads
448
- const allPayloads = [];
449
- analyzedAlphas.forEach(alpha => {
450
- alpha.variants.forEach(v => {
451
- // Add some metadata to the payload if useful, or just keep it clean
452
- const p = JSON.parse(JSON.stringify(v.simulation_payload));
453
- // p._origin_alpha_id = alpha.id; // Removed as requested
454
- allPayloads.push(p);
455
- });
456
- });
457
-
458
- const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(allPayloads, null, 2));
459
- const downloadAnchorNode = document.createElement('a');
460
- downloadAnchorNode.setAttribute("href", dataStr);
461
- downloadAnchorNode.setAttribute("download", "simulatable_alphas.json");
462
- document.body.appendChild(downloadAnchorNode);
463
- downloadAnchorNode.click();
464
- downloadAnchorNode.remove();
465
- }
466
-
467
- async function queueAllSimulations() {
468
- const buttons = document.querySelectorAll('.variant-btn');
469
- const queueBtn = document.getElementById('queueBtn');
470
-
471
- if (buttons.length === 0) {
472
- alert('没有可回测的变体');
473
- return;
474
- }
475
-
476
- if (!confirm(`确定要开始 ${buttons.length} 个变体的排队回测吗?这可能需要一些时间。`)) {
477
- return;
478
- }
479
-
480
- queueBtn.disabled = true;
481
- const originalText = queueBtn.textContent;
482
- queueBtn.textContent = '正在排队中... (请勿关闭页面)';
483
-
484
- let count = 0;
485
- for (const btn of buttons) {
486
- // Skip if already running or done
487
- if (btn.classList.contains('simulating') || btn.classList.contains('success')) {
488
- continue;
489
- }
490
-
491
- // Trigger click to start simulation
492
- btn.click();
493
- count++;
494
-
495
- // Update button text to show progress
496
- queueBtn.textContent = `正在排队... (${count}/${buttons.length})`;
497
-
498
- // Wait 500ms between requests to avoid rate limiting
499
- await new Promise(r => setTimeout(r, 500));
500
- }
501
-
502
- queueBtn.textContent = '排队完成';
503
- setTimeout(() => {
504
- queueBtn.disabled = false;
505
- queueBtn.textContent = originalText;
506
- }, 2000);
507
- }
508
- </script>
509
- <script src="{{ url_for('static', filename='usage_widget.js') }}"></script>
510
- </body>
511
- </html>