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,408 @@
1
+ # coding=utf-8
2
+ """
3
+ operators.custom - 用户友好自定义算子 API
4
+
5
+ 提供装饰器风格和 Builder 风格的算子定义接口。
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import inspect
11
+ from datetime import datetime
12
+ from typing import Any, Callable, Dict, List, Optional, Union
13
+
14
+ from polars import Expr
15
+
16
+ from QuantNodes.operators.registry import _CustomOperatorRegistry
17
+ from QuantNodes.operators.templates import OperatorTemplate
18
+
19
+
20
+ class CustomOperatorBuilder:
21
+ """链式构建器"""
22
+
23
+ def __init__(self, name: str, category: str):
24
+ self._name = name
25
+ self._category = category
26
+ self._params: Dict[str, dict] = {}
27
+ self._func: Optional[Callable] = None
28
+ self._doc: str = ""
29
+ self._aliases: List[str] = []
30
+ self._decorator_mode: bool = False
31
+
32
+ def param(
33
+ self, name: str, type_: Any = None, default: Any = None, desc: str = ""
34
+ ) -> "CustomOperatorBuilder":
35
+ """声明参数"""
36
+ self._params[name] = {"type": type_, "default": default, "desc": desc}
37
+ return self
38
+
39
+ def execute(self, func: Callable) -> "CustomOperatorBuilder":
40
+ """设置执行函数"""
41
+ self._func = func
42
+ return self
43
+
44
+ def doc(self, docstring: str) -> "CustomOperatorBuilder":
45
+ """设置文档"""
46
+ self._doc = docstring
47
+ return self
48
+
49
+ def alias(self, name: str) -> "CustomOperatorBuilder":
50
+ """添加别名"""
51
+ self._aliases.append(name)
52
+ return self
53
+
54
+ def register(self) -> Callable:
55
+ """注册并返回被装饰的函数"""
56
+ if self._func is None:
57
+ raise ValueError("execute() must be called before register()")
58
+
59
+ return self._do_register(self._func)
60
+
61
+ def _do_register(self, func: Callable) -> Callable:
62
+ """执行注册逻辑"""
63
+ if self._func is None:
64
+ self._func = func
65
+
66
+ sig = inspect.signature(self._func)
67
+
68
+ if not self._doc:
69
+ params_parts = []
70
+ for n, v in self._params.items():
71
+ if v["default"] is not None:
72
+ params_parts.append(f"{n}={v['default']!r}")
73
+ else:
74
+ params_parts.append(n)
75
+ params_str = ", ".join(params_parts)
76
+ self._doc = f"{self._name}({params_str})"
77
+
78
+ original_func = self._func
79
+
80
+ def wrapper(f: Union[Expr, str], **kwargs) -> Expr:
81
+ args = [f]
82
+ for param_name, param_info in self._params.items():
83
+ if param_name not in kwargs and param_info["default"] is not None:
84
+ kwargs[param_name] = param_info["default"]
85
+ bound = sig.bind(*args, **kwargs)
86
+ return original_func(*bound.args, **bound.kwargs)
87
+
88
+ wrapper.__name__ = self._name
89
+ wrapper.__qualname__ = f"CustomOperator.{self._name}"
90
+ wrapper.__doc__ = self._doc
91
+
92
+ _CustomOperatorRegistry.register(
93
+ self._category,
94
+ self._name,
95
+ wrapper,
96
+ self._doc,
97
+ self._params,
98
+ self._aliases,
99
+ )
100
+
101
+ for alias in self._aliases:
102
+ _CustomOperatorRegistry.register_alias(alias, self._name, self._category)
103
+
104
+ return wrapper
105
+
106
+ def __call__(self, func: Callable) -> Callable:
107
+ """当作为装饰器使用时直接注册"""
108
+ return self._do_register(func)
109
+
110
+
111
+ class CustomOperator:
112
+ """自定义算子工厂(类方法集合)"""
113
+
114
+ @classmethod
115
+ def point(cls, name: str) -> CustomOperatorBuilder:
116
+ """创建 point 算子构建器"""
117
+ return CustomOperatorBuilder(name, "point")
118
+
119
+ @classmethod
120
+ def time(cls, name: str) -> CustomOperatorBuilder:
121
+ """创建 time 算子构建器"""
122
+ return CustomOperatorBuilder(name, "time")
123
+
124
+ @classmethod
125
+ def section(cls, name: str) -> CustomOperatorBuilder:
126
+ """创建 section 算子构建器"""
127
+ return CustomOperatorBuilder(name, "section")
128
+
129
+ @classmethod
130
+ def multi_section(cls, name: str) -> CustomOperatorBuilder:
131
+ """创建 multi_section 算子构建器"""
132
+ return CustomOperatorBuilder(name, "multi_section")
133
+
134
+ @classmethod
135
+ def talib(cls, name: str) -> CustomOperatorBuilder:
136
+ """创建 talib 算子构建器"""
137
+ return CustomOperatorBuilder(name, "talib")
138
+
139
+ @classmethod
140
+ def from_template(
141
+ cls, name: str, template: str, category: str = None, **defaults
142
+ ) -> OperatorTemplate:
143
+ """基于模板创建算子"""
144
+ return OperatorTemplate(name, category or "time", template, defaults)
145
+
146
+ @classmethod
147
+ def time_from(cls, name: str, template: str, **defaults) -> OperatorTemplate:
148
+ """基于 time 模板创建算子"""
149
+ return OperatorTemplate(name, "time", template, defaults)
150
+
151
+ @classmethod
152
+ def section_from(
153
+ cls, name: str, template: str, **defaults
154
+ ) -> OperatorTemplate:
155
+ """基于 section 模板创建算子"""
156
+ return OperatorTemplate(name, "section", template, defaults)
157
+
158
+ @classmethod
159
+ def point_from(
160
+ cls, name: str, template: str, **defaults
161
+ ) -> OperatorTemplate:
162
+ """基于 point 模板创建算子"""
163
+ return OperatorTemplate(name, "point", template, defaults)
164
+
165
+ @classmethod
166
+ def list(
167
+ cls, category: Optional[str] = None, include_builtin: bool = False
168
+ ) -> List[str]:
169
+ """列出算子"""
170
+ custom = _CustomOperatorRegistry.list(category)
171
+ if not include_builtin:
172
+ return custom
173
+ from QuantNodes.factor_node.factor_functions import list_operators
174
+
175
+ builtin = list_operators(category)
176
+ seen = set()
177
+ result = []
178
+ for name in custom + builtin:
179
+ if name not in seen:
180
+ seen.add(name)
181
+ result.append(name)
182
+ return result
183
+
184
+ @classmethod
185
+ def get(cls, name: str) -> Optional[Callable]:
186
+ """获取算子函数(先查自定义,再查内置)"""
187
+ func = _CustomOperatorRegistry.get(name)
188
+ if func:
189
+ return func
190
+ from QuantNodes.factor_node.factor_functions import get_operator
191
+
192
+ return get_operator(name)
193
+
194
+ @classmethod
195
+ def info(cls, name: str) -> Optional[Dict[str, Any]]:
196
+ """获取算子详细信息"""
197
+ info = _CustomOperatorRegistry.info(name)
198
+ if info:
199
+ return info
200
+ from QuantNodes.factor_node.factor_functions import operator_info
201
+
202
+ return operator_info(name)
203
+
204
+ @classmethod
205
+ def unregister(cls, name: str) -> bool:
206
+ """注销自定义算子"""
207
+ return _CustomOperatorRegistry.unregister(name)
208
+
209
+ @classmethod
210
+ def unregister_all(cls) -> int:
211
+ """注销所有自定义算子"""
212
+ return _CustomOperatorRegistry.unregister_all()
213
+
214
+ @classmethod
215
+ def register(
216
+ cls, category: str, name: str, func: Callable, **kwargs
217
+ ) -> Callable:
218
+ """
219
+ 直接注册自定义算子的便捷方法
220
+
221
+ Args:
222
+ category: 算子类别 ("point", "time", "section", "multi_section", "talib")
223
+ name: 算子名称
224
+ func: 算子函数
225
+ **kwargs: 额外参数
226
+
227
+ Returns:
228
+ 注册后的函数
229
+
230
+ Example:
231
+ >>> def my_double(f, multiplier=2.0):
232
+ ... return f * multiplier
233
+ >>> CustomOperator.register("point", "my_double", my_double)
234
+ """
235
+ _CustomOperatorRegistry.register(category, name, func, **kwargs)
236
+ return func
237
+
238
+ @classmethod
239
+ def count(cls) -> int:
240
+ """返回自定义算子数量"""
241
+ return _CustomOperatorRegistry.count()
242
+
243
+ @classmethod
244
+ def export(cls, path: str, format: str = "yaml") -> None:
245
+ """导出到 YAML/JSON"""
246
+ data = {
247
+ "version": 1,
248
+ "exported_at": datetime.now().isoformat(),
249
+ "operators": [],
250
+ }
251
+
252
+ for cat in _CustomOperatorRegistry._registry:
253
+ for name, info in _CustomOperatorRegistry._registry[cat].items():
254
+ op_data = {
255
+ "name": name,
256
+ "category": cat,
257
+ "doc": info.get("doc", ""),
258
+ "source": info.get("source", ""),
259
+ }
260
+ params = info.get("params", {})
261
+ if params:
262
+ op_data["params"] = params
263
+ data["operators"].append(op_data)
264
+
265
+ if format == "yaml":
266
+ import yaml
267
+
268
+ with open(path, "w", encoding="utf-8") as f:
269
+ yaml.dump(data, f, allow_unicode=True, sort_keys=False)
270
+ else:
271
+ import json
272
+
273
+ with open(path, "w", encoding="utf-8") as f:
274
+ json.dump(data, f, indent=2, ensure_ascii=False)
275
+
276
+ @classmethod
277
+ def import_(cls, path: str) -> int:
278
+ """从 YAML/JSON 导入,返回导入数量"""
279
+ import yaml
280
+
281
+ with open(path, encoding="utf-8") as f:
282
+ data = yaml.safe_load(f)
283
+
284
+ count = 0
285
+ for op in data.get("operators", []):
286
+ source = op.get("source", "")
287
+ if source:
288
+ namespace = {}
289
+ exec(source, namespace)
290
+ func = namespace.get(op["name"])
291
+ if func:
292
+ _CustomOperatorRegistry.register(
293
+ op["category"],
294
+ op["name"],
295
+ func,
296
+ op.get("doc", ""),
297
+ op.get("params", {}),
298
+ )
299
+ count += 1
300
+ return count
301
+
302
+
303
+ def _make_decorator(category: str):
304
+ """创建分类装饰器"""
305
+
306
+ def decorator(name: str):
307
+ def wrapper(func: Callable) -> Callable:
308
+ _CustomOperatorRegistry.register(
309
+ category,
310
+ name,
311
+ func,
312
+ inspect.getdoc(func) or "",
313
+ )
314
+
315
+ def _wrapper(f: Union[Expr, str], **kwargs) -> Expr:
316
+ return func(f, **kwargs)
317
+
318
+ _wrapper.__name__ = func.__name__
319
+ _wrapper.__doc__ = func.__doc__
320
+ return _wrapper
321
+
322
+ return decorator(name) if callable(name) else lambda f: decorator(name)(f)
323
+
324
+ return decorator
325
+
326
+
327
+ def _register_point(name: str) -> Callable:
328
+ """point 算子装饰器"""
329
+
330
+ def decorator(func: Callable) -> Callable:
331
+ _CustomOperatorRegistry.register(
332
+ "point",
333
+ name,
334
+ func,
335
+ inspect.getdoc(func) or "",
336
+ )
337
+
338
+ def _wrapper(f: Union[Expr, str], **kwargs) -> Expr:
339
+ return func(f, **kwargs)
340
+
341
+ _wrapper.__name__ = func.__name__
342
+ _wrapper.__doc__ = func.__doc__
343
+ return _wrapper
344
+
345
+ return decorator
346
+
347
+
348
+ def point(name: str) -> Callable:
349
+ """point 算子装饰器"""
350
+
351
+ def decorator(func: Callable) -> Callable:
352
+ _CustomOperatorRegistry.register(
353
+ "point",
354
+ name,
355
+ func,
356
+ inspect.getdoc(func) or "",
357
+ )
358
+
359
+ def _wrapper(f: Union[Expr, str], **kwargs) -> Expr:
360
+ return func(f, **kwargs)
361
+
362
+ _wrapper.__name__ = func.__name__
363
+ _wrapper.__doc__ = func.__doc__
364
+ return _wrapper
365
+
366
+ return decorator
367
+
368
+
369
+ def time(name: str) -> Callable:
370
+ """time 算子装饰器"""
371
+
372
+ def decorator(func: Callable) -> Callable:
373
+ _CustomOperatorRegistry.register(
374
+ "time",
375
+ name,
376
+ func,
377
+ inspect.getdoc(func) or "",
378
+ )
379
+
380
+ def _wrapper(f: Union[Expr, str], **kwargs) -> Expr:
381
+ return func(f, **kwargs)
382
+
383
+ _wrapper.__name__ = func.__name__
384
+ _wrapper.__doc__ = func.__doc__
385
+ return _wrapper
386
+
387
+ return decorator
388
+
389
+
390
+ def section(name: str) -> Callable:
391
+ """section 算子装饰器"""
392
+
393
+ def decorator(func: Callable) -> Callable:
394
+ _CustomOperatorRegistry.register(
395
+ "section",
396
+ name,
397
+ func,
398
+ inspect.getdoc(func) or "",
399
+ )
400
+
401
+ def _wrapper(f: Union[Expr, str], **kwargs) -> Expr:
402
+ return func(f, **kwargs)
403
+
404
+ _wrapper.__name__ = func.__name__
405
+ _wrapper.__doc__ = func.__doc__
406
+ return _wrapper
407
+
408
+ return decorator
@@ -0,0 +1,164 @@
1
+ # coding=utf-8
2
+ """
3
+ operators.facade - 算子统一查询门面 (Facade, Phase 3.2, 2026-06-22)
4
+
5
+ QuantNodes 有 3 个并列的算子注册表 (docs/26 §3.3):
6
+
7
+ L0 内置 (_OPERATOR_REGISTRY) factor_node/factor_functions
8
+ L1 复合 DAG (_COMPOSITE_REGISTRY) operators/composite_dag.py
9
+ L2 自定义 (_CustomOperatorRegistry) operators/registry.py
10
+
11
+ 调用方 (agent/config/executor.py, loader.py) 此前需分别 import:
12
+ - get_operator / list_operators / operator_info (L0, 内部已级联 L2)
13
+ - is_composite_op / get_composite_spec / list_composite_ops (L1, 完全隔离)
14
+ - CustomOperator.get / _CustomOperatorRegistry.list (L2)
15
+
16
+ 本 Facade 提供**单一只读入口**统一这 3 层查询, 调用方只需:
17
+
18
+ from QuantNodes.operators import operator_facade as ops
19
+ fn = ops.resolve("ts_mean") # L0/L2 callable
20
+ spec = ops.get_composite(name) # L1 CompositeSpec
21
+ if ops.exists(name): ...
22
+ ops.kind(name) # -> "custom" / "builtin" / "composite" / None
23
+ ops.list_all() # 三层去重合并
24
+
25
+ 设计要点 (Facade 模式):
26
+ - **只委托, 不改行为**: 全部转调既有函数, 与旧 API bitwise 一致 (向后兼容)。
27
+ - **只读**: 注册仍走各自的 @register_operator / @composite_operator /
28
+ CustomOperator (写路径不收敛, 避免破坏隔离语义)。
29
+ - L0 的 ``get_operator`` 本身已级联 L2 (custom→builtin), Facade 借此保持
30
+ 与旧查询完全一致的优先级; L1 因严格隔离 (见 composite_dag.py:137-146)
31
+ 单独暴露 ``get_composite`` / ``is_composite``。
32
+ """
33
+ from __future__ import annotations
34
+
35
+ from typing import Any, Callable, Dict, List, Optional, TYPE_CHECKING
36
+
37
+ if TYPE_CHECKING:
38
+ from QuantNodes.operators.composite_dag import CompositeSpec
39
+
40
+
41
+ class OperatorFacade:
42
+ """3 层算子注册表的统一只读门面.
43
+
44
+ 所有方法均委托给既有查询函数, 不缓存、不持有状态, 因此对运行时新增的
45
+ 算子注册 (custom / composite) 实时可见。
46
+ """
47
+
48
+ # ---- L0 + L2 (callable 级联查询) ----
49
+
50
+ def resolve(self, name: str, category: Optional[str] = None) -> Optional[Callable]:
51
+ """获取算子 callable (级联: 自定义 L2 → 内置 L0)。
52
+
53
+ 与 ``factor_functions.get_operator`` 行为完全一致。composite (L1) 不在
54
+ 此返回 (它们不是直接 callable), 请用 :meth:`get_composite`。
55
+ """
56
+ from QuantNodes.factor_node.factor_functions import get_operator
57
+
58
+ return get_operator(name, category)
59
+
60
+ def info(self, name: str, category: Optional[str] = None) -> Optional[Dict[str, Any]]:
61
+ """获取算子详细信息 dict (级联: L2 → L0)。"""
62
+ from QuantNodes.factor_node.factor_functions import operator_info
63
+
64
+ return operator_info(name, category)
65
+
66
+ # ---- L1 (composite, 隔离查询) ----
67
+
68
+ def get_composite(self, name: str, engine: str = "any") -> Optional["CompositeSpec"]:
69
+ """获取 composite DAG 的 ``CompositeSpec`` (L1, 与 L0/L2 隔离)。
70
+
71
+ Args:
72
+ name: 算子名
73
+ engine: "any" (default) | "polars" | "pandas"
74
+ """
75
+ from QuantNodes.operators.composite_dag import get_composite_spec
76
+
77
+ return get_composite_spec(name, engine=engine)
78
+
79
+ def is_composite(self, name: str, engine: str = "any") -> bool:
80
+ """判断 name 是否是 composite 算子 (L1)。
81
+
82
+ Args:
83
+ name: 算子名
84
+ engine: "any" (default) | "polars" | "pandas"
85
+ """
86
+ from QuantNodes.operators.composite_dag import is_composite_op
87
+
88
+ return is_composite_op(name, engine=engine)
89
+
90
+ # ---- 跨层统一查询 ----
91
+
92
+ def exists(self, name: str) -> bool:
93
+ """name 是否在任一层注册 (callable 或 composite)。"""
94
+ if self.is_composite(name):
95
+ return True
96
+ return self.resolve(name) is not None
97
+
98
+ def kind(self, name: str) -> Optional[str]:
99
+ """返回 name 所属层: ``"custom"`` / ``"builtin"`` / ``"composite"`` / ``None``.
100
+
101
+ 优先级与查询级联一致 (custom → builtin → composite)。同名时返回最先
102
+ 命中的层 (与 :meth:`resolve` 实际返回的实现保持一致)。
103
+ """
104
+ from QuantNodes.operators.registry import _CustomOperatorRegistry
105
+
106
+ if _CustomOperatorRegistry.get(name) is not None:
107
+ return "custom"
108
+ if self.resolve(name) is not None:
109
+ return "builtin"
110
+ if self.is_composite(name):
111
+ return "composite"
112
+ return None
113
+
114
+ def list_all(
115
+ self,
116
+ category: Optional[str] = None,
117
+ include_custom: bool = True,
118
+ include_composite: bool = True,
119
+ ) -> List[str]:
120
+ """列出三层算子名 (去重, 保持 custom → builtin → composite 顺序)。
121
+
122
+ Args:
123
+ category: 限定类别 (point/time/section/multi_section/talib)。
124
+ include_custom: 是否含 L2 自定义 (默认 True)。
125
+ include_composite: 是否含 L1 composite (默认 True)。
126
+ """
127
+ from QuantNodes.factor_node.factor_functions import list_operators
128
+
129
+ # list_operators 已做 custom(L2) + builtin(L0) 去重合并
130
+ names = list(list_operators(category=category, include_custom=include_custom))
131
+
132
+ if include_composite:
133
+ from QuantNodes.operators.composite_dag import list_composite_ops
134
+
135
+ seen = set(names)
136
+ for name in list_composite_ops(category=category):
137
+ if name not in seen:
138
+ seen.add(name)
139
+ names.append(name)
140
+ return names
141
+
142
+ def documentation(
143
+ self, output_format: str = "markdown", category: Optional[str] = None
144
+ ) -> str:
145
+ """生成 L0 内置算子文档 (委托 ``generate_documentation``)。
146
+
147
+ composite (L1) 的 LLM 文档另有专用入口 :meth:`composite_doc_for_llm`。
148
+ """
149
+ from QuantNodes.factor_node.factor_functions import generate_documentation
150
+
151
+ return generate_documentation(output_format=output_format, category=category)
152
+
153
+ def composite_doc_for_llm(self) -> str:
154
+ """生成 composite (L1) 给 LLM 的 markdown 文档。"""
155
+ from QuantNodes.operators.composite_dag import get_composite_doc_for_llm
156
+
157
+ return get_composite_doc_for_llm()
158
+
159
+ def __repr__(self) -> str:
160
+ return "<OperatorFacade L0+L1+L2 unified read-only>"
161
+
162
+
163
+ # 模块级单例 — 调用方统一从这里查询
164
+ operator_facade = OperatorFacade()