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,404 +0,0 @@
1
- import requests
2
- import json
3
- import time
4
- from datetime import datetime
5
- import os
6
- from pathlib import Path
7
- import getpass
8
- import sys
9
-
10
- # Platform specific imports
11
- if sys.platform == 'win32':
12
- import msvcrt
13
- else:
14
- import tty
15
- import termios
16
-
17
- def input_with_asterisks(prompt):
18
- """Cross-platform password input showing asterisks"""
19
- print(prompt, end='', flush=True)
20
- password = []
21
-
22
- try:
23
- if sys.platform == 'win32':
24
- # Windows: Use msvcrt.getch()
25
- while True:
26
- char = msvcrt.getch()
27
-
28
- # Handle Enter key
29
- if char in [b'\r', b'\n']:
30
- print() # New line
31
- break
32
-
33
- # Handle Backspace
34
- elif char == b'\x08': # Backspace
35
- if password:
36
- password.pop()
37
- # Move cursor back, print space, move cursor back again
38
- print('\b \b', end='', flush=True)
39
-
40
- # Handle Ctrl+C
41
- elif char == b'\x03': # Ctrl+C
42
- print()
43
- raise KeyboardInterrupt
44
-
45
- # Handle printable characters (ASCII)
46
- elif 32 <= ord(char) <= 126: # Printable ASCII range
47
- password.append(char.decode('ascii'))
48
- print('*', end='', flush=True)
49
-
50
- # Handle extended characters
51
- else:
52
- try:
53
- decoded_char = char.decode('utf-8')
54
- if decoded_char.isprintable():
55
- password.append(decoded_char)
56
- print('*', end='', flush=True)
57
- except UnicodeDecodeError:
58
- continue
59
- else:
60
- # Unix/macOS: Use tty and termios
61
- fd = sys.stdin.fileno()
62
- old_settings = termios.tcgetattr(fd)
63
- try:
64
- tty.setraw(fd)
65
- while True:
66
- char = sys.stdin.read(1)
67
-
68
- # Handle Enter key
69
- if char in ['\r', '\n']:
70
- print('\r\n', end='', flush=True)
71
- break
72
-
73
- # Handle Backspace
74
- elif char in ['\x7f', '\x08']:
75
- if password:
76
- password.pop()
77
- print('\b \b', end='', flush=True)
78
-
79
- # Handle Ctrl+C
80
- elif char == '\x03':
81
- print('\r\n', end='', flush=True)
82
- raise KeyboardInterrupt
83
-
84
- # Handle printable characters
85
- elif char.isprintable():
86
- password.append(char)
87
- print('*', end='', flush=True)
88
- finally:
89
- termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
90
-
91
- except Exception as e:
92
- # Fallback to getpass
93
- print(f"\nError reading password: {e}")
94
- print("Falling back to getpass...")
95
- return getpass.getpass()
96
-
97
- return ''.join(password)
98
-
99
- def login(account_choice=None):
100
- """Login to WorldQuant Brain API"""
101
- s = requests.Session()
102
-
103
- # Prompt user for credentials
104
- print("\n=== WorldQuant Brain Login ===")
105
- email = input("Enter your email: ").strip()
106
-
107
- # Use custom password input with asterisk masking
108
- try:
109
- password = input_with_asterisks("Enter your password: ")
110
- if not password:
111
- print("❌ Password is required.")
112
- return None
113
- except Exception as e:
114
- print(f"❌ Error with custom password input: {e}")
115
- print("Trying standard getpass...")
116
- try:
117
- password = getpass.getpass("Enter your password: ")
118
- if not password:
119
- print("❌ Password is required.")
120
- return None
121
- except Exception as e2:
122
- print(f"❌ Error reading password: {e2}")
123
- return None
124
-
125
- if not email:
126
- print("❌ Email is required.")
127
- return None
128
-
129
- print(f"Logging in with: {email}")
130
-
131
- # Set basic auth
132
- s.auth = (email, password)
133
-
134
- try:
135
- # Send authentication request
136
- response = s.post('https://api.worldquantbrain.com/authentication')
137
- print(f"Login response status: {response.status_code}")
138
- print(f"Login response headers: {dict(response.headers)}")
139
-
140
- if response.text:
141
- try:
142
- response_json = response.json()
143
- print(f"Login response body: {json.dumps(response_json, indent=2)}")
144
- except json.JSONDecodeError:
145
- print(f"Login response body (not JSON): {response.text}")
146
-
147
- response.raise_for_status()
148
- print("Login successful!")
149
- return s
150
- except requests.exceptions.RequestException as e:
151
- print(f"Login failed: {e}")
152
- if hasattr(e, 'response') and e.response is not None:
153
- print(f"Error response status: {e.response.status_code}")
154
- print(f"Error response body: {e.response.text}")
155
- return None
156
-
157
- def check_alpha_exists(s, alpha_id):
158
- """Check if an alpha exists by making a GET request to /alphas/<alpha_id>"""
159
- try:
160
- response = s.get(f"https://api.worldquantbrain.com/alphas/{alpha_id}")
161
- print(f"Alpha check response status: {response.status_code}")
162
- print(f"Alpha check response headers: {dict(response.headers)}")
163
-
164
- if response.status_code == 200:
165
- alpha_data = response.json()
166
- print(f"✅ Alpha {alpha_id} exists - Type: {alpha_data.get('type', 'Unknown')}")
167
- print(f"Alpha data: {json.dumps(alpha_data, indent=2)}")
168
- return True, alpha_data
169
- elif response.status_code == 404:
170
- print(f"❌ Alpha {alpha_id} does not exist (404 Not Found)")
171
- if response.text:
172
- print(f"404 response body: {response.text}")
173
- return False, None
174
- else:
175
- print(f"⚠️ Unexpected response for alpha {alpha_id}: {response.status_code}")
176
- if response.text:
177
- print(f"Unexpected response body: {response.text}")
178
- return False, None
179
- except requests.exceptions.RequestException as e:
180
- print(f"❌ Error checking alpha {alpha_id}: {e}")
181
- if hasattr(e, 'response') and e.response is not None:
182
- print(f"Error response status: {e.response.status_code}")
183
- print(f"Error response body: {e.response.text}")
184
- return False, None
185
-
186
- def get_alpha_recordsets(s, alpha_id):
187
- """Get available record sets for an alpha"""
188
- try:
189
- response = s.get(f"https://api.worldquantbrain.com/alphas/{alpha_id}/recordsets")
190
- print(f"Recordsets response status: {response.status_code}")
191
- print(f"Recordsets response headers: {dict(response.headers)}")
192
-
193
- if response.status_code == 200:
194
- recordsets_data = response.json()
195
- print(f"📊 Alpha {alpha_id} has {recordsets_data.get('count', 0)} record sets available")
196
- print(f"Recordsets data: {json.dumps(recordsets_data, indent=2)}")
197
- return recordsets_data
198
- else:
199
- print(f"⚠️ Could not fetch record sets for alpha {alpha_id}: {response.status_code}")
200
- if response.text:
201
- print(f"Recordsets error response body: {response.text}")
202
- return None
203
- except requests.exceptions.RequestException as e:
204
- print(f"❌ Error fetching record sets for alpha {alpha_id}: {e}")
205
- if hasattr(e, 'response') and e.response is not None:
206
- print(f"Error response status: {e.response.status_code}")
207
- print(f"Error response body: {e.response.text}")
208
- return None
209
-
210
- def submit(s, alpha_id):
211
- """Submit a single alpha with retry logic - keeps trying until success"""
212
-
213
- def submit_inner(s, alpha_id):
214
- """Inner submit function with rate limiting handling"""
215
- try:
216
- result = s.post(f"https://api.worldquantbrain.com/alphas/{alpha_id}/submit")
217
- print(f"Alpha submit, alpha_id={alpha_id}, status_code={result.status_code}")
218
- print(f"Response headers: {dict(result.headers)}")
219
-
220
- # Handle rate limiting
221
- while True:
222
- if "retry-after" in result.headers:
223
- wait_time = float(result.headers["Retry-After"])
224
- print(f"Rate limited, waiting {wait_time} seconds...")
225
- time.sleep(wait_time)
226
- result = s.get(f"https://api.worldquantbrain.com/alphas/{alpha_id}/submit")
227
- print(f"Retry GET response, status_code={result.status_code}")
228
- print(f"Retry headers: {dict(result.headers)}")
229
- else:
230
- break
231
-
232
- return result
233
- except Exception as e:
234
- print(f'Connection error: {e}, attempting to re-login...')
235
- new_session = login()
236
- if new_session is None:
237
- return None
238
- return submit_inner(new_session, alpha_id)
239
-
240
- attempt_count = 1
241
- result = None
242
-
243
- while True:
244
- print(f"Submit attempt {attempt_count} for alpha {alpha_id}")
245
- result = submit_inner(s, alpha_id)
246
-
247
- if result is None:
248
- print(f"Failed to submit {alpha_id} - connection error")
249
- return None
250
-
251
- if result.status_code == 200:
252
- print(f"✅ Alpha {alpha_id} submit successful, status_code={result.status_code}")
253
- return result
254
- elif result.status_code == 403:
255
- print(f"❌ Alpha {alpha_id} submit forbidden, status_code={result.status_code}")
256
- return result
257
- else:
258
- print(f"⚠️ Alpha submit fail, status_code={result.status_code}, alpha_id={alpha_id}, attempt {attempt_count}")
259
- print(f"Waiting 2 minutes before retry...")
260
- time.sleep(120) # 2 minutes = 120 seconds
261
- attempt_count += 1
262
- continue
263
-
264
- def submit_alpha(alpha_id, session=None, account_choice=None):
265
- """Submit a single alpha with comprehensive error handling"""
266
- if session is None:
267
- s = login(account_choice)
268
- if s is None:
269
- return False
270
- else:
271
- s = session
272
-
273
- # First check if the alpha exists
274
- print(f"Checking if alpha {alpha_id} exists...")
275
- exists, alpha_data = check_alpha_exists(s, alpha_id)
276
- if not exists:
277
- print(f"❌ Cannot submit alpha {alpha_id} - it does not exist")
278
- return False
279
-
280
- # Submit the alpha
281
- res = submit(s, alpha_id)
282
-
283
- if res is None:
284
- print(f"Failed to submit {alpha_id} - connection error")
285
- return False
286
-
287
- # Parse response
288
- if res.text:
289
- try:
290
- res_json = res.json()
291
- print(f"Submit response parsed successfully")
292
- except json.JSONDecodeError:
293
- print(f"Submit response is not JSON: {res.text[:200]}...")
294
- return False
295
- else:
296
- print(f"Submit response has no text content")
297
- return False
298
-
299
- # Check for various error conditions
300
- if 'detail' in res_json and res_json['detail'] == 'Not found.':
301
- print(f"{alpha_id} - Alpha ID not found")
302
- return False
303
-
304
- # Check submission status
305
- submitted = True
306
- if 'is' in res_json and 'checks' in res_json['is']:
307
- for item in res_json['is']['checks']:
308
- if item['name'] == 'ALREADY_SUBMITTED':
309
- submitted = False
310
- print(f"{alpha_id} - Already submitted")
311
- break
312
- if item['result'] == 'FAIL':
313
- submitted = False
314
- print(f"{alpha_id} - {item['name']} check failed, limit = {item['limit']}, value = {item['value']}")
315
- break
316
-
317
- if submitted:
318
- print(f'{alpha_id} - Submission successful!')
319
- return True
320
- else:
321
- return False
322
-
323
- def main():
324
- """Main function to run the alpha submission script"""
325
- print("=== WorldQuant Brain Alpha Submitter ===")
326
- print("This script will help you submit alphas with automatic retry logic.")
327
- print("You will be prompted to enter your WorldQuant Brain credentials.\n")
328
-
329
- # Login with user credentials
330
- session = login()
331
- if session is None:
332
- print("Failed to login. Exiting.")
333
- return
334
-
335
- print("\n=== Alpha Submission Mode ===")
336
- print("Enter alpha IDs one by one. Type 'quit' to exit.")
337
- print("Type 'relogin' to login with different credentials.")
338
- print("Type 'info <alpha_id>' to check alpha details before submitting.")
339
-
340
- while True:
341
- alpha_id = input("\nEnter alpha ID (or 'quit' to exit, 'relogin' to change credentials): ").strip()
342
-
343
- if alpha_id.lower() == 'quit':
344
- print("Goodbye!")
345
- break
346
-
347
- if alpha_id.lower() == 'relogin':
348
- print("\nRe-logging in...")
349
- session = login()
350
- if session is None:
351
- print("Failed to login. Exiting.")
352
- return
353
- continue
354
-
355
- if alpha_id.lower().startswith('info '):
356
- info_alpha_id = alpha_id[5:].strip()
357
- if not info_alpha_id:
358
- print("Please provide an alpha ID after 'info'")
359
- continue
360
-
361
- print(f"\nChecking details for alpha: {info_alpha_id}")
362
- print("=" * 50)
363
-
364
- # Check if alpha exists
365
- exists, alpha_data = check_alpha_exists(session, info_alpha_id)
366
- if exists:
367
- # Get record sets
368
- get_alpha_recordsets(session, info_alpha_id)
369
-
370
- # Show some basic alpha info
371
- if alpha_data:
372
- print(f"📋 Alpha Details:")
373
- print(f" ID: {alpha_data.get('id', 'N/A')}")
374
- print(f" Type: {alpha_data.get('type', 'N/A')}")
375
- if 'settings' in alpha_data:
376
- print(f" Has settings: Yes")
377
- if 'regular' in alpha_data:
378
- print(f" Has regular data: Yes")
379
- if 'combo' in alpha_data:
380
- print(f" Has combo data: Yes")
381
- if 'selection' in alpha_data:
382
- print(f" Has selection data: Yes")
383
-
384
- print("=" * 50)
385
- continue
386
-
387
- if not alpha_id:
388
- print("Please enter a valid alpha ID.")
389
- continue
390
-
391
- print(f"\nSubmitting alpha: {alpha_id}")
392
- print("=" * 50)
393
-
394
- success = submit_alpha(alpha_id, session)
395
-
396
- if success:
397
- print(f"✅ Alpha {alpha_id} processed successfully!")
398
- else:
399
- print(f"❌ Alpha {alpha_id} failed to submit properly.")
400
-
401
- print("=" * 50)
402
-
403
- if __name__ == "__main__":
404
- main()