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,401 @@
1
+ # coding=utf-8
2
+ """
3
+ 配置驱动的回测工具
4
+
5
+ 接受 YAML 配置,通过 ConfigBacktestRunner 直接执行回测。
6
+ """
7
+
8
+ from typing import Any, Dict
9
+ import yaml
10
+
11
+ from QuantNodes.agent.tools.base import Tool
12
+
13
+
14
+ class ConfigBacktestTool(Tool):
15
+ """配置驱动的回测工具
16
+
17
+ 通过 YAML 配置文件定义策略,直接执行回测。
18
+
19
+ 工作流程:
20
+ 1. 加载 YAML 配置
21
+ 2. 检查算子覆盖度
22
+ 3. 调用 ConfigBacktestRunner 执行回测
23
+ 4. 返回结果
24
+ """
25
+
26
+ def __init__(self):
27
+ pass
28
+
29
+ @property
30
+ def name(self) -> str:
31
+ return "config_backtest"
32
+
33
+ @property
34
+ def description(self) -> str:
35
+ return (
36
+ "通过 YAML 配置文件执行策略回测。"
37
+ "支持因子定义、运算配置、组合因子和回测参数。"
38
+ )
39
+
40
+ @property
41
+ def parameters(self) -> Dict[str, Any]:
42
+ return {
43
+ "type": "object",
44
+ "properties": {
45
+ "config_yaml": {
46
+ "type": "string",
47
+ "description": "YAML 格式的策略配置字符串"
48
+ },
49
+ "config_path": {
50
+ "type": "string",
51
+ "description": "YAML 配置文件路径"
52
+ },
53
+ "data_path": {
54
+ "type": "string",
55
+ "description": "数据文件路径 (csv/parquet)"
56
+ },
57
+ "start_date": {
58
+ "type": "string",
59
+ "description": "覆盖配置中的开始日期"
60
+ },
61
+ "end_date": {
62
+ "type": "string",
63
+ "description": "覆盖配置中的结束日期"
64
+ },
65
+ "initial_cash": {
66
+ "type": "number",
67
+ "description": "覆盖配置中的初始资金"
68
+ }
69
+ },
70
+ "required": []
71
+ }
72
+
73
+ @property
74
+ def read_only(self) -> bool:
75
+ return False
76
+
77
+ @property
78
+ def concurrency_safe(self) -> bool:
79
+ return False
80
+
81
+ async def execute(
82
+ self,
83
+ config_yaml: str = None,
84
+ config_path: str = None,
85
+ data_path: str = None,
86
+ start_date: str = None,
87
+ end_date: str = None,
88
+ initial_cash: float = None,
89
+ **kwargs
90
+ ) -> Dict[str, Any]:
91
+ result = {
92
+ "status": "success",
93
+ "summary": {},
94
+ "config_info": {},
95
+ }
96
+
97
+ try:
98
+ # 1. 加载配置
99
+ strategy_config = self._load_config(config_yaml, config_path)
100
+
101
+ if strategy_config is None:
102
+ result["status"] = "error"
103
+ result["errors"] = ["Need config_yaml or config_path"]
104
+ return result
105
+
106
+ # 2. 覆盖参数
107
+ if start_date and strategy_config.backtest:
108
+ strategy_config.backtest.start_date = start_date
109
+ if end_date and strategy_config.backtest:
110
+ strategy_config.backtest.end_date = end_date
111
+ if initial_cash and strategy_config.backtest:
112
+ strategy_config.backtest.initial_cash = initial_cash
113
+
114
+ # 3. 检查覆盖度
115
+ from QuantNodes.agent.config.loader import ConfigLoader
116
+ loader = ConfigLoader()
117
+ coverage = loader.check_coverage(strategy_config)
118
+
119
+ if not coverage.is_complete:
120
+ result["status"] = "warning"
121
+ result["warnings"] = [
122
+ f"Unresolved operators: {coverage.unresolved}"
123
+ ]
124
+
125
+ # 4. 加载数据
126
+ data = self._load_data(strategy_config, data_path)
127
+
128
+ # 5. 调用 ConfigBacktestRunner
129
+ from QuantNodes.backtest.config_runner import ConfigBacktestRunner
130
+
131
+ runner = ConfigBacktestRunner()
132
+ bt_result = runner.run(strategy_config, data)
133
+
134
+ # 6. 保存输出文件
135
+ saved_files = {}
136
+ if strategy_config.output is not None:
137
+ signals_df = None
138
+ if bt_result.statistics.get("total_trades", 0) > 0:
139
+ signals_df = bt_result.trades
140
+ saved_files = runner.save_output(
141
+ bt_result, strategy_config, signals_df=signals_df
142
+ )
143
+
144
+ # 7. 格式化返回结果
145
+ result["status"] = "success"
146
+ result["summary"] = {
147
+ "total_trades": bt_result.statistics.get("total_trades", 0),
148
+ "final_cash": bt_result.final_cash,
149
+ "total_commission": bt_result.statistics.get("total_commission", 0),
150
+ "total_return": bt_result.total_return,
151
+ "sharpe_ratio": bt_result.sharpe_ratio,
152
+ "max_drawdown": bt_result.max_drawdown,
153
+ "win_rate": bt_result.win_rate,
154
+ "annualized_return": bt_result.statistics.get("annualized_return", 0),
155
+ "annualized_volatility": bt_result.statistics.get("annualized_volatility", 0),
156
+ "sortino_ratio": bt_result.statistics.get("sortino_ratio", 0),
157
+ "calmar_ratio": bt_result.statistics.get("calmar_ratio", 0),
158
+ "profit_factor": bt_result.statistics.get("profit_factor", 0),
159
+ "avg_trade_pnl": bt_result.statistics.get("avg_trade_pnl", 0),
160
+ "trading_days": bt_result.statistics.get("trading_days", 0),
161
+ }
162
+
163
+ # 8. 附加配置信息
164
+ result["config_info"] = {
165
+ "name": strategy_config.name,
166
+ "description": strategy_config.description,
167
+ "factors": len(strategy_config.factors),
168
+ "operations": len(strategy_config.operations),
169
+ "composites": len(strategy_config.composite),
170
+ "has_backtest": strategy_config.backtest is not None,
171
+ }
172
+
173
+ if saved_files:
174
+ result["output_files"] = saved_files
175
+
176
+ except Exception as e:
177
+ result["status"] = "error"
178
+ result["errors"] = [str(e)]
179
+
180
+ return result
181
+
182
+ def _load_config(self, config_yaml: str = None, config_path: str = None):
183
+ """加载配置"""
184
+ from QuantNodes.agent.config.loader import ConfigLoader
185
+
186
+ if config_yaml:
187
+ try:
188
+ data = yaml.safe_load(config_yaml)
189
+ if data is None:
190
+ return None
191
+ loader = ConfigLoader()
192
+ return loader._parse(data)
193
+ except yaml.YAMLError as e:
194
+ raise ValueError(f"Invalid YAML: {e}")
195
+
196
+ if config_path:
197
+ loader = ConfigLoader()
198
+ return loader.load(config_path)
199
+
200
+ return None
201
+
202
+ def _load_data(self, config, data_path: str = None):
203
+ """加载数据为 Polars LazyFrame
204
+
205
+ 数据加载分发逻辑:
206
+ 1. data_path 参数 → 直接读文件(向后兼容)
207
+ 2. config.data.source == "csv"/"parquet" → 读文件
208
+ 3. config.data.source == "clickhouse"/"mysql" → _load_from_db()
209
+ 4. config.data.source == "sqlite"/"duckdb" → _load_from_db() (path-based)
210
+ """
211
+
212
+ # 优先使用 data_path 参数
213
+ if data_path:
214
+ return self._read_data_file(data_path)
215
+
216
+ if not config.data:
217
+ raise ValueError("No data configuration provided. Set config.data or data_path")
218
+
219
+ source = config.data.source
220
+
221
+ # 文件类数据源
222
+ if source in ("csv", "parquet"):
223
+ if config.data.path:
224
+ lf = self._read_data_file(config.data.path)
225
+ # 应用列名映射
226
+ if config.data.column_mapping:
227
+ lf = lf.rename(config.data.column_mapping)
228
+ return lf
229
+ raise ValueError(f"source='{source}' requires config.data.path")
230
+
231
+ # 数据库类数据源
232
+ if source in ("clickhouse", "mysql", "sqlite", "duckdb"):
233
+ return self._load_from_db(config)
234
+
235
+ raise ValueError(f"Unsupported data source: {source}")
236
+
237
+ def _load_from_db(self, config):
238
+ """从 database_node 加载数据
239
+
240
+ 流程: 读取 conn.ini → 构建 SQL → 查询 → 列名映射 → 返回 LazyFrame
241
+
242
+ 如果 cache_enabled=True, 优先使用 MarketDataCacheNode 缓存查询结果。
243
+
244
+ 注意: DateTime 转换使用映射后的 date_column(而非 db_date_column)。
245
+ """
246
+ import polars as pl
247
+
248
+ data_cfg = config.data
249
+ source = data_cfg.source
250
+
251
+ # 1. 构建 Node 实例
252
+ node = self._build_db_node(source, data_cfg)
253
+
254
+ # 2. 缓存逻辑
255
+ if data_cfg.cache_enabled:
256
+ df = self._load_with_cache(data_cfg, node)
257
+ else:
258
+ df = self._load_from_db_direct(data_cfg, node)
259
+
260
+ # 3. 列名映射
261
+ if data_cfg.column_mapping:
262
+ if hasattr(df, "to_pandas"):
263
+ # Polars DataFrame — rename() takes positional dict
264
+ df = df.rename(data_cfg.column_mapping)
265
+ else:
266
+ # pandas DataFrame — rename() takes columns= kwarg
267
+ df = df.rename(columns=data_cfg.column_mapping)
268
+
269
+ # 4. DateTime → Date 类型转换(使用映射后的 date_column)
270
+ date_col = data_cfg.date_column
271
+ if date_col in df.columns:
272
+ try:
273
+ import polars as pl_polars
274
+ pdf = pl_polars.from_pandas(df)
275
+ if pdf.schema.get(date_col) == pl_polars.Datetime:
276
+ pdf = pdf.with_columns(pl_polars.col(date_col).cast(pl_polars.Date))
277
+ df = pdf.to_pandas()
278
+ except Exception:
279
+ pass
280
+
281
+ return pl.from_pandas(df).lazy()
282
+
283
+ def _load_with_cache(self, data_cfg, node):
284
+ """使用缓存加载数据"""
285
+ from QuantNodes.cache_node import MarketDataCacheNode
286
+
287
+ cache_node = MarketDataCacheNode(config={
288
+ "cache_dir": data_cfg.cache_dir,
289
+ "ttl_days": data_cfg.cache_ttl_days,
290
+ "force_refresh": data_cfg.cache_force_refresh,
291
+ })
292
+
293
+ return cache_node.execute({
294
+ "source": data_cfg.source,
295
+ "table": data_cfg.table,
296
+ "columns": data_cfg.columns,
297
+ "query_filter": data_cfg.query_filter,
298
+ "node": node,
299
+ "date_column": data_cfg.db_date_column or data_cfg.date_column,
300
+ })
301
+
302
+ def _load_from_db_direct(self, data_cfg, node):
303
+ """直接从数据库加载 (不使用缓存)"""
304
+ try:
305
+ node.connect()
306
+ sql = self._build_query(data_cfg)
307
+ df = node.query(sql)
308
+ finally:
309
+ node.disconnect()
310
+ return df
311
+
312
+ def _build_db_node(self, source, data_cfg):
313
+ """构建 database_node 实例 (委托 database_node.create_db_node 工厂)"""
314
+ from pathlib import Path
315
+ from QuantNodes.conf_node.ini_config import IniConfigNode
316
+ from QuantNodes.database_node import create_db_node
317
+
318
+ if source in ("sqlite", "duckdb"):
319
+ return self._build_embedded_node(source, data_cfg)
320
+
321
+ # clickhouse / mysql: 从 conn.ini 读取连接参数
322
+ if not data_cfg.conn_ini:
323
+ raise ValueError(f"source='{source}' requires conn_ini")
324
+
325
+ ini_path = Path(data_cfg.conn_ini)
326
+ if not ini_path.exists():
327
+ raise FileNotFoundError(f"conn.ini not found: {ini_path}")
328
+
329
+ ini = IniConfigNode(str(ini_path), section=data_cfg.conn_section)
330
+ conn_params = ini.execute()
331
+
332
+ if source == "clickhouse":
333
+ return create_db_node(
334
+ "clickhouse",
335
+ host=conn_params.get("host", "localhost"),
336
+ port=int(conn_params.get("port", 8123)),
337
+ user=conn_params.get("user", "default"),
338
+ passwd=conn_params.get("passwd", ""),
339
+ database=conn_params.get("db", "default"),
340
+ )
341
+ elif source == "mysql":
342
+ return create_db_node(
343
+ "mysql",
344
+ host=conn_params.get("host", "localhost"),
345
+ port=int(conn_params.get("port", 3306)),
346
+ user=conn_params.get("user", "root"),
347
+ passwd=conn_params.get("passwd", ""),
348
+ db=conn_params.get("db", ""),
349
+ )
350
+
351
+ def _build_embedded_node(self, source, data_cfg):
352
+ """构建嵌入式数据库 Node (sqlite/duckdb, 委托 create_db_node 工厂)"""
353
+ from QuantNodes.database_node import create_db_node
354
+
355
+ path = data_cfg.path
356
+ if not path:
357
+ raise ValueError(f"source='{source}' requires config.data.path")
358
+
359
+ if source == "sqlite":
360
+ return create_db_node("sqlite", database=path)
361
+ elif source == "duckdb":
362
+ return create_db_node("duckdb", database=path)
363
+
364
+ def _build_query(self, data_cfg):
365
+ """从 DataConfig 构建 SQL 查询
366
+
367
+ 使用 db_*_column 作为 SQL 标识符(数据库原始列名)。
368
+ 如果 db_*_column 为空,则 fallback 到 date_column/code_column。
369
+ """
370
+ cols = data_cfg.columns or ["*"]
371
+ cols_str = ", ".join(cols)
372
+ table = data_cfg.table
373
+
374
+ if not table:
375
+ raise ValueError("DataConfig.table is required for database sources")
376
+
377
+ sql = f"SELECT {cols_str} FROM {table}"
378
+
379
+ where_parts = []
380
+ if data_cfg.query_filter:
381
+ where_parts.append(data_cfg.query_filter.lstrip("WHERE "))
382
+
383
+ if where_parts:
384
+ sql += " WHERE " + " AND ".join(where_parts)
385
+
386
+ code_col = data_cfg.db_code_column or data_cfg.code_column
387
+ date_col = data_cfg.db_date_column or data_cfg.date_column
388
+ sql += f" ORDER BY {code_col}, {date_col}"
389
+
390
+ return sql
391
+
392
+ def _read_data_file(self, path: str):
393
+ """读取数据文件"""
394
+ import polars as pl
395
+
396
+ if path.endswith(".csv"):
397
+ return pl.scan_csv(path)
398
+ elif path.endswith(".parquet"):
399
+ return pl.scan_parquet(path)
400
+ else:
401
+ raise ValueError(f"Unsupported file format: {path}")
@@ -0,0 +1,97 @@
1
+ # coding=utf-8
2
+ """
3
+ Tool Context - Execution context for tools with permission checking
4
+ """
5
+
6
+ from dataclasses import dataclass, field
7
+ from typing import Any, Dict, List, Optional
8
+ import asyncio
9
+
10
+ from ..permission.service import PermissionService
11
+
12
+
13
+ @dataclass
14
+ class ToolContext:
15
+ """Tool execution context containing permission checking and session info.
16
+
17
+ This context is passed to tools during execution and provides
18
+ access to permission services and abort signals.
19
+ """
20
+ session_id: str
21
+ agent_id: str
22
+ project_root: str
23
+ permission_service: PermissionService
24
+ abort_signal: asyncio.Event = field(default_factory=asyncio.Event)
25
+ tool_defaults: Dict[str, Any] = field(default_factory=dict)
26
+
27
+ async def check_permission(
28
+ self,
29
+ tool: str,
30
+ permission: str,
31
+ patterns: List[str],
32
+ always_patterns: Optional[List[str]] = None,
33
+ metadata: Optional[Dict[str, Any]] = None,
34
+ ) -> bool:
35
+ """Check if an action is permitted.
36
+
37
+ Args:
38
+ tool: Tool name
39
+ permission: Permission category (e.g., "bash", "read", "edit")
40
+ patterns: Target patterns to check
41
+ always_patterns: Patterns that can be permanently allowed
42
+ metadata: Additional information (e.g., diff for edits)
43
+
44
+ Returns:
45
+ True if allowed
46
+
47
+ Raises:
48
+ PermissionDeniedError: If permission is denied
49
+ PermissionRejectedError: If user rejects
50
+ """
51
+ return await self.permission_service.check(
52
+ tool=tool,
53
+ permission=permission,
54
+ patterns=patterns,
55
+ always_patterns=always_patterns or [],
56
+ metadata=metadata or {},
57
+ )
58
+
59
+ def is_aborted(self) -> bool:
60
+ """Check if execution should abort"""
61
+ return self.abort_signal.is_set()
62
+
63
+ async def wait_for_abort(self, timeout: Optional[float] = None) -> bool:
64
+ """Wait for abort signal.
65
+
66
+ Args:
67
+ timeout: Maximum time to wait in seconds
68
+
69
+ Returns:
70
+ True if abort was signaled, False if timeout
71
+ """
72
+ try:
73
+ await asyncio.wait_for(self.abort_signal.wait(), timeout=timeout)
74
+ return True
75
+ except asyncio.TimeoutError:
76
+ return False
77
+
78
+
79
+ class ToolContextFactory:
80
+ """Factory for creating ToolContext instances"""
81
+
82
+ @staticmethod
83
+ def create(
84
+ session_id: str,
85
+ agent_id: str,
86
+ project_root: str,
87
+ permission_service: PermissionService,
88
+ **kwargs: Any,
89
+ ) -> ToolContext:
90
+ """Create a new ToolContext"""
91
+ return ToolContext(
92
+ session_id=session_id,
93
+ agent_id=agent_id,
94
+ project_root=project_root,
95
+ permission_service=permission_service,
96
+ **kwargs,
97
+ )
@@ -0,0 +1,77 @@
1
+ # coding=utf-8
2
+ """
3
+ DreamSkill - Agent Tool for Querying Dreams
4
+
5
+ Phase 4.2: Dream System
6
+ """
7
+
8
+ from typing import Any, Dict
9
+
10
+ from ..skills.base import Skill, SkillCategory, SkillMetadata, SkillResult
11
+
12
+
13
+ class DreamSkill(Skill):
14
+ """Skill for querying Dream system insights"""
15
+
16
+ @property
17
+ def metadata(self) -> SkillMetadata:
18
+ return SkillMetadata(
19
+ name="dream_insight",
20
+ description="查询 Dream 系统生成的投资洞察",
21
+ category=SkillCategory.DREAM,
22
+ examples=[
23
+ "查看最近的投资洞察",
24
+ "有什么新的市场发现",
25
+ ],
26
+ )
27
+
28
+ async def execute(self, context: Dict[str, Any]) -> SkillResult:
29
+ """Execute dream insight query"""
30
+ from ..core.memory import MemoryStore
31
+
32
+ workspace = context.get("workspace", ".")
33
+ dream_store = MemoryStore(workspace).get_dream_store()
34
+
35
+ query = context.get("query", "recent")
36
+ limit = context.get("limit", 5)
37
+
38
+ if query == "recent":
39
+ dreams = dream_store.get_recent_dreams(limit)
40
+ else:
41
+ dreams = dream_store.get_dreams_by_type(query, limit)
42
+
43
+ data = [
44
+ {
45
+ "id": d.id,
46
+ "type": d.type,
47
+ "content": d.content,
48
+ "insights": d.insights,
49
+ "source": d.source,
50
+ "confidence": d.confidence,
51
+ "timestamp": d.timestamp,
52
+ }
53
+ for d in dreams
54
+ ]
55
+
56
+ return SkillResult(success=True, data=data)
57
+
58
+ def get_parameters_schema(self) -> Dict[str, Any]:
59
+ """Return parameter schema"""
60
+ return {
61
+ "type": "object",
62
+ "properties": {
63
+ "query": {
64
+ "type": "string",
65
+ "description": (
66
+ "查询类型: recent 或具体类型 "
67
+ "(wiki_insight/factor_insight/strategy_insight)"
68
+ ),
69
+ "default": "recent",
70
+ },
71
+ "limit": {
72
+ "type": "integer",
73
+ "description": "返回数量",
74
+ "default": 5,
75
+ },
76
+ },
77
+ }
@@ -0,0 +1,38 @@
1
+ # coding=utf-8
2
+ """
3
+ Echo测试工具
4
+ """
5
+
6
+ from .base import Tool
7
+
8
+
9
+ class EchoTool(Tool):
10
+ """Echo测试工具 - 返回输入内容"""
11
+
12
+ @property
13
+ def name(self) -> str:
14
+ return "echo"
15
+
16
+ @property
17
+ def description(self) -> str:
18
+ return "返回输入的消息内容,用于测试工具调用功能"
19
+
20
+ @property
21
+ def parameters(self) -> dict:
22
+ return {
23
+ "type": "object",
24
+ "properties": {
25
+ "message": {
26
+ "type": "string",
27
+ "description": "要返回的消息内容"
28
+ }
29
+ },
30
+ "required": ["message"]
31
+ }
32
+
33
+ @property
34
+ def read_only(self) -> bool:
35
+ return True
36
+
37
+ async def execute(self, message: str, **kwargs) -> str:
38
+ return message