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,412 @@
1
+ # coding=utf-8
2
+ """
3
+ 控制流节点模块
4
+
5
+ 本模块提供流程控制节点,支持条件分支、分组映射、循环执行等功能:
6
+ 1. IfNode: 条件分支,根据输入决定执行哪个分支
7
+ 2. MapNode: 分组映射,对每个分组执行相同节点
8
+ 3. WhileNode: 条件循环,满足条件则循环执行
9
+
10
+ 支持多种条件表达方式:
11
+ 1. DSL 构建: Cond('value') > 50
12
+ 2. 字符串表达式: "df['value'] > 50"
13
+ 3. Lambda 函数: lambda x: x > 50 (向后兼容)
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import logging
19
+ import pandas as pd
20
+ from typing import Any, Callable, Dict, Generic, List, Optional, TypeVar, Union
21
+
22
+ from QuantNodes.core.node import BaseNode, SerializationError
23
+ from QuantNodes.core.expression import Expression, ExpressionBuilder, LambdaExpression
24
+ from QuantNodes.core.serializable import serializable
25
+
26
+
27
+ I = TypeVar('I') # 分组输入类型
28
+ O = TypeVar('O') # 分组输出类型
29
+
30
+
31
+ def _wrap_condition(
32
+ condition: Union[Expression, ExpressionBuilder, Callable[[Any], bool], str]
33
+ ) -> Expression:
34
+ """将条件转换为 Expression 对象"""
35
+ if isinstance(condition, ExpressionBuilder):
36
+ return condition._expr
37
+ if isinstance(condition, Expression):
38
+ return condition
39
+ if isinstance(condition, str):
40
+ return Expression.parse(condition)
41
+ if callable(condition):
42
+ return LambdaExpression(condition)
43
+ raise TypeError(f"Unsupported condition type: {type(condition)}")
44
+
45
+
46
+ @serializable
47
+ class IfNode(BaseNode):
48
+ """
49
+ 条件分支节点
50
+
51
+ 如果条件满足,执行 true_branch,否则执行 false_branch。
52
+
53
+ Examples:
54
+ >>> # DSL 构建方式
55
+ >>> IfNode(
56
+ ... condition=Cond('value') > 10,
57
+ ... true_branch=BigStrategy(),
58
+ ... false_branch=SmallStrategy(),
59
+ ... )
60
+ >>>
61
+ >>> # 字符串表达式方式
62
+ >>> IfNode("df['value'] > 10", BigStrategy(), SmallStrategy())
63
+ >>>
64
+ >>> # Lambda 方式(向后兼容)
65
+ >>> IfNode(lambda x: x > 10, BigStrategy())
66
+ """
67
+
68
+ def __init__(self,
69
+ condition: Union[Expression, ExpressionBuilder, Callable[[Any], bool], str],
70
+ true_branch: BaseNode,
71
+ false_branch: Optional[BaseNode] = None,
72
+ name: str = None,
73
+ config: Dict[str, Any] = None):
74
+ """
75
+ Args:
76
+ condition: 条件判断表达式,支持多种格式
77
+ true_branch: 条件为 True 时执行的节点
78
+ false_branch: 条件为 False 时执行的节点,None 表示直接返回原输入
79
+ name: 节点名称
80
+ config: 配置字典
81
+ """
82
+ super().__init__(name=name or "IfNode", config=config)
83
+ self.condition = _wrap_condition(condition)
84
+ self.true_branch = true_branch
85
+ self.false_branch = false_branch
86
+ self._last_branch_taken: Optional[bool] = None
87
+ self.logger = logging.getLogger(f"node.{self.node_id}")
88
+
89
+ def _execute(self, input_data: Any = None, **kwargs) -> Any:
90
+ """执行条件分支"""
91
+ cond_result = self.condition.evaluate(input_data)
92
+ self._last_branch_taken = cond_result
93
+
94
+ if cond_result:
95
+ self.logger.debug("Condition is True, executing true branch")
96
+ return self.true_branch.execute(input_data, **kwargs)
97
+ elif self.false_branch is not None:
98
+ self.logger.debug("Condition is False, executing false branch")
99
+ return self.false_branch.execute(input_data, **kwargs)
100
+ else:
101
+ self.logger.debug("Condition is False, no false branch, returning input")
102
+ return input_data
103
+
104
+ def _get_serializable_fields(self) -> Dict[str, Any]:
105
+ """返回需要序列化的额外字段"""
106
+ if isinstance(self.condition, LambdaExpression):
107
+ raise SerializationError(
108
+ "IfNode with lambda condition cannot be serialized. "
109
+ "Please use Cond() DSL or string expression instead."
110
+ )
111
+ result = {
112
+ "condition": self.condition.serialize(),
113
+ "true_branch": self.true_branch.serialize(),
114
+ }
115
+ if self.false_branch:
116
+ result["false_branch"] = self.false_branch.serialize()
117
+ return result
118
+
119
+ @classmethod
120
+ def _from_dict_impl(cls, data: Dict[str, Any]) -> 'IfNode':
121
+ """从字典反序列化重建 IfNode"""
122
+ condition = Expression.deserialize(data["condition"])
123
+ true_branch = BaseNode.deserialize(data["true_branch"])
124
+ false_branch_data = data.get("false_branch")
125
+ false_branch = BaseNode.deserialize(false_branch_data) if false_branch_data else None
126
+
127
+ return IfNode(
128
+ condition=condition,
129
+ true_branch=true_branch,
130
+ false_branch=false_branch,
131
+ name=data.get("name"),
132
+ config=data.get("config", {})
133
+ )
134
+
135
+ def to_info(self) -> Dict[str, Any]:
136
+ """导出节点信息"""
137
+ result = super().to_info()
138
+ result['condition'] = repr(self.condition)
139
+ result['condition_dict'] = self.condition.serialize()
140
+ result['true_branch'] = self.true_branch.to_info()
141
+ result['false_branch'] = self.false_branch.to_info() if self.false_branch else None
142
+ result['last_branch_taken'] = self._last_branch_taken
143
+ return result
144
+
145
+
146
+ @serializable
147
+ class MapNode(BaseNode, Generic[I, O]):
148
+ """
149
+ 分组映射节点
150
+
151
+ 对输入数据进行分组,对每个分组执行相同的节点,最后合并结果。
152
+ 支持并行处理,适合内存友好的流式回测。
153
+
154
+ Examples:
155
+ >>> # 按列名分组
156
+ >>> MapNode(
157
+ ... node=BacktestNode(),
158
+ ... group_by='date',
159
+ ... max_workers=4,
160
+ ... )
161
+ >>>
162
+ >>> # DSL 表达式分组
163
+ >>> MapNode(
164
+ ... node=FactorComputeNode(),
165
+ ... group_by=Cond('code').str[:3],
166
+ ... parallel=False,
167
+ ... )
168
+ """
169
+
170
+ def __init__(self,
171
+ node: BaseNode[I, O],
172
+ group_by: Union[str, Expression, ExpressionBuilder, Callable[[Any], Any]],
173
+ max_workers: Optional[int] = None,
174
+ parallel: bool = True,
175
+ name: str = None,
176
+ config: Dict[str, Any] = None):
177
+ """
178
+ Args:
179
+ node: 要在每个分组上执行的节点
180
+ group_by: 分组方式,支持多种格式
181
+ max_workers: 最大工作线程数,None 表示自动选择
182
+ parallel: 是否并行执行,False 表示串行(调试用)
183
+ name: 节点名称
184
+ config: 配置字典
185
+ """
186
+ super().__init__(name=name or "MapNode", config=config)
187
+ self.node = node
188
+ if group_by is None:
189
+ self.group_by_expr = None
190
+ elif isinstance(group_by, str):
191
+ self.group_by_expr = group_by
192
+ else:
193
+ self.group_by_expr = _wrap_condition(group_by)
194
+ self.max_workers = max_workers
195
+ self.parallel = parallel
196
+ self.logger = logging.getLogger(f"node.{self.node_id}")
197
+
198
+ def _execute(self, input_data: Any = None, **kwargs) -> List[O]:
199
+ """分组执行"""
200
+ groups = self._group(input_data)
201
+ self.logger.debug(f"Split into {len(groups)} groups")
202
+
203
+ if self.parallel:
204
+ results = self._execute_parallel(groups, **kwargs)
205
+ else:
206
+ results = self._execute_serial(groups, **kwargs)
207
+
208
+ return results
209
+
210
+ def _group(self, input_data: Any) -> List[tuple[Any, Any]]:
211
+ """对输入数据进行分组"""
212
+ if isinstance(input_data, pd.DataFrame):
213
+ if isinstance(self.group_by_expr, str):
214
+ return list(input_data.groupby(self.group_by_expr))
215
+ elif isinstance(self.group_by_expr, Expression):
216
+ keys = self.group_by_expr.evaluate(input_data)
217
+ return list(input_data.groupby(keys))
218
+ else:
219
+ raise ValueError(f"Unsupported group_by type: {type(self.group_by_expr)}")
220
+ else:
221
+ if isinstance(input_data, (list, tuple)):
222
+ if isinstance(self.group_by_expr, Expression):
223
+ from itertools import groupby
224
+ sorted_data = sorted(input_data, key=self.group_by_expr.evaluate)
225
+ return [
226
+ (k, list(v))
227
+ for k, v in groupby(sorted_data, key=self.group_by_expr.evaluate)
228
+ ]
229
+ else:
230
+ return [(i, item) for i, item in enumerate(input_data)]
231
+ else:
232
+ return [(None, input_data)]
233
+
234
+ def _execute_serial(self, groups: List[tuple[Any, Any]], **kwargs) -> List[O]:
235
+ """串行执行"""
236
+ results = []
237
+ for key, group in groups:
238
+ self.logger.debug(f"Processing group: {key}")
239
+ result = self.node.execute(group, **kwargs)
240
+ results.append((key, result))
241
+ return results
242
+
243
+ def _execute_parallel(self, groups: List[tuple[Any, Any]], **kwargs) -> List[O]:
244
+ """并行执行"""
245
+ from concurrent.futures import ThreadPoolExecutor, as_completed
246
+
247
+ results = []
248
+ with ThreadPoolExecutor(max_workers=self.max_workers) as executor:
249
+ future_to_key = {
250
+ executor.submit(self.node.execute, group, **kwargs): key
251
+ for key, group in groups
252
+ }
253
+
254
+ for future in as_completed(future_to_key):
255
+ key = future_to_key[future]
256
+ try:
257
+ result = future.result()
258
+ results.append((key, result))
259
+ except Exception as e:
260
+ self.logger.error(f"Group '{key}' failed: {e}")
261
+ raise
262
+
263
+ return results
264
+
265
+ def _get_serializable_fields(self) -> Dict[str, Any]:
266
+ """返回需要序列化的额外字段"""
267
+ return {
268
+ "node": self.node.serialize(),
269
+ "group_by": (
270
+ self.group_by_expr
271
+ if isinstance(self.group_by_expr, str)
272
+ else self.group_by_expr.serialize()
273
+ ),
274
+ "max_workers": self.max_workers,
275
+ "parallel": self.parallel,
276
+ }
277
+
278
+ @classmethod
279
+ def _from_dict_impl(cls, data: Dict[str, Any]) -> 'MapNode':
280
+ """从字典反序列化重建 MapNode"""
281
+ from QuantNodes.core.expression import Expression
282
+
283
+ node = BaseNode.deserialize(data["node"])
284
+ group_by = data["group_by"]
285
+ if isinstance(group_by, dict):
286
+ group_by = Expression.deserialize(group_by)
287
+
288
+ return MapNode(
289
+ node=node,
290
+ group_by=group_by,
291
+ max_workers=data.get("max_workers"),
292
+ parallel=data.get("parallel", True),
293
+ name=data.get("name"),
294
+ config=data.get("config", {})
295
+ )
296
+
297
+ def to_info(self) -> Dict[str, Any]:
298
+ """导出节点信息"""
299
+ result = super().to_info()
300
+ result['group_by'] = (
301
+ repr(self.group_by_expr)
302
+ if isinstance(self.group_by_expr, Expression)
303
+ else self.group_by_expr
304
+ )
305
+ result['node'] = self.node.to_info()
306
+ result['max_workers'] = self.max_workers
307
+ result['parallel'] = self.parallel
308
+ return result
309
+
310
+
311
+ @serializable
312
+ class WhileNode(BaseNode):
313
+ """
314
+ 条件循环节点
315
+
316
+ 只要条件满足,就循环执行 body 节点。
317
+ 每次迭代的输出作为下一次迭代的输入。
318
+
319
+ Examples:
320
+ >>> # DSL 方式
321
+ >>> WhileNode(
322
+ ... condition=Cond.attr('metrics').sharpe < 1.5,
323
+ ... body=ParameterTuningNode(),
324
+ ... max_iterations=10,
325
+ ... )
326
+ >>>
327
+ >>> # 字符串表达式方式
328
+ >>> WhileNode("result.metrics.sharpe < 1.5", ParameterTuningNode(), 10)
329
+ """
330
+
331
+ def __init__(self,
332
+ condition: Union[Expression, ExpressionBuilder, Callable[[Any], bool], str],
333
+ body: BaseNode,
334
+ max_iterations: int = 1000,
335
+ name: str = None,
336
+ config: Dict[str, Any] = None):
337
+ """
338
+ Args:
339
+ condition: 循环继续条件,接收当前结果返回 bool
340
+ body: 循环体节点
341
+ max_iterations: 最大迭代次数,防止死循环
342
+ name: 节点名称
343
+ config: 配置字典
344
+ """
345
+ super().__init__(name=name or "WhileNode", config=config)
346
+ self.condition = _wrap_condition(condition)
347
+ self.body = body
348
+ self.max_iterations = max_iterations
349
+ self._iteration_count: int = 0
350
+ self.logger = logging.getLogger(f"node.{self.node_id}")
351
+
352
+ def _execute(self, input_data: Any = None, **kwargs) -> Any:
353
+ """循环执行"""
354
+ result = input_data
355
+ self._iteration_count = 0
356
+
357
+ while self.condition.evaluate(result) and self._iteration_count < self.max_iterations:
358
+ self.logger.debug(f"Iteration {self._iteration_count + 1}/{self.max_iterations}")
359
+ result = self.body.execute(result, **kwargs)
360
+ self._iteration_count += 1
361
+
362
+ if self._iteration_count >= self.max_iterations:
363
+ self.logger.warning(
364
+ f"WhileNode reached max iterations {self.max_iterations}, "
365
+ f"stopping early. Last condition result: {self.condition.evaluate(result)}"
366
+ )
367
+
368
+ return result
369
+
370
+ @property
371
+ def iteration_count(self) -> int:
372
+ """返回最后一次执行的迭代次数"""
373
+ return self._iteration_count
374
+
375
+ def _get_serializable_fields(self) -> Dict[str, Any]:
376
+ """返回需要序列化的额外字段"""
377
+ if isinstance(self.condition, LambdaExpression):
378
+ raise SerializationError(
379
+ "WhileNode with lambda condition cannot be serialized. "
380
+ "Please use Cond() DSL or string expression instead."
381
+ )
382
+ return {
383
+ "condition": self.condition.serialize(),
384
+ "body": self.body.serialize(),
385
+ "max_iterations": self.max_iterations,
386
+ }
387
+
388
+ @classmethod
389
+ def _from_dict_impl(cls, data: Dict[str, Any]) -> 'WhileNode':
390
+ """从字典反序列化重建 WhileNode"""
391
+ from QuantNodes.core.expression import Expression
392
+
393
+ condition = Expression.deserialize(data["condition"])
394
+ body = BaseNode.deserialize(data["body"])
395
+
396
+ return WhileNode(
397
+ condition=condition,
398
+ body=body,
399
+ max_iterations=data["max_iterations"],
400
+ name=data.get("name"),
401
+ config=data.get("config", {})
402
+ )
403
+
404
+ def to_info(self) -> Dict[str, Any]:
405
+ """导出节点信息"""
406
+ result = super().to_info()
407
+ result['condition'] = repr(self.condition)
408
+ result['condition_dict'] = self.condition.serialize()
409
+ result['body'] = self.body.to_info()
410
+ result['max_iterations'] = self.max_iterations
411
+ result['last_iteration_count'] = self._iteration_count
412
+ return result