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,371 @@
1
+ # coding=utf-8
2
+ """
3
+ 代码安全沙箱
4
+
5
+ 提供代码安全校验和执行环境。
6
+ """
7
+ from __future__ import annotations
8
+
9
+ import ast
10
+ import re
11
+ import logging
12
+ from typing import Any, Dict, List, Optional, Set
13
+ from dataclasses import dataclass, field
14
+
15
+
16
+ @dataclass
17
+ class CodeValidationResult:
18
+ """代码验证结果"""
19
+ is_safe: bool
20
+ errors: List[str] = field(default_factory=list)
21
+ warnings: List[str] = field(default_factory=list)
22
+ warnings_only: bool = False
23
+
24
+
25
+ class DangerousCodeError(Exception):
26
+ """危险代码异常"""
27
+ pass
28
+
29
+
30
+ class CodeSandbox:
31
+ """
32
+ 代码安全沙箱
33
+
34
+ 提供代码安全校验,防止执行危险操作。
35
+
36
+ Examples:
37
+ >>> sandbox = CodeSandbox()
38
+ >>> result = sandbox.validate("import os\\nos.system('ls')")
39
+ >>> print(result.is_safe) # False
40
+ """
41
+
42
+ DANGEROUS_IMPORTS: Set[str] = {
43
+ 'os', 'sys', 'subprocess', 'socket', 'urllib', 'requests',
44
+ 'httplib', 'ftplib', 'telnetlib', 'telnet', 'poplib', 'imaplib',
45
+ 'smtplib', 'nntplib', 'anydbm', 'dbhash', 'gdbm', 'dbm',
46
+ 'marshal', 'pickle', 'cPickle', 'shelve', 'anydbm',
47
+ 'threading', 'multiprocessing', 'concurrent',
48
+ 'ctypes', 'cffi', 'mmap', 'resource', 'signal',
49
+ 'pty', 'tty', 'termios', 'fcntl', 'grp', 'pwd',
50
+ 'platform', 'syslog', 'crypt', 'spwd',
51
+ 'zipfile', 'tarfile', 'gzip', 'bz2', 'lzma',
52
+ 'tempfile', 'glob', 'fnmatch', 'linecache', 'macpath',
53
+ 'macurl2path', 'mailcap', 'mimetypes', 'MimeWriter',
54
+ 'mimify', 'multifile', 'mutex', 'newdir', 'rexec',
55
+ 'robotparser', 'user', 'whichdb', 'xdrlib',
56
+ }
57
+
58
+ DANGEROUS_PATTERNS: List[str] = [
59
+ r'eval\s*\(',
60
+ r'exec\s*\(',
61
+ r'compile\s*\(',
62
+ r'__import__\s*\(',
63
+ r'getattr\s*\(',
64
+ r'setattr\s*\(',
65
+ r'delattr\s*\(',
66
+ r'vars\s*\(',
67
+ r'locals\s*\(',
68
+ r'globals\s*\(',
69
+ r'mro\s*\(',
70
+ r'__subclasses__\s*\(',
71
+ r'__bases__\s*\(',
72
+ r'__init__\s*\(',
73
+ r'open\s*\(',
74
+ r'file\s*\(',
75
+ r'input\s*\(',
76
+ r'raw_input\s*\(',
77
+ r'print\s*\(',
78
+ r'execfile\s*\(',
79
+ r'runpy\s*\(',
80
+ r'os\.system\s*\(',
81
+ r'os\.popen\s*\(',
82
+ r'subprocess\.',
83
+ r'socket\.',
84
+ r'shelve\.open',
85
+ r'pickle\.load',
86
+ r'pickle\.loads',
87
+ r'marshal\.load',
88
+ r'yaml\.load',
89
+ r'yaml\.unsafe_load',
90
+ ]
91
+
92
+ ALLOWED_PATTERNS: List[str] = [
93
+ r'^import\s+quantnodes',
94
+ r'^from\s+quantnodes',
95
+ r'^import\s+pandas',
96
+ r'^from\s+pandas',
97
+ r'^import\s+numpy',
98
+ r'^from\s+numpy',
99
+ ]
100
+
101
+ def __init__(
102
+ self,
103
+ allow_warnings: bool = False,
104
+ max_code_length: int = 10000,
105
+ # ===== PR-QN-1 (2026-06-21): 实例级可配置白/黑名单 =====
106
+ allowed_imports: Optional[List[str]] = None,
107
+ blocked_imports: Optional[List[str]] = None,
108
+ # ===== PR-QN-4 (2026-06-22): 默认引擎 =====
109
+ default_engine: str = "polars",
110
+ **kwargs
111
+ ):
112
+ """
113
+ 初始化代码沙箱
114
+
115
+ Args:
116
+ allow_warnings: 是否允许警告(不阻断执行)
117
+ max_code_length: 最大代码长度
118
+ allowed_imports: 追加到白名单的 import pattern (regex 列表), 默认 None.
119
+ 实例级配置. 已默认允许的 (quantnodes/pandas/numpy) 不受影响.
120
+ PR-QN-1 新增, 之前需 monkey-patch 类属性.
121
+ blocked_imports: 追加到黑名单的 import pattern (regex/字面量列表), 默认 None.
122
+ 实例级配置. 增强默认黑名单 (60+ 危险模块).
123
+ default_engine: 默认引擎 ("polars" | "pandas" | "auto").
124
+ PR-QN-4 新增. "polars" (默认) 保持向后兼容;
125
+ "auto" 启用 import 扫描自动检测.
126
+
127
+ Note:
128
+ 默认参数 (allowed_imports/blocked_imports 均为 None) 时, 行为与 PR-QN-1
129
+ 之前**完全一致** — 现有 4608+ tests 无需任何修改.
130
+ """
131
+ self.allow_warnings = allow_warnings
132
+ self.max_code_length = max_code_length
133
+ # PR-QN-1: 实例级白/黑名单 (拷贝类级别作为基础, 再追加用户配置)
134
+ self._allowed_patterns: List[str] = list(self.ALLOWED_PATTERNS) + (
135
+ allowed_imports or []
136
+ )
137
+ self._blocked_imports: Set[str] = set(self.DANGEROUS_IMPORTS) | set(
138
+ blocked_imports or []
139
+ )
140
+ # PR-QN-4: 默认引擎
141
+ self.default_engine: str = default_engine
142
+ self.logger = logging.getLogger(f"sandbox.{self.__class__.__name__}")
143
+
144
+ def _detect_engine(self, code: str) -> str:
145
+ """Detect engine from code (PR-QN-4).
146
+
147
+ Scans import statements to determine polars or pandas.
148
+ Returns self.default_engine when no imports detected or when
149
+ default_engine is not "auto".
150
+ """
151
+ if self.default_engine != "auto":
152
+ return self.default_engine
153
+ try:
154
+ tree = ast.parse(code)
155
+ except SyntaxError:
156
+ return "polars"
157
+ has_pl = has_pd = False
158
+ for node in ast.walk(tree):
159
+ if isinstance(node, ast.Import):
160
+ for alias in node.names:
161
+ if alias.name == "polars" or alias.name.startswith("polars."):
162
+ has_pl = True
163
+ elif alias.name == "pandas" or alias.name.startswith("pandas."):
164
+ has_pd = True
165
+ elif isinstance(node, ast.ImportFrom):
166
+ if node.module and (node.module == "polars" or node.module.startswith("polars.")):
167
+ has_pl = True
168
+ elif node.module and (node.module == "pandas" or node.module.startswith("pandas.")):
169
+ has_pd = True
170
+ if has_pd and not has_pl:
171
+ return "pandas"
172
+ return "polars"
173
+
174
+ def validate(self, code: str) -> CodeValidationResult:
175
+ """
176
+ 验证代码安全性
177
+
178
+ Args:
179
+ code: 待验证的代码
180
+
181
+ Returns:
182
+ CodeValidationResult 验证结果
183
+ """
184
+ result = CodeValidationResult(is_safe=True)
185
+
186
+ if not code or not code.strip():
187
+ result.is_safe = False
188
+ result.errors.append("Empty code")
189
+ return result
190
+
191
+ if len(code) > self.max_code_length:
192
+ result.is_safe = False
193
+ result.errors.append(f"Code exceeds max length ({self.max_code_length})")
194
+ return result
195
+
196
+ result.warnings.extend(self._check_dangerous_imports(code))
197
+ result.errors.extend(self._check_dangerous_patterns(code))
198
+
199
+ if result.errors:
200
+ result.is_safe = False
201
+ elif result.warnings and not self.allow_warnings:
202
+ result.is_safe = False
203
+ result.warnings_only = True
204
+
205
+ return result
206
+
207
+ def _check_dangerous_imports(self, code: str) -> List[str]:
208
+ """检查危险导入 (PR-QN-1: 读 self._blocked_imports 实例属性)"""
209
+ warnings = []
210
+
211
+ try:
212
+ tree = ast.parse(code)
213
+ for node in ast.walk(tree):
214
+ if isinstance(node, ast.Import):
215
+ for alias in node.names:
216
+ if alias.name.split('.')[0] in self._blocked_imports:
217
+ warnings.append(f"Dangerous import: {alias.name}")
218
+ elif isinstance(node, ast.ImportFrom):
219
+ if node.module and node.module.split('.')[0] in self._blocked_imports:
220
+ warnings.append(f"Dangerous import: from {node.module}")
221
+
222
+ except SyntaxError:
223
+ pass
224
+
225
+ return warnings
226
+
227
+ def _check_dangerous_patterns(self, code: str) -> List[str]:
228
+ """检查危险模式"""
229
+ errors = []
230
+
231
+ for pattern in self.DANGEROUS_PATTERNS:
232
+ if re.search(pattern, code, re.IGNORECASE):
233
+ errors.append(f"Dangerous pattern detected: {pattern}")
234
+
235
+ return errors
236
+
237
+ def validate_and_execute(
238
+ self,
239
+ code: str,
240
+ context: Optional[Dict[str, Any]] = None,
241
+ engine: Optional[str] = None,
242
+ ) -> Any:
243
+ """
244
+ 验证并执行代码
245
+
246
+ Args:
247
+ code: 待执行的代码
248
+ context: 执行上下文
249
+ engine: 引擎覆盖 ("polars"|"pandas"|None). None = use default_engine.
250
+
251
+ Returns:
252
+ 执行结果
253
+
254
+ Raises:
255
+ DangerousCodeError: 代码不安全
256
+ SyntaxError: 代码语法错误
257
+ """
258
+ result = self.validate(code)
259
+
260
+ # PR-QN-4: detect engine (if not explicitly overridden)
261
+ detected_engine = engine or self._detect_engine(code)
262
+
263
+ if not result.is_safe:
264
+ if result.warnings_only:
265
+ self.logger.warning(f"Code has warnings: {result.warnings}")
266
+ else:
267
+ raise DangerousCodeError(f"Code validation failed: {result.errors}")
268
+
269
+ context = context or {}
270
+ safe_builtins = {
271
+ 'True': True,
272
+ 'False': False,
273
+ 'None': None,
274
+ 'abs': abs,
275
+ 'all': all,
276
+ 'any': any,
277
+ 'ascii': ascii,
278
+ 'bin': bin,
279
+ 'bool': bool,
280
+ 'bytes': bytes,
281
+ 'chr': chr,
282
+ 'dict': dict,
283
+ 'dir': dir,
284
+ 'divmod': divmod,
285
+ 'enumerate': enumerate,
286
+ 'filter': filter,
287
+ 'float': float,
288
+ 'format': format,
289
+ 'frozenset': frozenset,
290
+ 'hash': hash,
291
+ 'hex': hex,
292
+ 'id': id,
293
+ 'int': int,
294
+ 'isinstance': isinstance,
295
+ 'issubclass': issubclass,
296
+ 'iter': iter,
297
+ 'len': len,
298
+ 'list': list,
299
+ 'map': map,
300
+ 'max': max,
301
+ 'min': min,
302
+ 'next': next,
303
+ 'object': object,
304
+ 'oct': oct,
305
+ 'ord': ord,
306
+ 'pow': pow,
307
+ 'print': print,
308
+ 'range': range,
309
+ 'repr': repr,
310
+ 'reversed': reversed,
311
+ 'round': round,
312
+ 'set': set,
313
+ 'slice': slice,
314
+ 'sorted': sorted,
315
+ 'str': str,
316
+ 'sum': sum,
317
+ 'tuple': tuple,
318
+ 'zip': zip,
319
+ }
320
+
321
+ try:
322
+ compiled = compile(code, '<string>', 'exec')
323
+ exec_globals = {**safe_builtins, **context}
324
+ # PR-QN-4: inject detected engine info
325
+ exec_globals["__engine__"] = detected_engine
326
+ exec(compiled, exec_globals)
327
+ return exec_globals
328
+ except SyntaxError as e:
329
+ raise SyntaxError(f"Syntax error: {e}")
330
+ except Exception as e:
331
+ raise DangerousCodeError(f"Execution error: {e}")
332
+
333
+ def extract_imports(self, code: str) -> Dict[str, List[str]]:
334
+ """提取代码中的导入语句 (PR-QN-1: 读 self._blocked_imports 实例属性)"""
335
+ imports = {'standard': [], 'third_party': [], 'local': []}
336
+
337
+ try:
338
+ tree = ast.parse(code)
339
+ for node in ast.walk(tree):
340
+ if isinstance(node, ast.Import):
341
+ for alias in node.names:
342
+ name = alias.name
343
+ if name.split('.')[0] in self._blocked_imports:
344
+ continue
345
+ imports['standard'].append(name)
346
+ elif isinstance(node, ast.ImportFrom):
347
+ if node.module:
348
+ imports['third_party'].append(node.module)
349
+
350
+ except SyntaxError:
351
+ pass
352
+
353
+ return imports
354
+
355
+ def extract_quantnodes_usage(self, code: str) -> List[str]:
356
+ """提取代码中 QuantNodes 的使用情况"""
357
+ usage = []
358
+
359
+ patterns = [
360
+ (r'from\s+QuantNodes\.(\w+)', 'module'),
361
+ (r'import\s+QuantNodes\.(\w+)', 'module'),
362
+ (r'(\w+Node)\s*\(', 'node_class'),
363
+ (r'(\w+Node)\s*\[', 'node_class'),
364
+ ]
365
+
366
+ for pattern, usage_type in patterns:
367
+ matches = re.findall(pattern, code)
368
+ for match in matches:
369
+ usage.append(f"{usage_type}: {match}")
370
+
371
+ return list(set(usage))
@@ -0,0 +1,150 @@
1
+ # coding=utf-8
2
+ """Sandbox Pandas Bridge — auto-detect engine + inject context (PR-QN-4, 2026-06-22)
3
+
4
+ Provides engine detection for LLM-generated code and automatic context
5
+ injection into CodeSandbox.validate_and_execute().
6
+
7
+ Usage:
8
+ from QuantNodes.ai.sandbox_pandas_bridge import detect_and_inject_context
9
+
10
+ # Auto-detect engine from code, inject appropriate df + lib
11
+ ctx = detect_and_inject_context(code, df=polars_df)
12
+ # ctx now contains: df (polars or pandas), pl or pd, __version__, etc.
13
+ """
14
+ from __future__ import annotations
15
+
16
+ import ast
17
+ import logging
18
+ from typing import Any, Dict, Optional
19
+
20
+ logger = logging.getLogger(__name__)
21
+
22
+
23
+ def detect_engine_from_code(code: str) -> str:
24
+ """Scan code for import statements to detect engine.
25
+
26
+ Heuristics (same as _engine.detect_engine):
27
+ - import polars → polars
28
+ - import pandas → pandas
29
+ - both → polars (default, faster)
30
+ - neither → polars (safe default)
31
+
32
+ Returns:
33
+ "polars" or "pandas"
34
+ """
35
+ try:
36
+ tree = ast.parse(code)
37
+ except SyntaxError:
38
+ return "polars"
39
+
40
+ has_pl = False
41
+ has_pd = False
42
+
43
+ for node in ast.walk(tree):
44
+ if isinstance(node, ast.Import):
45
+ for alias in node.names:
46
+ if alias.name == "polars" or alias.name.startswith("polars."):
47
+ has_pl = True
48
+ elif alias.name == "pandas" or alias.name.startswith("pandas."):
49
+ has_pd = True
50
+ elif isinstance(node, ast.ImportFrom):
51
+ if node.module and (node.module == "polars" or node.module.startswith("polars.")):
52
+ has_pl = True
53
+ elif node.module and (node.module == "pandas" or node.module.startswith("pandas.")):
54
+ has_pd = True
55
+
56
+ if has_pd and not has_pl:
57
+ return "pandas"
58
+ return "polars"
59
+
60
+
61
+ def detect_and_inject_context(
62
+ code: str,
63
+ df: Any = None,
64
+ default_engine: str = "polars",
65
+ **extra_context: Any,
66
+ ) -> Dict[str, Any]:
67
+ """Detect engine from code and build context dict for sandbox execution.
68
+
69
+ Args:
70
+ code: LLM-generated code to analyze
71
+ df: Optional DataFrame to inject (auto-converted if needed)
72
+ default_engine: Fallback engine when detection is ambiguous
73
+ **extra_context: Additional context variables to inject
74
+
75
+ Returns:
76
+ Context dict ready for sandbox.validate_and_execute()
77
+ """
78
+ engine = detect_engine_from_code(code)
79
+ ctx: Dict[str, Any] = dict(extra_context)
80
+
81
+ if df is not None:
82
+ if engine == "pandas":
83
+ # Inject as pandas DataFrame
84
+ if hasattr(df, "to_pandas"):
85
+ ctx["df"] = df.to_pandas()
86
+ else:
87
+ ctx["df"] = df
88
+ try:
89
+ import pandas as pd
90
+ ctx["pd"] = pd
91
+ except ImportError:
92
+ pass
93
+ else:
94
+ # Inject as polars DataFrame (default)
95
+ ctx["df"] = df
96
+ try:
97
+ import polars as pl
98
+ ctx["pl"] = pl
99
+ except ImportError:
100
+ pass
101
+
102
+ # Always inject both libs for user convenience (LLM may mix)
103
+ try:
104
+ import polars as pl
105
+ ctx.setdefault("pl", pl)
106
+ except ImportError:
107
+ pass
108
+ try:
109
+ import pandas as pd
110
+ ctx.setdefault("pd", pd)
111
+ except ImportError:
112
+ pass
113
+
114
+ # Inject QuantNodes operators for LLM access
115
+ try:
116
+ import QuantNodes
117
+ ctx.setdefault("QuantNodes", QuantNodes)
118
+ except ImportError:
119
+ pass
120
+
121
+ ctx["__engine__"] = engine
122
+ return ctx
123
+
124
+
125
+ def patch_sandbox_with_bridge(sandbox: Any, df: Any = None) -> None:
126
+ """Monkey-patch a CodeSandbox instance with auto-detect bridge.
127
+
128
+ After patching, sandbox.validate_and_execute() will auto-detect
129
+ the engine from code and inject appropriate context.
130
+
131
+ Args:
132
+ sandbox: CodeSandbox instance
133
+ df: Optional DataFrame to inject
134
+ """
135
+ _original_validate = sandbox.validate_and_execute
136
+
137
+ def _patched_validate(code: str, context: Optional[Dict[str, Any]] = None) -> Any:
138
+ ctx = detect_and_inject_context(code, df=df)
139
+ if context:
140
+ ctx.update(context)
141
+ return _original_validate(code, context=ctx)
142
+
143
+ sandbox.validate_and_execute = _patched_validate # type: ignore[attr-defined]
144
+ logger.debug("Sandbox patched with pandas bridge (auto-detect)")
145
+
146
+ __all__ = [
147
+ "detect_engine_from_code",
148
+ "detect_and_inject_context",
149
+ "patch_sandbox_with_bridge",
150
+ ]