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,28 @@
1
+ # coding=utf-8
2
+ """
3
+ OperatorNode 操作节点模块
4
+
5
+ 提供数据操作、SQL 构建和转换的节点类型:
6
+
7
+ - OperatorNode: 操作节点基类
8
+ - ChainOperator: 链式操作节点
9
+ - SQLBuilderNode: SQL 构建节点
10
+ - TableQueryNode: 表查询执行节点
11
+ - TransformNode: 数据转换节点
12
+ - SQLBuilder: SQL 构建工具类
13
+ """
14
+
15
+ from QuantNodes.operator_node.base import OperatorNode, ChainOperator
16
+ from QuantNodes.operator_node.sql_builder import SQLBuilderNode
17
+ from QuantNodes.operator_node.query_node import TableQueryNode
18
+ from QuantNodes.operator_node.transform import TransformNode
19
+ from QuantNodes.operator_node.sql_utils import SQLBuilder
20
+
21
+ __all__ = [
22
+ 'OperatorNode',
23
+ 'ChainOperator',
24
+ 'SQLBuilderNode',
25
+ 'TableQueryNode',
26
+ 'TransformNode',
27
+ 'SQLBuilder',
28
+ ]
@@ -0,0 +1,97 @@
1
+ # coding=utf-8
2
+ """
3
+ OperatorNode 基类模块
4
+
5
+ 提供操作节点的基础架构,继承自 BaseNode。
6
+ 用于数据操作、SQL 构建和转换。
7
+ """
8
+ from __future__ import annotations
9
+
10
+ from abc import ABC, abstractmethod
11
+ from typing import Any, Dict, List
12
+
13
+ from QuantNodes.core.node import BaseNode
14
+
15
+
16
+ class OperatorNode(BaseNode, ABC):
17
+ """
18
+ 操作节点基类
19
+
20
+ 所有数据操作节点都继承自此类,提供统一的操作接口。
21
+ 支持链式调用,可以像构建 SQL 一样组合操作。
22
+
23
+ Subclasses must implement:
24
+ _execute_operation(): 执行具体操作
25
+
26
+ Examples:
27
+ >>> query_node = TableQueryNode(table="users")
28
+ >>> result = query_node.execute()
29
+ """
30
+
31
+ def __init__(self, name: str = None, config: Dict[str, Any] = None, **kwargs):
32
+ super().__init__(name=name or self.__class__.__name__, config=config, **kwargs)
33
+ self._chained_result: Any = None
34
+
35
+ @abstractmethod
36
+ def _execute_operation(self, input_data: Any = None, **kwargs) -> Any:
37
+ """
38
+ 执行具体操作
39
+
40
+ Args:
41
+ input_data: 输入数据
42
+ **kwargs: 执行参数
43
+
44
+ Returns:
45
+ 操作结果
46
+ """
47
+ pass
48
+
49
+ def _execute(self, input_data: Any = None, **kwargs) -> Any:
50
+ """执行操作"""
51
+ return self._execute_operation(input_data, **kwargs)
52
+
53
+ def then(self, other: 'OperatorNode') -> 'ChainOperator':
54
+ """
55
+ 链式调用:将操作链接到另一个操作
56
+
57
+ Args:
58
+ other: 下一个操作节点
59
+
60
+ Returns:
61
+ ChainOperator 包含两个操作的链接
62
+ """
63
+ return ChainOperator([self, other])
64
+
65
+ def __rshift__(self, other: 'OperatorNode') -> 'ChainOperator':
66
+ """重载 >> 运算符支持链式调用"""
67
+ return self.then(other)
68
+
69
+
70
+ class ChainOperator(OperatorNode):
71
+ """
72
+ 链式操作节点
73
+
74
+ 将多个 OperatorNode 链接在一起执行。
75
+ """
76
+
77
+ def __init__(
78
+ self, operators: List[OperatorNode], name: str = None,
79
+ config: Dict[str, Any] = None,
80
+ ):
81
+ super().__init__(name=name or "Chain", config=config)
82
+ self.operators = operators
83
+
84
+ def _execute_operation(self, input_data: Any = None, **kwargs) -> Any:
85
+ """依次执行每个操作"""
86
+ result = input_data
87
+ for op in self.operators:
88
+ result = op.execute(result, **kwargs)
89
+ return result
90
+
91
+ def _get_serializable_fields(self) -> Dict[str, Any]:
92
+ return {"operators": [op.serialize() for op in self.operators]}
93
+
94
+ @classmethod
95
+ def _from_dict_impl(cls, data: Dict[str, Any]) -> 'ChainOperator':
96
+ operators = [BaseNode.deserialize(op_data) for op_data in data["operators"]]
97
+ return ChainOperator(operators=operators, name=data.get("name"))
@@ -0,0 +1,129 @@
1
+ # coding=utf-8
2
+ """
3
+ TableQueryNode - 表查询执行节点
4
+
5
+ 执行 SQL 查询并返回 DataFrame 结果。
6
+ """
7
+ from __future__ import annotations
8
+
9
+ from typing import Any, Dict, List, Optional
10
+
11
+ from QuantNodes.core.node import BaseNode
12
+ from QuantNodes.operator_node.base import OperatorNode
13
+ from QuantNodes.operator_node.sql_builder import SQLBuilderNode
14
+
15
+
16
+ class TableQueryNode(OperatorNode):
17
+ """
18
+ 表查询执行节点
19
+
20
+ 执行 SQL 查询或使用 SQLBuilderNode 构建查询,返回 DataFrame。
21
+
22
+ Examples:
23
+ >>> # 直接执行 SQL
24
+ >>> node = TableQueryNode(db_node=clickhouse_node, sql="SELECT * FROM users")
25
+ >>> df = node.execute()
26
+ >>>
27
+ >>> # 使用链式调用
28
+ >>> node = TableQueryNode(db_node=clickhouse_node)
29
+ >>> df = (node
30
+ ... .from_table("users")
31
+ ... .select(["id", "name"])
32
+ ... .where(["active = 1"])
33
+ ... .execute())
34
+ """
35
+
36
+ def __init__(
37
+ self,
38
+ db_node: Optional[BaseNode] = None,
39
+ sql: Optional[str] = None,
40
+ builder: Optional[SQLBuilderNode] = None,
41
+ name: str = None,
42
+ config: Dict[str, Any] = None,
43
+ **kwargs
44
+ ):
45
+ """
46
+ Args:
47
+ db_node: 数据库节点 (DatabaseNode 实例)
48
+ sql: 直接执行的 SQL 语句
49
+ builder: SQLBuilderNode 用于构建查询
50
+ name: 节点名称
51
+ config: 额外配置
52
+ **kwargs: 额外参数
53
+ """
54
+ super().__init__(name=name or "TableQuery", config=config, **kwargs)
55
+ self._db_node = db_node
56
+ self._sql = sql
57
+ self._builder = builder
58
+
59
+ self._table: Optional[str] = None
60
+ self._columns: Optional[List[str]] = None
61
+ self._where: List[str] = []
62
+ self._group_by: List[str] = []
63
+ self._order_by: List[str] = []
64
+ self._limit: Optional[int] = None
65
+
66
+ def from_table(self, table: str) -> 'TableQueryNode':
67
+ """设置查询表"""
68
+ self._table = table
69
+ return self
70
+
71
+ def select(self, columns: List[str]) -> 'TableQueryNode':
72
+ """选择列"""
73
+ self._columns = columns
74
+ return self
75
+
76
+ def where(self, conditions: List[str]) -> 'TableQueryNode':
77
+ """添加 WHERE 条件"""
78
+ self._where.extend(conditions)
79
+ return self
80
+
81
+ def group_by(self, columns: List[str]) -> 'TableQueryNode':
82
+ """添加 GROUP BY"""
83
+ self._group_by.extend(columns)
84
+ return self
85
+
86
+ def order_by(self, columns: List[str]) -> 'TableQueryNode':
87
+ """添加 ORDER BY"""
88
+ self._order_by.extend(columns)
89
+ return self
90
+
91
+ def limit(self, n: int) -> 'TableQueryNode':
92
+ """添加 LIMIT"""
93
+ self._limit = n
94
+ return self
95
+
96
+ def _execute_operation(self, input_data: Any = None, **kwargs) -> Any:
97
+ """执行查询"""
98
+ if self._db_node is None:
99
+ raise ValueError("db_node is required for TableQueryNode")
100
+
101
+ if self._sql:
102
+ sql = self._sql
103
+ elif self._builder:
104
+ sql = self._builder.to_sql()
105
+ else:
106
+ sql = self._build_sql()
107
+
108
+ return self._db_node.execute(sql, **kwargs)
109
+
110
+ def _build_sql(self) -> str:
111
+ """构建 SQL 语句"""
112
+ if self._table is None:
113
+ raise ValueError("table or sql must be set")
114
+
115
+ builder = SQLBuilderNode(table=self._table, columns=self._columns or ['*'])
116
+
117
+ if self._where:
118
+ builder.where(self._where)
119
+ if self._group_by:
120
+ builder.group_by(self._group_by)
121
+ if self._order_by:
122
+ builder.order_by(self._order_by)
123
+ if self._limit:
124
+ builder.limit(self._limit)
125
+
126
+ return builder.to_sql()
127
+
128
+ def __repr__(self) -> str:
129
+ return f"<TableQueryNode table='{self._table}'>"
@@ -0,0 +1,125 @@
1
+ # coding=utf-8
2
+ """
3
+ SQLBuilderNode - SQL 构建节点
4
+
5
+ 基于 SQLUtils 构建的 SQL 生成节点。
6
+ """
7
+ from __future__ import annotations
8
+
9
+ from typing import Any, Dict, List, Optional
10
+
11
+ from QuantNodes.operator_node.base import OperatorNode
12
+
13
+
14
+ class SQLBuilderNode(OperatorNode):
15
+ """
16
+ SQL 构建节点
17
+
18
+ 构建 SQL 查询语句,支持链式调用。
19
+
20
+ Examples:
21
+ >>> builder = SQLBuilderNode(table="users")
22
+ >>> sql = builder.select(["id", "name"]).where(["active = 1"]).execute()
23
+ >>> print(sql)
24
+ SELECT id, name FROM users WHERE active = 1
25
+ """
26
+
27
+ def __init__(
28
+ self,
29
+ table: str,
30
+ columns: Optional[List[str]] = None,
31
+ name: str = None,
32
+ config: Dict[str, Any] = None,
33
+ **kwargs
34
+ ):
35
+ """
36
+ Args:
37
+ table: 表名 (格式: db.table 或 table)
38
+ columns: 要选择的列,None 表示 *
39
+ name: 节点名称
40
+ config: 额外配置
41
+ **kwargs: 额外参数
42
+ """
43
+ super().__init__(name=name or "SQLBuilder", config=config, **kwargs)
44
+ self._table = table
45
+ self._columns = columns or ['*']
46
+ self._where: List[str] = []
47
+ self._group_by: List[str] = []
48
+ self._order_by: List[str] = []
49
+ self._limit: Optional[int] = None
50
+ self._having: List[str] = []
51
+ self._joins: List[Dict[str, Any]] = []
52
+ self._sample: Optional[str] = None
53
+
54
+ def select(self, columns: List[str]) -> 'SQLBuilderNode':
55
+ """选择列"""
56
+ self._columns = columns
57
+ return self
58
+
59
+ def where(self, conditions: List[str]) -> 'SQLBuilderNode':
60
+ """添加 WHERE 条件"""
61
+ self._where.extend(conditions)
62
+ return self
63
+
64
+ def group_by(self, columns: List[str]) -> 'SQLBuilderNode':
65
+ """添加 GROUP BY"""
66
+ self._group_by.extend(columns)
67
+ return self
68
+
69
+ def having(self, conditions: List[str]) -> 'SQLBuilderNode':
70
+ """添加 HAVING 条件"""
71
+ self._having.extend(conditions)
72
+ return self
73
+
74
+ def order_by(self, columns: List[str]) -> 'SQLBuilderNode':
75
+ """添加 ORDER BY"""
76
+ self._order_by.extend(columns)
77
+ return self
78
+
79
+ def limit(self, n: int) -> 'SQLBuilderNode':
80
+ """添加 LIMIT"""
81
+ self._limit = n
82
+ return self
83
+
84
+ def join(self, join_type: str, table: str, condition: str) -> 'SQLBuilderNode':
85
+ """添加 JOIN"""
86
+ self._joins.append({
87
+ 'type': join_type,
88
+ 'table': table,
89
+ 'condition': condition
90
+ })
91
+ return self
92
+
93
+ def sample(self, ratio: str) -> 'SQLBuilderNode':
94
+ """添加 SAMPLE"""
95
+ self._sample = ratio
96
+ return self
97
+
98
+ def _execute_operation(self, input_data: Any = None, **kwargs) -> str:
99
+ """生成 SQL 语句"""
100
+ from QuantNodes.operator_node.sql_utils import SQLBuilder
101
+
102
+ db_table = self._table
103
+
104
+ sql = SQLBuilder.create_select_sql(
105
+ DB_TABLE=db_table,
106
+ cols=self._columns if self._columns != ['*'] else ['*'],
107
+ sample=self._sample,
108
+ array_join=None,
109
+ join=self._joins[0] if self._joins else None,
110
+ prewhere=None,
111
+ where=self._where if self._where else None,
112
+ having=self._having if self._having else None,
113
+ group_by=self._group_by if self._group_by else None,
114
+ order_by=self._order_by if self._order_by else None,
115
+ limit_by=None,
116
+ limit=self._limit
117
+ )
118
+ return sql
119
+
120
+ def to_sql(self) -> str:
121
+ """返回 SQL 语句(execute 的别名)"""
122
+ return self.execute()
123
+
124
+ def __repr__(self) -> str:
125
+ return f"<SQLBuilderNode table='{self._table}'>"
@@ -0,0 +1,172 @@
1
+ # coding=utf-8
2
+ """
3
+ SQL utilities
4
+
5
+ SQL building utilities for generating SQL queries.
6
+ """
7
+
8
+
9
+ class TableEngineCreator(object):
10
+ @staticmethod
11
+ def _assemble_cols_2_clause(prefix, cols, default=''):
12
+ if cols is None:
13
+ return default
14
+ else:
15
+ cols_str = ','.join(cols)
16
+ return f"{prefix} ( {cols_str} ) "
17
+
18
+ @classmethod
19
+ def ReplacingMergeTree_creator(cls, DB_TABLE, cols_def, order_by_cols,
20
+ sample_by_cols=None,
21
+ ON_CLUSTER='', partition_by_cols=None, primary_by_cols=None):
22
+
23
+ order_by_cols_str = ','.join(order_by_cols)
24
+ ORDER_BY_CLAUSE = f"ORDER BY ( {order_by_cols_str} )"
25
+
26
+ SAMPLE_CLAUSE = cls._assemble_cols_2_clause('SAMPLE BY', sample_by_cols, default='')
27
+
28
+ PRIMARY_BY_CLAUSE = cls._assemble_cols_2_clause('PRIMARY BY', primary_by_cols, default='')
29
+
30
+ PARTITION_by_CLAUSE = cls._assemble_cols_2_clause('PARTITION BY', partition_by_cols, default='') # noqa: E501 (long var name)
31
+
32
+ return cls.raw_create_ReplacingMergeTree_table_sql(
33
+ DB_TABLE, cols_def, ORDER_BY_CLAUSE,
34
+ PRIMARY_BY_CLAUSE=PRIMARY_BY_CLAUSE,
35
+ SAMPLE_CLAUSE=SAMPLE_CLAUSE,
36
+ ENGINE_TYPE='ReplacingMergeTree', ON_CLUSTER=ON_CLUSTER,
37
+ PARTITION_by_CLAUSE=PARTITION_by_CLAUSE,
38
+ )
39
+
40
+ @staticmethod
41
+ def raw_create_ReplacingMergeTree_table_sql(
42
+ DB_TABLE, cols_def, ORDER_BY_CLAUSE,
43
+ PRIMARY_BY_CLAUSE='', SAMPLE_CLAUSE='',
44
+ ENGINE_TYPE='ReplacingMergeTree', ON_CLUSTER='',
45
+ PARTITION_by_CLAUSE='', TTL='',
46
+ ):
47
+ maid_body = (
48
+ f"CREATE TABLE IF NOT EXISTS {DB_TABLE} {ON_CLUSTER} "
49
+ f"( {cols_def} ) ENGINE = {ENGINE_TYPE}"
50
+ )
51
+
52
+ settings = "SETTINGS index_granularity = 8192"
53
+ conds = f"{PARTITION_by_CLAUSE} {ORDER_BY_CLAUSE} {PRIMARY_BY_CLAUSE} {SAMPLE_CLAUSE} {TTL}"
54
+
55
+ base = f"{maid_body} {conds} {settings}"
56
+ return base
57
+
58
+
59
+ class SQLBuilder:
60
+ """SQL building utility class"""
61
+
62
+ @staticmethod
63
+ def _assemble_sample(sample):
64
+ if sample is None:
65
+ return ""
66
+ elif isinstance(sample, (int, float)):
67
+ if sample < 1:
68
+ return f"SAMPLE {sample}"
69
+ else:
70
+ return f"SAMPLE {sample}"
71
+ return ""
72
+
73
+ @staticmethod
74
+ def _assemble_array_join(array_join_list):
75
+ if array_join_list is None:
76
+ return ""
77
+ clauses = []
78
+ for arr in array_join_list:
79
+ clauses.append(f"ARRAY JOIN {arr}")
80
+ return " ".join(clauses)
81
+
82
+ @staticmethod
83
+ def _assemble_join(join_info):
84
+ if join_info is None:
85
+ return ""
86
+ join_type = join_info.get('type', '')
87
+ using = join_info.get('USING', '')
88
+ return f"{join_type} USING ( {using} )"
89
+
90
+ @staticmethod
91
+ def _assemble_where_like(where_list, prefix='WHERE'):
92
+ if where_list is None:
93
+ return ""
94
+ clauses = []
95
+ for where in where_list:
96
+ clauses.append(where)
97
+ where_clause = ' AND '.join(clauses)
98
+ return f"{prefix} {where_clause}"
99
+
100
+ @staticmethod
101
+ def _assemble_group_by(group_by_list):
102
+ if group_by_list is None:
103
+ return ""
104
+ cols_str = ','.join(group_by_list)
105
+ return f"GROUP BY ( {cols_str} )"
106
+
107
+ @staticmethod
108
+ def _assemble_order_by(order_by_list):
109
+ if order_by_list is None:
110
+ return ""
111
+ cols_str = ','.join(order_by_list)
112
+ return f"ORDER BY ( {cols_str} )"
113
+
114
+ @staticmethod
115
+ def _assemble_limit_by(limit_by):
116
+ if limit_by is None:
117
+ return ""
118
+ n = limit_by.get('N', 10)
119
+ cols = limit_by.get('limit_by_cols', [])
120
+ cols_str = ','.join(cols)
121
+ return f"LIMIT {n} BY {cols_str}"
122
+
123
+ @staticmethod
124
+ def _assemble_limit(limit):
125
+ if limit is None:
126
+ return ""
127
+ return f"LIMIT {limit}"
128
+
129
+ @classmethod
130
+ def raw_create_select_sql(cls, SELECT_CLAUSE, DB_TABLE, SAMPLE_CLAUSE='', ARRAY_JOIN_CLAUSE='',
131
+ JOIN_CLAUSE='', PREWHERE_CLAUSE='', WHERE_CLAUSE='',
132
+ GROUP_BY_CLAUSE='', HAVING_CLAUSE='', ORDER_BY_CLAUSE='',
133
+ LIMIT_N_CLAUSE='', LIMIT_CLAUSE=''):
134
+ if DB_TABLE.lower().startswith('select '):
135
+ DB_TABLE = f"( {DB_TABLE} )"
136
+ main_body = f"SELECT {SELECT_CLAUSE} FROM {DB_TABLE} {SAMPLE_CLAUSE}"
137
+ join = f"{ARRAY_JOIN_CLAUSE} {JOIN_CLAUSE}"
138
+ where_conditions = f"{PREWHERE_CLAUSE} {WHERE_CLAUSE} {GROUP_BY_CLAUSE} {HAVING_CLAUSE} "
139
+ order_limit = f"{ORDER_BY_CLAUSE} {LIMIT_N_CLAUSE} {LIMIT_CLAUSE}"
140
+ sql = f"{main_body} {join} {where_conditions} {order_limit}"
141
+ return sql
142
+
143
+ @classmethod
144
+ def create_select_sql(
145
+ cls, DB_TABLE: str, cols: list,
146
+ sample: (int, float, None) = None,
147
+ array_join: (list, None) = None, join: (dict, None) = None,
148
+ prewhere: (list, None) = None, where: (list, None) = None,
149
+ having: (list, None) = None, group_by: (list, None) = None,
150
+ order_by: (list, None) = None, limit_by: (dict, None) = None,
151
+ limit: (int, None) = None,
152
+ ) -> str:
153
+ SELECT_CLAUSE = ','.join(cols)
154
+ SAMPLE_CLAUSE = cls._assemble_sample(sample=sample)
155
+ ARRAY_JOIN_CLAUSE = cls._assemble_array_join(array_join_list=array_join)
156
+ JOIN_CLAUSE = cls._assemble_join(join)
157
+ PREWHERE_CLAUSE = cls._assemble_where_like(prewhere, prefix='PREWHERE')
158
+ WHERE_CLAUSE = cls._assemble_where_like(where, prefix='WHERE')
159
+ HAVING_CLAUSE = cls._assemble_where_like(having, prefix='HAVING')
160
+ GROUP_BY_CLAUSE = cls._assemble_group_by(group_by)
161
+ ORDER_BY_CLAUSE = cls._assemble_order_by(order_by)
162
+ LIMIT_N_CLAUSE = cls._assemble_limit_by(limit_by)
163
+ LIMIT_CLAUSE = cls._assemble_limit(limit)
164
+
165
+ return cls.raw_create_select_sql(
166
+ SELECT_CLAUSE, DB_TABLE, SAMPLE_CLAUSE, ARRAY_JOIN_CLAUSE, JOIN_CLAUSE,
167
+ PREWHERE_CLAUSE, WHERE_CLAUSE, GROUP_BY_CLAUSE, HAVING_CLAUSE,
168
+ ORDER_BY_CLAUSE, LIMIT_N_CLAUSE, LIMIT_CLAUSE,
169
+ )
170
+
171
+
172
+ __all__ = ['SQLBuilder', 'TableEngineCreator']
@@ -0,0 +1,130 @@
1
+ # coding=utf-8
2
+ """
3
+ TransformNode - 数据转换节点
4
+
5
+ 提供数据转换操作,如选择列、过滤、聚合等。
6
+ """
7
+ from __future__ import annotations
8
+
9
+ from typing import Any, Callable, Dict, List, Union
10
+
11
+ import pandas as pd
12
+
13
+ from QuantNodes.operator_node.base import OperatorNode
14
+
15
+
16
+ class TransformNode(OperatorNode):
17
+ """
18
+ 数据转换节点
19
+
20
+ 对 DataFrame 进行各种转换操作,支持链式调用。
21
+
22
+ Examples:
23
+ >>> # 选择列
24
+ >>> node = TransformNode().select(["col1", "col2"])
25
+ >>> result = node.execute(df)
26
+ >>>
27
+ >>> # 过滤行
28
+ >>> node = TransformNode().filter(lambda df: df["value"] > 0)
29
+ >>> result = node.execute(df)
30
+ >>>
31
+ >>> # 聚合
32
+ >>> node = TransformNode().aggregate(group_by=["category"], agg={"value": "sum"})
33
+ >>> result = node.execute(df)
34
+ """
35
+
36
+ def __init__(
37
+ self,
38
+ name: str = None,
39
+ config: Dict[str, Any] = None,
40
+ **kwargs
41
+ ):
42
+ super().__init__(name=name or "Transform", config=config, **kwargs)
43
+ self._operations: List[Callable] = []
44
+
45
+ def select(self, columns: List[str]) -> 'TransformNode':
46
+ """选择列"""
47
+ def op(df: pd.DataFrame) -> pd.DataFrame:
48
+ return df[columns]
49
+ self._operations.append(op)
50
+ return self
51
+
52
+ def drop(self, columns: List[str]) -> 'TransformNode':
53
+ """删除列"""
54
+ def op(df: pd.DataFrame) -> pd.DataFrame:
55
+ return df.drop(columns=columns)
56
+ self._operations.append(op)
57
+ return self
58
+
59
+ def filter(self, condition: Union[str, Callable]) -> 'TransformNode':
60
+ """过滤行"""
61
+ if isinstance(condition, str):
62
+ def op(df: pd.DataFrame) -> pd.DataFrame:
63
+ return df.query(condition)
64
+ else:
65
+ def op(df: pd.DataFrame) -> pd.DataFrame:
66
+ return df[condition(df)]
67
+ self._operations.append(op)
68
+ return self
69
+
70
+ def aggregate(
71
+ self,
72
+ group_by: List[str],
73
+ agg: Dict[str, Union[str, List[str]]]
74
+ ) -> 'TransformNode':
75
+ """聚合操作"""
76
+ def op(df: pd.DataFrame) -> pd.DataFrame:
77
+ return df.groupby(group_by).agg(agg).reset_index()
78
+ self._operations.append(op)
79
+ return self
80
+
81
+ def sort_by(self, columns: Union[str, List[str]], ascending: bool = True) -> 'TransformNode':
82
+ """排序"""
83
+ def op(df: pd.DataFrame) -> pd.DataFrame:
84
+ return df.sort_values(by=columns, ascending=ascending)
85
+ self._operations.append(op)
86
+ return self
87
+
88
+ def rename(self, columns: Dict[str, str]) -> 'TransformNode':
89
+ """重命名列"""
90
+ def op(df: pd.DataFrame) -> pd.DataFrame:
91
+ return df.rename(columns=columns)
92
+ self._operations.append(op)
93
+ return self
94
+
95
+ def fillna(self, value: Any) -> 'TransformNode':
96
+ """填充空值"""
97
+ def op(df: pd.DataFrame) -> pd.DataFrame:
98
+ return df.fillna(value)
99
+ self._operations.append(op)
100
+ return self
101
+
102
+ def apply(self, func: Callable, **kwargs) -> 'TransformNode':
103
+ """应用自定义函数"""
104
+ def op(df: pd.DataFrame) -> pd.DataFrame:
105
+ return df.apply(func, **kwargs)
106
+ self._operations.append(op)
107
+ return self
108
+
109
+ def then(self, other: 'TransformNode') -> 'TransformNode':
110
+ """链式调用"""
111
+ combined = TransformNode(name=f"{self.name}_then_{other.name}")
112
+ combined._operations = self._operations + other._operations
113
+ return combined
114
+
115
+ def _execute_operation(self, input_data: Any = None, **kwargs) -> Any:
116
+ """执行转换"""
117
+ if input_data is None:
118
+ raise ValueError("input_data (DataFrame) is required")
119
+
120
+ if not isinstance(input_data, pd.DataFrame):
121
+ raise TypeError(f"Expected DataFrame, got {type(input_data)}")
122
+
123
+ result = input_data
124
+ for op in self._operations:
125
+ result = op(result)
126
+
127
+ return result
128
+
129
+ def __repr__(self) -> str:
130
+ return f"<TransformNode operations={len(self._operations)}>"