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