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,365 @@
1
+ """Dashboard — 6 个 Plotly 图的 HTML 仪表板。
2
+
3
+ 3 类指标 × 2 个图 (汇总 + per-round) = 6 个 figure + 1 个概览表。
4
+
5
+ 图列表:
6
+ 1. RAG 折线 (HR@5/NDCG@5/MRR/Diversity 随 round 变化)
7
+ 2. RAG 散点 (NDCG@5 vs HR@5 关联性)
8
+ 3. 演化柱状 (pool_size / total / rejected per round)
9
+ 4. 演化折线 (best_metric 趋势)
10
+ 5. Quality Gate 堆叠柱 (3 通道 pass/fail)
11
+ 6. Quality Gate 拦截率折线 (per-round rejection rate)
12
+ """
13
+ from __future__ import annotations
14
+
15
+ from datetime import datetime
16
+ from pathlib import Path
17
+ from typing import Any
18
+
19
+ import pandas as pd
20
+
21
+ from .collector import MetricCollector
22
+ from QuantNodes.core.path_utils import ensure_parent
23
+
24
+ # Module-level lazy import for plotly. We try once at import time; if
25
+ # plotly is not installed, ``_PLOTLY_GO`` is None and the figure
26
+ # functions below return None. The HTML generators downstream skip
27
+ # None figures gracefully.
28
+ try:
29
+ import plotly.graph_objects as _PLOTLY_GO # noqa: F401
30
+ except ImportError:
31
+ _PLOTLY_GO = None
32
+
33
+ import warnings
34
+ warnings.warn(
35
+ "plotly not installed; visualization dashboard figures will be "
36
+ "skipped. Install plotly for full dashboard rendering: "
37
+ "pip install plotly",
38
+ ImportWarning,
39
+ stacklevel=1,
40
+ )
41
+
42
+
43
+ def _require_plotly_go():
44
+ """Return plotly's graph_objects or raise a clear ImportError.
45
+
46
+ Use this inside figure functions to give a friendly error message
47
+ when the user tries to render figures without plotly installed.
48
+ """
49
+ if _PLOTLY_GO is None:
50
+ raise ImportError(
51
+ "plotly is required for figure rendering. "
52
+ "Install with: pip install plotly"
53
+ )
54
+ return _PLOTLY_GO
55
+
56
+
57
+ def _fig_rag_lines(c: MetricCollector) -> Any:
58
+ """RAG 指标折线: HR/NDCG/MRR/Diversity 随 round。"""
59
+ if _PLOTLY_GO is None:
60
+ return None
61
+ go = _PLOTLY_GO
62
+ if not c.rag_history:
63
+ fig = go.Figure()
64
+ fig.update_layout(title="RAG 指标 (无数据)")
65
+ return fig
66
+ df = pd.DataFrame([m.__dict__ for m in c.rag_history])
67
+ fig = go.Figure()
68
+ for col, name, color in [
69
+ ("hit_at_5", "HitRate@5", "#2E86AB"),
70
+ ("ndcg_at_5", "NDCG@5", "#A23B72"),
71
+ ("mrr", "MRR", "#F18F01"),
72
+ ("diversity", "Diversity", "#6A994E"),
73
+ ]:
74
+ if col in df.columns:
75
+ fig.add_trace(go.Scatter(
76
+ x=df["round"], y=df[col], mode="lines+markers",
77
+ name=name, line=dict(color=color, width=2),
78
+ ))
79
+ fig.update_layout(
80
+ title="RAG 指标趋势 (per round)",
81
+ xaxis_title="round", yaxis_title="score",
82
+ height=400, plot_bgcolor="white",
83
+ )
84
+ return fig
85
+
86
+
87
+ def _fig_rag_scatter(c: MetricCollector) -> Any:
88
+ """RAG NDCG vs HitRate 散点。"""
89
+ if _PLOTLY_GO is None:
90
+ return None
91
+ go = _PLOTLY_GO
92
+ if not c.rag_history:
93
+ fig = go.Figure()
94
+ fig.update_layout(title="RAG 散点 (无数据)")
95
+ return fig
96
+ df = pd.DataFrame([m.__dict__ for m in c.rag_history])
97
+ fig = go.Figure()
98
+ fig.add_trace(go.Scatter(
99
+ x=df["hit_at_5"], y=df["ndcg_at_5"],
100
+ mode="markers+text", text=df["round"],
101
+ marker=dict(size=12, color="#4C78A8"),
102
+ hovertemplate="round %{text}<br>HR@5=%{x:.3f}<br>NDCG@5=%{y:.3f}<extra></extra>",
103
+ ))
104
+ fig.update_layout(
105
+ title="RAG: HitRate@5 vs NDCG@5",
106
+ xaxis_title="HitRate@5", yaxis_title="NDCG@5",
107
+ height=350, plot_bgcolor="white",
108
+ )
109
+ return fig
110
+
111
+
112
+ def _fig_evolution_bar(c: MetricCollector) -> Any:
113
+ """演化统计柱状: total / rejected per round。"""
114
+ if _PLOTLY_GO is None:
115
+ return None
116
+ go = _PLOTLY_GO
117
+ if not c.evolution_history:
118
+ fig = go.Figure()
119
+ fig.update_layout(title="演化统计 (无数据)")
120
+ return fig
121
+ df = pd.DataFrame([m.__dict__ for m in c.evolution_history])
122
+ fig = go.Figure()
123
+ fig.add_trace(go.Bar(x=df["round"], y=df["total_count"],
124
+ name="passed", marker_color="#54A24B"))
125
+ fig.add_trace(go.Bar(x=df["round"], y=df["rejected_count"],
126
+ name="rejected", marker_color="#E45756"))
127
+ fig.update_layout(
128
+ title="演化统计 (per round)",
129
+ barmode="stack", xaxis_title="round", yaxis_title="count",
130
+ height=400, plot_bgcolor="white",
131
+ )
132
+ return fig
133
+
134
+
135
+ def _fig_evolution_line(c: MetricCollector) -> Any:
136
+ """best_metric 折线趋势。"""
137
+ if _PLOTLY_GO is None:
138
+ return None
139
+ go = _PLOTLY_GO
140
+ if not c.evolution_history:
141
+ fig = go.Figure()
142
+ fig.update_layout(title="Best metric 趋势 (无数据)")
143
+ return fig
144
+ df = pd.DataFrame([m.__dict__ for m in c.evolution_history])
145
+ fig = go.Figure()
146
+ fig.add_trace(go.Scatter(
147
+ x=df["round"], y=df["best_metric"],
148
+ mode="lines+markers+text", text=df["best_factor_name"],
149
+ textposition="top center",
150
+ line=dict(color="#06A77D", width=3),
151
+ marker=dict(size=12),
152
+ ))
153
+ fig.update_layout(
154
+ title="Best Metric 趋势 (per round)",
155
+ xaxis_title="round", yaxis_title="best metric",
156
+ height=400, plot_bgcolor="white",
157
+ )
158
+ return fig
159
+
160
+
161
+ def _fig_quality_stacked(c: MetricCollector) -> Any:
162
+ """Quality Gate 3 通道 pass/fail 堆叠柱。"""
163
+ if _PLOTLY_GO is None:
164
+ return None
165
+ go = _PLOTLY_GO
166
+ if not c.quality_history:
167
+ fig = go.Figure()
168
+ fig.update_layout(title="Quality Gate (无数据)")
169
+ return fig
170
+ df = pd.DataFrame([m.__dict__ for m in c.quality_history])
171
+ channels = ["code", "value", "llm"]
172
+ pass_by_ch = {ch: [getattr(m, f"{ch}_pass") for m in c.quality_history] for ch in channels}
173
+ fail_by_ch = {ch: [getattr(m, f"{ch}_fail") for m in c.quality_history] for ch in channels}
174
+ fig = go.Figure()
175
+ for ch in channels:
176
+ fig.add_trace(go.Bar(name=f"{ch} pass", x=df["round"], y=pass_by_ch[ch],
177
+ marker_color="#54A24B",
178
+ legendgroup=ch, offsetgroup=ch))
179
+ fig.add_trace(go.Bar(name=f"{ch} fail", x=df["round"], y=fail_by_ch[ch],
180
+ marker_color="#E45756",
181
+ legendgroup=ch, offsetgroup=ch))
182
+ fig.update_layout(
183
+ title="Quality Gate 3 通道 (per round)",
184
+ barmode="stack", xaxis_title="round", yaxis_title="count",
185
+ height=400, plot_bgcolor="white",
186
+ )
187
+ return fig
188
+
189
+
190
+ def _fig_quality_rejection(c: MetricCollector) -> Any:
191
+ """Quality Gate 拦截率折线。"""
192
+ if _PLOTLY_GO is None:
193
+ return None
194
+ go = _PLOTLY_GO
195
+ if not c.quality_history:
196
+ fig = go.Figure()
197
+ fig.update_layout(title="Quality 拦截率 (无数据)")
198
+ return fig
199
+ df_dicts = []
200
+ for m in c.quality_history:
201
+ for ch in ("code", "value", "llm"):
202
+ pass_n = getattr(m, f"{ch}_pass")
203
+ fail_n = getattr(m, f"{ch}_fail")
204
+ total = pass_n + fail_n
205
+ rate = fail_n / total if total > 0 else 0.0
206
+ df_dicts.append({
207
+ "round": m.round, "channel": ch,
208
+ "rejection_rate": rate, "total": total,
209
+ })
210
+ df = pd.DataFrame(df_dicts)
211
+ fig = go.Figure()
212
+ colors = {"code": "#4C78A8", "value": "#F58518", "llm": "#E45756"}
213
+ for ch in ("code", "value", "llm"):
214
+ sub = df[df["channel"] == ch]
215
+ if sub.empty:
216
+ continue
217
+ fig.add_trace(go.Scatter(
218
+ x=sub["round"], y=sub["rejection_rate"],
219
+ mode="lines+markers", name=ch,
220
+ line=dict(color=colors[ch], width=2),
221
+ ))
222
+ fig.update_layout(
223
+ title="Quality Gate 拦截率 (per channel, per round)",
224
+ xaxis_title="round", yaxis_title="rejection rate",
225
+ yaxis=dict(range=[0, 1]),
226
+ height=400, plot_bgcolor="white",
227
+ )
228
+ return fig
229
+
230
+
231
+ _OVERVIEW_TEMPLATE = """
232
+ <h2>概览</h2>
233
+ <table border="1" cellpadding="6" style="border-collapse:collapse;">
234
+ <tr><th>指标</th><th>值</th></tr>
235
+ <tr><td>RAG 数据点</td><td>{n_rag}</td></tr>
236
+ <tr><td>演化数据点</td><td>{n_evo}</td></tr>
237
+ <tr><td>质量门数据点</td><td>{n_qg}</td></tr>
238
+ <tr><td>最终 best metric</td><td>{best_metric:.4f}</td></tr>
239
+ <tr><td>最终 best factor</td><td>{best_factor}</td></tr>
240
+ <tr><td>生成时间</td><td>{timestamp}</td></tr>
241
+ </table>
242
+ """
243
+
244
+
245
+ def generate_dashboard_html(
246
+ collector: MetricCollector,
247
+ title: str = "QuantNodes 演化 Dashboard",
248
+ output_path: Path | str | None = None,
249
+ streaming: bool = False,
250
+ refresh_interval_sec: int = 10,
251
+ ) -> str:
252
+ """生成完整 HTML dashboard, 6 figure + 概览表。
253
+
254
+ Args:
255
+ streaming: True → 加 JS 定时刷新 (读取同目录 metrics.json)
256
+ refresh_interval_sec: 刷新间隔秒数 (默认 10s)
257
+ """
258
+
259
+ figures = [
260
+ ("rag_lines", "RAG 指标趋势", _fig_rag_lines(collector)),
261
+ ("rag_scatter", "RAG HR@5 vs NDCG@5", _fig_rag_scatter(collector)),
262
+ ("evo_bar", "演化统计 (per round)", _fig_evolution_bar(collector)),
263
+ ("evo_line", "Best Metric 趋势", _fig_evolution_line(collector)),
264
+ ("qg_stacked", "Quality Gate 通道", _fig_quality_stacked(collector)),
265
+ ("qg_rejection", "Quality 拦截率", _fig_quality_rejection(collector)),
266
+ ]
267
+
268
+ overview = {
269
+ "n_rag": len(collector.rag_history),
270
+ "n_evo": len(collector.evolution_history),
271
+ "n_qg": len(collector.quality_history),
272
+ "best_metric": (
273
+ collector.evolution_history[-1].best_metric
274
+ if collector.evolution_history else 0.0
275
+ ),
276
+ "best_factor": (
277
+ collector.evolution_history[-1].best_factor_name
278
+ if collector.evolution_history else "(none)"
279
+ ),
280
+ "timestamp": datetime.now().isoformat(),
281
+ }
282
+
283
+ fig_html_parts = []
284
+ for key, name, fig in figures:
285
+ if fig is None:
286
+ # plotly not installed — skip the figure but keep the section
287
+ fig_html_parts.append(
288
+ f"<h2>{name}</h2>\n<p><em>(plotly not installed — install with "
289
+ f"<code>pip install plotly</code> to render this chart)</em></p>"
290
+ )
291
+ continue
292
+ fig_html = fig.to_html(full_html=False, include_plotlyjs=False, div_id=f"fig_{key}")
293
+ fig_html_parts.append(f"<h2>{name}</h2>\n{fig_html}")
294
+
295
+ plotly_cdn = '<script src="https://cdn.plot.ly/plotly-2.27.0.min.js"></script>'
296
+
297
+ # Streaming JS (可选)
298
+ streaming_js = ""
299
+ if streaming:
300
+ # JS: 定时刷新, 检测 metrics.json 变化后重新加载
301
+ streaming_js = f"""
302
+ <script>
303
+ (function() {{
304
+ var INTERVAL = {refresh_interval_sec} * 1000;
305
+ var lastModified = 0;
306
+ var metricsPath = "{str(Path(output_path).parent / (Path(output_path).stem + '_metrics.json'))
307
+ if output_path else 'metrics.json'}";
308
+
309
+ function checkUpdate() {{
310
+ fetch(metricsPath + '?t=' + Date.now(), {{method: 'HEAD'}})
311
+ .then(r => {{
312
+ var m = new Date(r.headers.get('Last-Modified') || 0).getTime();
313
+ if (m > lastModified) {{
314
+ lastModified = m;
315
+ location.reload();
316
+ }}
317
+ }})
318
+ .catch(() => {{}});
319
+ }}
320
+
321
+ setInterval(checkUpdate, INTERVAL);
322
+ console.log("[Streaming] 每 {refresh_interval_sec}s 检测更新...");
323
+ </script>
324
+ """
325
+ streaming_badge = (
326
+ '<span style="background:#06A77D;color:white;padding:2px 8px;'
327
+ 'border-radius:4px;font-size:12px;margin-left:10px;">LIVE</span>'
328
+ if streaming else ""
329
+ )
330
+
331
+ html = f"""<!DOCTYPE html>
332
+ <html lang="zh-CN">
333
+ <head>
334
+ <meta charset="utf-8">
335
+ <title>{title}</title>
336
+ <style>
337
+ body {{ font-family: -apple-system, sans-serif; margin: 20px; max-width: 1400px; }}
338
+ h1 {{ border-bottom: 2px solid #4C78A8; padding-bottom: 8px; }}
339
+ h2 {{ border-top: 1px solid #ddd; padding-top: 12px; color: #2E86AB; }}
340
+ table {{ background: #fafafa; }}
341
+ th {{ background: #4C78A8; color: white; }}
342
+ .live-badge {{ animation: pulse 2s infinite; }}
343
+ @keyframes pulse {{ 0%, 100% {{ opacity: 1; }} 50% {{ opacity: 0.5; }} }}
344
+ </style>
345
+ {plotly_cdn}
346
+ </head>
347
+ <body>
348
+ <h1>{title} {streaming_badge}</h1>
349
+ {_OVERVIEW_TEMPLATE.format(**overview)}
350
+ {"".join(fig_html_parts)}
351
+ <hr>
352
+ <p style="color: #888; font-size: 12px;">
353
+ 生成自 QuantNodes 演化框架 (Week 16 Streaming Dashboard)
354
+ {' · 自动刷新: ' + str(refresh_interval_sec) + 's' if streaming else ''}
355
+ </p>
356
+ {streaming_js}
357
+ </body>
358
+ </html>
359
+ """
360
+
361
+ if output_path is not None:
362
+ output_path = Path(output_path)
363
+ ensure_parent(output_path)
364
+ output_path.write_text(html, encoding="utf-8")
365
+ return html