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,106 @@
1
+ # coding=utf-8
2
+ """
3
+ 策略生成工具
4
+
5
+ 封装 QuantNodes AI 模块的 StrategyGenerator。
6
+ """
7
+
8
+ from typing import Any, Dict
9
+ import re
10
+
11
+ from QuantNodes.agent.tools.base import Tool
12
+
13
+
14
+ class StrategyTool(Tool):
15
+ """策略生成工具
16
+
17
+ 将自然语言描述转换为 QuantNodes Pipeline 代码。
18
+
19
+ 需要配置 LLM 客户端才能使用。如果未配置,将返回提示信息。
20
+ """
21
+
22
+ CODE_BLOCK_PATTERN = re.compile(r'```(?:python)?\s*(.*?)```', re.DOTALL)
23
+
24
+ def __init__(self, llm_client=None):
25
+ if llm_client is None:
26
+ from QuantNodes.ai.llm.gateway import get_llm_gateway
27
+ llm_client = get_llm_gateway()
28
+ self._llm_client = llm_client
29
+
30
+ @property
31
+ def name(self) -> str:
32
+ return "strategy"
33
+
34
+ @property
35
+ def description(self) -> str:
36
+ return "根据自然语言描述生成 QuantNodes Pipeline 代码"
37
+
38
+ @property
39
+ def parameters(self) -> Dict[str, Any]:
40
+ return {
41
+ "type": "object",
42
+ "properties": {
43
+ "description": {
44
+ "type": "string",
45
+ "description": "策略的自然语言描述,如'生成一个动量因子策略'"
46
+ },
47
+ "validate": {
48
+ "type": "boolean",
49
+ "description": "是否验证生成的代码",
50
+ "default": True
51
+ }
52
+ },
53
+ "required": ["description"]
54
+ }
55
+
56
+ @property
57
+ def read_only(self) -> bool:
58
+ return False
59
+
60
+ async def execute(self, description: str, validate: bool = True, **kwargs) -> Dict[str, Any]:
61
+ result = {
62
+ "code": "",
63
+ "is_valid": False,
64
+ "errors": [],
65
+ "warnings": [],
66
+ "description": description
67
+ }
68
+
69
+ if self._llm_client is None:
70
+ result["message"] = (
71
+ "Strategy generation requires LLM client configuration. "
72
+ "Please provide an LLM client when initializing StrategyTool."
73
+ )
74
+ result["status"] = "needs_configuration"
75
+ return result
76
+
77
+ try:
78
+ from QuantNodes.ai.strategy_gen import StrategyGenerator
79
+ from QuantNodes.ai.sandbox import CodeSandbox
80
+
81
+ generator = StrategyGenerator(
82
+ llm_client=self._llm_client,
83
+ code_sandbox=CodeSandbox()
84
+ )
85
+
86
+ gen_result = generator.generate(description, validate=validate)
87
+
88
+ result["code"] = gen_result.code
89
+ result["is_valid"] = gen_result.is_valid
90
+
91
+ if gen_result.error_message:
92
+ result["errors"].append(gen_result.error_message)
93
+
94
+ if gen_result.warnings:
95
+ result["warnings"] = gen_result.warnings
96
+
97
+ result["status"] = "success"
98
+
99
+ except ImportError as e:
100
+ result["status"] = "error"
101
+ result["errors"] = ["AI module not available: %s" % str(e)]
102
+ except Exception as e:
103
+ result["status"] = "error"
104
+ result["errors"] = [str(e)]
105
+
106
+ return result
@@ -0,0 +1,171 @@
1
+ # coding=utf-8
2
+ """
3
+ Task 工具
4
+
5
+ 提供简单的任务管理功能,支持创建、更新、列表任务。
6
+ 任务数据存储在 workspace/.quant_agent/tasks.json。
7
+ """
8
+
9
+ import json
10
+ import uuid
11
+ from datetime import datetime, timezone
12
+ from pathlib import Path
13
+ from typing import Any, Dict, List, Optional
14
+
15
+ from .base import Tool
16
+ from ._workspace import WorkspaceTool
17
+ from QuantNodes.core.path_utils import ensure_parent
18
+
19
+
20
+ class TaskTool(WorkspaceTool, Tool):
21
+ """任务管理工具
22
+
23
+ 创建、更新、列表任务。数据持久化到 JSON 文件。
24
+ """
25
+
26
+ MAX_TASKS = 100
27
+
28
+ def __init__(self, workspace: str | Path):
29
+ super().__init__(workspace)
30
+ self._tasks_file = self.workspace / "tasks.json"
31
+
32
+ @property
33
+ def name(self) -> str:
34
+ return "task"
35
+
36
+ @property
37
+ def description(self) -> str:
38
+ return (
39
+ "任务管理工具:创建、更新、列表任务。"
40
+ "支持按状态筛选,任务持久化到 JSON 文件。"
41
+ )
42
+
43
+ @property
44
+ def parameters(self) -> Dict[str, Any]:
45
+ return {
46
+ "type": "object",
47
+ "properties": {
48
+ "action": {
49
+ "type": "string",
50
+ "enum": ["create_task", "update_task", "list_tasks"],
51
+ "description": "操作类型",
52
+ },
53
+ "title": {
54
+ "type": "string",
55
+ "description": "任务标题(create_task 时必需)",
56
+ },
57
+ "description": {
58
+ "type": "string",
59
+ "description": "任务描述",
60
+ },
61
+ "priority": {
62
+ "type": "string",
63
+ "enum": ["low", "medium", "high"],
64
+ "description": "任务优先级(默认 medium)",
65
+ "default": "medium",
66
+ },
67
+ "task_id": {
68
+ "type": "string",
69
+ "description": "任务 ID(update_task 时必需)",
70
+ },
71
+ "status": {
72
+ "type": "string",
73
+ "enum": ["pending", "in_progress", "completed", "cancelled"],
74
+ "description": "任务状态(update_task 时使用)",
75
+ },
76
+ },
77
+ "required": ["action"],
78
+ }
79
+
80
+ @property
81
+ def read_only(self) -> bool:
82
+ return False
83
+
84
+ def _load_tasks(self) -> List[Dict[str, Any]]:
85
+ """从 JSON 文件加载任务"""
86
+ if not self._tasks_file.exists():
87
+ return []
88
+ try:
89
+ return json.loads(self._tasks_file.read_text(encoding="utf-8"))
90
+ except (json.JSONDecodeError, Exception):
91
+ return []
92
+
93
+ def _save_tasks(self, tasks: List[Dict[str, Any]]) -> None:
94
+ """保存任务到 JSON 文件"""
95
+ ensure_parent(self._tasks_file)
96
+ self._tasks_file.write_text(
97
+ json.dumps(tasks, ensure_ascii=False, indent=2),
98
+ encoding="utf-8",
99
+ )
100
+
101
+ async def _dispatch(self, action: str, registry: Dict[str, Any], **kwargs: Any) -> Any:
102
+ """Override: return error dict on unknown action (matches legacy)."""
103
+ fn = registry.get(action)
104
+ if not fn:
105
+ return {"error": f"Unknown action: {action}"}
106
+ return await fn(**kwargs)
107
+
108
+ async def execute(self, action: str, **kwargs: Any) -> Any:
109
+ return await self._dispatch(action, {
110
+ "create_task": self._create_task,
111
+ "update_task": self._update_task,
112
+ "list_tasks": self._list_tasks,
113
+ }, **kwargs)
114
+
115
+ async def _create_task(
116
+ self,
117
+ title: str = "",
118
+ description: str = "",
119
+ priority: str = "medium",
120
+ **kw,
121
+ ) -> Dict[str, Any]:
122
+ if not title:
123
+ return {"error": "title is required"}
124
+
125
+ tasks = self._load_tasks()
126
+ if len(tasks) >= self.MAX_TASKS:
127
+ return {"error": f"Task limit reached ({self.MAX_TASKS})"}
128
+
129
+ now = datetime.now(timezone.utc).isoformat()
130
+ task = {
131
+ "id": uuid.uuid4().hex[:8],
132
+ "title": title,
133
+ "description": description,
134
+ "status": "pending",
135
+ "priority": priority,
136
+ "created_at": now,
137
+ "updated_at": now,
138
+ }
139
+ tasks.append(task)
140
+ self._save_tasks(tasks)
141
+
142
+ return {"status": "ok", "task": task}
143
+
144
+ async def _update_task(
145
+ self,
146
+ task_id: str = "",
147
+ status: Optional[str] = None,
148
+ description: Optional[str] = None,
149
+ **kw,
150
+ ) -> Dict[str, Any]:
151
+ if not task_id:
152
+ return {"error": "task_id is required"}
153
+
154
+ tasks = self._load_tasks()
155
+ for task in tasks:
156
+ if task["id"] == task_id:
157
+ if status:
158
+ task["status"] = status
159
+ if description is not None:
160
+ task["description"] = description
161
+ task["updated_at"] = datetime.now(timezone.utc).isoformat()
162
+ self._save_tasks(tasks)
163
+ return {"status": "ok", "task": task}
164
+
165
+ return {"error": f"Task not found: {task_id}"}
166
+
167
+ async def _list_tasks(self, status: Optional[str] = None, **kw) -> Dict[str, Any]:
168
+ tasks = self._load_tasks()
169
+ if status:
170
+ tasks = [t for t in tasks if t["status"] == status]
171
+ return {"tasks": tasks, "total": len(tasks)}
@@ -0,0 +1,142 @@
1
+ # coding=utf-8
2
+ """
3
+ Web Fetch 工具
4
+
5
+ 抓取指定 URL 的网页内容,支持 text/html/markdown 格式。
6
+ """
7
+
8
+ import re
9
+ from typing import Any, Dict
10
+ from urllib.parse import urlparse
11
+
12
+ import httpx
13
+ from bs4 import BeautifulSoup
14
+
15
+ from .base import Tool
16
+
17
+
18
+ class WebFetchTool(Tool):
19
+ """网页抓取工具
20
+
21
+ 抓取指定 URL 的内容,支持纯文本、HTML、Markdown 格式。
22
+ """
23
+
24
+ MAX_CONTENT = 50 * 1024 # 50KB
25
+ TIMEOUT = 10.0
26
+ USER_AGENT = "Mozilla/5.0 (compatible; QuantNodes/1.0)"
27
+
28
+ def __init__(self) -> None:
29
+ # H9 (2026-06-20): per-instance AsyncClient for connection pooling.
30
+ # Previously each execute() opened a fresh client + paid a fresh
31
+ # TCP+TLS handshake. With many URLs in one agent run, that's
32
+ # multi-second savings.
33
+ self._client = httpx.AsyncClient(timeout=self.TIMEOUT, follow_redirects=True)
34
+
35
+ async def aclose(self) -> None:
36
+ """Close the underlying httpx client (call at end of session)."""
37
+ if self._client is not None:
38
+ await self._client.aclose()
39
+ self._client = None
40
+
41
+ @property
42
+ def name(self) -> str:
43
+ return "web_fetch"
44
+
45
+ @property
46
+ def description(self) -> str:
47
+ return (
48
+ "抓取指定 URL 的网页内容。"
49
+ "支持 text(提取纯文本)、html(返回原始 HTML)格式。"
50
+ "禁止访问本地地址。"
51
+ )
52
+
53
+ @property
54
+ def parameters(self) -> Dict[str, Any]:
55
+ return {
56
+ "type": "object",
57
+ "properties": {
58
+ "url": {
59
+ "type": "string",
60
+ "description": "要抓取的 URL(必须是 http/https)",
61
+ },
62
+ "format": {
63
+ "type": "string",
64
+ "enum": ["text", "html"],
65
+ "description": "返回格式:text 提取纯文本,html 返回原始 HTML",
66
+ "default": "text",
67
+ },
68
+ },
69
+ "required": ["url"],
70
+ }
71
+
72
+ @property
73
+ def read_only(self) -> bool:
74
+ return True
75
+
76
+ def _is_safe_url(self, url: str) -> bool:
77
+ """检查 URL 是否安全(禁止本地地址)"""
78
+ try:
79
+ parsed = urlparse(url)
80
+ if parsed.scheme not in ("http", "https"):
81
+ return False
82
+ hostname = parsed.hostname or ""
83
+ if hostname in ("localhost", "127.0.0.1", "::1", "0.0.0.0"):
84
+ return False
85
+ if hostname.startswith("192.168.") or hostname.startswith("10."):
86
+ return False
87
+ return True
88
+ except Exception:
89
+ return False
90
+
91
+ async def execute(self, url: str = "", format: str = "text", **kwargs: Any) -> Any:
92
+ if not url:
93
+ return {"error": "url is required"}
94
+ if not self._is_safe_url(url):
95
+ return {"error": f"URL not allowed: {url}"}
96
+
97
+ try:
98
+ resp = await self._client.get(url, headers={"User-Agent": self.USER_AGENT})
99
+ resp.raise_for_status()
100
+ except httpx.TimeoutException:
101
+ return {"error": f"Request timed out ({self.TIMEOUT}s)"}
102
+ except httpx.HTTPStatusError as e:
103
+ return {"error": f"HTTP {e.response.status_code}: {e.response.reason_phrase}"}
104
+ except Exception as e:
105
+ return {"error": f"Request failed: {str(e)}"}
106
+
107
+ content_type = resp.headers.get("content-type", "")
108
+ html = resp.text
109
+
110
+ if format == "html":
111
+ text = html[:self.MAX_CONTENT]
112
+ return {
113
+ "url": url,
114
+ "status_code": resp.status_code,
115
+ "content_type": content_type,
116
+ "content": text,
117
+ "truncated": len(html) > self.MAX_CONTENT,
118
+ }
119
+
120
+ soup = BeautifulSoup(html, "lxml")
121
+
122
+ for tag in soup(["script", "style", "nav", "footer", "header", "aside"]):
123
+ tag.decompose()
124
+
125
+ text = soup.get_text(separator="\n", strip=True)
126
+ text = re.sub(r"\n{3,}", "\n\n", text)
127
+
128
+ if len(text) > self.MAX_CONTENT:
129
+ text = text[:self.MAX_CONTENT] + "\n...[truncated]"
130
+
131
+ title = ""
132
+ title_tag = soup.find("title")
133
+ if title_tag:
134
+ title = title_tag.get_text(strip=True)
135
+
136
+ return {
137
+ "url": url,
138
+ "status_code": resp.status_code,
139
+ "title": title,
140
+ "content": text,
141
+ "truncated": len(text) > self.MAX_CONTENT,
142
+ }
@@ -0,0 +1,114 @@
1
+ # coding=utf-8
2
+ """
3
+ Web Search 工具
4
+
5
+ 使用 DuckDuckGo HTML 端点执行网络搜索。
6
+ """
7
+
8
+ from typing import Any, Dict, List
9
+
10
+ import httpx
11
+ from bs4 import BeautifulSoup
12
+
13
+ from .base import Tool
14
+
15
+
16
+ class WebSearchTool(Tool):
17
+ """网络搜索工具
18
+
19
+ 使用 DuckDuckGo HTML 端点搜索关键词,返回搜索结果。
20
+ """
21
+
22
+ TIMEOUT = 10.0
23
+ USER_AGENT = "Mozilla/5.0 (compatible; QuantNodes/1.0)"
24
+ SEARCH_URL = "https://html.duckduckgo.com/html/"
25
+
26
+ def __init__(self) -> None:
27
+ # H9 (2026-06-20): per-instance AsyncClient for connection pooling.
28
+ self._client = httpx.AsyncClient(timeout=self.TIMEOUT, follow_redirects=True)
29
+
30
+ async def aclose(self) -> None:
31
+ """Close the underlying httpx client."""
32
+ if self._client is not None:
33
+ await self._client.aclose()
34
+ self._client = None
35
+
36
+ @property
37
+ def name(self) -> str:
38
+ return "web_search"
39
+
40
+ @property
41
+ def description(self) -> str:
42
+ return (
43
+ "网络搜索工具:使用 DuckDuckGo 搜索关键词。"
44
+ "返回标题、URL、摘要。无需 API Key。"
45
+ )
46
+
47
+ @property
48
+ def parameters(self) -> Dict[str, Any]:
49
+ return {
50
+ "type": "object",
51
+ "properties": {
52
+ "query": {
53
+ "type": "string",
54
+ "description": "搜索关键词",
55
+ },
56
+ "max_results": {
57
+ "type": "integer",
58
+ "description": "最大返回结果数(默认 5,最大 20)",
59
+ "default": 5,
60
+ },
61
+ },
62
+ "required": ["query"],
63
+ }
64
+
65
+ @property
66
+ def read_only(self) -> bool:
67
+ return True
68
+
69
+ async def execute(self, query: str = "", max_results: int = 5, **kwargs: Any) -> Any:
70
+ if not query:
71
+ return {"error": "query is required"}
72
+
73
+ max_results = min(max(max_results, 1), 20)
74
+
75
+ try:
76
+ resp = await self._client.get(
77
+ self.SEARCH_URL,
78
+ params={"q": query},
79
+ headers={"User-Agent": self.USER_AGENT},
80
+ )
81
+ resp.raise_for_status()
82
+ except httpx.TimeoutException:
83
+ return {"error": f"Search timed out ({self.TIMEOUT}s)"}
84
+ except Exception as e:
85
+ return {"error": f"Search failed: {str(e)}"}
86
+
87
+ soup = BeautifulSoup(resp.text, "lxml")
88
+ results: List[Dict[str, str]] = []
89
+
90
+ for result_div in soup.select(".result"):
91
+ if len(results) >= max_results:
92
+ break
93
+
94
+ title_tag = result_div.select_one(".result__title a")
95
+ snippet_tag = result_div.select_one(".result__snippet")
96
+
97
+ if not title_tag:
98
+ continue
99
+
100
+ href = title_tag.get("href", "")
101
+ title = title_tag.get_text(strip=True)
102
+ snippet = snippet_tag.get_text(strip=True) if snippet_tag else ""
103
+
104
+ results.append({
105
+ "title": title,
106
+ "url": href,
107
+ "snippet": snippet,
108
+ })
109
+
110
+ return {
111
+ "query": query,
112
+ "results": results,
113
+ "total": len(results),
114
+ }