cnhkmcp 2.1.3__py3-none-any.whl → 2.1.5__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 (194) hide show
  1. cnhkmcp/__init__.py +126 -0
  2. 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 +38 -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/ace.log +0 -0
  4. 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 +6 -0
  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/get_knowledgeBase_tool/ace_lib.py +1514 -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/fetch_all_datasets.py +157 -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/get_knowledgeBase_tool/fetch_all_documentation.py +132 -0
  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/fetch_all_operators.py +99 -0
  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/helpful_functions.py +180 -0
  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/icon.ico +0 -0
  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/icon.png +0 -0
  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/knowledge/001_10_Steps_to_Start_on_BRAIN_documentation.json +14 -0
  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/knowledge/001_Intermediate_Pack_-_Improve_your_Alpha_2_2_documentation.json +174 -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/knowledge/001_Intermediate_Pack_-_Understand_Results_1_2_documentation.json +167 -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/001_Introduction_to_Alphas_documentation.json +145 -0
  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/knowledge/001_Introduction_to_BRAIN_Expression_Language_documentation.json +107 -0
  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/knowledge/001_WorldQuant_Challenge_documentation.json +56 -0
  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/knowledge/001__Read_this_First_-_Starter_Pack_documentation.json +404 -0
  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/knowledge/002_How_to_choose_the_Simulation_Settings_documentation.json +268 -0
  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/knowledge/002_Simulate_your_first_Alpha_documentation.json +88 -0
  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/knowledge/002__Alpha_Examples_for_Beginners_documentation.json +254 -0
  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/knowledge/002__Alpha_Examples_for_Bronze_Users_documentation.json +114 -0
  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/knowledge/002__Alpha_Examples_for_Silver_Users_documentation.json +79 -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/knowledge/002__How_BRAIN_works_documentation.json +184 -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/knowledge/003_Clear_these_tests_before_submitting_an_Alpha_documentation.json +388 -0
  26. 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/003_Parameters_in_the_Simulation_results_documentation.json +243 -0
  27. 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/004_Group_Data_Fields_documentation.json +69 -0
  28. 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/004_How_to_use_the_Data_Explorer_documentation.json +142 -0
  29. 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/004_Model77_dataset_documentation.json +14 -0
  30. 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/004_Sentiment1_dataset_documentation.json +14 -0
  31. 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/004_Understanding_Data_in_BRAIN_Key_Concepts_and_Tips_documentation.json +182 -0
  32. 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/004_Vector_Data_Fields_documentation.json +30 -0
  33. 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/005_Crowding_Risk-Neutralized_Alphas_documentation.json +64 -0
  34. 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/005_D0_documentation.json +66 -0
  35. 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/005_Double_Neutralization_documentation.json +53 -0
  36. 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/005_Fast_D1_Documentation_documentation.json +304 -0
  37. 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/005_Investability_Constrained_Metrics_documentation.json +129 -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/knowledge/005_Must-read_posts_How_to_improve_your_Alphas_documentation.json +14 -0
  39. 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/005_Neutralization_documentation.json +29 -0
  40. 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/005_RAM_Risk-Neutralized_Alphas_documentation.json +64 -0
  41. 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/005_Risk_Neutralization_Default_setting_documentation.json +75 -0
  42. 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/005_Risk_Neutralized_Alphas_documentation.json +171 -0
  43. 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/005_Statistical_Risk-Neutralized_Alphas_documentation.json +51 -0
  44. 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/006_EUR_TOP2500_Universe_documentation.json +35 -0
  45. 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/006_GLB_TOPDIV3000_Universe_documentation.json +48 -0
  46. 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/006_Getting_Started_China_Research_for_Consultants_Gold_documentation.json +142 -0
  47. 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/006_Getting_started_on_Illiquid_Universes_Gold_documentation.json +46 -0
  48. 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/006_Getting_started_with_USA_TOPSP500_universe_Gold_documentation.json +62 -0
  49. 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/006_Global_Alphas_Gold_documentation.json +66 -0
  50. 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/006_India_Alphas_documentation.json +35 -0
  51. 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/007_Consultant_Dos_and_Don_ts_documentation.json +35 -0
  52. 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/007_Consultant_Features_documentation.json +239 -0
  53. 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/007_Consultant_Simulation_Features_documentation.json +149 -0
  54. 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/007_Consultant_Submission_Tests_documentation.json +363 -0
  55. 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/007_Finding_Consultant_Alphas_documentation.json +333 -0
  56. 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/007_Power_Pool_Alphas_documentation.json +14 -0
  57. 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/007_Research_Advisory_Program_documentation.json +35 -0
  58. 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/007_Starting_Guide_for_Research_Consultants_documentation.json +14 -0
  59. 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/007_Visualization_Tool_documentation.json +99 -0
  60. 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/007_Your_Advisor_-_Kunqi_Jiang_documentation.json +53 -0
  61. 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/007__Brain_Genius_documentation.json +288 -0
  62. 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/007__Single_Dataset_Alphas_documentation.json +41 -0
  63. 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/008_Advisory_Theme_Calendar_documentation.json +14 -0
  64. 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/008_Multiplier_Rules_documentation.json +14 -0
  65. 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/008_Overview_of_Themes_documentation.json +14 -0
  66. 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/008_Theme_Calendar_documentation.json +14 -0
  67. 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/009_Combo_Expression_documentation.json +272 -0
  68. 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/009_Global_SuperAlphas_documentation.json +14 -0
  69. 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/009_Helpful_Tips_documentation.json +58 -0
  70. 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/009_Selection_Expression_documentation.json +1546 -0
  71. 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/009_SuperAlpha_Operators_documentation.json +890 -0
  72. 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/009_SuperAlpha_Results_documentation.json +83 -0
  73. 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/009_What_is_a_SuperAlpha_documentation.json +261 -0
  74. 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/010_BRAIN_API_documentation.json +515 -0
  75. 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/010_Documentation_for_ACE_API_Library_Gold_documentation.json +27 -0
  76. 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/010__Understanding_simulation_limits_documentation.json +210 -0
  77. 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/arithmetic_operators.json +209 -0
  78. 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/cross_sectional_operators.json +98 -0
  79. 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/group_operators.json +121 -0
  80. 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/logical_operators.json +145 -0
  81. 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/reduce_operators.json +156 -0
  82. 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/special_operators.json +35 -0
  83. 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 +1 -0
  84. 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/time_series_operators.json +386 -0
  85. 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/transformational_operators.json +61 -0
  86. 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/vector_operators.json +38 -0
  87. 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 +576 -0
  88. 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 +281 -0
  89. 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 +408 -0
  90. 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 +7 -0
  91. 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 +3 -0
  92. 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 +302 -0
  93. 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 +1 -0
  94. 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
  95. 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 +265 -0
  96. cnhkmcp/untracked/APP/.gitignore +32 -0
  97. cnhkmcp/untracked/APP/MODULAR_STRUCTURE.md +112 -0
  98. cnhkmcp/untracked/APP/README.md +309 -0
  99. cnhkmcp/untracked/APP/Tranformer/Transformer.py +4989 -0
  100. cnhkmcp/untracked/APP/Tranformer/ace.log +0 -0
  101. cnhkmcp/untracked/APP/Tranformer/ace_lib.py +1514 -0
  102. cnhkmcp/untracked/APP/Tranformer/helpful_functions.py +180 -0
  103. cnhkmcp/untracked/APP/Tranformer/output/Alpha_candidates.json +7187 -0
  104. cnhkmcp/untracked/APP/Tranformer/output/Alpha_candidates_/321/207/320/264/342/225/221/321/204/342/225/233/320/233.json +654 -0
  105. cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_error.json +1 -0
  106. cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_success.json +47312 -0
  107. 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 +22 -0
  108. cnhkmcp/untracked/APP/Tranformer/parsetab.py +60 -0
  109. cnhkmcp/untracked/APP/Tranformer/template_summary.txt +3182 -0
  110. cnhkmcp/untracked/APP/Tranformer/transformer_config.json +7 -0
  111. cnhkmcp/untracked/APP/Tranformer/validator.py +889 -0
  112. cnhkmcp/untracked/APP/ace.log +69 -0
  113. cnhkmcp/untracked/APP/ace_lib.py +1514 -0
  114. cnhkmcp/untracked/APP/blueprints/__init__.py +6 -0
  115. cnhkmcp/untracked/APP/blueprints/feature_engineering.py +347 -0
  116. cnhkmcp/untracked/APP/blueprints/idea_house.py +221 -0
  117. cnhkmcp/untracked/APP/blueprints/inspiration_house.py +432 -0
  118. cnhkmcp/untracked/APP/blueprints/paper_analysis.py +570 -0
  119. cnhkmcp/untracked/APP/custom_templates/templates.json +1257 -0
  120. cnhkmcp/untracked/APP/give_me_idea/BRAIN_Alpha_Template_Expert_SystemPrompt.md +400 -0
  121. cnhkmcp/untracked/APP/give_me_idea/ace_lib.py +1514 -0
  122. cnhkmcp/untracked/APP/give_me_idea/alpha_data_specific_template_master.py +252 -0
  123. cnhkmcp/untracked/APP/give_me_idea/fetch_all_datasets.py +157 -0
  124. cnhkmcp/untracked/APP/give_me_idea/fetch_all_operators.py +99 -0
  125. cnhkmcp/untracked/APP/give_me_idea/helpful_functions.py +180 -0
  126. cnhkmcp/untracked/APP/give_me_idea/what_is_Alpha_template.md +11 -0
  127. cnhkmcp/untracked/APP/helpful_functions.py +180 -0
  128. cnhkmcp/untracked/APP/hkSimulator/ace_lib.py +1501 -0
  129. cnhkmcp/untracked/APP/hkSimulator/autosimulator.py +447 -0
  130. cnhkmcp/untracked/APP/hkSimulator/helpful_functions.py +180 -0
  131. cnhkmcp/untracked/APP/mirror_config.txt +20 -0
  132. cnhkmcp/untracked/APP/operaters.csv +129 -0
  133. cnhkmcp/untracked/APP/requirements.txt +53 -0
  134. cnhkmcp/untracked/APP/run_app.bat +28 -0
  135. cnhkmcp/untracked/APP/run_app.sh +34 -0
  136. cnhkmcp/untracked/APP/setup_tsinghua.bat +39 -0
  137. cnhkmcp/untracked/APP/setup_tsinghua.sh +43 -0
  138. cnhkmcp/untracked/APP/simulator/alpha_submitter.py +404 -0
  139. cnhkmcp/untracked/APP/simulator/simulator_wqb.py +618 -0
  140. cnhkmcp/untracked/APP/ssrn-3332513.pdf +109188 -19
  141. cnhkmcp/untracked/APP/static/brain.js +589 -0
  142. cnhkmcp/untracked/APP/static/decoder.js +1540 -0
  143. cnhkmcp/untracked/APP/static/feature_engineering.js +1729 -0
  144. cnhkmcp/untracked/APP/static/idea_house.js +937 -0
  145. cnhkmcp/untracked/APP/static/inspiration.js +465 -0
  146. cnhkmcp/untracked/APP/static/inspiration_house.js +868 -0
  147. cnhkmcp/untracked/APP/static/paper_analysis.js +390 -0
  148. cnhkmcp/untracked/APP/static/script.js +3082 -0
  149. cnhkmcp/untracked/APP/static/simulator.js +597 -0
  150. cnhkmcp/untracked/APP/static/styles.css +3127 -0
  151. cnhkmcp/untracked/APP/static/usage_widget.js +508 -0
  152. cnhkmcp/untracked/APP/templates/alpha_inspector.html +511 -0
  153. cnhkmcp/untracked/APP/templates/feature_engineering.html +960 -0
  154. cnhkmcp/untracked/APP/templates/idea_house.html +564 -0
  155. cnhkmcp/untracked/APP/templates/index.html +932 -0
  156. cnhkmcp/untracked/APP/templates/inspiration_house.html +861 -0
  157. cnhkmcp/untracked/APP/templates/paper_analysis.html +91 -0
  158. cnhkmcp/untracked/APP/templates/simulator.html +343 -0
  159. cnhkmcp/untracked/APP/templates/transformer_web.html +580 -0
  160. cnhkmcp/untracked/APP/usage.md +351 -0
  161. 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 +1514 -0
  162. 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 +712 -0
  163. 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 +180 -0
  164. 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 +2460 -0
  165. cnhkmcp/untracked/__init__.py +0 -0
  166. cnhkmcp/untracked/arXiv_API_Tool_Manual.md +490 -0
  167. cnhkmcp/untracked/arxiv_api.py +229 -0
  168. cnhkmcp/untracked/back_up/forum_functions.py +998 -0
  169. cnhkmcp/untracked/back_up/platform_functions.py +2886 -0
  170. cnhkmcp/untracked/brain-consultant.md +31 -0
  171. cnhkmcp/untracked/forum_functions.py +407 -0
  172. 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 +407 -0
  173. 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 +2601 -0
  174. 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 +31 -0
  175. 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 +101 -0
  176. 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 +190 -0
  177. cnhkmcp/untracked/platform_functions.py +2601 -0
  178. cnhkmcp/untracked/sample_mcp_config.json +11 -0
  179. cnhkmcp/untracked/user_config.json +31 -0
  180. 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 +202 -0
  181. 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 +56 -0
  182. 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 +194 -0
  183. 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 +101 -0
  184. 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 +436 -0
  185. 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 +128 -0
  186. 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 +192 -0
  187. {cnhkmcp-2.1.3.dist-info → cnhkmcp-2.1.5.dist-info}/METADATA +1 -1
  188. cnhkmcp-2.1.5.dist-info/RECORD +192 -0
  189. cnhkmcp-2.1.5.dist-info/top_level.txt +1 -0
  190. cnhkmcp-2.1.3.dist-info/RECORD +0 -6
  191. cnhkmcp-2.1.3.dist-info/top_level.txt +0 -1
  192. {cnhkmcp-2.1.3.dist-info → cnhkmcp-2.1.5.dist-info}/WHEEL +0 -0
  193. {cnhkmcp-2.1.3.dist-info → cnhkmcp-2.1.5.dist-info}/entry_points.txt +0 -0
  194. {cnhkmcp-2.1.3.dist-info → cnhkmcp-2.1.5.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,712 @@
1
+ """Quick utilities for BRAIN OS alpha inspection.
2
+
3
+ Features:
4
+ - Login with email/password (supports persona detection).
5
+ - Fetch submitted OS alphas (optional top N).
6
+ - Pull operator list and parse each alpha expression into operators and datafields.
7
+ - Query datafield detail to list other available region/settings combinations.
8
+
9
+ Note: For convenience, a test credential is wired for ad-hoc runs. Override via
10
+ env vars `BRAIN_USERNAME` and `BRAIN_PASSWORD` in real use.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import os
16
+ import re
17
+ import json
18
+ import getpass
19
+ import itertools
20
+ from datetime import datetime
21
+ from typing import Dict, List, Optional, Sequence, Tuple, Union
22
+ import time
23
+ import requests
24
+ import pandas as pd
25
+
26
+ try:
27
+ from ace_lib import start_simulation, simulation_progress, get_instrument_type_region_delay
28
+ except ImportError as e:
29
+ print(f"Warning: ace_lib.py not found or failed to import: {e}")
30
+ start_simulation = None
31
+ simulation_progress = None
32
+ get_instrument_type_region_delay = None
33
+
34
+
35
+ BASE_URL = "https://api.worldquantbrain.com"
36
+
37
+
38
+ def brain_login(username: str, password: str, max_retries: int = 3) -> requests.Session:
39
+ """Authenticate against BRAIN API and return a live session.
40
+
41
+ Raises a RuntimeError if persona (biometric) auth is required so callers can
42
+ surface the URL to users.
43
+ """
44
+
45
+ session = requests.Session()
46
+ session.auth = (username, password)
47
+
48
+ for attempt in range(1, max_retries + 1):
49
+ response = session.post(f"{BASE_URL}/authentication")
50
+
51
+ if response.status_code == requests.codes.unauthorized:
52
+ if response.headers.get("WWW-Authenticate") == "persona":
53
+ location = response.headers.get("Location", "")
54
+ raise RuntimeError(
55
+ "Biometric authentication required. Complete it in browser: "
56
+ f"{location}"
57
+ )
58
+ raise RuntimeError("Invalid username or password.")
59
+
60
+ try:
61
+ response.raise_for_status()
62
+ return session
63
+ except requests.HTTPError as exc: # pragma: no cover - network path
64
+ if attempt >= max_retries:
65
+ raise exc
66
+
67
+ raise RuntimeError("Authentication failed after retries.")
68
+
69
+
70
+ def fetch_alphas_by_date_range(
71
+ session: requests.Session, start_date: str, end_date: str
72
+ ) -> List[Dict]:
73
+ """Return submitted (OS) alphas within the date range (inclusive).
74
+
75
+ Args:
76
+ start_date: Start date in YYYY-MM-DD format.
77
+ end_date: End date in YYYY-MM-DD format.
78
+ """
79
+ print(f"Fetching alphas from {start_date} to {end_date}...")
80
+
81
+ # Ensure dates are comparable strings (ISO format works for string comparison)
82
+ # Append time to make full comparison easy
83
+ # User suggested format: 2025-11-01T04:00:00.000Z
84
+ start_iso = f"{start_date}T00:00:00Z"
85
+ end_iso = f"{end_date}T23:59:59Z"
86
+
87
+ alphas: List[Dict] = []
88
+ limit = 50
89
+ offset = 0
90
+
91
+ while True:
92
+ # Use server-side filtering for performance
93
+ params = {
94
+ "stage": "OS",
95
+ "order": "-dateSubmitted",
96
+ "limit": limit,
97
+ "offset": offset,
98
+ "dateSubmitted>": start_iso,
99
+ "dateSubmitted<": end_iso,
100
+ }
101
+ resp = session.get(f"{BASE_URL}/users/self/alphas", params=params)
102
+ resp.raise_for_status()
103
+
104
+ payload = resp.json()
105
+ results = payload.get("results", []) if isinstance(payload, dict) else payload
106
+
107
+ if not results:
108
+ break
109
+
110
+ alphas.extend(results)
111
+
112
+ offset += limit
113
+ total = payload.get("count", 0) if isinstance(payload, dict) else 0
114
+
115
+ if offset >= total or len(results) < limit:
116
+ break
117
+
118
+ return alphas
119
+
120
+
121
+ def fetch_alphas_by_ids(
122
+ session: requests.Session, alpha_ids: List[str]
123
+ ) -> List[Dict]:
124
+ """Return submitted (OS) alphas by their IDs.
125
+
126
+ Args:
127
+ alpha_ids: List of Alpha IDs.
128
+ """
129
+ print(f"Fetching {len(alpha_ids)} alphas by ID...")
130
+ alphas: List[Dict] = []
131
+
132
+ for alpha_id in alpha_ids:
133
+ alpha_id = alpha_id.strip()
134
+ if not alpha_id:
135
+ continue
136
+
137
+ try:
138
+ resp = session.get(f"{BASE_URL}/alphas/{alpha_id}")
139
+ resp.raise_for_status()
140
+ alpha = resp.json()
141
+ alphas.append(alpha)
142
+ except Exception as e:
143
+ print(f"Error fetching alpha {alpha_id}: {e}")
144
+ continue
145
+
146
+ return alphas
147
+
148
+
149
+ def fetch_operators(session: requests.Session) -> List[Dict]:
150
+ """Fetch full operator catalog."""
151
+
152
+ resp = session.get(f"{BASE_URL}/operators")
153
+ resp.raise_for_status()
154
+ operators = resp.json()
155
+ return operators if isinstance(operators, list) else []
156
+
157
+
158
+ def _dedupe(seq: Sequence[str]) -> List[str]:
159
+ seen = set()
160
+ ordered: List[str] = []
161
+ for item in seq:
162
+ if item not in seen:
163
+ seen.add(item)
164
+ ordered.append(item)
165
+ return ordered
166
+
167
+
168
+ def _extract_expression(alpha: Dict) -> Optional[str]:
169
+ """Pick the first available expression/code from an alpha payload."""
170
+
171
+ for key in ("regular", "combo", "selection"):
172
+ block = alpha.get(key)
173
+ if isinstance(block, dict):
174
+ expr = block.get("expression") or block.get("code")
175
+ if isinstance(expr, str):
176
+ return expr
177
+ return None
178
+
179
+
180
+ def parse_expression(
181
+ expression: str, operator_names: Sequence[str]
182
+ ) -> Tuple[List[str], List[str]]:
183
+ """Split an expression into operators and datafields using a token scan."""
184
+
185
+ # Remove C-style comments /* ... */
186
+ expression = re.sub(r"/\*[\s\S]*?\*/", "", expression)
187
+ # Remove Python-style comments # ...
188
+ expression = re.sub(r"#.*", "", expression)
189
+
190
+ operator_set = set(operator_names)
191
+ tokens = re.findall(r"[A-Za-z_][A-Za-z0-9_]*", expression)
192
+
193
+ found_ops: List[str] = []
194
+ found_fields: List[str] = []
195
+
196
+ skip_tokens = {"if", "else", "true", "false", "nan", "inf"}
197
+
198
+ for token in tokens:
199
+ if token in skip_tokens:
200
+ continue
201
+ if token in operator_set:
202
+ found_ops.append(token)
203
+ else:
204
+ found_fields.append(token)
205
+
206
+ return _dedupe(found_ops), _dedupe(found_fields)
207
+
208
+
209
+ def analyze_alphas(
210
+ alphas: Sequence[Dict], operators: Sequence[Dict]
211
+ ) -> Dict[str, List[str]]:
212
+ """Return combined operator and datafield lists for provided alphas."""
213
+
214
+ operator_names = [op.get("name", "") for op in operators if isinstance(op, dict)]
215
+ all_ops: List[str] = []
216
+ all_fields: List[str] = []
217
+
218
+ for alpha in alphas:
219
+ expr = _extract_expression(alpha)
220
+ if not expr:
221
+ continue
222
+ ops, fields = parse_expression(expr, operator_names)
223
+ all_ops.extend(ops)
224
+ all_fields.extend(fields)
225
+
226
+ return {"operators": _dedupe(all_ops), "datafields": _dedupe(all_fields)}
227
+
228
+
229
+ def get_datafield_availability(
230
+ session: requests.Session,
231
+ field_name: str,
232
+ instrument_type: str = "EQUITY",
233
+ region: str = "USA",
234
+ delay: int = 1,
235
+ universe: str = "TOP3000",
236
+ ) -> Dict[str, List[Dict]]:
237
+ """Fetch detail for a datafield and summarize other available settings."""
238
+
239
+ params = {
240
+ "instrumentType": instrument_type,
241
+ "region": region,
242
+ "delay": delay,
243
+ "universe": universe,
244
+ }
245
+ time.sleep(2) # To avoid hitting rate limits
246
+ try:
247
+ resp = session.get(f"{BASE_URL}/data-fields/{field_name}", params=params)
248
+ resp.raise_for_status()
249
+ except requests.exceptions.HTTPError as e:
250
+ if e.response.status_code == 404:
251
+ return {"detail": {}, "availability": [], "error": "Datafield not found"}
252
+ raise e
253
+ detail = resp.json()
254
+
255
+ availability_candidates = []
256
+ for key in (
257
+ "availability",
258
+ "availabilities",
259
+ "availableSettings",
260
+ "availabilityList",
261
+ "regionAvailability",
262
+ "settings",
263
+ "data",
264
+ ):
265
+ value = detail.get(key)
266
+ if isinstance(value, list):
267
+ availability_candidates.extend(value)
268
+ elif isinstance(value, dict):
269
+ nested = value.get("availability") or value.get("items") or value.get("list")
270
+ if isinstance(nested, list):
271
+ availability_candidates.extend(nested)
272
+
273
+ def _pick(d, keys):
274
+ for k in keys:
275
+ val = d.get(k)
276
+ if val is not None:
277
+ return val
278
+ return None
279
+
280
+ normalized = []
281
+ for item in availability_candidates:
282
+ if not isinstance(item, dict):
283
+ continue
284
+ normalized.append(
285
+ {
286
+ "instrumentType": _pick(item, ["instrumentType", "instrument_type"]) or instrument_type,
287
+ "region": _pick(item, ["region", "regionCode"]),
288
+ "delay": _pick(item, ["delay", "lag"]),
289
+ "universe": _pick(item, ["universe", "universeName"]),
290
+ }
291
+ )
292
+
293
+ # Deduplicate normalized combos.
294
+ normalized = _dedupe(
295
+ [json.dumps(x, sort_keys=True) for x in normalized if any(x.values())]
296
+ )
297
+ combos = [json.loads(x) for x in normalized]
298
+
299
+ return {"detail": detail, "availability": combos}
300
+
301
+
302
+ def validate_setting(setting: Dict, options_df: Optional[pd.DataFrame]) -> bool:
303
+ """Check if a setting combination is valid according to simulation options."""
304
+ if options_df is None or options_df.empty:
305
+ return True # Skip validation if options not available
306
+
307
+ inst_type = setting.get("instrumentType", "EQUITY")
308
+ region = setting.get("region")
309
+ delay = setting.get("delay")
310
+ universe = setting.get("universe")
311
+ neutralization = setting.get("neutralization")
312
+
313
+ try:
314
+ delay = int(delay)
315
+ except (ValueError, TypeError):
316
+ pass
317
+
318
+ # Iterate to find match
319
+ for _, row in options_df.iterrows():
320
+ row_inst = row.get('InstrumentType')
321
+ row_region = row.get('Region')
322
+ row_delay = row.get('Delay')
323
+
324
+ try:
325
+ row_delay = int(row_delay)
326
+ except (ValueError, TypeError):
327
+ pass
328
+
329
+ if row_inst == inst_type and row_region == region and row_delay == delay:
330
+ # Check universe
331
+ valid_universes = row.get('Universe', [])
332
+ if isinstance(valid_universes, list) and universe not in valid_universes:
333
+ return False
334
+
335
+ # Check neutralization if present in setting
336
+ if neutralization:
337
+ valid_neutralizations = row.get('Neutralization', [])
338
+ if isinstance(valid_neutralizations, list) and neutralization not in valid_neutralizations:
339
+ return False
340
+
341
+ return True
342
+
343
+ return False
344
+
345
+
346
+ def find_common_availabilities(
347
+ session: requests.Session, datafields: List[str]
348
+ ) -> List[Dict]:
349
+ """Find the intersection of available settings for a list of datafields.
350
+
351
+ Returns a list of settings (region, universe, delay, instrumentType) that are
352
+ valid for ALL provided datafields.
353
+ """
354
+ if not datafields:
355
+ return []
356
+
357
+ common_settings = None
358
+
359
+ for field in datafields:
360
+ # Fetch availability for this field
361
+ info = get_datafield_availability(session, field)
362
+
363
+ # If field not found or has no availability, we skip it.
364
+ # It might be a local variable, a constant, or a vector not in the catalog.
365
+ if info.get("error") or not info.get("availability"):
366
+ print(f"Field '{field}' has no availability info (likely local var). Skipping constraint.")
367
+ continue
368
+
369
+ # Convert availability list to a set of JSON strings for set intersection
370
+ # We use JSON strings because dicts are not hashable
371
+ current_settings = set()
372
+ for item in info["availability"]:
373
+ # Normalize keys to ensure consistent JSON representation
374
+ normalized_item = {
375
+ "instrumentType": item.get("instrumentType"),
376
+ "region": item.get("region"),
377
+ "delay": item.get("delay"),
378
+ "universe": item.get("universe"),
379
+ }
380
+ current_settings.add(json.dumps(normalized_item, sort_keys=True))
381
+
382
+ if common_settings is None:
383
+ common_settings = current_settings
384
+ else:
385
+ common_settings = common_settings.intersection(current_settings)
386
+
387
+ # Optimization: if intersection becomes empty, we can stop early
388
+ if not common_settings:
389
+ print(f"Intersection became empty after checking field '{field}'.")
390
+ return []
391
+
392
+ # If common_settings is still None, it means no fields returned valid availability.
393
+ if common_settings is None:
394
+ return []
395
+
396
+ # Convert back to list of dicts
397
+ result = [json.loads(s) for s in common_settings]
398
+
399
+ # Sort for consistent output (optional but nice)
400
+ result.sort(key=lambda x: (x.get("region", ""), x.get("universe", ""), x.get("delay", 0)))
401
+
402
+ return result
403
+
404
+
405
+ def get_alpha_variants(
406
+ session: requests.Session, alpha: Dict, operators: List[Dict], simulation_options: Optional[pd.DataFrame] = None
407
+ ) -> Dict:
408
+ """Analyze alpha and find valid setting variants without simulating."""
409
+ alpha_id = alpha.get("id", "Unknown")
410
+ alpha_type = alpha.get("type")
411
+
412
+ if alpha_type != "REGULAR":
413
+ return {"id": alpha_id, "valid": False, "reason": "Not REGULAR type", "variants": []}
414
+
415
+ expr = _extract_expression(alpha)
416
+ if not expr:
417
+ return {"id": alpha_id, "valid": False, "reason": "No expression found", "variants": []}
418
+
419
+ operator_names = [op.get("name", "") for op in operators if isinstance(op, dict)]
420
+ _, fields = parse_expression(expr, operator_names)
421
+
422
+ if not fields:
423
+ return {"id": alpha_id, "valid": False, "reason": "No datafields found", "variants": []}
424
+
425
+ common_settings = find_common_availabilities(session, fields)
426
+
427
+ if not common_settings:
428
+ return {"id": alpha_id, "valid": False, "reason": "No common settings", "variants": []}
429
+
430
+ original_settings = alpha.get("settings", {})
431
+ valid_variants = []
432
+
433
+ for new_setting in common_settings:
434
+ # Construct full simulation payload (merge first to validate full settings)
435
+ merged_settings = original_settings.copy()
436
+ merged_settings.update(new_setting)
437
+
438
+ # Validate against simulation options if provided
439
+ if simulation_options is not None:
440
+ if not validate_setting(merged_settings, simulation_options):
441
+ continue
442
+
443
+ # Check duplicate
444
+ is_duplicate = True
445
+ for key in ["region", "universe", "delay", "instrumentType"]:
446
+ val_orig = str(original_settings.get(key, ""))
447
+ val_new = str(new_setting.get(key, ""))
448
+ if val_orig != val_new:
449
+ is_duplicate = False
450
+ break
451
+
452
+ if not is_duplicate:
453
+ # Ensure required fields for ace_lib compatibility if missing
454
+ if "language" not in merged_settings:
455
+ merged_settings["language"] = "FASTEXPR"
456
+
457
+ # Add maxTrade: ON for specific regions
458
+ # if merged_settings.get("region") in ["ASI", "JPN", "HKG", "KOR", "TWN"]:
459
+ # merged_settings["maxTrade"] = "ON"
460
+
461
+ payload = {
462
+ "type": "REGULAR",
463
+ "settings": merged_settings,
464
+ "regular": expr,
465
+ }
466
+
467
+ valid_variants.append({
468
+ "diff_settings": new_setting,
469
+ "simulation_payload": payload
470
+ })
471
+
472
+ return {
473
+ "id": alpha_id,
474
+ "dateSubmitted": alpha.get("dateSubmitted"),
475
+ "expression": expr,
476
+ "valid": True,
477
+ "variants": valid_variants,
478
+ "original_settings": original_settings
479
+ }
480
+
481
+
482
+ def run_simulation_payload(
483
+ session: requests.Session,
484
+ payload: Dict,
485
+ ) -> Tuple[bool, Union[Dict, str]]:
486
+ """Send a simulation request and wait for the result.
487
+
488
+ Returns: (success, result_or_error_message)
489
+ """
490
+ if not start_simulation or not simulation_progress:
491
+ return False, "Simulation tools (ace_lib) not available or failed to import."
492
+
493
+ settings = payload.get("settings", {})
494
+ print(f" -> Submitting simulation for {settings.get('region')} / {settings.get('universe')}...")
495
+
496
+ try:
497
+ resp = start_simulation(session, payload)
498
+
499
+ # Check if response is valid (status code 200-299)
500
+ if not resp.ok:
501
+ error_msg = f"Simulation API Error: {resp.status_code} - {resp.text}"
502
+ print(f" -> {error_msg}")
503
+ return False, error_msg
504
+
505
+ result = simulation_progress(session, resp)
506
+ if result.get("completed"):
507
+ return True, result.get("result")
508
+ else:
509
+ msg = result.get("message") or "Simulation failed or incomplete."
510
+ print(f" -> {msg}")
511
+ return False, msg
512
+ except Exception as e:
513
+ import traceback
514
+ traceback.print_exc()
515
+ print(f" -> Error during simulation: {e}")
516
+ return False, str(e)
517
+
518
+ # Deprecated but kept for compatibility if needed
519
+ def run_simulation_for_setting(
520
+ session: requests.Session,
521
+ expression: str,
522
+ settings: Dict,
523
+ ) -> Optional[Dict]:
524
+ payload = {
525
+ "type": "REGULAR",
526
+ "settings": settings,
527
+ "regular": expression,
528
+ }
529
+ success, res = run_simulation_payload(session, payload)
530
+ return res if success else None
531
+
532
+
533
+ def process_alpha_variants(
534
+ session: requests.Session, alpha: Dict, operators: List[Dict], simulation_options: Optional[pd.DataFrame] = None
535
+ ) -> List[Dict]:
536
+ """Analyze alpha, find common availabilities, and simulate variants.
537
+
538
+ Returns a list of simulation results (new alphas).
539
+ """
540
+ generated_alphas = []
541
+
542
+ alpha_id = alpha.get("id", "Unknown")
543
+ alpha_type = alpha.get("type")
544
+
545
+ if alpha_type != "REGULAR":
546
+ print(f"Skipping Alpha {alpha_id}: Type is {alpha_type}, not REGULAR.")
547
+ return []
548
+
549
+ print(f"\nProcessing Alpha {alpha_id}...")
550
+
551
+ # Extract expression
552
+ expr = _extract_expression(alpha)
553
+ if not expr:
554
+ print(" -> No expression found.")
555
+ return []
556
+
557
+ # Parse datafields
558
+ operator_names = [op.get("name", "") for op in operators if isinstance(op, dict)]
559
+ _, fields = parse_expression(expr, operator_names)
560
+
561
+ if not fields:
562
+ print(" -> No datafields found to check availability.")
563
+ return []
564
+
565
+ # Find common availabilities
566
+ print(f" -> Checking availability for {len(fields)} fields...")
567
+ common_settings = find_common_availabilities(session, fields)
568
+
569
+ if not common_settings:
570
+ print(" -> No common settings found.")
571
+ return []
572
+
573
+ print(f" -> Found {len(common_settings)} valid setting combinations.")
574
+
575
+ # Base settings from original alpha
576
+ original_settings = alpha.get("settings", {})
577
+
578
+ for i, new_setting in enumerate(common_settings):
579
+ print(f"\n [Variant {i+1}/{len(common_settings)}]")
580
+
581
+ # Merge settings: keep original unless overwritten by new availability
582
+ # Availability gives: region, universe, delay, instrumentType
583
+ # Original has: decay, neutralization, truncation, etc.
584
+ merged_settings = original_settings.copy()
585
+ merged_settings.update(new_setting)
586
+
587
+ # Validate against simulation options if provided
588
+ if simulation_options is not None:
589
+ if not validate_setting(merged_settings, simulation_options):
590
+ print(f" -> Skipping: Invalid simulation setting combination ({new_setting.get('region')}/{new_setting.get('universe')}).")
591
+ continue
592
+
593
+ # Check if this variant duplicates the original alpha's settings
594
+ is_duplicate = True
595
+ for key in ["region", "universe", "delay", "instrumentType"]:
596
+ # Compare as strings to handle potential type mismatches (e.g. delay int vs str)
597
+ val_orig = str(original_settings.get(key, ""))
598
+ val_new = str(new_setting.get(key, ""))
599
+ if val_orig != val_new:
600
+ is_duplicate = False
601
+ break
602
+
603
+ if is_duplicate:
604
+ print(f" -> Skipping: Settings match original alpha ({new_setting.get('region')}/{new_setting.get('universe')}).")
605
+ continue
606
+
607
+ # Add maxTrade: ON for specific regions
608
+ # if merged_settings.get("region") in ["ASI", "JPN", "HKG", "KOR", "TWN"]:
609
+ # merged_settings["maxTrade"] = "ON"
610
+
611
+ # Run simulation
612
+ result = run_simulation_for_setting(session, expr, merged_settings)
613
+
614
+ if result:
615
+ # Print some stats
616
+ stats = result.get("is", {})
617
+ sharpe = stats.get("sharpe", "N/A")
618
+ returns = stats.get("returns", "N/A")
619
+ turnover = stats.get("turnover", "N/A")
620
+ new_alpha_id = result.get("id")
621
+ print(f" -> Result: ID={new_alpha_id}, Sharpe={sharpe}, Returns={returns}, Turnover={turnover}")
622
+
623
+ # Add metadata about origin
624
+ result["_origin_alpha_id"] = alpha_id
625
+ result["_origin_variant_settings"] = new_setting
626
+ generated_alphas.append(result)
627
+
628
+ return generated_alphas
629
+
630
+
631
+ def main() -> None:
632
+ """Interactive main function."""
633
+ print("=== BRAIN Alpha Variant Generator ===")
634
+
635
+ # 1. Interactive Login
636
+ username = input("Enter BRAIN Username (Email): ").strip()
637
+ if not username:
638
+ print("Username is required.")
639
+ return
640
+
641
+ password = getpass.getpass("Enter BRAIN Password: ").strip()
642
+ if not password:
643
+ print("Password is required.")
644
+ return
645
+
646
+ try:
647
+ print(f"Logging in as {username}...")
648
+ session = brain_login(username, password)
649
+ print("Login successful.")
650
+ except Exception as e:
651
+ print(f"Login failed: {e}")
652
+ return
653
+
654
+ # 2. Date Range
655
+ print("\n--- Date Range Selection ---")
656
+ start_date = input("Enter Start Date (YYYY-MM-DD): ").strip()
657
+ end_date = input("Enter End Date (YYYY-MM-DD): ").strip()
658
+
659
+ # Basic validation
660
+ try:
661
+ datetime.strptime(start_date, "%Y-%m-%d")
662
+ datetime.strptime(end_date, "%Y-%m-%d")
663
+ except ValueError:
664
+ print("Invalid date format. Please use YYYY-MM-DD.")
665
+ return
666
+
667
+ # Fetch Alphas
668
+ alphas = fetch_alphas_by_date_range(session, start_date, end_date)
669
+ print(f"Fetched {len(alphas)} alphas from {start_date} to {end_date}.")
670
+
671
+ if not alphas:
672
+ print("No alphas found in this range. Exiting.")
673
+ return
674
+
675
+ print("Fetching operator catalog...")
676
+ operators = fetch_operators(session)
677
+
678
+ print("Fetching simulation options...")
679
+ simulation_options = None
680
+ if get_instrument_type_region_delay:
681
+ try:
682
+ simulation_options = get_instrument_type_region_delay(session)
683
+ print("Simulation options fetched successfully.")
684
+ except Exception as e:
685
+ print(f"Warning: Failed to fetch simulation options: {e}")
686
+ else:
687
+ print("Warning: get_instrument_type_region_delay not available.")
688
+
689
+ # 3. Process Alphas
690
+ all_generated_alphas = []
691
+
692
+ for i, alpha in enumerate(alphas):
693
+ new_alphas = process_alpha_variants(session, alpha, operators, simulation_options)
694
+ all_generated_alphas.extend(new_alphas)
695
+
696
+ # 4. Output
697
+ if all_generated_alphas:
698
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
699
+ filename = f"generated_alphas_{timestamp}.json"
700
+
701
+ print(f"\nTotal generated alphas: {len(all_generated_alphas)}")
702
+ print(f"Saving results to {filename}...")
703
+
704
+ with open(filename, "w", encoding="utf-8") as f:
705
+ json.dump(all_generated_alphas, f, indent=2, ensure_ascii=False)
706
+
707
+ print("Done.")
708
+ else:
709
+ print("\nNo new alphas were generated.")
710
+
711
+ if __name__ == "__main__":
712
+ main()