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,190 @@
1
+ # coding=utf-8
2
+ """漂移检测器 - 三种检测算法"""
3
+
4
+ from __future__ import annotations
5
+
6
+ from typing import List, Optional
7
+
8
+ from ..storage.models import DriftAlert, PerformanceSnapshot
9
+ from ..storage.repository import DriftAlertRepository, PerformanceRepository
10
+
11
+
12
+ class DriftDetector:
13
+ """漂移检测器
14
+
15
+ 支持三种检测:
16
+ 1. KS检验: 收益率分布是否发生变化
17
+ 2. 夏普比率下降: 夏普比率是否显著下降
18
+ 3. 最大回撤超标: 最大回撤是否超过预设阈值
19
+ """
20
+
21
+ def __init__(
22
+ self,
23
+ alert_repo: DriftAlertRepository,
24
+ perf_repo: PerformanceRepository,
25
+ ks_threshold: float = 0.05,
26
+ sharpe_drop_pct: float = 0.3,
27
+ max_drawdown_limit: float = -0.20,
28
+ ):
29
+ self.alert_repo = alert_repo
30
+ self.perf_repo = perf_repo
31
+ self.ks_threshold = ks_threshold
32
+ self.sharpe_drop_pct = sharpe_drop_pct
33
+ self.max_drawdown_limit = max_drawdown_limit
34
+
35
+ def detect_ks_drift(
36
+ self,
37
+ current_returns: List[float],
38
+ baseline_returns: List[float],
39
+ strategy_name: str,
40
+ ) -> Optional[DriftAlert]:
41
+ """KS检验: 收益率分布是否发生变化
42
+
43
+ 使用 scipy.stats.ks_2samp 检验两个样本是否来自同一分布。
44
+ p_value < threshold → 分布发生显著变化 → 漂移。
45
+ """
46
+ if len(current_returns) < 5 or len(baseline_returns) < 5:
47
+ return None
48
+
49
+ try:
50
+ from scipy.stats import ks_2samp
51
+ statistic, p_value = ks_2samp(current_returns, baseline_returns)
52
+ except ImportError:
53
+ return None
54
+
55
+ if p_value < self.ks_threshold:
56
+ severity = "critical" if p_value < 0.01 else "warning"
57
+ alert = DriftAlert(
58
+ strategy_name=strategy_name,
59
+ alert_type="ks_test",
60
+ severity=severity,
61
+ metric_name="return_distribution",
62
+ current_value=statistic,
63
+ p_value=p_value,
64
+ message=(
65
+ f"收益分布发生漂移 (KS statistic={statistic:.4f}, "
66
+ f"p_value={p_value:.4f} < {self.ks_threshold})"
67
+ ),
68
+ )
69
+ self.alert_repo.create_alert(alert)
70
+ return alert
71
+ return None
72
+
73
+ def detect_sharpe_drop(
74
+ self,
75
+ current_snapshot: PerformanceSnapshot,
76
+ baseline_snapshot: Optional[PerformanceSnapshot],
77
+ strategy_name: str,
78
+ ) -> Optional[DriftAlert]:
79
+ """夏普比率下降检测
80
+
81
+ 当前夏普 < 基线夏普 * (1 - drop_pct) → 告警。
82
+ """
83
+ if baseline_snapshot is None or current_snapshot.sharpe_ratio is None:
84
+ return None
85
+
86
+ baseline_sharpe = baseline_snapshot.sharpe_ratio
87
+ current_sharpe = current_snapshot.sharpe_ratio
88
+
89
+ if baseline_sharpe is None or baseline_sharpe <= 0:
90
+ return None
91
+
92
+ threshold = baseline_sharpe * (1 - self.sharpe_drop_pct)
93
+ if current_sharpe < threshold:
94
+ drop_pct = (baseline_sharpe - current_sharpe) / baseline_sharpe
95
+ severity = "critical" if drop_pct > 0.5 else "warning"
96
+ alert = DriftAlert(
97
+ strategy_name=strategy_name,
98
+ alert_type="sharpe_drop",
99
+ severity=severity,
100
+ metric_name="sharpe_ratio",
101
+ current_value=current_sharpe,
102
+ baseline_value=baseline_sharpe,
103
+ message=(
104
+ f"夏普比率下降 {drop_pct:.1%} "
105
+ f"(当前={current_sharpe:.4f}, 基线={baseline_sharpe:.4f}, "
106
+ f"阈值={threshold:.4f})"
107
+ ),
108
+ )
109
+ self.alert_repo.create_alert(alert)
110
+ return alert
111
+ return None
112
+
113
+ def detect_drawdown_breach(
114
+ self,
115
+ current_snapshot: PerformanceSnapshot,
116
+ strategy_name: str,
117
+ ) -> Optional[DriftAlert]:
118
+ """最大回撤超标检测
119
+
120
+ |current_dd| > max_allowed_dd → 告警。
121
+ """
122
+ if current_snapshot.max_drawdown is None:
123
+ return None
124
+
125
+ current_dd = current_snapshot.max_drawdown
126
+ if abs(current_dd) > abs(self.max_drawdown_limit):
127
+ critical_threshold = abs(self.max_drawdown_limit) * 1.5
128
+ severity = (
129
+ "critical" if abs(current_dd) > critical_threshold else "warning"
130
+ )
131
+ alert = DriftAlert(
132
+ strategy_name=strategy_name,
133
+ alert_type="drawdown_breach",
134
+ severity=severity,
135
+ metric_name="max_drawdown",
136
+ current_value=current_dd,
137
+ baseline_value=self.max_drawdown_limit,
138
+ message=(
139
+ f"最大回撤超标 "
140
+ f"(当前={current_dd:.4f}, 限制={self.max_drawdown_limit:.4f})"
141
+ ),
142
+ )
143
+ self.alert_repo.create_alert(alert)
144
+ return alert
145
+ return None
146
+
147
+ def run_all_checks(
148
+ self,
149
+ strategy_name: str,
150
+ current_returns: Optional[List[float]] = None,
151
+ ) -> List[DriftAlert]:
152
+ """运行所有漂移检测
153
+
154
+ Args:
155
+ strategy_name: 策略名称
156
+ current_returns: 当前收益率序列 (用于KS检验)
157
+
158
+ Returns:
159
+ 触发的告警列表
160
+ """
161
+ alerts = []
162
+
163
+ # 获取最新快照和基线
164
+ current = self.perf_repo.get_latest(strategy_name)
165
+ baseline = self.perf_repo.get_baseline(strategy_name)
166
+
167
+ if current is None:
168
+ return alerts
169
+
170
+ # 1. KS检验
171
+ if current_returns and baseline:
172
+ baseline_returns_str = baseline.daily_returns
173
+ if baseline_returns_str:
174
+ import json
175
+ baseline_returns = json.loads(baseline_returns_str)
176
+ alert = self.detect_ks_drift(current_returns, baseline_returns, strategy_name)
177
+ if alert:
178
+ alerts.append(alert)
179
+
180
+ # 2. 夏普比率下降
181
+ alert = self.detect_sharpe_drop(current, baseline, strategy_name)
182
+ if alert:
183
+ alerts.append(alert)
184
+
185
+ # 3. 最大回撤超标
186
+ alert = self.detect_drawdown_breach(current, strategy_name)
187
+ if alert:
188
+ alerts.append(alert)
189
+
190
+ return alerts
@@ -0,0 +1,4 @@
1
+ from .scheduler import StrategyScheduler
2
+ from .runner import StrategyRunner
3
+
4
+ __all__ = ["StrategyScheduler", "StrategyRunner"]
@@ -0,0 +1,133 @@
1
+ # coding=utf-8
2
+ """策略执行器 - 被调度器调用"""
3
+
4
+ from __future__ import annotations
5
+
6
+ import logging
7
+ import traceback
8
+ from datetime import datetime
9
+ from pathlib import Path
10
+ from typing import Optional, Dict, Any
11
+
12
+ from ..storage.models import StrategyRun
13
+ from ..storage.repository import DatabaseManager, StrategyRunRepository
14
+ from ..monitor.collector import MetricsCollector
15
+ from ..monitor.drift import DriftDetector
16
+ from ..monitor.alerter import Alerter
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ class StrategyRunner:
22
+ """策略执行器
23
+
24
+ 被调度器调用,执行策略并记录结果。
25
+ """
26
+
27
+ def __init__(
28
+ self,
29
+ run_repo: StrategyRunRepository,
30
+ metrics_collector: MetricsCollector,
31
+ drift_detector: DriftDetector,
32
+ alerter: Alerter,
33
+ ):
34
+ self.run_repo = run_repo
35
+ self.collector = metrics_collector
36
+ self.drift_detector = drift_detector
37
+ self.alerter = alerter
38
+
39
+ @classmethod
40
+ def from_default_db(cls, db_path: str = "~/.quantnodes/monitor.db") -> StrategyRunner:
41
+ """从默认数据库创建StrategyRunner"""
42
+ db = DatabaseManager(db_path)
43
+ db.connect()
44
+ run_repo = StrategyRunRepository(db)
45
+ from ..storage.repository import PerformanceRepository, DriftAlertRepository
46
+ perf_repo = PerformanceRepository(db)
47
+ alert_repo = DriftAlertRepository(db)
48
+ collector = MetricsCollector(perf_repo)
49
+ drift = DriftDetector(alert_repo, perf_repo)
50
+ alerter = Alerter(alert_repo)
51
+ return cls(run_repo, collector, drift, alerter)
52
+
53
+ def run_strategy(
54
+ self,
55
+ strategy_name: str,
56
+ config_path: str,
57
+ run_type: str = "sample_out",
58
+ version: str = None,
59
+ ) -> Optional[Dict[str, Any]]:
60
+ """执行策略并记录结果
61
+
62
+ Args:
63
+ strategy_name: 策略名称
64
+ config_path: YAML配置文件路径
65
+ run_type: 运行类型 (backtest/live/sample_out)
66
+ version: 策略版本号
67
+
68
+ Returns:
69
+ 执行结果字典
70
+ """
71
+ # 读取配置快照
72
+ config_snapshot = ""
73
+ try:
74
+ config_snapshot = Path(config_path).read_text(encoding="utf-8")
75
+ except Exception:
76
+ pass
77
+
78
+ # 创建运行记录
79
+ run = StrategyRun(
80
+ strategy_name=strategy_name,
81
+ run_type=run_type,
82
+ status="running",
83
+ strategy_version=version,
84
+ start_time=datetime.now(),
85
+ config_snapshot=config_snapshot,
86
+ )
87
+ run_id = self.run_repo.create(run)
88
+
89
+ try:
90
+ # 执行回测
91
+ statistics = self._execute_backtest(config_path)
92
+
93
+ # 更新运行记录
94
+ self.run_repo.update_status(run_id, "success", statistics=statistics)
95
+
96
+ # 采集绩效指标
97
+ if statistics:
98
+ self.collector.collect_from_backtest(strategy_name, statistics)
99
+
100
+ # 运行漂移检测
101
+ alerts = self.drift_detector.run_all_checks(strategy_name)
102
+ if alerts:
103
+ logger.warning(
104
+ f"Strategy {strategy_name}: {len(alerts)} drift alerts"
105
+ )
106
+
107
+ logger.info(f"Strategy {strategy_name} completed successfully")
108
+ return {
109
+ "status": "success",
110
+ "run_id": run_id,
111
+ "statistics": statistics,
112
+ "alerts": [a.message for a in alerts] if alerts else [],
113
+ }
114
+
115
+ except Exception as e:
116
+ error_msg = traceback.format_exc()
117
+ self.run_repo.update_status(run_id, "failed", error_message=error_msg)
118
+ logger.error(f"Strategy {strategy_name} failed: {e}")
119
+ return {
120
+ "status": "failed",
121
+ "run_id": run_id,
122
+ "error": str(e),
123
+ }
124
+
125
+ def _execute_backtest(self, config_path: str) -> Optional[Dict[str, Any]]:
126
+ """执行回测"""
127
+ from QuantNodes.agent.config.loader import ConfigLoader
128
+
129
+ loader = ConfigLoader()
130
+ config = loader.load(config_path)
131
+
132
+ # TODO: integrate ConfigBacktestTool when stub is ready
133
+ return {"status": "completed", "config": config.name}
@@ -0,0 +1,184 @@
1
+ # coding=utf-8
2
+ """基于APScheduler的策略调度器"""
3
+
4
+ from __future__ import annotations
5
+
6
+ import logging
7
+ from pathlib import Path
8
+ from typing import List, Dict, Any
9
+
10
+ from apscheduler.schedulers.background import BackgroundScheduler
11
+ from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
12
+ from apscheduler.executors.pool import ThreadPoolExecutor
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ def _run_strategy_job_static(strategy_name: str, config_path: str, **kwargs):
18
+ """静态函数: 执行策略任务 (避免序列化问题)"""
19
+ from .runner import StrategyRunner
20
+ runner = StrategyRunner.from_default_db()
21
+ runner.run_strategy(strategy_name, config_path, **kwargs)
22
+
23
+
24
+ class StrategyScheduler:
25
+ """基于APScheduler的策略调度器
26
+
27
+ 支持三种触发方式:
28
+ - cron: cron表达式定时
29
+ - interval: 间隔定时
30
+ - date: 指定时间执行一次
31
+ """
32
+
33
+ def __init__(self, db_path: str = "~/.quantnodes/monitor.db"):
34
+ db_url = f"sqlite:///{Path(db_path).expanduser()}"
35
+ self.scheduler = BackgroundScheduler(
36
+ jobstores={"default": SQLAlchemyJobStore(url=db_url)},
37
+ executors={"default": ThreadPoolExecutor(max_workers=4)},
38
+ job_defaults={"coalesce": True, "max_instances": 1},
39
+ )
40
+ self._started = False
41
+
42
+ def add_cron_job(
43
+ self,
44
+ strategy_name: str,
45
+ cron_expr: str,
46
+ config_path: str,
47
+ **kwargs,
48
+ ) -> str:
49
+ """添加cron定时任务
50
+
51
+ Args:
52
+ strategy_name: 策略名称 (作为job id)
53
+ cron_expr: cron表达式, 如 "0 18 * * 1-5"
54
+ config_path: YAML配置文件路径
55
+ **kwargs: 传递给StrategyRunner.run_strategy的额外参数
56
+
57
+ Returns:
58
+ job id
59
+ """
60
+ job_id = f"strategy_{strategy_name}"
61
+ parts = cron_expr.split()
62
+ cron_kwargs = {}
63
+ if len(parts) >= 5:
64
+ cron_kwargs = {
65
+ "minute": parts[0],
66
+ "hour": parts[1],
67
+ "day": parts[2],
68
+ "month": parts[3],
69
+ "day_of_week": parts[4],
70
+ }
71
+
72
+ self.scheduler.add_job(
73
+ _run_strategy_job_static,
74
+ "cron",
75
+ id=job_id,
76
+ replace_existing=True,
77
+ args=[strategy_name, config_path],
78
+ kwargs=kwargs,
79
+ **cron_kwargs,
80
+ )
81
+ logger.info(f"Added cron job: {job_id} ({cron_expr})")
82
+ return job_id
83
+
84
+ def add_interval_job(
85
+ self,
86
+ strategy_name: str,
87
+ interval_minutes: int,
88
+ config_path: str,
89
+ **kwargs,
90
+ ) -> str:
91
+ """添加间隔定时任务"""
92
+ job_id = f"strategy_{strategy_name}"
93
+ self.scheduler.add_job(
94
+ _run_strategy_job_static,
95
+ "interval",
96
+ id=job_id,
97
+ replace_existing=True,
98
+ minutes=interval_minutes,
99
+ args=[strategy_name, config_path],
100
+ kwargs=kwargs,
101
+ )
102
+ logger.info(f"Added interval job: {job_id} ({interval_minutes}min)")
103
+ return job_id
104
+
105
+ def add_date_job(
106
+ self,
107
+ strategy_name: str,
108
+ run_date,
109
+ config_path: str,
110
+ **kwargs,
111
+ ) -> str:
112
+ """添加一次性定时任务"""
113
+ job_id = f"strategy_{strategy_name}_{run_date}"
114
+ self.scheduler.add_job(
115
+ _run_strategy_job_static,
116
+ "date",
117
+ id=job_id,
118
+ run_date=run_date,
119
+ args=[strategy_name, config_path],
120
+ kwargs=kwargs,
121
+ )
122
+ logger.info(f"Added date job: {job_id} ({run_date})")
123
+ return job_id
124
+
125
+ def remove_job(self, strategy_name: str) -> bool:
126
+ """移除任务"""
127
+ job_id = f"strategy_{strategy_name}"
128
+ try:
129
+ self.scheduler.remove_job(job_id)
130
+ logger.info(f"Removed job: {job_id}")
131
+ return True
132
+ except Exception:
133
+ return False
134
+
135
+ def get_jobs(self) -> List[Dict[str, Any]]:
136
+ """获取所有任务"""
137
+ jobs = []
138
+ for job in self.scheduler.get_jobs():
139
+ next_run = None
140
+ try:
141
+ next_run_time = job.next_run_time
142
+ if next_run_time:
143
+ next_run = str(next_run_time)
144
+ except Exception:
145
+ pass
146
+ jobs.append({
147
+ "id": job.id,
148
+ "name": job.name,
149
+ "next_run_time": next_run,
150
+ "trigger": str(job.trigger),
151
+ })
152
+ return jobs
153
+
154
+ def pause_job(self, strategy_name: str) -> bool:
155
+ """暂停任务"""
156
+ job_id = f"strategy_{strategy_name}"
157
+ try:
158
+ self.scheduler.pause_job(job_id)
159
+ return True
160
+ except Exception:
161
+ return False
162
+
163
+ def resume_job(self, strategy_name: str) -> bool:
164
+ """恢复任务"""
165
+ job_id = f"strategy_{strategy_name}"
166
+ try:
167
+ self.scheduler.resume_job(job_id)
168
+ return True
169
+ except Exception:
170
+ return False
171
+
172
+ def start(self):
173
+ """启动调度器"""
174
+ if not self._started:
175
+ self.scheduler.start()
176
+ self._started = True
177
+ logger.info("Scheduler started")
178
+
179
+ def shutdown(self):
180
+ """关闭调度器"""
181
+ if self._started:
182
+ self.scheduler.shutdown(wait=False)
183
+ self._started = False
184
+ logger.info("Scheduler shutdown")
@@ -0,0 +1,16 @@
1
+ from .models import (
2
+ StrategyRun, PerformanceSnapshot, DriftAlert, StrategyVersion,
3
+ )
4
+ from .repository import (
5
+ DatabaseManager,
6
+ StrategyRunRepository,
7
+ PerformanceRepository,
8
+ DriftAlertRepository,
9
+ VersionRepository,
10
+ )
11
+
12
+ __all__ = [
13
+ "StrategyRun", "PerformanceSnapshot", "DriftAlert", "StrategyVersion",
14
+ "DatabaseManager", "StrategyRunRepository", "PerformanceRepository",
15
+ "DriftAlertRepository", "VersionRepository",
16
+ ]
@@ -0,0 +1,70 @@
1
+ # coding=utf-8
2
+ """监控数据模型 - SQLite表结构定义"""
3
+
4
+ from __future__ import annotations
5
+
6
+ from dataclasses import dataclass
7
+ from datetime import date, datetime
8
+ from typing import Optional
9
+
10
+
11
+ @dataclass
12
+ class StrategyRun:
13
+ """策略运行记录"""
14
+ strategy_name: str
15
+ run_type: str # 'backtest' | 'live' | 'sample_out'
16
+ status: str # 'running' | 'success' | 'failed'
17
+ strategy_version: Optional[str] = None
18
+ start_time: Optional[datetime] = None
19
+ end_time: Optional[datetime] = None
20
+ config_snapshot: Optional[str] = None
21
+ statistics: Optional[str] = None # JSON字符串
22
+ error_message: Optional[str] = None
23
+ id: Optional[int] = None
24
+ created_at: Optional[datetime] = None
25
+
26
+
27
+ @dataclass
28
+ class PerformanceSnapshot:
29
+ """绩效快照"""
30
+ strategy_name: str
31
+ snapshot_date: date
32
+ sharpe_ratio: Optional[float] = None
33
+ sortino_ratio: Optional[float] = None
34
+ max_drawdown: Optional[float] = None
35
+ annualized_return: Optional[float] = None
36
+ annualized_volatility: Optional[float] = None
37
+ win_rate: Optional[float] = None
38
+ profit_factor: Optional[float] = None
39
+ total_trades: Optional[int] = None
40
+ daily_returns: Optional[str] = None # JSON数组
41
+ id: Optional[int] = None
42
+ created_at: Optional[datetime] = None
43
+
44
+
45
+ @dataclass
46
+ class DriftAlert:
47
+ """漂移告警"""
48
+ strategy_name: str
49
+ alert_type: str # 'ks_test' | 'sharpe_drop' | 'drawdown_breach'
50
+ severity: str # 'warning' | 'critical'
51
+ metric_name: Optional[str] = None
52
+ current_value: Optional[float] = None
53
+ baseline_value: Optional[float] = None
54
+ p_value: Optional[float] = None
55
+ message: Optional[str] = None
56
+ acknowledged: bool = False
57
+ id: Optional[int] = None
58
+ created_at: Optional[datetime] = None
59
+
60
+
61
+ @dataclass
62
+ class StrategyVersion:
63
+ """策略版本"""
64
+ strategy_name: str
65
+ version: str
66
+ config_snapshot: str # YAML配置内容
67
+ commit_hash: Optional[str] = None
68
+ description: Optional[str] = None
69
+ id: Optional[int] = None
70
+ created_at: Optional[datetime] = None