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,287 @@
1
+ # coding=utf-8
2
+ """
3
+ parser.py - Logic Mining 输出解析
4
+
5
+ 解析三个 Agent 的输出 JSON,包含 Schema 校验和默认值。
6
+
7
+ Usage::
8
+
9
+ from QuantNodes.research.quant_alpha.logic_mining.parser import (
10
+ parse_formula_structure, parse_financial_semantics,
11
+ parse_market_logic, _mock_structure_response, _mock_semantics_response,
12
+ _mock_abstraction_response,
13
+ )
14
+
15
+ structure = parse_formula_structure(llm_output)
16
+ semantics = parse_financial_semantics(llm_output)
17
+ logic = parse_market_logic(llm_output)
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import json
23
+ import logging
24
+ import re
25
+ from dataclasses import dataclass
26
+ from typing import Any, Dict, List, Optional, Tuple
27
+
28
+ logger = logging.getLogger(__name__)
29
+
30
+ __all__ = [
31
+ "ParseResult",
32
+ "parse_json_response",
33
+ "parse_formula_structure",
34
+ "parse_financial_semantics",
35
+ "parse_market_logic",
36
+ "_mock_structure_response",
37
+ "_mock_semantics_response",
38
+ "_mock_abstraction_response",
39
+ ]
40
+
41
+
42
+ @dataclass
43
+ class ParseResult:
44
+ """JSON 解析结果"""
45
+ ok: bool
46
+ data: Optional[Dict[str, Any]] = None
47
+ error: Optional[str] = None
48
+ raw: str = ""
49
+
50
+
51
+ def parse_json_response(raw: str) -> ParseResult:
52
+ """三层 fallback JSON parser
53
+
54
+ 1. 直接 json.loads
55
+ 2. 从 markdown ```json ... ``` 中提取
56
+ 3. 从文本中找第一个 {...} 块
57
+
58
+ Args:
59
+ raw: LLM 输出文本
60
+
61
+ Returns:
62
+ ParseResult
63
+ """
64
+ if not raw:
65
+ return ParseResult(ok=False, error="empty response", raw=raw)
66
+
67
+ # 第 1 层: 直接 JSON
68
+ try:
69
+ return ParseResult(ok=True, data=json.loads(raw), raw=raw)
70
+ except json.JSONDecodeError:
71
+ pass
72
+
73
+ # 第 2 层: 从 ```json ... ``` 中提取
74
+ md_match = re.search(r"```(?:json)?\s*(\{.*?\})\s*```", raw, re.DOTALL)
75
+ if md_match:
76
+ try:
77
+ return ParseResult(ok=True, data=json.loads(md_match.group(1)), raw=raw)
78
+ except json.JSONDecodeError:
79
+ pass
80
+
81
+ # 第 3 层: 找第一个 {...} 块
82
+ brace_match = re.search(r"\{.*\}", raw, re.DOTALL)
83
+ if brace_match:
84
+ try:
85
+ return ParseResult(ok=True, data=json.loads(brace_match.group(0)), raw=raw)
86
+ except json.JSONDecodeError:
87
+ pass
88
+
89
+ return ParseResult(ok=False, error="Cannot parse JSON after 3 layers", raw=raw)
90
+
91
+
92
+ def parse_formula_structure(raw: str) -> ParseResult:
93
+ """解析 FormulaStructureAgent 输出
94
+
95
+ 期望格式:
96
+ {
97
+ "operations": ["rank", "ts_corr"],
98
+ "window_length": 10,
99
+ "has_ranking": true,
100
+ "has_normalization": false
101
+ }
102
+ """
103
+ result = parse_json_response(raw)
104
+ if not result.ok:
105
+ return result
106
+
107
+ data = result.data
108
+ if not isinstance(data, dict):
109
+ return ParseResult(ok=False, error="data is not a dict", raw=raw)
110
+
111
+ # 必填字段验证
112
+ if "operations" not in data:
113
+ return ParseResult(ok=False, error="missing 'operations' field", raw=raw)
114
+
115
+ # 填充默认值
116
+ validated = {
117
+ "operations": data.get("operations", []),
118
+ "window_length": data.get("window_length", 0),
119
+ "has_ranking": data.get("has_ranking", False),
120
+ "has_normalization": data.get("has_normalization", False),
121
+ }
122
+
123
+ return ParseResult(ok=True, data=validated, raw=raw)
124
+
125
+
126
+ def parse_financial_semantics(raw: str) -> ParseResult:
127
+ """解析 FinancialSemanticsMappingAgent 输出
128
+
129
+ 期望格式:
130
+ {
131
+ "price_role": "initial reaction",
132
+ "volume_role": "participation",
133
+ "time_pattern": "persistent co-movement",
134
+ "behavior_interpretation": "lack of confirmation indicates reversal"
135
+ }
136
+ """
137
+ result = parse_json_response(raw)
138
+ if not result.ok:
139
+ return result
140
+
141
+ data = result.data
142
+ if not isinstance(data, dict):
143
+ return ParseResult(ok=False, error="data is not a dict", raw=raw)
144
+
145
+ validated = {
146
+ "price_role": data.get("price_role", "unknown"),
147
+ "volume_role": data.get("volume_role", "unknown"),
148
+ "time_pattern": data.get("time_pattern", "unknown"),
149
+ "behavior_interpretation": data.get("behavior_interpretation", "unknown"),
150
+ }
151
+
152
+ return ParseResult(ok=True, data=validated, raw=raw)
153
+
154
+
155
+ def parse_market_logic(raw: str) -> ParseResult:
156
+ """解析 MarketLogicAbstractionAgent 输出
157
+
158
+ 期望格式:
159
+ {
160
+ "predicates": [{"variable": "open", "op": "rank", "threshold": 0}],
161
+ "behavior": {"target": "forward_return_5", "direction": -1, "horizon": 5},
162
+ "operator_whitelist": ["rank", "ts_corr", "sign"],
163
+ "parameter_ranges": {"ts_corr": [5, 30]},
164
+ "sign_constraint": -1
165
+ }
166
+ """
167
+ result = parse_json_response(raw)
168
+ if not result.ok:
169
+ return result
170
+
171
+ data = result.data
172
+ if not isinstance(data, dict):
173
+ return ParseResult(ok=False, error="data is not a dict", raw=raw)
174
+
175
+ # 必填字段验证
176
+ if "predicates" not in data or "behavior" not in data:
177
+ return ParseResult(ok=False, error="missing 'predicates' or 'behavior'", raw=raw)
178
+
179
+ return ParseResult(ok=True, data=data, raw=raw)
180
+
181
+
182
+ # ==============================================================================
183
+ # Mock 响应(用于离线测试)
184
+ # ==============================================================================
185
+
186
+
187
+ def _mock_structure_response(formula: str) -> str:
188
+ """生成 FormulaStructureAgent 的 mock 响应"""
189
+ import re as _re
190
+
191
+ # 提取算子
192
+ ops = set(_re.findall(r"\b([a-zA-Z_]\w*)\s*\(", formula))
193
+ ops.discard("if")
194
+ ops.discard("else")
195
+
196
+ # 提取最大窗口
197
+ nums = [int(n) for n in _re.findall(r",\s*(\d+)\s*\)", formula)]
198
+ max_window = max(nums) if nums else 0
199
+
200
+ return json.dumps({
201
+ "operations": sorted(ops),
202
+ "window_length": max_window,
203
+ "has_ranking": "rank(" in formula,
204
+ "has_normalization": any(op in formula for op in ["zscore", "normalize"]),
205
+ })
206
+
207
+
208
+ def _mock_semantics_response(formula: str) -> str:
209
+ """生成 FinancialSemanticsMappingAgent 的 mock 响应"""
210
+ # 基于算子推断语义
211
+ has_corr = "corr(" in formula or "ts_corr" in formula
212
+ has_volume = "vol" in formula.lower() or "amount" in formula
213
+ has_ts_mean = "ts_mean(" in formula
214
+ has_rank = "rank(" in formula
215
+
216
+ price_role = "mean reversion" if "delta(" in formula else "trend indicator"
217
+ volume_role = "participation" if has_volume else "not used"
218
+ time_pattern = (
219
+ "windowed co-movement" if has_corr else
220
+ "moving average" if has_ts_mean else "single point"
221
+ )
222
+ behavior = (
223
+ "divergence signal" if has_corr and has_volume else
224
+ "momentum/reversal indicator" if has_rank else
225
+ "neutral"
226
+ )
227
+
228
+ return json.dumps({
229
+ "price_role": price_role,
230
+ "volume_role": volume_role,
231
+ "time_pattern": time_pattern,
232
+ "behavior_interpretation": behavior,
233
+ })
234
+
235
+
236
+ def _mock_abstraction_response(
237
+ formula: str,
238
+ structure: Dict[str, Any],
239
+ semantics: Dict[str, Any],
240
+ ) -> str:
241
+ """生成 MarketLogicAbstractionAgent 的 mock 响应"""
242
+ # 基于公式特征生成结构化逻辑
243
+ operations = structure.get("operations", [])
244
+ has_volume = semantics.get("volume_role", "not used") != "not used"
245
+ has_corr = "ts_corr" in operations or "corr" in operations
246
+ has_ts_mean = "ts_mean" in operations
247
+
248
+ # 行为推断
249
+ if has_corr and has_volume:
250
+ direction = -1 # 量价背离 → 反转
251
+ target = "forward_return_5"
252
+ horizon = 5
253
+ predicates = [
254
+ {"variable": "open", "op": "rank", "threshold": 0},
255
+ {"variable": "volume", "op": "rank", "threshold": 0},
256
+ {"variable": "open", "op": "ts_corr", "threshold": -0.5,
257
+ "window": 10, "second_variable": "volume"},
258
+ ]
259
+ whitelist = ["rank", "ts_corr", "sign", "sub", "mul", "div"]
260
+ param_ranges = {"ts_corr": [5, 30]}
261
+ sign = -1
262
+ elif has_ts_mean:
263
+ direction = -1
264
+ target = "forward_return_5"
265
+ horizon = 5
266
+ predicates = [
267
+ {"variable": "close", "op": "ts_mean", "threshold": 0, "window": 20},
268
+ ]
269
+ whitelist = ["ts_mean", "rank", "sub", "div", "sign"]
270
+ param_ranges = {"ts_mean": [5, 60]}
271
+ sign = -1
272
+ else:
273
+ direction = 1
274
+ target = "forward_return_1"
275
+ horizon = 1
276
+ predicates = [{"variable": "close", "op": "rank", "threshold": 0}]
277
+ whitelist = operations if operations else ["rank"]
278
+ param_ranges = {}
279
+ sign = 1
280
+
281
+ return json.dumps({
282
+ "predicates": predicates,
283
+ "behavior": {"target": target, "direction": direction, "horizon": horizon},
284
+ "operator_whitelist": whitelist,
285
+ "parameter_ranges": param_ranges,
286
+ "sign_constraint": sign,
287
+ })
@@ -0,0 +1,297 @@
1
+ # coding=utf-8
2
+ """
3
+ pipelines.py - Logic Mining 三段式 Agent Pipeline
4
+
5
+ 基于 AlphaLogics 论文 (arXiv 2603.20247) §3.1 实现。
6
+
7
+ 三段式流程:
8
+ FormulaStructureAgent → FinancialSemanticsMappingAgent → MarketLogicAbstractionAgent
9
+ → WikiLogicStructured
10
+
11
+ Usage::
12
+
13
+ from QuantNodes.research.quant_alpha.logic_mining.pipelines import (
14
+ LogicMiningPipeline, mine_logic_from_formula, build_initial_logic_library,
15
+ )
16
+
17
+ # 单条公式
18
+ logic = mine_logic_from_formula(
19
+ formula="-ts_corr(rank(open), rank(volume), 10)",
20
+ source_lib="alpha101",
21
+ )
22
+
23
+ # 批量构建逻辑库
24
+ logics = build_initial_logic_library(
25
+ source_libs=("alpha101", "alpha158"),
26
+ max_per_lib=20,
27
+ )
28
+ """
29
+
30
+ from __future__ import annotations
31
+
32
+ import logging
33
+ import re
34
+ from dataclasses import dataclass, field
35
+ from typing import Any, Dict, List, Optional, Tuple
36
+
37
+ from QuantNodes.research.quant_alpha.logic_mining.models import (
38
+ LogicBehavior,
39
+ LogicCondition,
40
+ LogicAbstractionResult,
41
+ WikiLogicStructured,
42
+ )
43
+ from QuantNodes.research.quant_alpha.logic_mining.parser import (
44
+ parse_financial_semantics,
45
+ parse_formula_structure,
46
+ parse_market_logic,
47
+ _mock_structure_response,
48
+ _mock_semantics_response,
49
+ _mock_abstraction_response,
50
+ )
51
+ from QuantNodes.research.quant_alpha.logic_mining.sources import get_formulas_from_source
52
+
53
+ logger = logging.getLogger(__name__)
54
+
55
+ __all__ = [
56
+ "LogicMiningPipeline",
57
+ "mine_logic_from_formula",
58
+ "build_initial_logic_library",
59
+ ]
60
+
61
+
62
+ def _call_llm(llm_client: Any, agent_id: str, prompt: str, default_response: str) -> str:
63
+ """调用 LLM,无客户端或失败时返回 mock"""
64
+ if llm_client is None:
65
+ return default_response
66
+
67
+ try:
68
+ if hasattr(llm_client, "complete"):
69
+ return llm_client.complete(agent_id=agent_id, prompt=prompt)
70
+ return llm_client(prompt)
71
+ except Exception as e:
72
+ logger.warning("LLM call failed for %s: %s, falling back to mock", agent_id, e)
73
+ return default_response
74
+
75
+
76
+ def _build_structure_prompt(formula: str) -> str:
77
+ """FormulaStructureAgent prompt"""
78
+ return (
79
+ f"Analyze the structure of this alpha formula:\n"
80
+ f" {formula}\n\n"
81
+ f"Output STRICT JSON with these fields:\n"
82
+ f"- operations: list of function names used\n"
83
+ f"- window_length: largest numeric window parameter\n"
84
+ f"- has_ranking: true if rank() is used\n"
85
+ f"- has_normalization: true if zscore/normalize is used\n\n"
86
+ f"Example output:\n"
87
+ f'{{"operations": ["rank", "ts_corr", "sign"], '
88
+ f'"window_length": 10, "has_ranking": true, "has_normalization": false}}'
89
+ )
90
+
91
+
92
+ def _build_semantics_prompt(formula: str, structure: Dict[str, Any]) -> str:
93
+ """FinancialSemanticsMappingAgent prompt"""
94
+ ops = structure.get("operations", [])
95
+ return (
96
+ f"Given formula: {formula}\n"
97
+ f"Operations: {ops}\n\n"
98
+ f"Map to financial semantics. Output STRICT JSON:\n"
99
+ f"- price_role: role of price (e.g., 'trend', 'reversion', 'momentum')\n"
100
+ f"- volume_role: role of volume ('participation', 'confirmation', 'not used')\n"
101
+ f"- time_pattern: time pattern ('windowed', 'moving average', 'cumulative')\n"
102
+ f"- behavior_interpretation: behavior interpretation (e.g., 'divergence signal')\n\n"
103
+ f'Example: {{"price_role": "trend", "volume_role": "participation", '
104
+ f'"time_pattern": "windowed", "behavior_interpretation": "divergence signal"}}'
105
+ )
106
+
107
+
108
+ def _build_abstraction_prompt(
109
+ formula: str,
110
+ structure: Dict[str, Any],
111
+ semantics: Dict[str, Any],
112
+ ) -> str:
113
+ """MarketLogicAbstractionAgent prompt"""
114
+ return (
115
+ f"Abstract this alpha into a formal market logic H = ⟨𝒞, ℬ⟩.\n\n"
116
+ f"Formula: {formula}\n"
117
+ f"Structure: {structure}\n"
118
+ f"Semantics: {semantics}\n\n"
119
+ f"Output STRICT JSON:\n"
120
+ f"- predicates: list of {{variable, op, threshold, window, second_variable}}\n"
121
+ f"- behavior: {{target, direction, horizon}} (target='forward_return_5', direction=+1/-1)\n"
122
+ f"- operator_whitelist: list of allowed operators\n"
123
+ f"- parameter_ranges: {{op: [min, max]}}\n"
124
+ f"- sign_constraint: +1/-1 or null\n\n"
125
+ f'Example: {{"predicates": [{{"variable": "open", "op": "ts_corr", '
126
+ f'"threshold": -0.5, "window": 10, "second_variable": "volume"}}], '
127
+ f'"behavior": {{"target": "forward_return_5", "direction": -1, "horizon": 5}}, '
128
+ f'"operator_whitelist": ["rank", "ts_corr", "sign"], '
129
+ f'"parameter_ranges": {{"ts_corr": [5, 30]}}, '
130
+ f'"sign_constraint": -1}}'
131
+ )
132
+
133
+
134
+ def _structured_from_dict(data: Dict[str, Any]) -> WikiLogicStructured:
135
+ """从 dict 构建 WikiLogicStructured"""
136
+ predicates = []
137
+ for p in data.get("predicates", []):
138
+ predicates.append(LogicCondition(
139
+ variable=p["variable"],
140
+ op=p["op"],
141
+ threshold=p.get("threshold", 0.0),
142
+ window=p.get("window"),
143
+ weight=p.get("weight", 1.0),
144
+ second_variable=p.get("second_variable"),
145
+ ))
146
+
147
+ beh_data = data.get("behavior", {})
148
+ behavior = LogicBehavior(
149
+ target=beh_data.get("target", "forward_return_5"),
150
+ direction=beh_data.get("direction", 1),
151
+ horizon=beh_data.get("horizon", 5),
152
+ )
153
+
154
+ param_ranges = None
155
+ if data.get("parameter_ranges"):
156
+ param_ranges = {k: tuple(v) for k, v in data["parameter_ranges"].items()}
157
+
158
+ return WikiLogicStructured(
159
+ predicates=predicates,
160
+ behavior=behavior,
161
+ operator_whitelist=data.get("operator_whitelist"),
162
+ parameter_ranges=param_ranges,
163
+ sign_constraint=data.get("sign_constraint"),
164
+ )
165
+
166
+
167
+ class LogicMiningPipeline:
168
+ """Logic Mining 三段式 Pipeline
169
+
170
+ FormulaStructureAgent → FinancialSemanticsMappingAgent → MarketLogicAbstractionAgent
171
+ """
172
+
173
+ def __init__(self, llm_client: Any = None):
174
+ self.llm_client = llm_client
175
+
176
+ def run(self, formula: str, source_lib: str = "alpha101") -> LogicAbstractionResult:
177
+ """运行三段式 Pipeline
178
+
179
+ Args:
180
+ formula: 因子公式字符串
181
+ source_lib: 来源库名称
182
+
183
+ Returns:
184
+ LogicAbstractionResult
185
+ """
186
+ result = LogicAbstractionResult(
187
+ source_formula=formula,
188
+ source_lib=source_lib,
189
+ )
190
+
191
+ # Step 1: FormulaStructureAgent
192
+ structure_resp = _call_llm(
193
+ self.llm_client,
194
+ "logic-mining-structure",
195
+ _build_structure_prompt(formula),
196
+ _mock_structure_response(formula),
197
+ )
198
+ struct_result = parse_formula_structure(structure_resp)
199
+ if not struct_result.ok:
200
+ logger.warning("FormulaStructureAgent parse failed: %s", struct_result.error)
201
+ result.formula_structure = {"operations": [], "window_length": 0,
202
+ "has_ranking": False, "has_normalization": False}
203
+ else:
204
+ result.formula_structure = struct_result.data
205
+
206
+ # Step 2: FinancialSemanticsMappingAgent
207
+ semantics_resp = _call_llm(
208
+ self.llm_client,
209
+ "logic-mining-semantics",
210
+ _build_semantics_prompt(formula, result.formula_structure),
211
+ _mock_semantics_response(formula),
212
+ )
213
+ sem_result = parse_financial_semantics(semantics_resp)
214
+ if not sem_result.ok:
215
+ logger.warning("FinancialSemanticsMappingAgent parse failed: %s", sem_result.error)
216
+ result.financial_semantics = {
217
+ "price_role": "unknown", "volume_role": "unknown",
218
+ "time_pattern": "unknown", "behavior_interpretation": "unknown",
219
+ }
220
+ else:
221
+ result.financial_semantics = sem_result.data
222
+
223
+ # Step 3: MarketLogicAbstractionAgent
224
+ abstract_resp = _call_llm(
225
+ self.llm_client,
226
+ "logic-mining-abstraction",
227
+ _build_abstraction_prompt(formula, result.formula_structure, result.financial_semantics),
228
+ _mock_abstraction_response(formula, result.formula_structure, result.financial_semantics),
229
+ )
230
+ abs_result = parse_market_logic(abstract_resp)
231
+ if not abs_result.ok:
232
+ logger.warning("MarketLogicAbstractionAgent parse failed: %s", abs_result.error)
233
+ return result
234
+
235
+ try:
236
+ result.structured_logic = _structured_from_dict(abs_result.data)
237
+ except (KeyError, TypeError) as e:
238
+ logger.warning("Failed to build WikiLogicStructured: %s", e)
239
+
240
+ return result
241
+
242
+
243
+ def mine_logic_from_formula(
244
+ formula: str,
245
+ source_lib: str = "alpha101",
246
+ llm_client: Any = None,
247
+ ) -> LogicAbstractionResult:
248
+ """从单条公式抽取市场逻辑(三段式)
249
+
250
+ Args:
251
+ formula: 因子公式字符串
252
+ source_lib: 来源库
253
+ llm_client: LLM 客户端 (None 时使用 mock)
254
+
255
+ Returns:
256
+ LogicAbstractionResult
257
+ """
258
+ pipeline = LogicMiningPipeline(llm_client=llm_client)
259
+ return pipeline.run(formula, source_lib)
260
+
261
+
262
+ def build_initial_logic_library(
263
+ source_libs: Tuple[str, ...] = ("alpha101", "alpha158"),
264
+ llm_client: Any = None,
265
+ max_per_lib: int = 20,
266
+ only_volume_price: bool = True,
267
+ ) -> List[LogicAbstractionResult]:
268
+ """构建初始逻辑库
269
+
270
+ Args:
271
+ source_libs: 来源库列表
272
+ llm_client: LLM 客户端
273
+ max_per_lib: 每个库最多提取多少条
274
+ only_volume_price: 仅提取量价类
275
+
276
+ Returns:
277
+ List of LogicAbstractionResult
278
+ """
279
+ pipeline = LogicMiningPipeline(llm_client=llm_client)
280
+ results = []
281
+
282
+ for lib in source_libs:
283
+ formulas = get_formulas_from_source(
284
+ lib, max_count=max_per_lib, only_volume_price=only_volume_price
285
+ )
286
+ logger.info("Mining %d formulas from %s", len(formulas), lib)
287
+
288
+ for f in formulas:
289
+ try:
290
+ result = pipeline.run(f["formula"], lib)
291
+ if result.structured_logic is not None:
292
+ results.append(result)
293
+ except Exception as e:
294
+ logger.warning("Failed to mine logic for %s: %s", f.get("id"), e)
295
+
296
+ logger.info("Built initial logic library: %d logics", len(results))
297
+ return results