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,60 @@
1
+ # coding=utf-8
2
+ """
3
+ QuantNodes 对象基类
4
+
5
+ 使用 dataclass 替代 traits.HasTraits
6
+ """
7
+
8
+ import logging
9
+ from dataclasses import dataclass, field
10
+ from typing import Any, Dict
11
+
12
+
13
+ @dataclass
14
+ class QuantNodesObject:
15
+ """
16
+ QuantNodes 基础对象类
17
+
18
+ 使用 dataclass 提供配置属性系统
19
+
20
+ Attributes:
21
+ name: 对象名称
22
+ config: 配置字典
23
+ """
24
+
25
+ name: str = "QuantNodesObject"
26
+ config: Dict[str, Any] = field(default_factory=dict)
27
+ _logger: logging.Logger = field(default=None, repr=False)
28
+
29
+ def __post_init__(self):
30
+ if self._logger is None:
31
+ self._logger = logging.getLogger(f"QuantNodes.{self.__class__.__name__}")
32
+
33
+ def get_config(self, key: str, default: Any = None) -> Any:
34
+ """
35
+ 获取配置值
36
+
37
+ Args:
38
+ key: 配置键
39
+ default: 默认值
40
+
41
+ Returns:
42
+ 配置值
43
+ """
44
+ return self.config.get(key, default)
45
+
46
+ def set_config(self, key: str, value: Any) -> None:
47
+ """
48
+ 设置配置值
49
+
50
+ Args:
51
+ key: 配置键
52
+ value: 配置值
53
+ """
54
+ self.config[key] = value
55
+
56
+ def __repr__(self) -> str:
57
+ return f"<{self.__class__.__name__}: {self.name}>"
58
+
59
+ def __str__(self) -> str:
60
+ return self.__repr__()
@@ -0,0 +1,27 @@
1
+ # coding=utf-8
2
+ """QuantNodes MCP server.
3
+
4
+ Exposes the 8 core quant tools as MCP (Model Context Protocol) tools so
5
+ they can be invoked by:
6
+ - HKUDS/nanobot 0.2.1 (via nanobot_config.json mcpServers entry)
7
+ - Any MCP client (Claude Desktop, Cursor, VSCode, ...)
8
+ - A second nanobot instance pointing at this server
9
+
10
+ Run as stdio (default for nanobot)::
11
+
12
+ python -m QuantNodes.mcp_server
13
+
14
+ Run with HTTP transport (for testing / inspector)::
15
+
16
+ python -m QuantNodes.mcp_server --transport http --port 8765
17
+
18
+ Inspect with MCP devtools::
19
+
20
+ mcp dev QuantNodes.mcp_server.server:app
21
+ """
22
+
23
+ from .server import app, mcp, main
24
+
25
+ __version__ = "3.0.0"
26
+
27
+ __all__ = ["app", "mcp", "main", "__version__"]
@@ -0,0 +1,4 @@
1
+ """Allow ``python -m QuantNodes.mcp_server`` to start the MCP server."""
2
+ from QuantNodes.mcp_server.server import main
3
+
4
+ raise SystemExit(main())
@@ -0,0 +1,272 @@
1
+ # coding=utf-8
2
+ """FastMCP server exposing QuantNodes quant tools over MCP.
3
+
4
+ Approach
5
+ --------
6
+ Each QuantNodes tool is a class with ``name``, ``description``, ``parameters``
7
+ (JSON Schema), and ``async execute(**kwargs)``. FastMCP doesn't support
8
+ ``**kwargs`` function signatures, so we use a single ``call_quant_tool``
9
+ dispatcher MCP tool that:
10
+ 1. Accepts ``tool_name`` + arbitrary ``arguments`` dict (object).
11
+ 2. Looks up the QuantNodes tool by name.
12
+ 3. Invokes ``tool.execute(**arguments)`` and returns the result.
13
+
14
+ This is cleaner than registering 8 separate MCP tools (which would require
15
+ dynamic signature generation) and provides a uniform contract.
16
+
17
+ Run as stdio (default for nanobot)::
18
+
19
+ python -m QuantNodes.mcp_server
20
+
21
+ Run with HTTP transport (for inspector)::
22
+
23
+ python -m QuantNodes.mcp_server --transport http --port 8765
24
+
25
+ Inspect with MCP devtools::
26
+
27
+ mcp dev QuantNodes.mcp_server.server:app
28
+ """
29
+
30
+ from __future__ import annotations
31
+
32
+ import argparse
33
+ import inspect
34
+ import json
35
+ import logging
36
+ import sys
37
+ from pathlib import Path
38
+ from typing import Any, Dict, List, Optional
39
+
40
+ from fastmcp import FastMCP
41
+ from pydantic import Field, create_model
42
+
43
+ from QuantNodes.constants import DEFAULT_HOST, DEFAULT_WEBSOCKET_PORT
44
+
45
+ logger = logging.getLogger(__name__)
46
+
47
+
48
+ _DEFAULT_WORKSPACE = Path(".agent")
49
+
50
+ mcp = FastMCP(
51
+ name="quant",
52
+ instructions=(
53
+ "QuantNodes quant toolkit dispatcher. Use `list_quant_tools` to discover "
54
+ "available tools, then `call_quant_tool(tool_name, arguments)` to invoke. "
55
+ "Each tool accepts a JSON Schema-defined arguments object."
56
+ ),
57
+ )
58
+
59
+
60
+ def _build_tools_registry(workspace: Path) -> Dict[str, Any]:
61
+ """Instantiate the 8 core quant tools (lazy + cached)."""
62
+ if hasattr(mcp, "_quant_tools_cache") and mcp._quant_tools_cache is not None:
63
+ return mcp._quant_tools_cache
64
+
65
+ try:
66
+ from QuantNodes.agent.tools import (
67
+ BacktestTool,
68
+ ConfigBacktestTool,
69
+ FactorTool,
70
+ PipelineTool,
71
+ SandboxTool,
72
+ StrategyTool,
73
+ WikiTool,
74
+ )
75
+ workspace_dep = {"WikiTool": {"wiki_path": str(workspace / "wiki")}}
76
+ factories = [BacktestTool, ConfigBacktestTool, FactorTool, PipelineTool,
77
+ SandboxTool, StrategyTool, WikiTool]
78
+ except Exception as exc:
79
+ logger.warning("QuantNodes tool stack unavailable: %s", exc)
80
+ mcp._quant_tools_cache = {}
81
+ return mcp._quant_tools_cache
82
+
83
+ registry: Dict[str, Any] = {}
84
+ for factory in factories:
85
+ kwargs = workspace_dep.get(factory.__name__, {})
86
+ try:
87
+ tool = factory(**kwargs) if kwargs else factory()
88
+ except Exception as exc:
89
+ logger.warning("Failed to instantiate %s: %s", factory.__name__, exc)
90
+ continue
91
+ registry[tool.name] = tool
92
+ mcp._quant_tools_cache = registry
93
+ return registry
94
+
95
+
96
+ def _safe_field_type(prop: Dict[str, Any]):
97
+ """Map JSON Schema type to a Python type suitable for Pydantic Field."""
98
+ t = prop.get("type", "string")
99
+ return {
100
+ "string": str,
101
+ "integer": int,
102
+ "number": float,
103
+ "boolean": bool,
104
+ "array": list,
105
+ "object": dict,
106
+ }.get(t, Any)
107
+
108
+
109
+ def _build_pydantic_model(name: str, schema: Dict[str, Any]):
110
+ """Build a Pydantic model from a JSON Schema object for a tool's arguments."""
111
+ props = schema.get("properties", {})
112
+ required = set(schema.get("required", []))
113
+ fields: Dict[str, Any] = {}
114
+ for pname, pschema in props.items():
115
+ py_type = _safe_field_type(pschema)
116
+ default = ... if pname in required else pschema.get("default", None)
117
+ description = pschema.get("description", "")
118
+ fields[pname] = (py_type, Field(default=default, description=description))
119
+ if not fields:
120
+ return create_model(name)
121
+ return create_model(name, **fields)
122
+
123
+
124
+ def _register_tool_call_dispatcher(workspace: Path) -> None:
125
+ """Register a dynamic Pydantic-model-based MCP tool for each QuantNodes tool.
126
+
127
+ Each tool's arguments are typed via a dynamically generated Pydantic model,
128
+ so FastMCP can produce a proper JSON Schema in the MCP tool listing.
129
+ """
130
+ registry = _build_tools_registry(workspace)
131
+ for tool_name, tool in registry.items():
132
+ schema = tool.parameters if hasattr(tool, "parameters") else {"type": "object", "properties": {}}
133
+ model_name = f"{tool_name.title().replace('_', '')}Args"
134
+ ArgsModel = _build_pydantic_model(model_name, schema)
135
+
136
+ async def _call(arguments: Dict[str, Any], _tool=tool) -> Dict[str, Any]:
137
+ try:
138
+ result = await _tool.execute(**arguments)
139
+ if isinstance(result, (dict, list, str, int, float, bool)) or result is None:
140
+ return {"status": "ok", "result": result}
141
+ return {"status": "ok", "result": str(result)}
142
+ except Exception as exc:
143
+ logger.exception("Tool %s failed", tool_name)
144
+ return {"status": "error", "tool": tool_name, "error": str(exc)}
145
+
146
+ _call.__name__ = f"call_{tool_name}"
147
+ _call.__doc__ = (
148
+ f"Call QuantNodes tool '{tool_name}'. {tool.description}"
149
+ )
150
+
151
+ decorated = mcp.tool(
152
+ name=f"call_{tool_name}",
153
+ description=_call.__doc__,
154
+ exclude_args=["_tool"],
155
+ )
156
+ decorated(_call)
157
+
158
+
159
+ def _register_list_tools(workspace: Path) -> None:
160
+ """Register a `list_quant_tools` MCP tool that lists available tools + schemas."""
161
+
162
+ @mcp.tool
163
+ async def list_quant_tools() -> Dict[str, Any]:
164
+ """List all available QuantNodes tools with their JSON Schema.
165
+
166
+ Returns a dict with keys:
167
+ - tools: list of {name, description, parameters, mcp_name}
168
+ - count: number of tools
169
+ """
170
+ registry = _build_tools_registry(workspace)
171
+ tools = []
172
+ for tname, tool in registry.items():
173
+ tools.append({
174
+ "name": tname,
175
+ "description": tool.description,
176
+ "parameters": tool.parameters,
177
+ "mcp_name": f"call_{tname}",
178
+ })
179
+ return {"count": len(tools), "tools": tools}
180
+
181
+ list_quant_tools.__doc__ = (
182
+ "List all available QuantNodes tools (with JSON Schema). "
183
+ "Use this to discover what tools are exposed via this MCP server."
184
+ )
185
+
186
+
187
+ def _register_data_query(workspace: Path) -> None:
188
+ """Register a data_query MCP tool — DuckDB query (v0)."""
189
+ from pydantic import Field as _F
190
+
191
+ class DataQueryArgs:
192
+ pass
193
+
194
+ @mcp.tool
195
+ async def data_query(sql: str = _F(..., description="Read-only SQL query to execute"),
196
+ source: str = _F("duckdb", description="Data source: duckdb or clickhouse")) -> Dict[str, Any]:
197
+ """Execute a read-only SQL query against the default DuckDB source (v0)."""
198
+ if source != "duckdb":
199
+ return {"status": "error", "error": f"source={source} not yet supported in v0"}
200
+ try:
201
+ import duckdb
202
+ db_path = workspace / "quantnodes.db"
203
+ if not db_path.exists():
204
+ return {"status": "error", "error": f"db not found: {db_path}"}
205
+ con = duckdb.connect(str(db_path), read_only=True)
206
+ try:
207
+ rows = con.execute(sql).fetchall()
208
+ cols = [d[0] for d in con.description] if con.description else []
209
+ return {
210
+ "status": "ok",
211
+ "columns": cols,
212
+ "rows": [list(r) for r in rows[:1000]],
213
+ "row_count": len(rows),
214
+ }
215
+ finally:
216
+ con.close()
217
+ except Exception as exc:
218
+ return {"status": "error", "error": str(exc)}
219
+
220
+
221
+ # Eager registration at import time
222
+ _register_tool_call_dispatcher(_DEFAULT_WORKSPACE)
223
+ _register_list_tools(_DEFAULT_WORKSPACE)
224
+ _register_data_query(_DEFAULT_WORKSPACE)
225
+
226
+
227
+ # FastMCP exposes the ASGI app as ``mcp.http_app`` for HTTP transports
228
+ app = mcp.http_app
229
+
230
+
231
+ def main(argv: list[str] | None = None) -> int:
232
+ parser = argparse.ArgumentParser(
233
+ description="QuantNodes MCP server (exposes quant tools to nanobot/Claude/Cursor)"
234
+ )
235
+ parser.add_argument("--transport", choices=["stdio", "http", "sse", "streamable-http"],
236
+ default="stdio", help="MCP transport (default: stdio)")
237
+ parser.add_argument("--port", type=int, default=DEFAULT_WEBSOCKET_PORT,
238
+ help="HTTP port (only for http/sse transports)")
239
+ parser.add_argument("--host", default=DEFAULT_HOST,
240
+ help="HTTP host (only for http/sse transports)")
241
+ parser.add_argument("--workspace", default=".agent",
242
+ help="QuantNodes workspace path (default: .agent)")
243
+ parser.add_argument("-v", "--verbose", action="store_true")
244
+ args = parser.parse_args(argv)
245
+
246
+ logging.basicConfig(
247
+ level=logging.DEBUG if args.verbose else logging.INFO,
248
+ format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
249
+ )
250
+
251
+ ws = Path(args.workspace).expanduser().resolve()
252
+ if ws != _DEFAULT_WORKSPACE.resolve():
253
+ mcp._quant_tools_cache = None
254
+ _register_tool_call_dispatcher(ws)
255
+ _register_list_tools(ws)
256
+ _register_data_query(ws)
257
+
258
+ logger.info("Starting QuantNodes MCP server (transport=%s, workspace=%s)",
259
+ args.transport, ws)
260
+ if args.transport == "stdio":
261
+ mcp.run(transport="stdio", show_banner=not args.verbose)
262
+ elif args.transport in ("http", "streamable-http"):
263
+ mcp.run(transport=args.transport, host=args.host, port=args.port,
264
+ show_banner=not args.verbose)
265
+ elif args.transport == "sse":
266
+ mcp.run(transport="sse", host=args.host, port=args.port,
267
+ show_banner=not args.verbose)
268
+ return 0
269
+
270
+
271
+ if __name__ == "__main__":
272
+ sys.exit(main())
@@ -0,0 +1,28 @@
1
+ # coding=utf-8
2
+ """
3
+ QuantNodes Methods Package
4
+
5
+ Pure method implementations for external agents.
6
+ These methods can be called via API without LLM dependencies.
7
+
8
+ 核心入口:
9
+ - validate_code / execute_code: 代码沙箱执行 (api/routers/code.py)
10
+ - validate_pipeline: pipeline 校验 (api/routers/code.py)
11
+
12
+ 历史:
13
+ 早期版本曾导出 run_backtest / analyze_factor / query_wiki / FileOperations /
14
+ CodeSearch / GitOperations 等,均无生产调用方,已在 v3.0.0 清理。
15
+ 对应 Agent 工具实现见 `agent/tools/`。
16
+ """
17
+
18
+ from .sandbox import execute_code, validate_code, ExecutionResult, ValidationResult
19
+ from .pipeline import validate_pipeline, PipelineValidationResult
20
+
21
+ __all__ = [
22
+ "validate_code",
23
+ "execute_code",
24
+ "ValidationResult",
25
+ "ExecutionResult",
26
+ "validate_pipeline",
27
+ "PipelineValidationResult",
28
+ ]
@@ -0,0 +1,100 @@
1
+ # coding=utf-8
2
+ """
3
+ Pipeline Method
4
+
5
+ validate_pipeline(code) -> PipelineValidationResult
6
+
7
+ Validates QuantNodes Pipeline code for external agents.
8
+ """
9
+
10
+ import re
11
+ from dataclasses import dataclass, field
12
+ from typing import List
13
+
14
+
15
+ @dataclass
16
+ class PipelineValidationResult:
17
+ is_valid: bool
18
+ errors: List[str] = field(default_factory=list)
19
+ warnings: List[str] = field(default_factory=list)
20
+ nodes: List[str] = field(default_factory=list)
21
+ security_status: str = "unknown"
22
+
23
+
24
+ CODE_BLOCK_PATTERN = re.compile(r'```(?:python)?\s*(.*?)```', re.DOTALL)
25
+
26
+
27
+ def validate_pipeline(code: str, **kwargs) -> PipelineValidationResult:
28
+ """Validate QuantNodes Pipeline code.
29
+
30
+ Checks:
31
+ - Syntax validity
32
+ - Security (via CodeSandbox)
33
+ - Node extraction
34
+
35
+ Args:
36
+ code: QuantNodes Pipeline Python代码
37
+
38
+ Returns:
39
+ PipelineValidationResult with validation status and extracted nodes
40
+ """
41
+ result = PipelineValidationResult(is_valid=True)
42
+
43
+ extracted_code = _extract_code(code)
44
+ if not extracted_code:
45
+ result.is_valid = False
46
+ result.errors.append("No valid code found")
47
+ return result
48
+
49
+ try:
50
+ compile(extracted_code, '<string>', 'exec')
51
+ except SyntaxError as e:
52
+ result.is_valid = False
53
+ result.errors.append("Syntax error: %s" % str(e))
54
+ return result
55
+
56
+ try:
57
+ from QuantNodes.ai.sandbox import CodeSandbox
58
+
59
+ sandbox = CodeSandbox()
60
+ validation = sandbox.validate(extracted_code)
61
+
62
+ result.security_status = "safe" if validation.is_safe else "unsafe"
63
+
64
+ if not validation.is_safe:
65
+ result.is_valid = False
66
+ result.errors.extend(validation.errors)
67
+
68
+ if validation.warnings:
69
+ result.warnings.extend(validation.warnings)
70
+
71
+ except ImportError:
72
+ result.security_status = "skipped"
73
+ result.warnings.append("CodeSandbox not available, security check skipped")
74
+
75
+ result.nodes = _extract_nodes(extracted_code)
76
+
77
+ return result
78
+
79
+
80
+ def _extract_code(code: str) -> str:
81
+ """Extract code from markdown code blocks if present."""
82
+ match = CODE_BLOCK_PATTERN.search(code)
83
+ if match:
84
+ return match.group(1).strip()
85
+ return code.strip()
86
+
87
+
88
+ def _extract_nodes(code: str) -> List[str]:
89
+ """Extract node types from code."""
90
+ nodes = []
91
+ patterns = [
92
+ r'(\w+Node)\s*\(',
93
+ r'FactorPipeline\s*\(',
94
+ r'Pipeline\s*\(',
95
+ r'BacktestPipeline\s*\(',
96
+ ]
97
+ for pattern in patterns:
98
+ matches = re.findall(pattern, code)
99
+ nodes.extend(matches)
100
+ return list(set(nodes))
@@ -0,0 +1,102 @@
1
+ # coding=utf-8
2
+ """
3
+ Sandbox Method
4
+
5
+ validate_code(code) -> ValidationResult
6
+ execute_code(code, **kwargs) -> ExecutionResult
7
+
8
+ Provides code security validation for external agents.
9
+ """
10
+
11
+ from dataclasses import dataclass, field
12
+ from typing import Any, Dict, List
13
+
14
+
15
+ @dataclass
16
+ class ValidationResult:
17
+ is_safe: bool
18
+ errors: List[str] = field(default_factory=list)
19
+ warnings: List[str] = field(default_factory=list)
20
+ warnings_only: bool = False
21
+
22
+
23
+ @dataclass
24
+ class ExecutionResult:
25
+ status: str
26
+ result: Any = None
27
+ errors: List[str] = field(default_factory=list)
28
+ warnings: List[str] = field(default_factory=list)
29
+
30
+
31
+ def validate_code(
32
+ code: str,
33
+ allow_warnings: bool = False,
34
+ max_code_length: int = 10000,
35
+ **kwargs
36
+ ) -> ValidationResult:
37
+ """Validate Python code安全性.
38
+
39
+ Args:
40
+ code: 待验证的Python代码
41
+ allow_warnings: 是否允许警告
42
+ max_code_length: 最大代码长度
43
+
44
+ Returns:
45
+ ValidationResult with is_safe, errors, warnings
46
+ """
47
+ from QuantNodes.ai.sandbox import CodeSandbox
48
+
49
+ sandbox = CodeSandbox(
50
+ allow_warnings=allow_warnings,
51
+ max_code_length=max_code_length
52
+ )
53
+
54
+ result = sandbox.validate(code)
55
+
56
+ return ValidationResult(
57
+ is_safe=result.is_safe,
58
+ errors=result.errors,
59
+ warnings=result.warnings,
60
+ warnings_only=result.warnings_only
61
+ )
62
+
63
+
64
+ def execute_code(
65
+ code: str,
66
+ context: Dict[str, Any] = None,
67
+ **kwargs
68
+ ) -> ExecutionResult:
69
+ """Execute code in sandbox environment.
70
+
71
+ Args:
72
+ code: 待执行的Python代码
73
+ context: 执行上下文(可选)
74
+
75
+ Returns:
76
+ ExecutionResult with status, result, errors
77
+ """
78
+ from QuantNodes.ai.sandbox import CodeSandbox
79
+
80
+ sandbox = CodeSandbox()
81
+ validation = sandbox.validate(code)
82
+
83
+ if not validation.is_safe:
84
+ return ExecutionResult(
85
+ status="error",
86
+ errors=validation.errors,
87
+ warnings=validation.warnings
88
+ )
89
+
90
+ try:
91
+ namespace = sandbox.validate_and_execute(code, context or {})
92
+ return ExecutionResult(
93
+ status="success",
94
+ result={k: v for k, v in namespace.items() if not k.startswith('_')},
95
+ warnings=validation.warnings
96
+ )
97
+ except Exception as e:
98
+ return ExecutionResult(
99
+ status="error",
100
+ errors=[str(e)],
101
+ warnings=validation.warnings
102
+ )
@@ -0,0 +1,27 @@
1
+ """策略监控与优化模块
2
+
3
+ 功能2: 调度层 + 监控层 + 版本管理层
4
+ """
5
+
6
+ from .storage.models import (
7
+ StrategyRun, PerformanceSnapshot, DriftAlert, StrategyVersion,
8
+ )
9
+ from .storage.repository import (
10
+ DatabaseManager,
11
+ StrategyRunRepository,
12
+ PerformanceRepository,
13
+ DriftAlertRepository,
14
+ VersionRepository,
15
+ )
16
+
17
+ __all__ = [
18
+ "StrategyRun",
19
+ "PerformanceSnapshot",
20
+ "DriftAlert",
21
+ "StrategyVersion",
22
+ "DatabaseManager",
23
+ "StrategyRunRepository",
24
+ "PerformanceRepository",
25
+ "DriftAlertRepository",
26
+ "VersionRepository",
27
+ ]
@@ -0,0 +1,5 @@
1
+ from .monitor_tool import MonitorTool
2
+ from .schedule_tool import ScheduleTool
3
+ from .version_tool import VersionTool
4
+
5
+ __all__ = ["MonitorTool", "ScheduleTool", "VersionTool"]