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,173 @@
1
+ # coding=utf-8
2
+ """
3
+ 工具系统模块
4
+
5
+ Tool基类(继承自 HKUDS nanobot upstream Tool)/ 注册表 / 具体工具实现
6
+ """
7
+
8
+ import logging
9
+ from pathlib import Path
10
+ from typing import Any
11
+
12
+ from .base import Tool, ToolExecutionResult
13
+ from .context import ToolContext, ToolContextFactory
14
+ from .registry import ToolRegistry
15
+ from .echo import EchoTool
16
+ from .sandbox import SandboxTool
17
+ from .pipeline import PipelineTool
18
+ from .strategy import StrategyTool
19
+ from .backtest import BacktestTool
20
+ from .factor import FactorTool
21
+ from .config_backtest import ConfigBacktestTool
22
+ from .wiki import WikiTool
23
+ from .file_ops import FileOpsTool
24
+ from .code_search import CodeSearchTool
25
+ from .git_ops import GitOpsTool
26
+ from .web_fetch import WebFetchTool
27
+ from .web_search import WebSearchTool
28
+ from .task import TaskTool
29
+ from .alpha_evaluate import AlphaEvaluateTool
30
+ from .alpha_backtest import AlphaBacktestTool
31
+ from .operator_lookup import OperatorLookupTool
32
+
33
+ logger = logging.getLogger(__name__)
34
+
35
+
36
+ _QUANT_TOOL_FACTORIES = [
37
+ EchoTool,
38
+ SandboxTool,
39
+ PipelineTool,
40
+ StrategyTool,
41
+ BacktestTool,
42
+ FactorTool,
43
+ ConfigBacktestTool,
44
+ WikiTool,
45
+ FileOpsTool,
46
+ CodeSearchTool,
47
+ GitOpsTool,
48
+ WebFetchTool,
49
+ WebSearchTool,
50
+ TaskTool,
51
+ AlphaEvaluateTool,
52
+ AlphaBacktestTool,
53
+ OperatorLookupTool,
54
+ ]
55
+
56
+
57
+ def register_all_quant_tools(
58
+ registry: ToolRegistry,
59
+ workspace: Path | None = None,
60
+ llm_client: Any = None,
61
+ model: str | None = None,
62
+ ) -> int:
63
+ """Register all 17 quant tool classes (echo/sandbox/.../operator_lookup) into a registry.
64
+
65
+ Returns the number of quant tools registered. Idempotent: re-registration
66
+ of an existing tool name is skipped (the upstream registry overwrites by
67
+ name, but we prefer explicit skip to surface duplicate-name bugs early).
68
+
69
+ Plugin discovery (P2 Step 10):
70
+ 优先使用 entry_points (quantnodes.tools 组) 发现插件。
71
+ 如 entry_points 为空 (dev 模式未安装), 回退到硬编码 _QUANT_TOOL_FACTORIES。
72
+ 第三方插件可通过自己的 pyproject.toml 声明 entry_points 自动接入。
73
+
74
+ ``workspace`` is forwarded to tools that need it (``WikiTool``,
75
+ ``FileOpsTool``, ``CodeSearchTool``, ``GitOpsTool``, ``TaskTool``).
76
+ Other tools take no constructor args.
77
+
78
+ ``llm_client`` and ``model`` are forwarded to ``WorkflowTool`` (if
79
+ nanobot is available). When ``llm_client`` is provided, the
80
+ ``run_workflow`` tool is registered, enabling LLM-driven pipeline
81
+ execution via ``WorkflowRegistry``.
82
+
83
+ Usage from Agent.__init__::
84
+
85
+ from nanobot.agent.tools.registry import ToolRegistry
86
+ from QuantNodes.agent import register_all_quant_tools
87
+ register_all_quant_tools(self._loop.tools, workspace=self.workspace)
88
+ """
89
+ if workspace is None:
90
+ workspace = Path(".agent")
91
+ workspace = Path(workspace)
92
+
93
+ workspace_dep = {
94
+ "WikiTool": {"wiki_path": str(workspace / "wiki")},
95
+ "FileOpsTool": {"workspace": workspace},
96
+ "CodeSearchTool": {"workspace": workspace},
97
+ "GitOpsTool": {"workspace": workspace},
98
+ "TaskTool": {"workspace": workspace},
99
+ }
100
+
101
+ # 尝试通过 entry_points 发现插件 (P2 Step 10)
102
+ plugin_tools: dict[str, type] = {}
103
+ try:
104
+ from QuantNodes.core.plugin import discover_tools
105
+
106
+ plugin_tools = discover_tools()
107
+ except Exception as e:
108
+ logger.debug("Plugin discovery unavailable, using fallback: %s", e)
109
+
110
+ # 选择 tool factories 来源: 优先 entry_points, 否则回退硬编码
111
+ if plugin_tools:
112
+ tool_factories = list(plugin_tools.values())
113
+ logger.debug("Using %d tool plugins from entry_points", len(tool_factories))
114
+ else:
115
+ tool_factories = _QUANT_TOOL_FACTORIES
116
+
117
+ registered = 0
118
+ for factory in tool_factories:
119
+ kwargs = workspace_dep.get(factory.__name__, {})
120
+ try:
121
+ tool = factory(**kwargs) if kwargs else factory()
122
+ except (TypeError, Exception) as exc:
123
+ logger.warning("Failed to register quant tool %s: %s", factory.__name__, exc)
124
+ continue
125
+ if registry.has(tool.name):
126
+ continue
127
+ registry.register(tool)
128
+ registered += 1
129
+
130
+ # Register WorkflowTool (run_workflow) if llm_client is provided
131
+ if llm_client is not None:
132
+ try:
133
+ from ..workflows.tool import WorkflowTool
134
+
135
+ wt = WorkflowTool(
136
+ llm_client=llm_client,
137
+ model=model,
138
+ results_dir=workspace / "results",
139
+ )
140
+ if not registry.has(wt.name):
141
+ registry.register(wt)
142
+ registered += 1
143
+ except Exception as exc:
144
+ logger.warning("Failed to register WorkflowTool: %s", exc)
145
+
146
+ return registered
147
+
148
+
149
+ __all__ = [
150
+ "Tool",
151
+ "ToolExecutionResult",
152
+ "ToolContext",
153
+ "ToolContextFactory",
154
+ "ToolRegistry",
155
+ "register_all_quant_tools",
156
+ "EchoTool",
157
+ "SandboxTool",
158
+ "PipelineTool",
159
+ "StrategyTool",
160
+ "BacktestTool",
161
+ "FactorTool",
162
+ "ConfigBacktestTool",
163
+ "WikiTool",
164
+ "FileOpsTool",
165
+ "CodeSearchTool",
166
+ "GitOpsTool",
167
+ "WebFetchTool",
168
+ "WebSearchTool",
169
+ "TaskTool",
170
+ "AlphaEvaluateTool",
171
+ "AlphaBacktestTool",
172
+ "OperatorLookupTool",
173
+ ]
@@ -0,0 +1,51 @@
1
+ """WorkspaceTool mixin — Phase J1 (2026-06-20).
2
+
3
+ Consolidates the 4-times-repeated pattern across agent tools:
4
+ - self.workspace = Path(workspace).resolve()
5
+ - _safe_path(rel_path) guard against ../ path traversal
6
+
7
+ Used by:
8
+ - CodeSearchTool
9
+ - FileOpsTool
10
+ - GitOpsTool
11
+ - TaskTool
12
+
13
+ Filling the gap: git_ops and task originally did NOT have a _safe_path
14
+ guard (relied on Git's own safety or just trusting the input). Now
15
+ both inherit WorkspaceTool so they can use the same guard.
16
+
17
+ The mixin does NOT inherit from Tool — that's the job of the subclass.
18
+ Just include it in the inheritance list:
19
+ class CodeSearchTool(WorkspaceTool, Tool):
20
+ ...
21
+ """
22
+ from __future__ import annotations
23
+
24
+ from pathlib import Path
25
+
26
+
27
+ class WorkspaceTool:
28
+ """Mix-in providing workspace path + path-traversal-safe resolver.
29
+
30
+ Subclasses MUST call ``super().__init__(workspace)`` or assign
31
+ ``self.workspace`` themselves; the mixin only stores/guards it.
32
+ """
33
+
34
+ workspace: Path
35
+
36
+ def __init__(self, workspace: str | Path) -> None:
37
+ self.workspace = Path(workspace).resolve()
38
+
39
+ def _safe_path(self, rel_path: str = "") -> Path:
40
+ """Resolve a workspace-relative path, blocking '../' escapes.
41
+
42
+ Returns the workspace root when rel_path is empty.
43
+ Raises ValueError if the resolved path is outside the workspace.
44
+ """
45
+ if not rel_path:
46
+ return self.workspace
47
+ rel_path = rel_path.lstrip("/")
48
+ target = (self.workspace / rel_path).resolve()
49
+ if not str(target).startswith(str(self.workspace)):
50
+ raise ValueError(f"Path traversal not allowed: {rel_path}")
51
+ return target
@@ -0,0 +1,328 @@
1
+ # coding=utf-8
2
+ """
3
+ alpha_backtest.py - Alpha 公式 Trading 回测工具
4
+
5
+ Alpha-GPT 工作流的【Evaluator】可选工具。
6
+ 对 top-K 候选公式做完整 Trading 回测,返回年化收益 / Sharpe / 最大回撤。
7
+
8
+ 复用:
9
+ - 现有 BacktestTool 思路(CodeSandbox → Strategy → Broker)
10
+ - 但更轻量:直接用 top-K 等权组合,不需要完整 Pipeline
11
+
12
+ Usage::
13
+
14
+ tool = AlphaBacktestTool()
15
+ result = await tool.execute(
16
+ formulas=["rank(-ts_mean(returns, 20))"],
17
+ data=df,
18
+ top_k=10,
19
+ initial_cash=1_000_000,
20
+ )
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import logging
26
+ from pathlib import Path
27
+ from typing import Any, Dict, List, Optional, Sequence
28
+
29
+ import numpy as np
30
+
31
+ from .base import Tool
32
+
33
+ logger = logging.getLogger(__name__)
34
+
35
+
36
+ class AlphaBacktestTool(Tool):
37
+ """Alpha 公式 Trading 回测工具(top-K 等权组合)"""
38
+
39
+ def __init__(self) -> None:
40
+ pass
41
+
42
+ @property
43
+ def name(self) -> str:
44
+ return "alpha_backtest"
45
+
46
+ @property
47
+ def description(self) -> str:
48
+ return (
49
+ "对 alpha 公式做 Trading 回测。"
50
+ "对每公式计算 top-K 等权组合的:年化收益 / Sharpe / 最大回撤 / 胜率。"
51
+ "输入 formulas 列表 + 数据 + top_k。"
52
+ )
53
+
54
+ @property
55
+ def parameters(self) -> Dict[str, Any]:
56
+ return {
57
+ "type": "object",
58
+ "properties": {
59
+ "formulas": {
60
+ "type": "array",
61
+ "items": {"type": "string"},
62
+ "description": "待回测的公式列表(建议 ≤ 20)",
63
+ },
64
+ "data_path": {
65
+ "type": "string",
66
+ "description": "数据路径(parquet/csv)",
67
+ },
68
+ "top_k": {
69
+ "type": "integer",
70
+ "default": 10,
71
+ "description": "每期持有 top-K 股票(默认 10)",
72
+ },
73
+ "bottom_k": {
74
+ "type": "integer",
75
+ "default": 0,
76
+ "description": "做空 bottom-K(0=不做空,默认 0)",
77
+ },
78
+ "rebalance_freq": {
79
+ "type": "integer",
80
+ "default": 5,
81
+ "description": "调仓频率(交易日,默认 5 = 周度)",
82
+ },
83
+ "initial_cash": {
84
+ "type": "number",
85
+ "default": 1_000_000.0,
86
+ "description": "初始资金(默认 100 万)",
87
+ },
88
+ "commission": {
89
+ "type": "number",
90
+ "default": 0.001,
91
+ "description": "手续费率(默认 0.001)",
92
+ },
93
+ "date_column": {
94
+ "type": "string",
95
+ "default": "date",
96
+ "description": "日期列名",
97
+ },
98
+ "code_column": {
99
+ "type": "string",
100
+ "default": "code",
101
+ "description": "股票代码列名",
102
+ },
103
+ },
104
+ "required": ["formulas"],
105
+ }
106
+
107
+ @property
108
+ def read_only(self) -> bool:
109
+ return True
110
+
111
+ async def execute(
112
+ self,
113
+ formulas: Sequence[str],
114
+ data_path: Optional[str] = None,
115
+ top_k: int = 10,
116
+ bottom_k: int = 0,
117
+ rebalance_freq: int = 5,
118
+ initial_cash: float = 1_000_000.0,
119
+ commission: float = 0.001,
120
+ date_column: str = "date",
121
+ code_column: str = "code",
122
+ data: Any = None,
123
+ **kwargs: Any,
124
+ ) -> Dict[str, Any]:
125
+ try:
126
+ import polars as pl
127
+ from QuantNodes.research.quant_alpha.adapters import (
128
+ PolarsAlphaCalculator,
129
+ )
130
+ from QuantNodes.agent.tools.alpha_evaluate import AlphaEvaluateTool
131
+
132
+ df = AlphaEvaluateTool._resolve_data(
133
+ data, data_path, date_column, code_column
134
+ )
135
+ if df is None:
136
+ return {"backtests": [], "summary": {"error": "no data"}}
137
+
138
+ forward_returns_dict = AlphaEvaluateTool._build_forward_returns(
139
+ df, [1], date_column, code_column,
140
+ )
141
+
142
+ calc = PolarsAlphaCalculator(
143
+ data=df,
144
+ forward_returns=forward_returns_dict,
145
+ date_column=date_column,
146
+ code_column=code_column,
147
+ )
148
+
149
+ backtests: List[Dict[str, Any]] = []
150
+ for formula in formulas:
151
+ backtests.append(
152
+ self._backtest_one(
153
+ calc,
154
+ formula,
155
+ top_k=top_k,
156
+ bottom_k=bottom_k,
157
+ rebalance_freq=rebalance_freq,
158
+ initial_cash=initial_cash,
159
+ commission=commission,
160
+ date_column=date_column,
161
+ code_column=code_column,
162
+ )
163
+ )
164
+
165
+ successful = [b for b in backtests if b["status"] == "success"]
166
+ sharpes = [
167
+ b["backtest"]["sharpe"] for b in successful if b["backtest"]["sharpe"] is not None
168
+ ]
169
+ return {
170
+ "backtests": backtests,
171
+ "summary": {
172
+ "total": len(backtests),
173
+ "success": len(successful),
174
+ "failed": len(backtests) - len(successful),
175
+ "avg_sharpe": float(np.mean(sharpes)) if sharpes else 0.0,
176
+ "best_sharpe": float(np.max(sharpes)) if sharpes else 0.0,
177
+ },
178
+ }
179
+ except Exception as exc:
180
+ logger.exception("alpha_backtest failed")
181
+ return {"backtests": [], "summary": {"error": str(exc)}}
182
+
183
+ def _backtest_one(
184
+ self,
185
+ calc: Any,
186
+ formula: str,
187
+ top_k: int,
188
+ bottom_k: int,
189
+ rebalance_freq: int,
190
+ initial_cash: float,
191
+ commission: float,
192
+ date_column: str,
193
+ code_column: str,
194
+ ) -> Dict[str, Any]:
195
+ try:
196
+ import polars as pl
197
+
198
+ from QuantNodes.agent.tools.alpha_evaluate import AlphaEvaluateTool
199
+
200
+ expr = AlphaEvaluateTool._parse_simple_formula(formula)
201
+ factor_series = calc._evaluate_factor(expr)
202
+ if factor_series is None:
203
+ return {
204
+ "formula": formula,
205
+ "status": "failed",
206
+ "backtest": {},
207
+ "error_msg": "factor evaluation returned None",
208
+ }
209
+
210
+ dates = sorted(calc.data[date_column].unique().to_list())
211
+ if len(dates) < 2:
212
+ return {
213
+ "formula": formula,
214
+ "status": "failed",
215
+ "backtest": {},
216
+ "error_msg": "not enough dates",
217
+ }
218
+
219
+ work = calc.data.select([date_column, code_column, "close"]).with_columns(
220
+ factor_series.alias("_factor")
221
+ )
222
+ fwd = calc.forward_returns[1]
223
+ work = work.with_columns(fwd.alias("_fwd"))
224
+
225
+ holdings_returns: List[float] = []
226
+ cash = initial_cash
227
+ equity_curve: List[float] = [initial_cash]
228
+ entry_days: List[int] = list(range(0, len(dates) - 1, rebalance_freq))
229
+ prev_longs: List[str] = []
230
+ prev_shorts: List[str] = []
231
+
232
+ for entry_idx in entry_days:
233
+ if entry_idx + 1 >= len(dates):
234
+ break
235
+ entry_date = dates[entry_idx]
236
+ exit_date = dates[entry_idx + 1]
237
+
238
+ day_slice = work.filter(pl.col(date_column) == entry_date)
239
+ ranked = day_slice.filter(pl.col("_factor").is_not_null()).sort(
240
+ "_factor", descending=True
241
+ )
242
+ longs = ranked.head(top_k)[code_column].to_list()
243
+ shorts = (
244
+ ranked.tail(bottom_k)[code_column].to_list() if bottom_k > 0 else []
245
+ )
246
+
247
+ if not longs:
248
+ continue
249
+
250
+ next_close = work.filter(
251
+ (pl.col(date_column) == exit_date)
252
+ & pl.col(code_column).is_in(longs + shorts)
253
+ )
254
+
255
+ if bottom_k > 0 and shorts:
256
+ long_ret = (
257
+ next_close.filter(pl.col(code_column).is_in(longs))["_fwd"]
258
+ .drop_nulls()
259
+ .mean()
260
+ )
261
+ short_ret = (
262
+ -next_close.filter(pl.col(code_column).is_in(shorts))["_fwd"]
263
+ .drop_nulls()
264
+ .mean()
265
+ )
266
+ period_ret = float((long_ret or 0) + (short_ret or 0)) / 2.0
267
+ else:
268
+ long_ret = next_close.filter(pl.col(code_column).is_in(longs))[
269
+ "_fwd"
270
+ ].drop_nulls().mean()
271
+ period_ret = float(long_ret or 0)
272
+
273
+ changed = len(set(longs) ^ set(prev_longs)) + len(set(shorts) ^ set(prev_shorts))
274
+ total = max(1, len(longs) + len(shorts))
275
+ turnover = changed / total
276
+ cost = turnover * commission
277
+ net_ret = period_ret - cost
278
+ cash *= 1.0 + net_ret
279
+ holdings_returns.append(net_ret)
280
+ equity_curve.append(cash)
281
+ prev_longs, prev_shorts = longs, shorts
282
+
283
+ if not holdings_returns:
284
+ return {
285
+ "formula": formula,
286
+ "status": "failed",
287
+ "backtest": {},
288
+ "error_msg": "no valid periods",
289
+ }
290
+
291
+ rets = np.array(holdings_returns)
292
+ ann_factor = 252.0 / rebalance_freq
293
+ annual_return = float(np.mean(rets) * ann_factor)
294
+ sharpe = (
295
+ float(np.mean(rets) / (np.std(rets) + 1e-12) * np.sqrt(ann_factor))
296
+ if np.std(rets) > 1e-12
297
+ else 0.0
298
+ )
299
+ equity = np.array(equity_curve)
300
+ running_max = np.maximum.accumulate(equity)
301
+ drawdown = (equity - running_max) / running_max
302
+ max_dd = float(np.min(drawdown)) if drawdown.size else 0.0
303
+ wins = int(np.sum(rets > 0))
304
+ win_rate = wins / len(rets) if len(rets) else 0.0
305
+
306
+ return {
307
+ "formula": formula,
308
+ "status": "success",
309
+ "backtest": {
310
+ "annual_return": annual_return,
311
+ "sharpe": sharpe,
312
+ "max_drawdown": max_dd,
313
+ "win_rate": float(win_rate),
314
+ "n_periods": len(rets),
315
+ "equity_curve": equity_curve[:: max(1, len(equity_curve) // 50)],
316
+ },
317
+ "error_msg": None,
318
+ }
319
+ except Exception as exc:
320
+ return {
321
+ "formula": formula,
322
+ "status": "failed",
323
+ "backtest": {},
324
+ "error_msg": str(exc),
325
+ }
326
+
327
+
328
+ __all__ = ["AlphaBacktestTool"]