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.
- {cnhkmcp-2.1.1.dist-info → cnhkmcp-2.1.3.dist-info}/METADATA +1 -1
- cnhkmcp-2.1.3.dist-info/RECORD +6 -0
- cnhkmcp-2.1.3.dist-info/top_level.txt +1 -0
- cnhkmcp/__init__.py +0 -125
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- cnhkmcp/untracked/APP/.gitignore +0 -32
- cnhkmcp/untracked/APP/MODULAR_STRUCTURE.md +0 -112
- cnhkmcp/untracked/APP/README.md +0 -309
- cnhkmcp/untracked/APP/Tranformer/Transformer.py +0 -4985
- cnhkmcp/untracked/APP/Tranformer/ace.log +0 -0
- cnhkmcp/untracked/APP/Tranformer/ace_lib.py +0 -1510
- cnhkmcp/untracked/APP/Tranformer/helpful_functions.py +0 -180
- cnhkmcp/untracked/APP/Tranformer/output/Alpha_candidates.json +0 -2421
- cnhkmcp/untracked/APP/Tranformer/output/Alpha_candidates_/321/207/320/264/342/225/221/321/204/342/225/233/320/233.json +0 -654
- cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_error.json +0 -1034
- cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_success.json +0 -444
- 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
- cnhkmcp/untracked/APP/Tranformer/parsetab.py +0 -60
- cnhkmcp/untracked/APP/Tranformer/template_summary.txt +0 -3182
- cnhkmcp/untracked/APP/Tranformer/transformer_config.json +0 -7
- cnhkmcp/untracked/APP/Tranformer/validator.py +0 -889
- cnhkmcp/untracked/APP/ace.log +0 -69
- cnhkmcp/untracked/APP/ace_lib.py +0 -1510
- cnhkmcp/untracked/APP/blueprints/__init__.py +0 -6
- cnhkmcp/untracked/APP/blueprints/feature_engineering.py +0 -347
- cnhkmcp/untracked/APP/blueprints/idea_house.py +0 -221
- cnhkmcp/untracked/APP/blueprints/inspiration_house.py +0 -432
- cnhkmcp/untracked/APP/blueprints/paper_analysis.py +0 -570
- cnhkmcp/untracked/APP/custom_templates/templates.json +0 -1257
- cnhkmcp/untracked/APP/give_me_idea/BRAIN_Alpha_Template_Expert_SystemPrompt.md +0 -400
- cnhkmcp/untracked/APP/give_me_idea/ace_lib.py +0 -1510
- cnhkmcp/untracked/APP/give_me_idea/alpha_data_specific_template_master.py +0 -252
- cnhkmcp/untracked/APP/give_me_idea/fetch_all_datasets.py +0 -157
- cnhkmcp/untracked/APP/give_me_idea/fetch_all_operators.py +0 -99
- cnhkmcp/untracked/APP/give_me_idea/helpful_functions.py +0 -180
- cnhkmcp/untracked/APP/give_me_idea/what_is_Alpha_template.md +0 -11
- cnhkmcp/untracked/APP/helpful_functions.py +0 -180
- cnhkmcp/untracked/APP/hkSimulator/ace_lib.py +0 -1497
- cnhkmcp/untracked/APP/hkSimulator/autosimulator.py +0 -447
- cnhkmcp/untracked/APP/hkSimulator/helpful_functions.py +0 -180
- cnhkmcp/untracked/APP/mirror_config.txt +0 -20
- cnhkmcp/untracked/APP/operaters.csv +0 -129
- cnhkmcp/untracked/APP/requirements.txt +0 -53
- cnhkmcp/untracked/APP/run_app.bat +0 -28
- cnhkmcp/untracked/APP/run_app.sh +0 -34
- cnhkmcp/untracked/APP/setup_tsinghua.bat +0 -39
- cnhkmcp/untracked/APP/setup_tsinghua.sh +0 -43
- cnhkmcp/untracked/APP/simulator/alpha_submitter.py +0 -404
- cnhkmcp/untracked/APP/simulator/simulator_wqb.py +0 -618
- cnhkmcp/untracked/APP/ssrn-3332513.pdf +6 -109201
- cnhkmcp/untracked/APP/static/brain.js +0 -589
- cnhkmcp/untracked/APP/static/decoder.js +0 -1540
- cnhkmcp/untracked/APP/static/feature_engineering.js +0 -1729
- cnhkmcp/untracked/APP/static/idea_house.js +0 -937
- cnhkmcp/untracked/APP/static/inspiration.js +0 -465
- cnhkmcp/untracked/APP/static/inspiration_house.js +0 -868
- cnhkmcp/untracked/APP/static/paper_analysis.js +0 -390
- cnhkmcp/untracked/APP/static/script.js +0 -3082
- cnhkmcp/untracked/APP/static/simulator.js +0 -597
- cnhkmcp/untracked/APP/static/styles.css +0 -3127
- cnhkmcp/untracked/APP/static/usage_widget.js +0 -508
- cnhkmcp/untracked/APP/templates/alpha_inspector.html +0 -511
- cnhkmcp/untracked/APP/templates/feature_engineering.html +0 -960
- cnhkmcp/untracked/APP/templates/idea_house.html +0 -564
- cnhkmcp/untracked/APP/templates/index.html +0 -932
- cnhkmcp/untracked/APP/templates/inspiration_house.html +0 -861
- cnhkmcp/untracked/APP/templates/paper_analysis.html +0 -91
- cnhkmcp/untracked/APP/templates/simulator.html +0 -343
- cnhkmcp/untracked/APP/templates/transformer_web.html +0 -580
- cnhkmcp/untracked/APP/usage.md +0 -351
- 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
- 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
- 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
- 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
- cnhkmcp/untracked/arXiv_API_Tool_Manual.md +0 -490
- cnhkmcp/untracked/arxiv_api.py +0 -229
- cnhkmcp/untracked/forum_functions.py +0 -998
- 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
- 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
- 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
- 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
- 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
- cnhkmcp/untracked/platform_functions.py +0 -2886
- cnhkmcp/untracked/sample_mcp_config.json +0 -11
- cnhkmcp/untracked/user_config.json +0 -31
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- cnhkmcp-2.1.1.dist-info/RECORD +0 -115
- cnhkmcp-2.1.1.dist-info/top_level.txt +0 -1
- {cnhkmcp-2.1.1.dist-info → cnhkmcp-2.1.3.dist-info}/WHEEL +0 -0
- {cnhkmcp-2.1.1.dist-info → cnhkmcp-2.1.3.dist-info}/entry_points.txt +0 -0
- {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()
|