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,157 +0,0 @@
1
- import getpass
2
- import json
3
- import os
4
- import sys
5
- from typing import List
6
-
7
- import pandas as pd
8
-
9
- # Ensure we can import ace_lib from the project root
10
- SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
11
- ROOT_DIR = os.path.dirname(SCRIPT_DIR)
12
- if ROOT_DIR not in sys.path:
13
- sys.path.append(ROOT_DIR)
14
-
15
- import ace_lib # noqa: E402
16
-
17
-
18
- def prompt_credentials() -> tuple[str, str]:
19
- """Prompt user for platform credentials."""
20
- email = input("Enter BRAIN Email: ").strip()
21
- while not email:
22
- email = input("Email is required. Enter BRAIN Email: ").strip()
23
-
24
- password = getpass.getpass("Enter BRAIN Password: ").strip()
25
- while not password:
26
- password = getpass.getpass("Password is required. Enter BRAIN Password: ").strip()
27
-
28
- return email, password
29
-
30
-
31
- def fetch_all_combinations(session: ace_lib.SingleSession) -> pd.DataFrame:
32
- """Return all valid instrument/region/delay/universe combos from platform settings."""
33
- options_df = ace_lib.get_instrument_type_region_delay(session)
34
- if options_df is None or options_df.empty:
35
- raise RuntimeError("No simulation options fetched; cannot enumerate datasets.")
36
- return options_df
37
-
38
-
39
- def fetch_datasets_for_combo(
40
- session: ace_lib.SingleSession,
41
- instrument_type: str,
42
- region: str,
43
- delay: int,
44
- universe: str,
45
- ) -> pd.DataFrame:
46
- """Fetch datasets for one combination (theme ALL to include both theme true/false)."""
47
- df = ace_lib.get_datasets(
48
- session,
49
- instrument_type=instrument_type,
50
- region=region,
51
- delay=delay,
52
- universe=universe,
53
- theme="ALL",
54
- )
55
- if df is None:
56
- return pd.DataFrame()
57
-
58
- df = df.copy()
59
- df["param_instrument_type"] = instrument_type
60
- df["param_region"] = region
61
- df["param_delay"] = delay
62
- df["param_universe"] = universe
63
- df["combo_key"] = df.apply(
64
- lambda row: f"{instrument_type}-{region}-D{delay}-{universe}",
65
- axis=1,
66
- )
67
- return df
68
-
69
-
70
- def merge_and_deduplicate(datasets: List[pd.DataFrame]) -> pd.DataFrame:
71
- """Merge fetched datasets and deduplicate by dataset id, keeping all combo metadata."""
72
- combined = pd.concat([df for df in datasets if not df.empty], ignore_index=True)
73
- if combined.empty:
74
- return combined
75
-
76
- # Aggregate availability combos per dataset id
77
- availability = (
78
- combined.groupby("id")["combo_key"]
79
- .agg(lambda x: " | ".join(sorted(set(x))))
80
- .rename("available_in")
81
- .reset_index()
82
- )
83
-
84
- # Drop duplicate rows by dataset id, keep first occurrence of other columns
85
- unique_df = combined.drop_duplicates(subset=["id"]).copy()
86
- unique_df = unique_df.merge(availability, on="id", how="left")
87
-
88
- # Sort for readability
89
- sort_cols = [col for col in ["category", "subcategory", "id"] if col in unique_df.columns]
90
- if sort_cols:
91
- # Ensure sort keys are hashable/strings to avoid unhashable dict errors
92
- for col in sort_cols:
93
- unique_df[col] = unique_df[col].apply(
94
- lambda v: v
95
- if pd.isna(v) or isinstance(v, (int, float, str, bool))
96
- else json.dumps(v, ensure_ascii=False, sort_keys=True)
97
- )
98
- unique_df = unique_df.sort_values(sort_cols).reset_index(drop=True)
99
-
100
- return unique_df
101
-
102
-
103
- def main():
104
- print("=== Fetch All BRAIN Datasets (all regions/universes/delays) ===")
105
-
106
- email, password = prompt_credentials()
107
-
108
- # Monkey-patch ace_lib credential retrieval so start_session uses provided credentials
109
- ace_lib.get_credentials = lambda: (email, password)
110
-
111
- print("Logging in...")
112
- try:
113
- session = ace_lib.start_session()
114
- print("Login successful.")
115
- except Exception as exc:
116
- print(f"Login failed: {exc}")
117
- return
118
-
119
- print("Fetching valid instrument/region/delay/universe combinations from platform settings...")
120
- try:
121
- options_df = fetch_all_combinations(session)
122
- except Exception as exc:
123
- print(f"Failed to fetch simulation options: {exc}")
124
- return
125
-
126
- all_datasets: List[pd.DataFrame] = []
127
- total_combos = 0
128
-
129
- for _, row in options_df.iterrows():
130
- instrument_type = row.get("InstrumentType")
131
- region = row.get("Region")
132
- delay = row.get("Delay")
133
- universes = row.get("Universe") or []
134
-
135
- for universe in universes:
136
- total_combos += 1
137
- print(f"[{total_combos}] Fetching datasets for {instrument_type} / {region} / D{delay} / {universe}...")
138
- try:
139
- df = fetch_datasets_for_combo(session, instrument_type, region, delay, universe)
140
- print(f" -> Retrieved {len(df)} rows")
141
- all_datasets.append(df)
142
- except Exception as exc:
143
- print(f" -> Failed for {instrument_type}-{region}-D{delay}-{universe}: {exc}")
144
-
145
- result_df = merge_and_deduplicate(all_datasets)
146
-
147
- if result_df.empty:
148
- print("No datasets fetched; nothing to save.")
149
- return
150
-
151
- output_path = os.path.join(SCRIPT_DIR, "all_datasets_full.csv")
152
- result_df.to_csv(output_path, index=False)
153
- print(f"Saved {len(result_df)} unique datasets to {output_path}")
154
-
155
-
156
- if __name__ == "__main__":
157
- main()
@@ -1,132 +0,0 @@
1
- """Minimal helper script to log in, list tutorials, and dump each tutorial page.
2
-
3
- - Prompts for email/password at runtime (keeps credentials out of source).
4
- - Uses only the requests standard stack; no project-internal imports.
5
- - Saves each page JSON to tutorial_dump/<index>_<page_id>.json for inspection.
6
-
7
- Run with: python doc_fetch_sample.py
8
- """
9
- import base64
10
- import getpass
11
- import json
12
- import os
13
- from typing import Any, Dict, Iterable, List, Optional
14
-
15
- import requests
16
-
17
- BASE_URL = "https://api.worldquantbrain.com"
18
-
19
-
20
- def _basic_auth_header(email: str, password: str) -> Dict[str, str]:
21
- token = base64.b64encode(f"{email}:{password}".encode()).decode()
22
- return {"Authorization": f"Basic {token}"}
23
-
24
-
25
- def authenticate(email: str, password: str) -> requests.Session:
26
- """Authenticate and return a session carrying the JWT cookie."""
27
- session = requests.Session()
28
- resp = session.post(f"{BASE_URL}/authentication", headers=_basic_auth_header(email, password), timeout=30)
29
- if resp.status_code != 201:
30
- raise RuntimeError(f"Authentication failed (status {resp.status_code}): {resp.text}")
31
- return session
32
-
33
-
34
- def fetch_tutorials(session: requests.Session) -> List[Dict[str, Any]]:
35
- """Fetch tutorials list; handle a few common response shapes."""
36
- resp = session.get(f"{BASE_URL}/tutorials", timeout=30)
37
- resp.raise_for_status()
38
- data = resp.json()
39
- if isinstance(data, list):
40
- return data
41
- if isinstance(data, dict):
42
- for key in ("items", "results", "data", "tutorials"):
43
- maybe = data.get(key)
44
- if isinstance(maybe, list):
45
- return maybe
46
- return []
47
-
48
-
49
- def fetch_tutorial_pages(session: requests.Session, tutorial_id: str) -> List[Dict[str, Any]]:
50
- """Fetch pages for a tutorial when the list entry only gives a tutorial id/slug."""
51
- resp = session.get(f"{BASE_URL}/tutorials/{tutorial_id}/pages", timeout=30)
52
- if resp.status_code == 404:
53
- return [] # graceful fallback
54
- resp.raise_for_status()
55
- data = resp.json()
56
- if isinstance(data, list):
57
- return data
58
- if isinstance(data, dict):
59
- for key in ("items", "results", "pages", "data"):
60
- maybe = data.get(key)
61
- if isinstance(maybe, list):
62
- return maybe
63
- return []
64
-
65
-
66
- def _extract_page_id(entry: Dict[str, Any]) -> Optional[str]:
67
- for key in ("page_id", "pageId", "id", "pageID", "slug", "code"):
68
- if key in entry and entry[key] is not None:
69
- return str(entry[key])
70
- return None
71
-
72
-
73
- def fetch_page(session: requests.Session, page_id: str) -> Dict[str, Any]:
74
- resp = session.get(f"{BASE_URL}/tutorial-pages/{page_id}", timeout=30)
75
- resp.raise_for_status()
76
- return resp.json()
77
-
78
-
79
- def dump_pages(session: requests.Session, tutorials: List[Dict[str, Any]], out_dir: str = "tutorial_dump") -> None:
80
- os.makedirs(out_dir, exist_ok=True)
81
-
82
- # Save raw tutorials list for inspection
83
- with open(os.path.join(out_dir, "tutorials_raw.json"), "w", encoding="utf-8") as f:
84
- json.dump(tutorials, f, ensure_ascii=False, indent=2)
85
-
86
- def _iter_page_candidates(item: Dict[str, Any]) -> Iterable[Dict[str, Any]]:
87
- # If the tutorial entry already has pages array, yield them
88
- if isinstance(item.get("pages"), list):
89
- for p in item["pages"]:
90
- yield p
91
- # Else, try fetching pages via tutorial id/slug
92
- tutorial_id = _extract_page_id(item)
93
- if tutorial_id:
94
- pages = fetch_tutorial_pages(session, tutorial_id)
95
- for p in pages:
96
- yield p
97
- # Lastly, treat the tutorial itself as a single page if it has an id/slug
98
- if tutorial_id:
99
- yield {"id": tutorial_id, "title": item.get("title")}
100
-
101
- seen = 0
102
- for idx, item in enumerate(tutorials, start=1):
103
- for page_entry in _iter_page_candidates(item):
104
- page_id = _extract_page_id(page_entry)
105
- if not page_id:
106
- print(f"[{idx:03d}] skipped page (no id): {page_entry}")
107
- continue
108
- try:
109
- page = fetch_page(session, page_id)
110
- except requests.HTTPError as e:
111
- print(f"[{idx:03d}] page {page_id} -> HTTP {e.response.status_code} ({page_entry})")
112
- continue
113
- seen += 1
114
- title = page.get("title") or page_entry.get("title") or item.get("title") or f"page_{page_id}"
115
- out_path = os.path.join(out_dir, f"{idx:03d}_{seen:02d}_{page_id}.json")
116
- with open(out_path, "w", encoding="utf-8") as f:
117
- json.dump(page, f, ensure_ascii=False, indent=2)
118
- snippet = page.get("code") or page.get("content") or str(page)[:120]
119
- print(f"[{idx:03d}] saved {title} -> {out_path}; sample: {str(snippet)[:80]}")
120
-
121
-
122
- def main() -> None:
123
- email = input("BRAIN email: ").strip()
124
- password = getpass.getpass("BRAIN password: ")
125
- session = authenticate(email, password)
126
- tutorials = fetch_tutorials(session)
127
- print(f"Fetched {len(tutorials)} tutorials")
128
- dump_pages(session, tutorials)
129
-
130
-
131
- if __name__ == "__main__":
132
- main()
@@ -1,99 +0,0 @@
1
- import getpass
2
- import os
3
- import sys
4
- from typing import List
5
-
6
- import pandas as pd
7
-
8
- # Make ace_lib importable
9
- SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
10
- ROOT_DIR = os.path.dirname(SCRIPT_DIR)
11
- if ROOT_DIR not in sys.path:
12
- sys.path.append(ROOT_DIR)
13
-
14
- import ace_lib # noqa: E402
15
-
16
-
17
- def prompt_credentials() -> tuple[str, str]:
18
- email = input("Enter BRAIN Email: ").strip()
19
- while not email:
20
- email = input("Email is required. Enter BRAIN Email: ").strip()
21
-
22
- password = getpass.getpass("Enter BRAIN Password: ").strip()
23
- while not password:
24
- password = getpass.getpass("Password is required. Enter BRAIN Password: ").strip()
25
-
26
- return email, password
27
-
28
-
29
- def fetch_operators(session: ace_lib.SingleSession) -> pd.DataFrame:
30
- df = ace_lib.get_operators(session)
31
- if df is None or df.empty:
32
- return pd.DataFrame()
33
-
34
- df = df.copy()
35
-
36
- # Choose an identifier column robustly
37
- id_col = "id" if "id" in df.columns else None
38
- if id_col is None:
39
- if "name" in df.columns:
40
- id_col = "name"
41
- else:
42
- id_col = "_row_id"
43
- df[id_col] = df.index
44
-
45
- # Re-aggregate scopes so each operator id is unique
46
- if "scope" in df.columns:
47
- scope_map = (
48
- df.groupby(id_col)["scope"]
49
- .agg(lambda x: sorted(set([item for item in x if pd.notna(item)])))
50
- .rename("scopes")
51
- .reset_index()
52
- )
53
- else:
54
- scope_map = pd.DataFrame({id_col: df[id_col].unique(), "scopes": [[] for _ in range(df[id_col].nunique())]})
55
-
56
- unique_df = df.drop(columns=["scope"], errors="ignore").drop_duplicates(subset=[id_col]).merge(
57
- scope_map, on=id_col, how="left"
58
- )
59
-
60
- # Sort for readability
61
- sort_cols: List[str] = [col for col in ["category", "subcategory", "name", id_col] if col in unique_df.columns]
62
- if sort_cols:
63
- unique_df = unique_df.sort_values(sort_cols).reset_index(drop=True)
64
-
65
- return unique_df
66
-
67
-
68
- def main():
69
- print("=== Fetch All BRAIN Operators ===")
70
-
71
- email, password = prompt_credentials()
72
- ace_lib.get_credentials = lambda: (email, password)
73
-
74
- print("Logging in...")
75
- try:
76
- session = ace_lib.start_session()
77
- print("Login successful.")
78
- except Exception as exc:
79
- print(f"Login failed: {exc}")
80
- return
81
-
82
- print("Fetching operators...")
83
- try:
84
- operators_df = fetch_operators(session)
85
- except Exception as exc:
86
- print(f"Failed to fetch operators: {exc}")
87
- return
88
-
89
- if operators_df.empty:
90
- print("No operators returned; nothing to save.")
91
- return
92
-
93
- output_path = os.path.join(SCRIPT_DIR, "all_operators.csv")
94
- operators_df.to_csv(output_path, index=False)
95
- print(f"Saved {len(operators_df)} operators to {output_path}")
96
-
97
-
98
- if __name__ == "__main__":
99
- main()
@@ -1,180 +0,0 @@
1
- import json
2
- import os
3
- from typing import Union
4
-
5
- import pandas as pd
6
- from pandas.io.formats.style import Styler
7
-
8
- brain_api_url = os.environ.get("BRAIN_API_URL", "https://api.worldquantbrain.com")
9
- brain_url = os.environ.get("BRAIN_URL", "https://platform.worldquantbrain.com")
10
-
11
-
12
- def make_clickable_alpha_id(alpha_id: str) -> str:
13
- """
14
- Create a clickable HTML link for an alpha ID.
15
-
16
- Args:
17
- alpha_id (str): The ID of the alpha.
18
-
19
- Returns:
20
- str: An HTML string containing a clickable link to the alpha's page on the platform.
21
- """
22
-
23
- url = brain_url + "/alpha/"
24
- return f'<a href="{url}{alpha_id}">{alpha_id}</a>'
25
-
26
-
27
- def prettify_result(
28
- result: list, detailed_tests_view: bool = False, clickable_alpha_id: bool = False
29
- ) -> Union[pd.DataFrame, Styler]:
30
- """
31
- Combine and format simulation results into a single DataFrame for analysis.
32
-
33
- Args:
34
- result (list): A list of dictionaries containing simulation results.
35
- detailed_tests_view (bool, optional): If True, include detailed test results. Defaults to False.
36
- clickable_alpha_id (bool, optional): If True, make alpha IDs clickable. Defaults to False.
37
-
38
- Returns:
39
- pandas.DataFrame or pandas.io.formats.style.Styler: A DataFrame containing formatted results,
40
- optionally with clickable alpha IDs.
41
- """
42
- list_of_is_stats = [result[x]["is_stats"] for x in range(len(result)) if result[x]["is_stats"] is not None]
43
- is_stats_df = pd.concat(list_of_is_stats).reset_index(drop=True)
44
- is_stats_df = is_stats_df.sort_values("fitness", ascending=False)
45
-
46
- expressions = {
47
- result[x]["alpha_id"]: (
48
- {
49
- "selection": result[x]["simulate_data"]["selection"],
50
- "combo": result[x]["simulate_data"]["combo"],
51
- }
52
- if result[x]["simulate_data"]["type"] == "SUPER"
53
- else result[x]["simulate_data"]["regular"]
54
- )
55
- for x in range(len(result))
56
- if result[x]["is_stats"] is not None
57
- }
58
- expression_df = pd.DataFrame(list(expressions.items()), columns=["alpha_id", "expression"])
59
-
60
- list_of_is_tests = [result[x]["is_tests"] for x in range(len(result)) if result[x]["is_tests"] is not None]
61
- is_tests_df = pd.concat(list_of_is_tests, sort=True).reset_index(drop=True)
62
- is_tests_df = is_tests_df[is_tests_df["result"] != "WARNING"]
63
- if detailed_tests_view:
64
- cols = ["limit", "result", "value"]
65
- is_tests_df["details"] = is_tests_df[cols].to_dict(orient="records")
66
- is_tests_df = is_tests_df.pivot(index="alpha_id", columns="name", values="details").reset_index()
67
- else:
68
- is_tests_df = is_tests_df.pivot(index="alpha_id", columns="name", values="result").reset_index()
69
-
70
- alpha_stats = pd.merge(is_stats_df, expression_df, on="alpha_id")
71
- alpha_stats = pd.merge(alpha_stats, is_tests_df, on="alpha_id")
72
- alpha_stats = alpha_stats.drop(columns=alpha_stats.columns[(alpha_stats == "PENDING").any()])
73
- alpha_stats.columns = alpha_stats.columns.str.replace("(?<=[a-z])(?=[A-Z])", "_", regex=True).str.lower()
74
- if clickable_alpha_id:
75
- return alpha_stats.style.format({"alpha_id": lambda x: make_clickable_alpha_id(str(x))})
76
- return alpha_stats
77
-
78
-
79
- def concat_pnl(result: list) -> pd.DataFrame:
80
- """
81
- Combine PnL results from multiple alphas into a single DataFrame.
82
-
83
- Args:
84
- result (list): A list of dictionaries containing simulation results with PnL data.
85
-
86
- Returns:
87
- pandas.DataFrame: A DataFrame containing combined PnL data for all alphas.
88
- """
89
- list_of_pnls = [result[x]["pnl"] for x in range(len(result)) if result[x]["pnl"] is not None]
90
- pnls_df = pd.concat(list_of_pnls).reset_index()
91
-
92
- return pnls_df
93
-
94
-
95
- def concat_is_tests(result: list) -> pd.DataFrame:
96
- """
97
- Combine in-sample test results from multiple alphas into a single DataFrame.
98
-
99
- Args:
100
- result (list): A list of dictionaries containing simulation results with in-sample test data.
101
-
102
- Returns:
103
- pandas.DataFrame: A DataFrame containing combined in-sample test results for all alphas.
104
- """
105
- is_tests_list = [result[x]["is_tests"] for x in range(len(result)) if result[x]["is_tests"] is not None]
106
- is_tests_df = pd.concat(is_tests_list, sort=True).reset_index(drop=True)
107
- return is_tests_df
108
-
109
-
110
- def save_simulation_result(result: dict) -> None:
111
- """
112
- Save the simulation result to a JSON file in the 'simulation_results' folder.
113
-
114
- Args:
115
- result (dict): A dictionary containing the simulation result for an alpha.
116
- """
117
-
118
- alpha_id = result["id"]
119
- region = result["settings"]["region"]
120
- folder_path = "simulation_results/"
121
- file_path = os.path.join(folder_path, f"{alpha_id}_{region}")
122
-
123
- os.makedirs(folder_path, exist_ok=True)
124
-
125
- with open(file_path, "w", encoding="utf-8") as file:
126
- json.dump(result, file)
127
-
128
-
129
- def save_pnl(pnl_df: pd.DataFrame, alpha_id: str, region: str) -> None:
130
- """
131
- Save the PnL data for an alpha to a CSV file in the 'alphas_pnl' folder.
132
-
133
- Args:
134
- pnl_df (pandas.DataFrame): The DataFrame containing PnL data.
135
- alpha_id (str): The ID of the alpha.
136
- region (str): The region for which the PnL data was generated.
137
- """
138
-
139
- folder_path = "alphas_pnl/"
140
- file_path = os.path.join(folder_path, f"{alpha_id}_{region}.csv")
141
- os.makedirs(folder_path, exist_ok=True)
142
-
143
- pnl_df.to_csv(file_path)
144
-
145
-
146
- def save_yearly_stats(yearly_stats: pd.DataFrame, alpha_id: str, region: str):
147
- """
148
- Save the yearly statistics for an alpha to a CSV file in the 'yearly_stats' folder.
149
-
150
- Args:
151
- yearly_stats (pandas.DataFrame): The DataFrame containing yearly statistics.
152
- alpha_id (str): The ID of the alpha.
153
- region (str): The region for which the statistics were generated.
154
- """
155
-
156
- folder_path = "yearly_stats/"
157
- file_path = os.path.join(folder_path, f"{alpha_id}_{region}.csv")
158
- os.makedirs(folder_path, exist_ok=True)
159
-
160
- yearly_stats.to_csv(file_path, index=False)
161
-
162
-
163
- def expand_dict_columns(data: pd.DataFrame) -> pd.DataFrame:
164
- """
165
- Expand dictionary columns in a DataFrame into separate columns.
166
-
167
- Args:
168
- data (pandas.DataFrame): The input DataFrame with dictionary columns.
169
-
170
- Returns:
171
- pandas.DataFrame: A new DataFrame with expanded columns.
172
- """
173
- dict_columns = list(filter(lambda x: isinstance(data[x].iloc[0], dict), data.columns))
174
- new_columns = pd.concat(
175
- [data[col].apply(pd.Series).rename(columns=lambda x: f"{col}_{x}") for col in dict_columns],
176
- axis=1,
177
- )
178
-
179
- data = pd.concat([data, new_columns], axis=1)
180
- return data
@@ -1 +0,0 @@
1
- 我们之间的暗号是”炸弹超人“我说炸弹的时候 你要回答超人