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,14 @@
1
+ # coding=utf-8
2
+ """
3
+ Factor Skills
4
+ """
5
+
6
+ from .ic_analysis import ICAnalysisSkill
7
+ from .group_backtest import GroupBacktestSkill
8
+ from .correlation import CorrelationSkill
9
+
10
+ __all__ = [
11
+ "ICAnalysisSkill",
12
+ "GroupBacktestSkill",
13
+ "CorrelationSkill",
14
+ ]
@@ -0,0 +1,99 @@
1
+ # coding=utf-8
2
+ """
3
+ Correlation Analysis Skill
4
+
5
+ Phase 4.4: Factor Skills
6
+ """
7
+
8
+ from typing import Any, Dict
9
+
10
+ from ..base import Skill, SkillCategory, SkillMetadata, SkillResult
11
+
12
+
13
+ class CorrelationSkill(Skill):
14
+ """Factor Correlation Analysis Skill"""
15
+
16
+ @property
17
+ def metadata(self) -> SkillMetadata:
18
+ return SkillMetadata(
19
+ name="correlation",
20
+ description="计算因子之间的相关性矩阵,分析因子独立性",
21
+ category=SkillCategory.FACTOR,
22
+ tags=["因子分析", "相关性", "多重共线性"],
23
+ examples=[
24
+ "计算多个因子的相关性矩阵",
25
+ "检测高相关性因子",
26
+ ],
27
+ )
28
+
29
+ async def execute(self, context: Dict[str, Any]) -> SkillResult:
30
+ """Execute correlation analysis"""
31
+ factors = context.get("factors", ["factor1", "factor2"])
32
+
33
+ code = f'''
34
+ def correlation_analysis(data, factor_cols={factors}):
35
+ """
36
+ 相关性分析
37
+ - 计算因子之间的Pearson相关系数矩阵
38
+ - 识别高相关性因子对 (|corr| > 0.8)
39
+
40
+ Parameters:
41
+ - data: DataFrame with factor columns
42
+ - factor_cols: 因子列名列表
43
+
44
+ Returns:
45
+ - corr_matrix: 相关性矩阵
46
+ - high_corr_pairs: 高相关性因子对
47
+ """
48
+ import pandas as pd
49
+ import numpy as np
50
+
51
+ factor_data = data[factor_cols]
52
+
53
+ corr_matrix = factor_data.corr()
54
+
55
+ high_corr_threshold = 0.8
56
+ high_corr_pairs = []
57
+ for i in range(len(factor_cols)):
58
+ for j in range(i + 1, len(factor_cols)):
59
+ corr_val = corr_matrix.iloc[i, j]
60
+ if abs(corr_val) > high_corr_threshold:
61
+ high_corr_pairs.append({{
62
+ "factor1": factor_cols[i],
63
+ "factor2": factor_cols[j],
64
+ "correlation": corr_val,
65
+ }})
66
+
67
+ result = {{
68
+ "factors": {factors},
69
+ "corr_matrix": corr_matrix.to_dict(),
70
+ "high_corr_pairs": high_corr_pairs,
71
+ "mean_abs_corr": corr_matrix.abs().values[
72
+ np.triu_indices_from(corr_matrix.values, k=1)
73
+ ].mean(),
74
+ }}
75
+ return result
76
+ '''
77
+ return SkillResult(
78
+ success=True,
79
+ data={
80
+ "skill": "correlation",
81
+ "factors": factors,
82
+ "code": code.strip(),
83
+ "description": f"相关性分析: {', '.join(factors)}",
84
+ },
85
+ )
86
+
87
+ def get_parameters_schema(self) -> Dict[str, Any]:
88
+ """Return parameter schema"""
89
+ return {
90
+ "type": "object",
91
+ "properties": {
92
+ "factors": {
93
+ "type": "array",
94
+ "items": {"type": "string"},
95
+ "description": "因子列表",
96
+ "default": ["factor1", "factor2"],
97
+ },
98
+ },
99
+ }
@@ -0,0 +1,114 @@
1
+ # coding=utf-8
2
+ """
3
+ Group Backtest Skill
4
+
5
+ Phase 4.4: Factor Skills
6
+ """
7
+
8
+ from typing import Any, Dict
9
+
10
+ from ..base import Skill, SkillCategory, SkillMetadata, SkillResult
11
+
12
+
13
+ class GroupBacktestSkill(Skill):
14
+ """Group Backtest by Factor Quantiles"""
15
+
16
+ @property
17
+ def metadata(self) -> SkillMetadata:
18
+ return SkillMetadata(
19
+ name="group_backtest",
20
+ description="按因子分位数分组回测,计算各组收益差异",
21
+ category=SkillCategory.FACTOR,
22
+ tags=["因子分析", "分组回测", "分位数", "多空组合"],
23
+ examples=[
24
+ "按因子分5组回测",
25
+ "计算多空组合收益",
26
+ ],
27
+ )
28
+
29
+ async def execute(self, context: Dict[str, Any]) -> SkillResult:
30
+ """Execute group backtest"""
31
+ n_groups = context.get("n_groups", 5)
32
+ period = context.get("period", 20)
33
+
34
+ code = f'''
35
+ def group_backtest(
36
+ data, factor_col="factor", return_col="return",
37
+ n_groups={n_groups}, period={period},
38
+ ):
39
+ """
40
+ 分组回测
41
+ - 按因子值分{n_groups}组
42
+ - 计算每组未来{period}天收益
43
+ - 计算多空组合收益 (Group{n_groups} - Group1)
44
+
45
+ Parameters:
46
+ - data: DataFrame with factor and return columns
47
+ - factor_col: 因子列名
48
+ - return_col: 收益列名
49
+ - n_groups: 分组数量
50
+ - period: 持有周期
51
+
52
+ Returns:
53
+ - group_returns: 各组平均收益
54
+ - long_short_return: 多空组合收益
55
+ - turnover: 换手率
56
+ """
57
+ import pandas as pd
58
+ import numpy as np
59
+
60
+ data = data.copy()
61
+ data["group"] = pd.qcut(data[factor_col], q={n_groups}, labels=False, duplicates="drop")
62
+
63
+ future_returns = data[return_col].shift(-{period})
64
+ data["future_return"] = future_returns
65
+
66
+ group_returns = data.groupby("group")["future_return"].mean()
67
+
68
+ if len(group_returns) >= {n_groups}:
69
+ long_short_return = group_returns.iloc[-1] - group_returns.iloc[0]
70
+ else:
71
+ long_short_return = np.nan
72
+
73
+ position = data.groupby("date")["group"].shift(1)
74
+ turnover = (position != position.shift(1)).sum() / len(data)
75
+
76
+ result = {{
77
+ "n_groups": {n_groups},
78
+ "period": {period},
79
+ "group_returns": group_returns.to_dict(),
80
+ "long_short_return": long_short_return,
81
+ "turnover": turnover,
82
+ "top_group_return": group_returns.iloc[-1] if len(group_returns) > 0 else np.nan,
83
+ "bottom_group_return": group_returns.iloc[0] if len(group_returns) > 0 else np.nan,
84
+ }}
85
+ return result
86
+ '''
87
+ return SkillResult(
88
+ success=True,
89
+ data={
90
+ "skill": "group_backtest",
91
+ "n_groups": n_groups,
92
+ "period": period,
93
+ "code": code.strip(),
94
+ "description": f"分组回测: {n_groups}组, {period}天持有期",
95
+ },
96
+ )
97
+
98
+ def get_parameters_schema(self) -> Dict[str, Any]:
99
+ """Return parameter schema"""
100
+ return {
101
+ "type": "object",
102
+ "properties": {
103
+ "n_groups": {
104
+ "type": "integer",
105
+ "description": "分组数量",
106
+ "default": 5,
107
+ },
108
+ "period": {
109
+ "type": "integer",
110
+ "description": "持有周期(天)",
111
+ "default": 20,
112
+ },
113
+ },
114
+ }
@@ -0,0 +1,106 @@
1
+ # coding=utf-8
2
+ """
3
+ IC Analysis Skill
4
+
5
+ Phase 4.4: Factor Skills
6
+ """
7
+
8
+ from typing import Any, Dict
9
+
10
+ from ..base import Skill, SkillCategory, SkillMetadata, SkillResult
11
+
12
+
13
+ class ICAnalysisSkill(Skill):
14
+ """IC (Information Coefficient) Analysis Skill"""
15
+
16
+ @property
17
+ def metadata(self) -> SkillMetadata:
18
+ return SkillMetadata(
19
+ name="ic_analysis",
20
+ description="计算并分析因子IC值,包括IC均值、ICIR、Rank IC等指标",
21
+ category=SkillCategory.FACTOR,
22
+ tags=["因子分析", "IC", "ICIR", "Rank IC"],
23
+ examples=[
24
+ "分析因子的IC表现",
25
+ "计算ICIR指标",
26
+ ],
27
+ )
28
+
29
+ async def execute(self, context: Dict[str, Any]) -> SkillResult:
30
+ """Execute IC analysis"""
31
+ factor_name = context.get("factor_name", "factor")
32
+ n_days = context.get("n_days", 252)
33
+
34
+ code = f'''
35
+ def calculate_ic_analysis(data, factor_col="factor", return_col="return", n_days={n_days}):
36
+ """
37
+ IC分析
38
+ - 计算因子IC序列
39
+ - 计算IC均值、IC标准差、ICIR
40
+ - 计算Rank IC
41
+
42
+ Parameters:
43
+ - data: DataFrame with factor and return columns
44
+ - factor_col: 因子列名
45
+ - return_col: 收益列名
46
+ - n_days: 计算周期
47
+
48
+ Returns:
49
+ - ic_series: IC时间序列
50
+ - ic_mean: IC均值
51
+ - ic_std: IC标准差
52
+ - icir: ICIR (IC均值/IC标准差)
53
+ - rank_ic_mean: Rank IC均值
54
+ """
55
+ import pandas as pd
56
+ import numpy as np
57
+
58
+ ic_series = data[factor_col].corr(data[return_col])
59
+ rank_ic_series = data[factor_col].rank().corr(data[return_col].rank())
60
+
61
+ ic_mean = ic_series.mean()
62
+ ic_std = ic_series.std()
63
+ icir = ic_mean / ic_std if ic_std != 0 else 0
64
+
65
+ rank_ic_mean = rank_ic_series.mean()
66
+
67
+ result = {{
68
+ "factor_name": "{factor_name}",
69
+ "n_dates": n_days,
70
+ "ic_series": ic_series,
71
+ "ic_mean": ic_mean,
72
+ "ic_std": ic_std,
73
+ "icir": icir,
74
+ "rank_ic_mean": rank_ic_mean,
75
+ "ic_t_stat": ic_mean / (ic_std / np.sqrt(n_days)) if ic_std != 0 else 0,
76
+ }}
77
+ return result
78
+ '''
79
+ return SkillResult(
80
+ success=True,
81
+ data={
82
+ "skill": "ic_analysis",
83
+ "factor_name": factor_name,
84
+ "n_days": n_days,
85
+ "code": code.strip(),
86
+ "description": f"IC分析: {factor_name}, {n_days}天",
87
+ },
88
+ )
89
+
90
+ def get_parameters_schema(self) -> Dict[str, Any]:
91
+ """Return parameter schema"""
92
+ return {
93
+ "type": "object",
94
+ "properties": {
95
+ "factor_name": {
96
+ "type": "string",
97
+ "description": "因子名称",
98
+ "default": "factor",
99
+ },
100
+ "n_days": {
101
+ "type": "integer",
102
+ "description": "分析天数",
103
+ "default": 252,
104
+ },
105
+ },
106
+ }
@@ -0,0 +1,107 @@
1
+ # coding=utf-8
2
+ """
3
+ Skill Loader - Progressive Skill Loader
4
+
5
+ Phase 4.1: Skill Infrastructure
6
+ """
7
+
8
+ import importlib.util
9
+ from pathlib import Path
10
+ from typing import Dict, List, Any
11
+
12
+ from .base import Skill, SkillCategory
13
+ from .registry import SkillRegistry
14
+
15
+
16
+ class SkillLoader:
17
+ """Progressive Skill Loader"""
18
+
19
+ def __init__(self, registry: SkillRegistry = None):
20
+ self.registry = registry or SkillRegistry()
21
+ self._loaded: Dict[str, bool] = {}
22
+ self._load_order: List[str] = []
23
+ self._failed: Dict[str, str] = {}
24
+
25
+ def discover_skills(self, skills_dir: Path) -> List[str]:
26
+ """Discover all skills in the skills directory"""
27
+ discovered = []
28
+ if not skills_dir.exists():
29
+ return discovered
30
+ for item in skills_dir.iterdir():
31
+ if item.is_dir() and not item.name.startswith("_"):
32
+ skill_file = item / f"{item.name}.py"
33
+ if skill_file.exists():
34
+ discovered.append(str(item))
35
+ return discovered
36
+
37
+ async def load_skill(
38
+ self, skill_path: Path, category: SkillCategory = None
39
+ ) -> bool:
40
+ """Load a single skill from path"""
41
+ spec = importlib.util.spec_from_file_location("skill_module", skill_path)
42
+ if spec is None or spec.loader is None:
43
+ return False
44
+ module = importlib.util.module_from_spec(spec)
45
+ try:
46
+ spec.loader.exec_module(module)
47
+ except Exception as e:
48
+ self._failed[str(skill_path)] = str(e)
49
+ return False
50
+ for attr_name in dir(module):
51
+ attr = getattr(module, attr_name)
52
+ if isinstance(attr, type) and issubclass(attr, Skill) and attr != Skill:
53
+ skill_instance = attr()
54
+ if category:
55
+ skill_instance._metadata.category = category
56
+ self.registry.register(skill_instance)
57
+ self._loaded[skill_instance.name] = True
58
+ self._load_order.append(skill_instance.name)
59
+ return True
60
+ return False
61
+
62
+ async def load_all(self, skills_dir: Path) -> Dict[str, bool]:
63
+ """Load all discovered skills"""
64
+ results = {}
65
+ for skill_path in self.discover_skills(skills_dir):
66
+ skill_name = Path(skill_path).name
67
+ success = await self.load_skill(
68
+ Path(skill_path) / f"{skill_name}.py"
69
+ )
70
+ results[skill_name] = success
71
+ return results
72
+
73
+ async def progressive_load(
74
+ self, skills_dir: Path, requested_skills: List[str]
75
+ ) -> Dict[str, Skill]:
76
+ """Progressive load: only load requested skills"""
77
+ loaded = {}
78
+ for skill_name in requested_skills:
79
+ skill_path = skills_dir / skill_name / f"{skill_name}.py"
80
+ if skill_path.exists() and skill_name not in self._loaded:
81
+ success = await self.load_skill(skill_path)
82
+ if success:
83
+ skill = self.registry.get(skill_name)
84
+ if skill:
85
+ loaded[skill_name] = skill
86
+ return loaded
87
+
88
+ def get_loading_status(self) -> Dict[str, Any]:
89
+ """Get loading status"""
90
+ return {
91
+ "loaded": self._loaded,
92
+ "load_order": self._load_order,
93
+ "failed": self._failed,
94
+ "total_loaded": len(self._loaded),
95
+ }
96
+
97
+ def reload_skill(self, name: str) -> bool:
98
+ """Reload a skill"""
99
+ if name in self._loaded:
100
+ self._loaded.pop(name)
101
+ self._load_order.remove(name)
102
+ self.registry.unregister(name)
103
+ return True
104
+
105
+ def is_loaded(self, name: str) -> bool:
106
+ """Check if a skill is loaded"""
107
+ return name in self._loaded
@@ -0,0 +1,105 @@
1
+ # coding=utf-8
2
+ """
3
+ Skill Registry - Singleton Registry for Skills (Thread-Safe)
4
+
5
+ Phase 4.1: Skill Infrastructure
6
+ """
7
+
8
+ import threading
9
+ from typing import Dict, List, Optional
10
+ from collections import defaultdict
11
+
12
+ from .base import Skill, SkillCategory
13
+
14
+
15
+ class SkillRegistry:
16
+ """Skill Registry (Singleton + Thread-Safe)"""
17
+
18
+ _instance: Optional["SkillRegistry"] = None
19
+ _lock = threading.RLock()
20
+
21
+ def __new__(cls):
22
+ with cls._lock:
23
+ if cls._instance is None:
24
+ cls._instance = super().__new__(cls)
25
+ cls._instance._skills: Dict[str, Skill] = {}
26
+ cls._instance._categories: Dict[
27
+ SkillCategory, List[str]
28
+ ] = defaultdict(list)
29
+ cls._instance._aliases: Dict[str, str] = {}
30
+ return cls._instance
31
+
32
+ def register(self, skill: Skill, aliases: List[str] = None) -> None:
33
+ """Register a skill"""
34
+ name = skill.name
35
+ if name in self._skills:
36
+ raise ValueError(f"Skill '{name}' already registered")
37
+ self._skills[name] = skill
38
+ self._categories[skill.category].append(name)
39
+ if aliases:
40
+ for alias in aliases:
41
+ self._aliases[alias] = name
42
+
43
+ def get(self, name: str) -> Optional[Skill]:
44
+ """Get a skill by name or alias"""
45
+ resolved = self._aliases.get(name, name)
46
+ return self._skills.get(resolved)
47
+
48
+ def list_by_category(self, category: SkillCategory) -> List[Skill]:
49
+ """List all skills in a category"""
50
+ return [self._skills[name] for name in self._categories.get(category, [])]
51
+
52
+ def list_all(self) -> List[Skill]:
53
+ """List all registered skills"""
54
+ return list(self._skills.values())
55
+
56
+ def list_names(self) -> List[str]:
57
+ """List all skill names"""
58
+ return list(self._skills.keys())
59
+
60
+ def exists(self, name: str) -> bool:
61
+ """Check if a skill exists"""
62
+ return name in self._skills or name in self._aliases
63
+
64
+ def unregister(self, name: str) -> bool:
65
+ """Unregister a skill"""
66
+ resolved = self._aliases.pop(name, None) or name
67
+ if resolved not in self._skills:
68
+ return False
69
+ skill = self._skills.pop(resolved)
70
+ if resolved in self._categories[skill.category]:
71
+ self._categories[skill.category].remove(resolved)
72
+ return True
73
+
74
+ def clear(self) -> None:
75
+ """Clear all skills"""
76
+ self._skills.clear()
77
+ self._categories.clear()
78
+ self._aliases.clear()
79
+
80
+ def get_skill_info(self, name: str) -> Optional[Dict]:
81
+ """Get skill information"""
82
+ skill = self.get(name)
83
+ if not skill:
84
+ return None
85
+ return {
86
+ "name": skill.name,
87
+ "description": skill.description,
88
+ "category": skill.category.value,
89
+ "version": skill.metadata.version,
90
+ "tags": skill.metadata.tags,
91
+ }
92
+
93
+ def search(self, query: str, limit: int = 10) -> List[Dict]:
94
+ """Search skills by name or description"""
95
+ results = []
96
+ query_lower = query.lower()
97
+ for skill in self._skills.values():
98
+ if (
99
+ query_lower in skill.name.lower()
100
+ or query_lower in skill.description.lower()
101
+ ):
102
+ results.append(self.get_skill_info(skill.name))
103
+ if len(results) >= limit:
104
+ break
105
+ return results
@@ -0,0 +1,16 @@
1
+ # coding=utf-8
2
+ """
3
+ Strategy Skills
4
+ """
5
+
6
+ from .dual_ma import DualMaSkill
7
+ from .bollinger import BollingerSkill
8
+ from .momentum import MomentumSkill
9
+ from .rsi_reversal import RSIReversalSkill
10
+
11
+ __all__ = [
12
+ "DualMaSkill",
13
+ "BollingerSkill",
14
+ "MomentumSkill",
15
+ "RSIReversalSkill",
16
+ ]
@@ -0,0 +1,86 @@
1
+ # coding=utf-8
2
+ """
3
+ Bollinger Bands Strategy Skill
4
+
5
+ Phase 4.3: Strategy Skills
6
+ """
7
+
8
+ from typing import Any, Dict
9
+
10
+ from ..base import Skill, SkillCategory, SkillMetadata, SkillResult
11
+
12
+
13
+ class BollingerSkill(Skill):
14
+ """Bollinger Bands Strategy"""
15
+
16
+ @property
17
+ def metadata(self) -> SkillMetadata:
18
+ return SkillMetadata(
19
+ name="bollinger_strategy",
20
+ description="布林带策略 - 价格触及下轨买入,触及上轨卖出",
21
+ category=SkillCategory.STRATEGY,
22
+ tags=["趋势跟踪", "布林带", "均值回归"],
23
+ examples=[
24
+ "生成布林带策略代码",
25
+ "布林带策略参数优化",
26
+ ],
27
+ )
28
+
29
+ async def execute(self, context: Dict[str, Any]) -> SkillResult:
30
+ """Execute Bollinger bands strategy generation"""
31
+ period = context.get("period", 20)
32
+ std_dev = context.get("std_dev", 2)
33
+
34
+ code = f'''
35
+ def bollinger_strategy(data, period={period}, std_dev={std_dev}):
36
+ """
37
+ 布林带策略
38
+ - Period: {period}日移动平均
39
+ - Std Dev: {std_dev}倍标准差
40
+ Signals:
41
+ - 价格触及下轨买入(1)
42
+ - 价格触及上轨卖出(-1)
43
+ - 持有(0)
44
+ """
45
+ import pandas as pd
46
+
47
+ data["mid"] = data["close"].rolling({period}).mean()
48
+ data["std"] = data["close"].rolling({period}).std()
49
+ data["upper"] = data["mid"] + {std_dev} * data["std"]
50
+ data["lower"] = data["mid"] - {std_dev} * data["std"]
51
+
52
+ data["signal"] = 0
53
+ data.loc[data["close"] <= data["lower"], "signal"] = 1
54
+ data.loc[data["close"] >= data["upper"], "signal"] = -1
55
+
56
+ data["position"] = data["signal"].shift(1)
57
+ return data
58
+ '''
59
+ return SkillResult(
60
+ success=True,
61
+ data={
62
+ "strategy": "bollinger",
63
+ "period": period,
64
+ "std_dev": std_dev,
65
+ "code": code.strip(),
66
+ "description": f"布林带策略: {period}日周期,{std_dev}倍标准差",
67
+ },
68
+ )
69
+
70
+ def get_parameters_schema(self) -> Dict[str, Any]:
71
+ """Return parameter schema"""
72
+ return {
73
+ "type": "object",
74
+ "properties": {
75
+ "period": {
76
+ "type": "integer",
77
+ "description": "移动平均周期",
78
+ "default": 20,
79
+ },
80
+ "std_dev": {
81
+ "type": "number",
82
+ "description": "标准差倍数",
83
+ "default": 2,
84
+ },
85
+ },
86
+ }