quantnodes 3.0.0__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 (399) hide show
  1. QuantNodes/__init__.py +15 -0
  2. QuantNodes/__main__.py +14 -0
  3. QuantNodes/agent/__init__.py +158 -0
  4. QuantNodes/agent/agents/__init__.py +13 -0
  5. QuantNodes/agent/agents/definition.py +180 -0
  6. QuantNodes/agent/agents/manager.py +73 -0
  7. QuantNodes/agent/config/__init__.py +34 -0
  8. QuantNodes/agent/config/executor.py +958 -0
  9. QuantNodes/agent/config/loader.py +427 -0
  10. QuantNodes/agent/config/templates/bollinger_bands.yaml +84 -0
  11. QuantNodes/agent/config/templates/dual_ma.yaml +72 -0
  12. QuantNodes/agent/config/templates/empty.yaml +56 -0
  13. QuantNodes/agent/config/templates/mean_reversion.yaml +47 -0
  14. QuantNodes/agent/config/templates/mean_reversion_zscore.yaml +90 -0
  15. QuantNodes/agent/config/templates/momentum.yaml +81 -0
  16. QuantNodes/agent/config/templates/momentum_breakout.yaml +84 -0
  17. QuantNodes/agent/config/templates/rsi_strategy.yaml +72 -0
  18. QuantNodes/agent/config/templates/volume_price.yaml +86 -0
  19. QuantNodes/agent/config/types.py +156 -0
  20. QuantNodes/agent/config_mapper.py +293 -0
  21. QuantNodes/agent/core/__init__.py +19 -0
  22. QuantNodes/agent/core/dream.py +47 -0
  23. QuantNodes/agent/core/quant_dream.py +274 -0
  24. QuantNodes/agent/cron_jobs.py +314 -0
  25. QuantNodes/agent/nanobot_bridge.py +242 -0
  26. QuantNodes/agent/permission/__init__.py +30 -0
  27. QuantNodes/agent/permission/defaults.py +36 -0
  28. QuantNodes/agent/permission/evaluate.py +41 -0
  29. QuantNodes/agent/permission/models.py +59 -0
  30. QuantNodes/agent/permission/service.py +133 -0
  31. QuantNodes/agent/providers/__init__.py +11 -0
  32. QuantNodes/agent/providers/base.py +102 -0
  33. QuantNodes/agent/providers/quantnodes.py +610 -0
  34. QuantNodes/agent/providers/rate_limiter.py +326 -0
  35. QuantNodes/agent/providers/registry.py +163 -0
  36. QuantNodes/agent/skills/__init__.py +20 -0
  37. QuantNodes/agent/skills/base.py +118 -0
  38. QuantNodes/agent/skills/bridge.py +73 -0
  39. QuantNodes/agent/skills/factor/__init__.py +14 -0
  40. QuantNodes/agent/skills/factor/correlation.py +99 -0
  41. QuantNodes/agent/skills/factor/group_backtest.py +114 -0
  42. QuantNodes/agent/skills/factor/ic_analysis.py +106 -0
  43. QuantNodes/agent/skills/loader.py +107 -0
  44. QuantNodes/agent/skills/registry.py +105 -0
  45. QuantNodes/agent/skills/strategy/__init__.py +16 -0
  46. QuantNodes/agent/skills/strategy/bollinger.py +86 -0
  47. QuantNodes/agent/skills/strategy/dual_ma.py +82 -0
  48. QuantNodes/agent/skills/strategy/momentum.py +74 -0
  49. QuantNodes/agent/skills/strategy/rsi_reversal.py +99 -0
  50. QuantNodes/agent/skills_quant/__init__.py +14 -0
  51. QuantNodes/agent/skills_quant/backtest-analyze/SKILL.md +42 -0
  52. QuantNodes/agent/skills_quant/config-driven/SKILL.md +72 -0
  53. QuantNodes/agent/skills_quant/factor-research/SKILL.md +40 -0
  54. QuantNodes/agent/skills_quant/quant-dream/SKILL.md +55 -0
  55. QuantNodes/agent/skills_quant/risk-management/SKILL.md +45 -0
  56. QuantNodes/agent/skills_quant/strategy-design/SKILL.md +43 -0
  57. QuantNodes/agent/templates/__init__.py +4 -0
  58. QuantNodes/agent/tools/__init__.py +173 -0
  59. QuantNodes/agent/tools/_workspace.py +51 -0
  60. QuantNodes/agent/tools/alpha_backtest.py +328 -0
  61. QuantNodes/agent/tools/alpha_evaluate.py +493 -0
  62. QuantNodes/agent/tools/backtest.py +226 -0
  63. QuantNodes/agent/tools/base.py +133 -0
  64. QuantNodes/agent/tools/code_search.py +207 -0
  65. QuantNodes/agent/tools/config_backtest.py +401 -0
  66. QuantNodes/agent/tools/context.py +97 -0
  67. QuantNodes/agent/tools/dream_skill.py +77 -0
  68. QuantNodes/agent/tools/echo.py +38 -0
  69. QuantNodes/agent/tools/factor.py +231 -0
  70. QuantNodes/agent/tools/file_ops.py +201 -0
  71. QuantNodes/agent/tools/git_ops.py +190 -0
  72. QuantNodes/agent/tools/operator_lookup.py +218 -0
  73. QuantNodes/agent/tools/output_truncation.py +77 -0
  74. QuantNodes/agent/tools/path_check.py +43 -0
  75. QuantNodes/agent/tools/pipeline.py +62 -0
  76. QuantNodes/agent/tools/registry.py +150 -0
  77. QuantNodes/agent/tools/sandbox.py +62 -0
  78. QuantNodes/agent/tools/shell_safety.py +63 -0
  79. QuantNodes/agent/tools/strategy.py +106 -0
  80. QuantNodes/agent/tools/task.py +171 -0
  81. QuantNodes/agent/tools/web_fetch.py +142 -0
  82. QuantNodes/agent/tools/web_search.py +114 -0
  83. QuantNodes/agent/tools/wiki.py +370 -0
  84. QuantNodes/agent/utils/__init__.py +11 -0
  85. QuantNodes/agent/utils/helpers.py +43 -0
  86. QuantNodes/agent/utils/prompt_templates.py +30 -0
  87. QuantNodes/agent/workflows/__init__.py +20 -0
  88. QuantNodes/agent/workflows/implementations/__init__.py +8 -0
  89. QuantNodes/agent/workflows/implementations/alpha_gpt.py +508 -0
  90. QuantNodes/agent/workflows/implementations/mcts.py +442 -0
  91. QuantNodes/agent/workflows/parsers.py +44 -0
  92. QuantNodes/agent/workflows/registry.py +119 -0
  93. QuantNodes/agent/workflows/step_agent.py +219 -0
  94. QuantNodes/agent/workflows/tool.py +198 -0
  95. QuantNodes/ai/__init__.py +93 -0
  96. QuantNodes/ai/llm/__init__.py +75 -0
  97. QuantNodes/ai/llm/base.py +233 -0
  98. QuantNodes/ai/llm/decorators.py +281 -0
  99. QuantNodes/ai/llm/gateway.py +571 -0
  100. QuantNodes/ai/llm/null.py +76 -0
  101. QuantNodes/ai/llm/openai.py +435 -0
  102. QuantNodes/ai/optimizer.py +405 -0
  103. QuantNodes/ai/prompts/__init__.py +229 -0
  104. QuantNodes/ai/sandbox.py +371 -0
  105. QuantNodes/ai/sandbox_pandas_bridge.py +150 -0
  106. QuantNodes/ai/strategy_gen.py +396 -0
  107. QuantNodes/backtest/__init__.py +64 -0
  108. QuantNodes/backtest/backtest_node.py +188 -0
  109. QuantNodes/backtest/broker_node.py +378 -0
  110. QuantNodes/backtest/config_runner.py +397 -0
  111. QuantNodes/backtest/config_strategy.py +64 -0
  112. QuantNodes/backtest/risk_node.py +360 -0
  113. QuantNodes/backtest/strategy_node.py +268 -0
  114. QuantNodes/cache_node/__init__.py +19 -0
  115. QuantNodes/cache_node/base.py +244 -0
  116. QuantNodes/cache_node/cache_store.py +99 -0
  117. QuantNodes/cache_node/metadata.py +100 -0
  118. QuantNodes/cli/__init__.py +109 -0
  119. QuantNodes/cli/_helpers.py +511 -0
  120. QuantNodes/cli/command.py +110 -0
  121. QuantNodes/cli/commands/__init__.py +69 -0
  122. QuantNodes/cli/commands/agent.py +158 -0
  123. QuantNodes/cli/commands/alpha.py +951 -0
  124. QuantNodes/cli/commands/chat.py +38 -0
  125. QuantNodes/cli/commands/evolve.py +120 -0
  126. QuantNodes/cli/commands/factor.py +569 -0
  127. QuantNodes/cli/commands/init.py +190 -0
  128. QuantNodes/cli/commands/run.py +259 -0
  129. QuantNodes/cli/commands/serve.py +398 -0
  130. QuantNodes/cli/commands/version.py +120 -0
  131. QuantNodes/cli/enhanced.py +146 -0
  132. QuantNodes/conf_node/__init__.py +37 -0
  133. QuantNodes/conf_node/base.py +120 -0
  134. QuantNodes/conf_node/env_config.py +132 -0
  135. QuantNodes/conf_node/ini_config.py +70 -0
  136. QuantNodes/conf_node/json_config.py +69 -0
  137. QuantNodes/conf_node/yaml_config.py +78 -0
  138. QuantNodes/constants.py +17 -0
  139. QuantNodes/core/__init__.py +196 -0
  140. QuantNodes/core/_lookback_helpers.py +49 -0
  141. QuantNodes/core/ast_parser.py +198 -0
  142. QuantNodes/core/base.py +61 -0
  143. QuantNodes/core/cache_manager.py +344 -0
  144. QuantNodes/core/cache_utils.py +150 -0
  145. QuantNodes/core/cond_builder.py +53 -0
  146. QuantNodes/core/config.py +170 -0
  147. QuantNodes/core/constants.py +48 -0
  148. QuantNodes/core/control.py +412 -0
  149. QuantNodes/core/data_preprocessing.py +453 -0
  150. QuantNodes/core/data_source.py +46 -0
  151. QuantNodes/core/events.py +178 -0
  152. QuantNodes/core/evolution/__init__.py +22 -0
  153. QuantNodes/core/evolution/loop.py +583 -0
  154. QuantNodes/core/evolution/operators.py +289 -0
  155. QuantNodes/core/evolution/settings.py +44 -0
  156. QuantNodes/core/expression.py +841 -0
  157. QuantNodes/core/feedback/__init__.py +38 -0
  158. QuantNodes/core/feedback/channels.py +182 -0
  159. QuantNodes/core/feedback/collector.py +91 -0
  160. QuantNodes/core/feedback/dataclass.py +239 -0
  161. QuantNodes/core/feedback/llm_judge.py +138 -0
  162. QuantNodes/core/knowledge/__init__.py +69 -0
  163. QuantNodes/core/knowledge/knowledge_base.py +217 -0
  164. QuantNodes/core/knowledge/lineage_compress.py +196 -0
  165. QuantNodes/core/knowledge/lineage_expand.py +123 -0
  166. QuantNodes/core/knowledge/metrics/__init__.py +43 -0
  167. QuantNodes/core/knowledge/metrics/evaluator.py +176 -0
  168. QuantNodes/core/knowledge/metrics/metrics.py +220 -0
  169. QuantNodes/core/knowledge/rag_prompt.py +196 -0
  170. QuantNodes/core/knowledge/retriever.py +209 -0
  171. QuantNodes/core/lambda_node.py +81 -0
  172. QuantNodes/core/monitoring/__init__.py +22 -0
  173. QuantNodes/core/monitoring/collector.py +292 -0
  174. QuantNodes/core/monitoring/dashboard.py +365 -0
  175. QuantNodes/core/node.py +375 -0
  176. QuantNodes/core/pandas_utils.py +504 -0
  177. QuantNodes/core/parallel/__init__.py +15 -0
  178. QuantNodes/core/parallel/worker.py +140 -0
  179. QuantNodes/core/parallel/worker_process.py +265 -0
  180. QuantNodes/core/path_utils.py +73 -0
  181. QuantNodes/core/pipeline.py +328 -0
  182. QuantNodes/core/plugin.py +135 -0
  183. QuantNodes/core/quality_gate/__init__.py +32 -0
  184. QuantNodes/core/quality_gate/complexity.py +94 -0
  185. QuantNodes/core/quality_gate/consistency.py +26 -0
  186. QuantNodes/core/quality_gate/node.py +97 -0
  187. QuantNodes/core/quality_gate/redundancy.py +51 -0
  188. QuantNodes/core/quality_gate/settings.py +43 -0
  189. QuantNodes/core/quality_gate/zoo.py +98 -0
  190. QuantNodes/core/serializable.py +116 -0
  191. QuantNodes/core/serialization.py +673 -0
  192. QuantNodes/core/tools.py +333 -0
  193. QuantNodes/core/trajectory/__init__.py +25 -0
  194. QuantNodes/core/trajectory/entry.py +116 -0
  195. QuantNodes/core/trajectory/lineage.py +67 -0
  196. QuantNodes/core/trajectory/pool.py +211 -0
  197. QuantNodes/core/trajectory/selector.py +140 -0
  198. QuantNodes/core/visualization/__init__.py +33 -0
  199. QuantNodes/core/visualization/builder.py +233 -0
  200. QuantNodes/core/visualization/gate_breakdown.py +140 -0
  201. QuantNodes/core/visualization/lineage_dag.py +203 -0
  202. QuantNodes/core/visualization/metric_distribution.py +125 -0
  203. QuantNodes/core/visualization/report.py +68 -0
  204. QuantNodes/database_node/__init__.py +69 -0
  205. QuantNodes/database_node/base.py +135 -0
  206. QuantNodes/database_node/clickhouse_node.py +272 -0
  207. QuantNodes/database_node/csv_node.py +83 -0
  208. QuantNodes/database_node/duckdb_node.py +86 -0
  209. QuantNodes/database_node/factory.py +83 -0
  210. QuantNodes/database_node/mysql_node.py +100 -0
  211. QuantNodes/database_node/parquet_node.py +75 -0
  212. QuantNodes/database_node/sqlite_node.py +67 -0
  213. QuantNodes/factor_node/__init__.py +50 -0
  214. QuantNodes/factor_node/factor.py +563 -0
  215. QuantNodes/factor_node/factor_db.py +421 -0
  216. QuantNodes/factor_node/factor_functions/__init__.py +252 -0
  217. QuantNodes/factor_node/factor_functions/_helpers.py +358 -0
  218. QuantNodes/factor_node/factor_functions/_helpers_debug.py +317 -0
  219. QuantNodes/factor_node/factor_functions/composite_ops.py +136 -0
  220. QuantNodes/factor_node/factor_functions/math_ops.py +433 -0
  221. QuantNodes/factor_node/factor_functions/section_ops.py +290 -0
  222. QuantNodes/factor_node/factor_functions/talib_ops.py +1293 -0
  223. QuantNodes/factor_node/factor_functions/time_ops.py +535 -0
  224. QuantNodes/factor_node/factor_operation.py +1115 -0
  225. QuantNodes/factor_node/factor_table.py +1073 -0
  226. QuantNodes/factor_node/quant_nodes_object.py +60 -0
  227. QuantNodes/mcp_server/__init__.py +27 -0
  228. QuantNodes/mcp_server/__main__.py +4 -0
  229. QuantNodes/mcp_server/server.py +272 -0
  230. QuantNodes/methods/__init__.py +28 -0
  231. QuantNodes/methods/pipeline.py +100 -0
  232. QuantNodes/methods/sandbox.py +102 -0
  233. QuantNodes/monitor/__init__.py +27 -0
  234. QuantNodes/monitor/agent_tools/__init__.py +5 -0
  235. QuantNodes/monitor/agent_tools/monitor_tool.py +98 -0
  236. QuantNodes/monitor/agent_tools/schedule_tool.py +98 -0
  237. QuantNodes/monitor/agent_tools/version_tool.py +133 -0
  238. QuantNodes/monitor/monitor/__init__.py +6 -0
  239. QuantNodes/monitor/monitor/alerter.py +60 -0
  240. QuantNodes/monitor/monitor/collector.py +164 -0
  241. QuantNodes/monitor/monitor/dashboard.py +115 -0
  242. QuantNodes/monitor/monitor/drift.py +190 -0
  243. QuantNodes/monitor/scheduler/__init__.py +4 -0
  244. QuantNodes/monitor/scheduler/runner.py +133 -0
  245. QuantNodes/monitor/scheduler/scheduler.py +184 -0
  246. QuantNodes/monitor/storage/__init__.py +16 -0
  247. QuantNodes/monitor/storage/models.py +70 -0
  248. QuantNodes/monitor/storage/repository.py +407 -0
  249. QuantNodes/monitor/version/__init__.py +4 -0
  250. QuantNodes/monitor/version/diff.py +81 -0
  251. QuantNodes/monitor/version/version_manager.py +182 -0
  252. QuantNodes/operator_node/__init__.py +28 -0
  253. QuantNodes/operator_node/base.py +97 -0
  254. QuantNodes/operator_node/query_node.py +129 -0
  255. QuantNodes/operator_node/sql_builder.py +125 -0
  256. QuantNodes/operator_node/sql_utils.py +172 -0
  257. QuantNodes/operator_node/transform.py +130 -0
  258. QuantNodes/operators/__init__.py +90 -0
  259. QuantNodes/operators/_engine.py +108 -0
  260. QuantNodes/operators/composite.py +161 -0
  261. QuantNodes/operators/composite_dag.py +667 -0
  262. QuantNodes/operators/composite_dag_ops.py +343 -0
  263. QuantNodes/operators/composite_dag_pandas_ops.py +382 -0
  264. QuantNodes/operators/custom.py +408 -0
  265. QuantNodes/operators/facade.py +164 -0
  266. QuantNodes/operators/math.py +163 -0
  267. QuantNodes/operators/proxy.py +29 -0
  268. QuantNodes/operators/registry.py +144 -0
  269. QuantNodes/operators/section.py +99 -0
  270. QuantNodes/operators/talib.py +757 -0
  271. QuantNodes/operators/templates.py +95 -0
  272. QuantNodes/operators/time_series.py +136 -0
  273. QuantNodes/prompts/__init__.py +20 -0
  274. QuantNodes/prompts/backtest/__init__.py +12 -0
  275. QuantNodes/prompts/backtest/factor_based.py +86 -0
  276. QuantNodes/prompts/backtest/standard.py +73 -0
  277. QuantNodes/prompts/factor/__init__.py +14 -0
  278. QuantNodes/prompts/factor/correlation.py +77 -0
  279. QuantNodes/prompts/factor/group_backtest.py +86 -0
  280. QuantNodes/prompts/factor/ic_analysis.py +91 -0
  281. QuantNodes/prompts/strategy/__init__.py +18 -0
  282. QuantNodes/prompts/strategy/market_neutral.py +96 -0
  283. QuantNodes/prompts/strategy/mean_reversion.py +107 -0
  284. QuantNodes/prompts/strategy/momentum.py +160 -0
  285. QuantNodes/prompts/strategy/pairs_trading.py +107 -0
  286. QuantNodes/prompts/strategy/trend_following.py +96 -0
  287. QuantNodes/research/README.md +106 -0
  288. QuantNodes/research/__init__.py +154 -0
  289. QuantNodes/research/_legacy_3c/__init__.py +61 -0
  290. QuantNodes/research/_legacy_3c/auto_researcher.py +289 -0
  291. QuantNodes/research/_legacy_3c/factor_evaluator.py +560 -0
  292. QuantNodes/research/_legacy_3c/factor_miner.py +318 -0
  293. QuantNodes/research/_legacy_3c/mcts_search.py +324 -0
  294. QuantNodes/research/factor_test/__init__.py +25 -0
  295. QuantNodes/research/factor_test/config.py +184 -0
  296. QuantNodes/research/factor_test/config_builder.py +276 -0
  297. QuantNodes/research/factor_test/e2e/data_prep.py +163 -0
  298. QuantNodes/research/factor_test/e2e/run_evolution_e2e.py +309 -0
  299. QuantNodes/research/factor_test/evolution_adapter.py +231 -0
  300. QuantNodes/research/factor_test/feedback_wrapper.py +102 -0
  301. QuantNodes/research/factor_test/ifind_db/__init__.py +7 -0
  302. QuantNodes/research/factor_test/ifind_db/fetcher.py +224 -0
  303. QuantNodes/research/factor_test/ifind_db/ifind_database.py +689 -0
  304. QuantNodes/research/factor_test/nodes/__init__.py +1 -0
  305. QuantNodes/research/factor_test/nodes/_base.py +91 -0
  306. QuantNodes/research/factor_test/nodes/adjust_date_node.py +48 -0
  307. QuantNodes/research/factor_test/nodes/configs.py +240 -0
  308. QuantNodes/research/factor_test/nodes/factor_neutralize_node.py +87 -0
  309. QuantNodes/research/factor_test/nodes/factor_preprocess_node.py +222 -0
  310. QuantNodes/research/factor_test/nodes/factor_score_node.py +141 -0
  311. QuantNodes/research/factor_test/nodes/factor_test_report_node.py +153 -0
  312. QuantNodes/research/factor_test/nodes/group_analyzer_node.py +317 -0
  313. QuantNodes/research/factor_test/nodes/ic_analyzer_node.py +112 -0
  314. QuantNodes/research/factor_test/nodes/load_data_node.py +100 -0
  315. QuantNodes/research/factor_test/nodes/long_short_node.py +93 -0
  316. QuantNodes/research/factor_test/nodes/neutralizers.py +222 -0
  317. QuantNodes/research/factor_test/nodes/preprocess_strategies.py +277 -0
  318. QuantNodes/research/factor_test/nodes/risk_correlation_node.py +112 -0
  319. QuantNodes/research/factor_test/nodes/sample_pool_filter_node.py +110 -0
  320. QuantNodes/research/factor_test/nodes/tradability_filter_node.py +92 -0
  321. QuantNodes/research/factor_test/pipeline_runner.py +305 -0
  322. QuantNodes/research/factor_test/pipeline_spec.py +216 -0
  323. QuantNodes/research/factor_test/utils/__init__.py +26 -0
  324. QuantNodes/research/factor_test/utils/constants.py +86 -0
  325. QuantNodes/research/factor_test/utils/data_loader.py +141 -0
  326. QuantNodes/research/factor_test/utils/date_utils.py +232 -0
  327. QuantNodes/research/factor_test/utils/file_loaders.py +150 -0
  328. QuantNodes/research/factor_test/utils/labels.py +37 -0
  329. QuantNodes/research/factor_test/utils/metrics_extractor.py +55 -0
  330. QuantNodes/research/factor_test/utils/performance_metrics.py +175 -0
  331. QuantNodes/research/factor_test/utils/safe_load.py +106 -0
  332. QuantNodes/research/quant_alpha/CHANGELOG.md +80 -0
  333. QuantNodes/research/quant_alpha/README.md +142 -0
  334. QuantNodes/research/quant_alpha/__init__.py +45 -0
  335. QuantNodes/research/quant_alpha/adapters/__init__.py +99 -0
  336. QuantNodes/research/quant_alpha/adapters/calculator.py +503 -0
  337. QuantNodes/research/quant_alpha/adapters/expression.py +387 -0
  338. QuantNodes/research/quant_alpha/alpha101_design/__init__.py +50 -0
  339. QuantNodes/research/quant_alpha/alpha101_design/few_shot_examples.py +243 -0
  340. QuantNodes/research/quant_alpha/alpha101_design/philosophy.py +474 -0
  341. QuantNodes/research/quant_alpha/alpha158_design/__init__.py +63 -0
  342. QuantNodes/research/quant_alpha/alpha158_design/few_shot_examples.py +219 -0
  343. QuantNodes/research/quant_alpha/alpha158_design/philosophy.py +240 -0
  344. QuantNodes/research/quant_alpha/evaluation/__init__.py +47 -0
  345. QuantNodes/research/quant_alpha/evaluation/baselines/__init__.py +8 -0
  346. QuantNodes/research/quant_alpha/evaluation/baselines/g1_handcrafted.py +135 -0
  347. QuantNodes/research/quant_alpha/evaluation/baselines/g2_llm_only.py +269 -0
  348. QuantNodes/research/quant_alpha/evaluation/baselines/g3_alpha_gpt.py +152 -0
  349. QuantNodes/research/quant_alpha/evaluation/clickhouse_data_loader.py +227 -0
  350. QuantNodes/research/quant_alpha/evaluation/contracts.py +376 -0
  351. QuantNodes/research/quant_alpha/evaluation/evaluators/__init__.py +6 -0
  352. QuantNodes/research/quant_alpha/evaluation/evaluators/polars_evaluator.py +545 -0
  353. QuantNodes/research/quant_alpha/evaluation/mock_data_loader.py +226 -0
  354. QuantNodes/research/quant_alpha/evaluation/runner.py +243 -0
  355. QuantNodes/research/quant_alpha/llm/__init__.py +38 -0
  356. QuantNodes/research/quant_alpha/llm/parser.py +681 -0
  357. QuantNodes/research/quant_alpha/logic_driven_pipeline.py +411 -0
  358. QuantNodes/research/quant_alpha/logic_mining/__init__.py +74 -0
  359. QuantNodes/research/quant_alpha/logic_mining/compiler.py +457 -0
  360. QuantNodes/research/quant_alpha/logic_mining/generator.py +366 -0
  361. QuantNodes/research/quant_alpha/logic_mining/models.py +252 -0
  362. QuantNodes/research/quant_alpha/logic_mining/parser.py +287 -0
  363. QuantNodes/research/quant_alpha/logic_mining/pipelines.py +297 -0
  364. QuantNodes/research/quant_alpha/logic_mining/sources.py +149 -0
  365. QuantNodes/research/quant_alpha/mcts/__init__.py +66 -0
  366. QuantNodes/research/quant_alpha/mcts/cache.py +262 -0
  367. QuantNodes/research/quant_alpha/mcts/extension_ops.py +320 -0
  368. QuantNodes/research/quant_alpha/mcts/feedback.py +825 -0
  369. QuantNodes/research/quant_alpha/mcts/op_prior.py +180 -0
  370. QuantNodes/research/quant_alpha/mcts/search.py +540 -0
  371. QuantNodes/research/quant_alpha/mcts/tree.py +201 -0
  372. QuantNodes/research/quant_alpha/operator_vocab/__init__.py +50 -0
  373. QuantNodes/research/quant_alpha/operator_vocab/config.py +54 -0
  374. QuantNodes/research/quant_alpha/operator_vocab/metadata.py +263 -0
  375. QuantNodes/research/quant_alpha/operator_vocab/vocabulary.py +481 -0
  376. QuantNodes/research/quant_alpha/pipeline.py +1027 -0
  377. QuantNodes/research/quant_alpha/types/__init__.py +27 -0
  378. QuantNodes/research/quant_alpha/types/constants.py +28 -0
  379. QuantNodes/research/quant_alpha/types/state.py +205 -0
  380. QuantNodes/research/quant_alpha/workflow/__init__.py +32 -0
  381. QuantNodes/research/quant_alpha/workflow/alpha_gpt.py +911 -0
  382. QuantNodes/research/quant_alpha/workflow/alpha_logics.py +416 -0
  383. QuantNodes/research/quant_alpha/workflow/state.py +27 -0
  384. QuantNodes/research/report_reproducer.py +485 -0
  385. QuantNodes/research/wiki.py +1155 -0
  386. QuantNodes/symbolic/__init__.py +51 -0
  387. QuantNodes/symbolic/compiler.py +113 -0
  388. QuantNodes/symbolic/dialect.py +260 -0
  389. QuantNodes/symbolic/executor.py +147 -0
  390. QuantNodes/symbolic/expression.py +234 -0
  391. QuantNodes/symbolic/functions.py +433 -0
  392. QuantNodes/symbolic/optimizer.py +165 -0
  393. QuantNodes/ui_node/__init__.py +30 -0
  394. QuantNodes/ui_node/base.py +222 -0
  395. quantnodes-3.0.0.dist-info/METADATA +463 -0
  396. quantnodes-3.0.0.dist-info/RECORD +399 -0
  397. quantnodes-3.0.0.dist-info/WHEEL +5 -0
  398. quantnodes-3.0.0.dist-info/entry_points.txt +24 -0
  399. quantnodes-3.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,503 @@
1
+ # coding=utf-8
2
+ """
3
+ adapters/calculator.py - AlphaCalculator ABC + PolarsAlphaCalculator
4
+
5
+ 参考:AlphaGen (KDD 2023, github.com/ICT-FinD-Lab/alphagen)
6
+ 源文件: alphagen/data/calculator.py::AlphaCalculator
7
+
8
+ AlphaGen 用 7 个抽象方法把"数据后端"和"RL 训练"解耦:
9
+ - calc_single_IC_ret: 单因子 IC(与单期前瞻收益)
10
+ - calc_single_rIC_ret: 单因子 rank IC
11
+ - calc_single_all_ret: 单因子 vs 多期前瞻
12
+ - calc_mutual_IC: 两因子互 IC(用于去重)
13
+ - calc_pool_IC_ret: 因子集合 ensemble IC(joint 优化用)
14
+ - calc_pool_rIC_ret: 因子集合 ensemble rank IC
15
+ - calc_pool_all_ret: 因子集合 vs 多期前瞻
16
+
17
+ AlphaGen 默认实现用 qlib 数据后端,本模块用 QuantNodes
18
+ 的 OperatorVocab + polars 重新实现,让 QuantNodes 算子可被
19
+ 任何 RL 训练脚本使用(无需 qlib 依赖)。
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import logging
25
+ from abc import ABC, abstractmethod
26
+ from typing import Any, Dict, List, Optional, Sequence, Union
27
+
28
+ import numpy as np
29
+ import polars as pl
30
+
31
+ from QuantNodes.research.quant_alpha.adapters.expression import (
32
+ Expression,
33
+ expression_to_formula,
34
+ )
35
+ from QuantNodes.research.quant_alpha.operator_vocab import OperatorVocab
36
+
37
+ logger = logging.getLogger(__name__)
38
+
39
+
40
+ # ==============================================================================
41
+ # 抽象基类
42
+ # ==============================================================================
43
+
44
+
45
+ class BaseAlphaCalculator(ABC):
46
+ """AlphaGen 兼容的 AlphaCalculator 抽象基类
47
+
48
+ 任何 RL 训练(AlphaGen / Alpha² / 自研)只需实现这 7 个方法,
49
+ 即可用 QuantNodes 算子 + factor_test 评估。
50
+
51
+ M4 范围:仅提供 ABC 接口。
52
+ PolarsAlphaCalculator 是参考实现。
53
+ """
54
+
55
+ @abstractmethod
56
+ def calc_single_IC_ret(self, expr: Expression, ret_offset: int = 1) -> np.ndarray:
57
+ """单因子 IC(与单期前瞻收益的 Pearson 相关系数序列)
58
+
59
+ Args:
60
+ expr: 因子表达式
61
+ ret_offset: 前瞻期数(1 = 1 日后,5 = 5 日后)
62
+
63
+ Returns:
64
+ np.ndarray of shape (n_dates,): 每个日期的截面 IC
65
+ """
66
+ raise NotImplementedError
67
+
68
+ @abstractmethod
69
+ def calc_single_rIC_ret(self, expr: Expression, ret_offset: int = 1) -> np.ndarray:
70
+ """单因子 rank IC(Spearman 秩相关)
71
+
72
+ Args:
73
+ expr: 因子表达式
74
+ ret_offset: 前瞻期数
75
+
76
+ Returns:
77
+ np.ndarray of shape (n_dates,): 每个日期的截面 rank IC
78
+ """
79
+ raise NotImplementedError
80
+
81
+ @abstractmethod
82
+ def calc_single_all_ret(self, expr: Expression) -> np.ndarray:
83
+ """单因子 vs 多期前瞻(多步 IC)
84
+
85
+ Args:
86
+ expr: 因子表达式
87
+
88
+ Returns:
89
+ np.ndarray of shape (n_dates, n_ret_offsets): 每对 (date, offset) 的 IC
90
+ """
91
+ raise NotImplementedError
92
+
93
+ @abstractmethod
94
+ def calc_mutual_IC(self, expr1: Expression, expr2: Expression) -> np.ndarray:
95
+ """两因子互 IC(用于去重)
96
+
97
+ Args:
98
+ expr1, expr2: 两个因子表达式
99
+
100
+ Returns:
101
+ np.ndarray of shape (n_dates,): 每个日期的两因子 Pearson 相关
102
+ """
103
+ raise NotImplementedError
104
+
105
+ @abstractmethod
106
+ def calc_pool_IC_ret(
107
+ self,
108
+ exprs: List[Expression],
109
+ weights: Optional[List[float]] = None,
110
+ ret_offset: int = 1,
111
+ ) -> np.ndarray:
112
+ """因子集合的 ensemble IC(joint 优化用)
113
+
114
+ ensemble = sum(weight * factor_i)
115
+
116
+ Args:
117
+ exprs: 因子表达式列表
118
+ weights: 因子权重(None=等权)
119
+ ret_offset: 前瞻期数
120
+
121
+ Returns:
122
+ np.ndarray of shape (n_dates,): 每个日期的 ensemble IC
123
+ """
124
+ raise NotImplementedError
125
+
126
+ @abstractmethod
127
+ def calc_pool_rIC_ret(
128
+ self,
129
+ exprs: List[Expression],
130
+ weights: Optional[List[float]] = None,
131
+ ret_offset: int = 1,
132
+ ) -> np.ndarray:
133
+ """因子集合的 ensemble rank IC
134
+
135
+ Args:
136
+ exprs: 因子表达式列表
137
+ weights: 因子权重(None=等权)
138
+ ret_offset: 前瞻期数
139
+
140
+ Returns:
141
+ np.ndarray of shape (n_dates,): 每个日期的 ensemble rank IC
142
+ """
143
+ raise NotImplementedError
144
+
145
+ @abstractmethod
146
+ def calc_pool_all_ret(
147
+ self,
148
+ exprs: List[Expression],
149
+ weights: Optional[List[float]] = None,
150
+ ) -> np.ndarray:
151
+ """因子集合 vs 多期前瞻(多步 ensemble IC)
152
+
153
+ Args:
154
+ exprs: 因子表达式列表
155
+ weights: 因子权重(None=等权)
156
+
157
+ Returns:
158
+ np.ndarray of shape (n_dates, n_ret_offsets)
159
+ """
160
+ raise NotImplementedError
161
+
162
+
163
+ # ==============================================================================
164
+ # Polars 实现
165
+ # ==============================================================================
166
+
167
+
168
+ class PolarsAlphaCalculator(BaseAlphaCalculator):
169
+ """基于 polars + OperatorVocab 的 AlphaCalculator 参考实现
170
+
171
+ 设计原则:
172
+ - 用 OperatorVocab.evaluate() 计算因子值(162 算子 + per-date over())
173
+ - 用 polars 原生 corr() 计算截面 IC
174
+ - 用 per-date cross_sectional 语义(与 M1 修复一致)
175
+
176
+ 示例:
177
+ >>> from QuantNodes.research.quant_alpha.adapters import PolarsAlphaCalculator
178
+ >>> from QuantNodes.research.quant_alpha.adapters.expression import *
179
+ >>> import polars as pl
180
+ >>> df = pl.DataFrame({...}) # 行情数据
181
+ >>> forward_returns = {1: df["forward_return_1d"]} # 前瞻收益
182
+ >>> calc = PolarsAlphaCalculator(df, forward_returns)
183
+ >>> expr = Sub(Ref(Feature("close"), 5), Feature("close"))
184
+ >>> ic = calc.calc_single_IC_ret(expr, ret_offset=1)
185
+ """
186
+
187
+ def __init__(
188
+ self,
189
+ data: pl.DataFrame,
190
+ forward_returns: Dict[int, pl.Series],
191
+ date_column: str = "date",
192
+ code_column: str = "code",
193
+ vocab: Optional[OperatorVocab] = None,
194
+ cross_sectional: bool = True,
195
+ ):
196
+ """
197
+ Args:
198
+ data: 行情数据(必须包含 date_column)
199
+ forward_returns: {前瞻期: 前瞻收益 Series} 映射
200
+ 例: {1: ret_1d_series, 5: ret_5d_series}
201
+ date_column: 日期列名
202
+ code_column: 股票代码列名
203
+ vocab: OperatorVocab 实例(None=默认)
204
+ cross_sectional: rank/zscore 是否 per-date 截面
205
+ """
206
+ # 重要:按 (code_column, date_column) 排序,确保 ts_*/rolling_* 算子
207
+ # 在每只股票内独立计算(否则跨股票滚动会出错)
208
+ self.data = data.sort([code_column, date_column])
209
+ self.forward_returns = forward_returns
210
+ self.date_column = date_column
211
+ self.code_column = code_column
212
+ self.vocab = vocab or OperatorVocab.default()
213
+ self.cross_sectional = cross_sectional
214
+ # 缓存:避免重复计算
215
+ self._factor_cache: Dict[str, pl.Series] = {}
216
+
217
+ # ==================================================================
218
+ # 核心:因子计算(带缓存)
219
+ # ==================================================================
220
+
221
+ def _evaluate_factor(
222
+ self,
223
+ expr: Expression,
224
+ ) -> Optional[pl.Series]:
225
+ """计算因子值(带缓存)"""
226
+ formula = expression_to_formula(expr)
227
+ if formula in self._factor_cache:
228
+ return self._factor_cache[formula]
229
+ try:
230
+ result = self.vocab.evaluate(
231
+ formula=formula,
232
+ data=self.data,
233
+ date_column=self.date_column,
234
+ code_column=self.code_column,
235
+ cross_sectional=self.cross_sectional,
236
+ )
237
+ if result is not None:
238
+ self._factor_cache[formula] = result
239
+ return result
240
+ except Exception as e:
241
+ logger.debug("Factor eval failed: formula=%r, error=%s", formula, e)
242
+ return None
243
+
244
+ def _evaluate_factors(
245
+ self,
246
+ exprs: List[Expression],
247
+ ) -> List[Optional[pl.Series]]:
248
+ """计算多个因子值"""
249
+ return [self._evaluate_factor(e) for e in exprs]
250
+
251
+ # ==================================================================
252
+ # 截面 IC 计算(per-date)
253
+ # ==================================================================
254
+
255
+ def _per_date_pearson_ic(
256
+ self,
257
+ factor: pl.Series,
258
+ target: pl.Series,
259
+ ) -> np.ndarray:
260
+ """per-date Pearson IC
261
+
262
+ Returns:
263
+ np.ndarray: 每个日期的 IC(无效日期为 NaN)
264
+ """
265
+ df = self.data.select([
266
+ pl.col(self.date_column).alias("_d"),
267
+ ]).with_columns([
268
+ factor.alias("_f"),
269
+ target.alias("_t"),
270
+ ]).filter(
271
+ pl.col("_f").is_not_null() & pl.col("_t").is_not_null()
272
+ )
273
+ if len(df) == 0:
274
+ return np.array([], dtype=np.float64)
275
+
276
+ per_date = df.group_by("_d").agg(
277
+ pl.corr("_f", "_t").alias("_ic")
278
+ ).sort("_d")
279
+
280
+ return per_date["_ic"].to_numpy().astype(np.float64)
281
+
282
+ def _per_date_spearman_ic(
283
+ self,
284
+ factor: pl.Series,
285
+ target: pl.Series,
286
+ ) -> np.ndarray:
287
+ """per-date Spearman rank IC
288
+
289
+ Returns:
290
+ np.ndarray: 每个日期的 rank IC
291
+ """
292
+ df = self.data.select([
293
+ pl.col(self.date_column).alias("_d"),
294
+ ]).with_columns([
295
+ factor.rank().alias("_f"),
296
+ target.rank().alias("_t"),
297
+ ]).filter(
298
+ pl.col("_f").is_not_null() & pl.col("_t").is_not_null()
299
+ )
300
+ if len(df) == 0:
301
+ return np.array([], dtype=np.float64)
302
+
303
+ per_date = df.group_by("_d").agg(
304
+ pl.corr("_f", "_t").alias("_ic")
305
+ ).sort("_d")
306
+
307
+ return per_date["_ic"].to_numpy().astype(np.float64)
308
+
309
+ def _per_date_pearson_corr(
310
+ self,
311
+ f1: pl.Series,
312
+ f2: pl.Series,
313
+ ) -> np.ndarray:
314
+ """per-date 两因子互 IC(Pearson)"""
315
+ df = self.data.select([
316
+ pl.col(self.date_column).alias("_d"),
317
+ ]).with_columns([
318
+ f1.alias("_f1"),
319
+ f2.alias("_f2"),
320
+ ]).filter(
321
+ pl.col("_f1").is_not_null() & pl.col("_f2").is_not_null()
322
+ )
323
+ if len(df) == 0:
324
+ return np.array([], dtype=np.float64)
325
+
326
+ per_date = df.group_by("_d").agg(
327
+ pl.corr("_f1", "_f2").alias("_ic")
328
+ ).sort("_d")
329
+
330
+ return per_date["_ic"].to_numpy().astype(np.float64)
331
+
332
+ # ==================================================================
333
+ # 7 个 ABC 方法实现
334
+ # ==================================================================
335
+
336
+ def calc_single_IC_ret(
337
+ self, expr: Expression, ret_offset: int = 1,
338
+ ) -> np.ndarray:
339
+ factor = self._evaluate_factor(expr)
340
+ if factor is None:
341
+ return np.array([], dtype=np.float64)
342
+ ret = self.forward_returns.get(ret_offset)
343
+ if ret is None:
344
+ raise ValueError(
345
+ f"No forward return for offset {ret_offset}. "
346
+ f"Available: {list(self.forward_returns.keys())}"
347
+ )
348
+ return self._per_date_pearson_ic(factor, ret)
349
+
350
+ def calc_single_rIC_ret(
351
+ self, expr: Expression, ret_offset: int = 1,
352
+ ) -> np.ndarray:
353
+ factor = self._evaluate_factor(expr)
354
+ if factor is None:
355
+ return np.array([], dtype=np.float64)
356
+ ret = self.forward_returns.get(ret_offset)
357
+ if ret is None:
358
+ raise ValueError(
359
+ f"No forward return for offset {ret_offset}. "
360
+ f"Available: {list(self.forward_returns.keys())}"
361
+ )
362
+ return self._per_date_spearman_ic(factor, ret)
363
+
364
+ def calc_single_all_ret(
365
+ self, expr: Expression,
366
+ ) -> np.ndarray:
367
+ """多步 IC:(n_dates, n_ret_offsets)"""
368
+ factor = self._evaluate_factor(expr)
369
+ if factor is None:
370
+ n_dates = self.data[self.date_column].n_unique()
371
+ return np.full(
372
+ (n_dates, len(self.forward_returns)),
373
+ np.nan, dtype=np.float64,
374
+ )
375
+ results = []
376
+ for offset in sorted(self.forward_returns.keys()):
377
+ ret = self.forward_returns[offset]
378
+ ic = self._per_date_pearson_ic(factor, ret)
379
+ results.append(ic)
380
+ # 对齐长度
381
+ max_len = max(len(r) for r in results)
382
+ padded = []
383
+ for r in results:
384
+ if len(r) < max_len:
385
+ r = np.concatenate([r, np.full(max_len - len(r), np.nan)])
386
+ padded.append(r)
387
+ return np.stack(padded, axis=-1) # (n_dates, n_offsets)
388
+
389
+ def calc_mutual_IC(
390
+ self, expr1: Expression, expr2: Expression,
391
+ ) -> np.ndarray:
392
+ f1 = self._evaluate_factor(expr1)
393
+ f2 = self._evaluate_factor(expr2)
394
+ if f1 is None or f2 is None:
395
+ return np.array([], dtype=np.float64)
396
+ return self._per_date_pearson_corr(f1, f2)
397
+
398
+ def _build_ensemble(
399
+ self,
400
+ factors: List[pl.Series],
401
+ weights: List[float],
402
+ ) -> pl.Series:
403
+ """构造 ensemble = sum(weight_i * factor_i)"""
404
+ if not factors:
405
+ raise ValueError("No factors to ensemble")
406
+ # 过滤掉 None
407
+ valid = [(f, w) for f, w in zip(factors, weights) if f is not None]
408
+ if not valid:
409
+ raise ValueError("No valid factors to ensemble")
410
+ # 等权归一化
411
+ total_w = sum(w for _, w in valid)
412
+ if total_w == 0:
413
+ weights = [1.0 / len(valid)] * len(valid)
414
+ else:
415
+ weights = [w / total_w for _, w in valid]
416
+ # 加权求和
417
+ ensemble = None
418
+ for (factor, _), w in zip(valid, weights):
419
+ if ensemble is None:
420
+ ensemble = w * factor.fill_null(0.0)
421
+ else:
422
+ ensemble = ensemble + w * factor.fill_null(0.0)
423
+ return ensemble
424
+
425
+ def calc_pool_IC_ret(
426
+ self,
427
+ exprs: List[Expression],
428
+ weights: Optional[List[float]] = None,
429
+ ret_offset: int = 1,
430
+ ) -> np.ndarray:
431
+ if not exprs:
432
+ raise ValueError("exprs is empty")
433
+ if weights is None:
434
+ weights = [1.0 / len(exprs)] * len(exprs)
435
+ factors = self._evaluate_factors(exprs)
436
+ ensemble = self._build_ensemble(factors, weights)
437
+ ret = self.forward_returns.get(ret_offset)
438
+ if ret is None:
439
+ raise ValueError(
440
+ f"No forward return for offset {ret_offset}. "
441
+ f"Available: {list(self.forward_returns.keys())}"
442
+ )
443
+ return self._per_date_pearson_ic(ensemble, ret)
444
+
445
+ def calc_pool_rIC_ret(
446
+ self,
447
+ exprs: List[Expression],
448
+ weights: Optional[List[float]] = None,
449
+ ret_offset: int = 1,
450
+ ) -> np.ndarray:
451
+ if not exprs:
452
+ raise ValueError("exprs is empty")
453
+ if weights is None:
454
+ weights = [1.0 / len(exprs)] * len(exprs)
455
+ factors = self._evaluate_factors(exprs)
456
+ ensemble = self._build_ensemble(factors, weights)
457
+ ret = self.forward_returns.get(ret_offset)
458
+ if ret is None:
459
+ raise ValueError(
460
+ f"No forward return for offset {ret_offset}. "
461
+ f"Available: {list(self.forward_returns.keys())}"
462
+ )
463
+ return self._per_date_spearman_ic(ensemble, ret)
464
+
465
+ def calc_pool_all_ret(
466
+ self,
467
+ exprs: List[Expression],
468
+ weights: Optional[List[float]] = None,
469
+ ) -> np.ndarray:
470
+ if not exprs:
471
+ raise ValueError("exprs is empty")
472
+ if weights is None:
473
+ weights = [1.0 / len(exprs)] * len(exprs)
474
+ factors = self._evaluate_factors(exprs)
475
+ ensemble = self._build_ensemble(factors, weights)
476
+ # 多步前瞻
477
+ results = []
478
+ for offset in sorted(self.forward_returns.keys()):
479
+ ret = self.forward_returns[offset]
480
+ ic = self._per_date_pearson_ic(ensemble, ret)
481
+ results.append(ic)
482
+ max_len = max(len(r) for r in results)
483
+ padded = []
484
+ for r in results:
485
+ if len(r) < max_len:
486
+ r = np.concatenate([r, np.full(max_len - len(r), np.nan)])
487
+ padded.append(r)
488
+ return np.stack(padded, axis=-1)
489
+
490
+ # ==================================================================
491
+ # 工具方法
492
+ # ==================================================================
493
+
494
+ def stats(self) -> Dict[str, Any]:
495
+ """计算器统计"""
496
+ return {
497
+ "n_factors_cached": len(self._factor_cache),
498
+ "n_data_rows": len(self.data),
499
+ "n_dates": self.data[self.date_column].n_unique(),
500
+ "n_codes": self.data[self.code_column].n_unique(),
501
+ "forward_returns": sorted(self.forward_returns.keys()),
502
+ "cross_sectional": self.cross_sectional,
503
+ }