aria-code 0.167.0__py3-none-win_amd64.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 (601) hide show
  1. aria_bots/__init__.py +7 -0
  2. aria_bots/channels/README.md +97 -0
  3. aria_bots/channels/__init__.py +1 -0
  4. aria_bots/channels/approvals.py +263 -0
  5. aria_bots/channels/conversation.py +280 -0
  6. aria_bots/channels/digest.py +186 -0
  7. aria_bots/channels/registry.py +95 -0
  8. aria_bots/engine.py +144 -0
  9. aria_bots/feishu_bot.py +1385 -0
  10. aria_bots/logistics/__init__.py +1 -0
  11. aria_bots/logistics/carriers.py +253 -0
  12. aria_bots/logistics/freight.py +154 -0
  13. aria_bots/logistics/inventory.py +242 -0
  14. aria_bots/logistics/mcp_server.py +156 -0
  15. aria_bots/logistics/records.py +119 -0
  16. aria_bots/logistics/tenancy.py +152 -0
  17. aria_bots/market.py +91 -0
  18. aria_bots/relay_client.py +326 -0
  19. aria_bots/telegram_bot.py +299 -0
  20. aria_code/__init__.py +111 -0
  21. aria_code/_bin/aria-native.exe +0 -0
  22. aria_code/_bin/aria-runtime.exe +0 -0
  23. aria_code/_version.py +20 -0
  24. aria_code/account_memory.py +296 -0
  25. aria_code/account_session.py +166 -0
  26. aria_code/adk_apps/__init__.py +1 -0
  27. aria_code/adk_apps/aria_code_review/__init__.py +1 -0
  28. aria_code/adk_apps/aria_code_review/agent.py +32 -0
  29. aria_code/adk_apps/aria_research/__init__.py +1 -0
  30. aria_code/adk_apps/aria_research/agent.py +31 -0
  31. aria_code/agents/__init__.py +49 -0
  32. aria_code/agents/base.py +329 -0
  33. aria_code/agents/code_review.py +200 -0
  34. aria_code/agents/deep/__init__.py +37 -0
  35. aria_code/agents/deep/calibration_loop.py +144 -0
  36. aria_code/agents/deep/critic.py +125 -0
  37. aria_code/agents/deep/deepen.py +193 -0
  38. aria_code/agents/deep/models.py +149 -0
  39. aria_code/agents/deep/pipeline.py +164 -0
  40. aria_code/agents/deep/quant_fusion.py +192 -0
  41. aria_code/agents/deep/themes.py +95 -0
  42. aria_code/agents/deep/tiers.py +106 -0
  43. aria_code/agents/engineering/__init__.py +14 -0
  44. aria_code/agents/engineering/coder.py +222 -0
  45. aria_code/agents/engineering/tester.py +145 -0
  46. aria_code/agents/financial/__init__.py +21 -0
  47. aria_code/agents/financial/cashflow_burn.py +119 -0
  48. aria_code/agents/financial/catalyst.py +279 -0
  49. aria_code/agents/financial/corporate_finance.py +175 -0
  50. aria_code/agents/financial/debate.py +224 -0
  51. aria_code/agents/financial/earnings.py +315 -0
  52. aria_code/agents/financial/fundamental.py +178 -0
  53. aria_code/agents/financial/macro.py +111 -0
  54. aria_code/agents/financial/news.py +231 -0
  55. aria_code/agents/financial/risk.py +146 -0
  56. aria_code/agents/financial/sector.py +279 -0
  57. aria_code/agents/financial/strategist.py +121 -0
  58. aria_code/agents/financial/stripe_revenue.py +127 -0
  59. aria_code/agents/financial/synthesis.py +274 -0
  60. aria_code/agents/financial/technical.py +277 -0
  61. aria_code/agents/orchestrator.py +44 -0
  62. aria_code/agents/portfolio_agent.py +392 -0
  63. aria_code/agents/realty/__init__.py +62 -0
  64. aria_code/agents/realty/asset_diagnosis.py +152 -0
  65. aria_code/agents/realty/business_match.py +166 -0
  66. aria_code/agents/realty/cashflow_verify.py +209 -0
  67. aria_code/agents/realty/contract_rules.py +210 -0
  68. aria_code/agents/realty/energy_anomaly.py +189 -0
  69. aria_code/agents/realty/exit_settlement.py +208 -0
  70. aria_code/agents/realty/fulfillment_risk.py +206 -0
  71. aria_code/agents/realty/ops_optimize.py +160 -0
  72. aria_code/agents/realty/revenue_share.py +215 -0
  73. aria_code/agents/registry.py +168 -0
  74. aria_code/agents/signal_scheme.py +111 -0
  75. aria_code/agents/sports/__init__.py +0 -0
  76. aria_code/agents/sports/football_agent.py +197 -0
  77. aria_code/agents/supervisor.py +113 -0
  78. aria_code/agents/team.py +500 -0
  79. aria_code/agents/video/__init__.py +16 -0
  80. aria_code/agents/video/director.py +376 -0
  81. aria_code/agents/video/qa_agent.py +143 -0
  82. aria_code/agents/video/script_doctor.py +112 -0
  83. aria_code/agents/warehouse/__init__.py +25 -0
  84. aria_code/agents/warehouse/contracts.py +26 -0
  85. aria_code/agents/warehouse/dashboard.py +155 -0
  86. aria_code/agents/warehouse/fulfillment_leadtime.py +95 -0
  87. aria_code/agents/warehouse/inbound_exceptions.py +25 -0
  88. aria_code/agents/warehouse/inventory_health.py +24 -0
  89. aria_code/agents/warehouse/local_run.py +71 -0
  90. aria_code/agents/warehouse/local_snapshot.py +132 -0
  91. aria_code/agents/warehouse/logistics_cost.py +84 -0
  92. aria_code/agents/warehouse/logistics_sync.py +21 -0
  93. aria_code/agents/warehouse/navigation.schema.json +110 -0
  94. aria_code/agents/warehouse/task_agent.py +172 -0
  95. aria_code/agents/warehouse/workflow.py +31 -0
  96. aria_code/aliyun_data_client.py +4 -0
  97. aria_code/apps/README.md +12 -0
  98. aria_code/apps/__init__.py +2 -0
  99. aria_code/apps/channels/README.md +9 -0
  100. aria_code/apps/channels/__init__.py +17 -0
  101. aria_code/apps/channels/approvals.py +11 -0
  102. aria_code/apps/channels/conversation.py +11 -0
  103. aria_code/apps/channels/digest.py +11 -0
  104. aria_code/apps/channels/intake.py +92 -0
  105. aria_code/apps/channels/registry.py +11 -0
  106. aria_code/apps/channels/tradingview.py +94 -0
  107. aria_code/apps/cli/README.md +13 -0
  108. aria_code/apps/cli/__init__.py +2 -0
  109. aria_code/apps/cli/_optional.py +120 -0
  110. aria_code/apps/cli/app_server.py +656 -0
  111. aria_code/apps/cli/auto_update.py +125 -0
  112. aria_code/apps/cli/bootstrap.py +206 -0
  113. aria_code/apps/cli/broker_render.py +206 -0
  114. aria_code/apps/cli/chat_turn.py +1327 -0
  115. aria_code/apps/cli/cloud_models.py +231 -0
  116. aria_code/apps/cli/codegen_paths.py +29 -0
  117. aria_code/apps/cli/commands/__init__.py +34 -0
  118. aria_code/apps/cli/commands/_business_render.py +78 -0
  119. aria_code/apps/cli/commands/_ui.py +71 -0
  120. aria_code/apps/cli/commands/analysis_cmds.py +378 -0
  121. aria_code/apps/cli/commands/ashare_prediction_cmds.py +327 -0
  122. aria_code/apps/cli/commands/auth_cmds.py +215 -0
  123. aria_code/apps/cli/commands/backtest_cmds.py +2518 -0
  124. aria_code/apps/cli/commands/broker_cmds.py +1236 -0
  125. aria_code/apps/cli/commands/business_workflow_cmds.py +379 -0
  126. aria_code/apps/cli/commands/canvas_cmds.py +77 -0
  127. aria_code/apps/cli/commands/catalog.py +189 -0
  128. aria_code/apps/cli/commands/core_cmds.py +2748 -0
  129. aria_code/apps/cli/commands/data_cmds.py +521 -0
  130. aria_code/apps/cli/commands/diagnostic_cmds.py +285 -0
  131. aria_code/apps/cli/commands/diagnostic_ops_cmds.py +813 -0
  132. aria_code/apps/cli/commands/engineering_cmds.py +399 -0
  133. aria_code/apps/cli/commands/file_cmds.py +312 -0
  134. aria_code/apps/cli/commands/finance_service_cmds.py +60 -0
  135. aria_code/apps/cli/commands/fx_commodity_cmds.py +123 -0
  136. aria_code/apps/cli/commands/market.py +544 -0
  137. aria_code/apps/cli/commands/market_cmds.py +1419 -0
  138. aria_code/apps/cli/commands/market_context.py +432 -0
  139. aria_code/apps/cli/commands/market_render.py +7 -0
  140. aria_code/apps/cli/commands/model_cmds.py +2374 -0
  141. aria_code/apps/cli/commands/ops_cmds.py +721 -0
  142. aria_code/apps/cli/commands/orchestrator_cmds.py +181 -0
  143. aria_code/apps/cli/commands/pdf_export_cmds.py +125 -0
  144. aria_code/apps/cli/commands/portfolio_cmds.py +1316 -0
  145. aria_code/apps/cli/commands/report.py +476 -0
  146. aria_code/apps/cli/commands/scaffold_templates.py +617 -0
  147. aria_code/apps/cli/commands/session_cmds.py +236 -0
  148. aria_code/apps/cli/commands/session_ux_cmds.py +359 -0
  149. aria_code/apps/cli/commands/team.py +723 -0
  150. aria_code/apps/cli/commands/team_render.py +8 -0
  151. aria_code/apps/cli/commands/ui_cmds.py +401 -0
  152. aria_code/apps/cli/commands/warehouse_cmds.py +297 -0
  153. aria_code/apps/cli/commands/workflow_cmds.py +629 -0
  154. aria_code/apps/cli/commands/workspace_cmds.py +1543 -0
  155. aria_code/apps/cli/config_paths.py +73 -0
  156. aria_code/apps/cli/config_store.py +158 -0
  157. aria_code/apps/cli/constants.py +88 -0
  158. aria_code/apps/cli/context.py +34 -0
  159. aria_code/apps/cli/conversation_policy.py +53 -0
  160. aria_code/apps/cli/deterministic.py +200 -0
  161. aria_code/apps/cli/direct.py +48 -0
  162. aria_code/apps/cli/earnings_view.py +172 -0
  163. aria_code/apps/cli/endpoint_migration.py +64 -0
  164. aria_code/apps/cli/exec_events.py +255 -0
  165. aria_code/apps/cli/file_references.py +155 -0
  166. aria_code/apps/cli/finance_service_catalog.py +111 -0
  167. aria_code/apps/cli/football_reports.py +231 -0
  168. aria_code/apps/cli/github_app_auth.py +135 -0
  169. aria_code/apps/cli/google_login.py +239 -0
  170. aria_code/apps/cli/handlers/__init__.py +11 -0
  171. aria_code/apps/cli/handlers/broker_handlers.py +122 -0
  172. aria_code/apps/cli/handlers/chart_handlers.py +1314 -0
  173. aria_code/apps/cli/handlers/market_handlers.py +2570 -0
  174. aria_code/apps/cli/handlers/realty_handlers.py +114 -0
  175. aria_code/apps/cli/handlers/sports_handlers.py +22 -0
  176. aria_code/apps/cli/handlers/strategy_advice.py +82 -0
  177. aria_code/apps/cli/headless.py +352 -0
  178. aria_code/apps/cli/helpers.py +326 -0
  179. aria_code/apps/cli/hooks.py +180 -0
  180. aria_code/apps/cli/i18n.py +310 -0
  181. aria_code/apps/cli/intent.py +136 -0
  182. aria_code/apps/cli/intent_router.py +305 -0
  183. aria_code/apps/cli/intent_shadow.py +72 -0
  184. aria_code/apps/cli/intent_signals.py +347 -0
  185. aria_code/apps/cli/lifecycle_hooks.py +48 -0
  186. aria_code/apps/cli/local_tool_schemas.py +550 -0
  187. aria_code/apps/cli/main.py +39 -0
  188. aria_code/apps/cli/market_hours.py +100 -0
  189. aria_code/apps/cli/market_metadata.py +135 -0
  190. aria_code/apps/cli/market_universe.py +487 -0
  191. aria_code/apps/cli/message_processing.py +310 -0
  192. aria_code/apps/cli/mixin_binding.py +32 -0
  193. aria_code/apps/cli/model_catalog.py +652 -0
  194. aria_code/apps/cli/model_probe.py +169 -0
  195. aria_code/apps/cli/model_retirement.py +65 -0
  196. aria_code/apps/cli/native_branding.py +12 -0
  197. aria_code/apps/cli/native_bridge.py +118 -0
  198. aria_code/apps/cli/native_entry.py +58 -0
  199. aria_code/apps/cli/pdf_report.py +977 -0
  200. aria_code/apps/cli/plan_mode.py +139 -0
  201. aria_code/apps/cli/plotly_html.py +15 -0
  202. aria_code/apps/cli/prediction_feedback.py +202 -0
  203. aria_code/apps/cli/preflight.py +502 -0
  204. aria_code/apps/cli/project_aria.py +60 -0
  205. aria_code/apps/cli/prompt_assembly.py +78 -0
  206. aria_code/apps/cli/prompts/__init__.py +0 -0
  207. aria_code/apps/cli/prompts/coding.py +71 -0
  208. aria_code/apps/cli/prompts/select.py +193 -0
  209. aria_code/apps/cli/prompts/system_prompts.py +562 -0
  210. aria_code/apps/cli/prompts/ui.py +436 -0
  211. aria_code/apps/cli/provider_endpoints.py +237 -0
  212. aria_code/apps/cli/provider_keys.py +73 -0
  213. aria_code/apps/cli/providers/__init__.py +1 -0
  214. aria_code/apps/cli/providers/base.py +775 -0
  215. aria_code/apps/cli/providers/chat_routing.py +139 -0
  216. aria_code/apps/cli/providers/collaboration.py +98 -0
  217. aria_code/apps/cli/providers/llm/__init__.py +1 -0
  218. aria_code/apps/cli/providers/llm/offline_responses.py +68 -0
  219. aria_code/apps/cli/providers/llm/ollama_stream.py +1574 -0
  220. aria_code/apps/cli/providers/llm/response_cache.py +60 -0
  221. aria_code/apps/cli/providers/llm/sse_stream.py +298 -0
  222. aria_code/apps/cli/providers/runtime_bridge.py +586 -0
  223. aria_code/apps/cli/providers/vertexai_stream.py +592 -0
  224. aria_code/apps/cli/release_download.py +159 -0
  225. aria_code/apps/cli/review_runner.py +111 -0
  226. aria_code/apps/cli/runtime_consumer.py +769 -0
  227. aria_code/apps/cli/sandbox.py +32 -0
  228. aria_code/apps/cli/session_export.py +120 -0
  229. aria_code/apps/cli/session_jsonl.py +208 -0
  230. aria_code/apps/cli/session_refresh.py +123 -0
  231. aria_code/apps/cli/session_store.py +125 -0
  232. aria_code/apps/cli/skills_catalog.py +273 -0
  233. aria_code/apps/cli/task_isolation.py +211 -0
  234. aria_code/apps/cli/terminal_chrome.py +412 -0
  235. aria_code/apps/cli/todo_tracker.py +190 -0
  236. aria_code/apps/cli/tool_executor.py +932 -0
  237. aria_code/apps/cli/tool_registry.py +34 -0
  238. aria_code/apps/cli/tool_scope.py +113 -0
  239. aria_code/apps/cli/tools/__init__.py +40 -0
  240. aria_code/apps/cli/tools/context.py +46 -0
  241. aria_code/apps/cli/tools/file_tools.py +181 -0
  242. aria_code/apps/cli/tools/market_tools.py +626 -0
  243. aria_code/apps/cli/tools/notebook_tools.py +111 -0
  244. aria_code/apps/cli/tools/system_tools.py +656 -0
  245. aria_code/apps/cli/tools/write_tools.py +961 -0
  246. aria_code/apps/cli/tradingview_bridge.py +529 -0
  247. aria_code/apps/cli/transactions.py +269 -0
  248. aria_code/apps/cli/turn_planning.py +137 -0
  249. aria_code/apps/cli/update_check.py +257 -0
  250. aria_code/apps/cli/updater.py +373 -0
  251. aria_code/apps/cli/utils/__init__.py +0 -0
  252. aria_code/apps/cli/utils/market_detect.py +1663 -0
  253. aria_code/apps/cli/web_login.py +136 -0
  254. aria_code/apps/cli/workflow_runner.py +127 -0
  255. aria_code/apps/cli/workspace_route.py +121 -0
  256. aria_code/apps/daemon/README.md +14 -0
  257. aria_code/apps/vscode/README.md +115 -0
  258. aria_code/apps/vscode/package.json +70 -0
  259. aria_code/aria_cli.py +5244 -0
  260. aria_code/aria_daemon.py +1372 -0
  261. aria_code/aria_feishu_bot.py +16 -0
  262. aria_code/aria_mcp_server.py +61 -0
  263. aria_code/aria_relay_client.py +4 -0
  264. aria_code/aria_telegram_bot.py +11 -0
  265. aria_code/ariarc.py +385 -0
  266. aria_code/artifacts.py +581 -0
  267. aria_code/backtest_engine.py +4 -0
  268. aria_code/backtest_report.py +4 -0
  269. aria_code/brokers/__init__.py +78 -0
  270. aria_code/brokers/automation.py +193 -0
  271. aria_code/brokers/base.py +231 -0
  272. aria_code/brokers/capabilities.py +264 -0
  273. aria_code/brokers/cn/__init__.py +10 -0
  274. aria_code/brokers/cn/easytrader_broker.py +193 -0
  275. aria_code/brokers/cn/futu_broker.py +194 -0
  276. aria_code/brokers/cn/longbridge_broker.py +190 -0
  277. aria_code/brokers/cn/tiger_broker.py +196 -0
  278. aria_code/brokers/cn/xtquant_broker.py +225 -0
  279. aria_code/brokers/config.py +414 -0
  280. aria_code/brokers/intl/__init__.py +5 -0
  281. aria_code/brokers/intl/alpaca_broker.py +183 -0
  282. aria_code/brokers/intl/ibkr_broker.py +215 -0
  283. aria_code/brokers/intl/trading212_broker.py +183 -0
  284. aria_code/brokers/intl/webull_broker.py +156 -0
  285. aria_code/brokers/paper_broker.py +266 -0
  286. aria_code/brokers/planning.py +296 -0
  287. aria_code/brokers/registry.py +213 -0
  288. aria_code/brokers/trading.py +267 -0
  289. aria_code/canva_client.py +4 -0
  290. aria_code/change_store.py +127 -0
  291. aria_code/clients/__init__.py +0 -0
  292. aria_code/clients/aliyun_data_client.py +660 -0
  293. aria_code/clients/aria_relay_client.py +16 -0
  294. aria_code/clients/canva_client.py +284 -0
  295. aria_code/clients/figma_client.py +100 -0
  296. aria_code/clients/football_data_client.py +1671 -0
  297. aria_code/clients/kling_video_client.py +182 -0
  298. aria_code/clients/market_data_client.py +1985 -0
  299. aria_code/clients/openai_image_client.py +242 -0
  300. aria_code/clients/runway_video_client.py +157 -0
  301. aria_code/clients/warehouse_erp_client.py +105 -0
  302. aria_code/cloud_memory.py +190 -0
  303. aria_code/command_safety.py +19 -0
  304. aria_code/computer_use_server.py +276 -0
  305. aria_code/computer_use_tools.py +4 -0
  306. aria_code/dashboard_generator.py +579 -0
  307. aria_code/data_analysis_tools.py +4 -0
  308. aria_code/data_cleaner.py +483 -0
  309. aria_code/data_service.py +513 -0
  310. aria_code/datasources/__init__.py +23 -0
  311. aria_code/datasources/base.py +166 -0
  312. aria_code/datasources/router.py +253 -0
  313. aria_code/datasources/sec_statements.py +217 -0
  314. aria_code/datasources/sources/__init__.py +15 -0
  315. aria_code/datasources/sources/akshare_source.py +269 -0
  316. aria_code/datasources/sources/alpha_vantage_source.py +203 -0
  317. aria_code/datasources/sources/edgar_source.py +219 -0
  318. aria_code/datasources/sources/finnhub_source.py +198 -0
  319. aria_code/datasources/sources/fred_source.py +223 -0
  320. aria_code/datasources/sources/tushare_source.py +143 -0
  321. aria_code/datasources/sources/web_scraper_source.py +278 -0
  322. aria_code/datasources/sources/world_bank_source.py +206 -0
  323. aria_code/datasources/sources/yfinance_source.py +152 -0
  324. aria_code/doctor.py +860 -0
  325. aria_code/domain/__init__.py +0 -0
  326. aria_code/domain/_finance_core/__init__.py +5 -0
  327. aria_code/domain/_finance_core/backtest_engine.py +325 -0
  328. aria_code/domain/_finance_core/performance_stats.py +101 -0
  329. aria_code/domain/backtest_engine.py +75 -0
  330. aria_code/domain/backtest_report.py +488 -0
  331. aria_code/domain/finance_formulas.py +389 -0
  332. aria_code/domain/performance_stats.py +6 -0
  333. aria_code/domain/portfolio_ledger.py +307 -0
  334. aria_code/domain/strategy_vault.py +421 -0
  335. aria_code/evals/__init__.py +37 -0
  336. aria_code/evals/behavior.py +113 -0
  337. aria_code/evals/gap.py +93 -0
  338. aria_code/evals/harness.py +949 -0
  339. aria_code/evals/review_probe.py +132 -0
  340. aria_code/evals/runner.py +425 -0
  341. aria_code/evals/scorecard.py +322 -0
  342. aria_code/evals/summary.py +125 -0
  343. aria_code/external_agent_runner.py +115 -0
  344. aria_code/figma_client.py +4 -0
  345. aria_code/file_analysis_tools.py +4 -0
  346. aria_code/finance_formulas.py +4 -0
  347. aria_code/football_data_client.py +4 -0
  348. aria_code/image_gen_tools.py +4 -0
  349. aria_code/intent_classifier.py +459 -0
  350. aria_code/kling_video_client.py +4 -0
  351. aria_code/licensing.py +151 -0
  352. aria_code/local_finance_tools.py +4 -0
  353. aria_code/local_image_provider.py +4 -0
  354. aria_code/local_llm_provider.py +4 -0
  355. aria_code/macro_tools.py +4 -0
  356. aria_code/markdown_pdf.py +289 -0
  357. aria_code/market_data_client.py +4 -0
  358. aria_code/mcp_client.py +744 -0
  359. aria_code/memory_manager.py +273 -0
  360. aria_code/model_capability.py +512 -0
  361. aria_code/notification_tools.py +4 -0
  362. aria_code/openai_image_client.py +4 -0
  363. aria_code/packages/__init__.py +26 -0
  364. aria_code/packages/adk_bridge/__init__.py +11 -0
  365. aria_code/packages/adk_bridge/code_review_tools.py +49 -0
  366. aria_code/packages/adk_bridge/market_tools.py +125 -0
  367. aria_code/packages/aria_agents/__init__.py +5 -0
  368. aria_code/packages/aria_agents/manifest.py +78 -0
  369. aria_code/packages/aria_core/__init__.py +34 -0
  370. aria_code/packages/aria_core/architecture.py +269 -0
  371. aria_code/packages/aria_core/export.py +147 -0
  372. aria_code/packages/aria_core/manifest.py +65 -0
  373. aria_code/packages/aria_core/paths.py +57 -0
  374. aria_code/packages/aria_core/secure_file.py +68 -0
  375. aria_code/packages/aria_infra/__init__.py +15 -0
  376. aria_code/packages/aria_infra/arthera.py +58 -0
  377. aria_code/packages/aria_infra/doctor.py +246 -0
  378. aria_code/packages/aria_infra/product.py +40 -0
  379. aria_code/packages/aria_mcp/__init__.py +25 -0
  380. aria_code/packages/aria_mcp/bridge.py +232 -0
  381. aria_code/packages/aria_mcp/circuit.py +82 -0
  382. aria_code/packages/aria_mcp/config.py +162 -0
  383. aria_code/packages/aria_mcp/installer.py +95 -0
  384. aria_code/packages/aria_mcp/server.py +1705 -0
  385. aria_code/packages/aria_mcp/tools.py +81 -0
  386. aria_code/packages/aria_sdk/__init__.py +19 -0
  387. aria_code/packages/aria_sdk/client.py +393 -0
  388. aria_code/packages/aria_sdk/providers.py +70 -0
  389. aria_code/packages/aria_sdk/streaming.py +75 -0
  390. aria_code/packages/aria_sdk/types.py +86 -0
  391. aria_code/packages/aria_services/__init__.py +92 -0
  392. aria_code/packages/aria_services/cache.py +60 -0
  393. aria_code/packages/aria_services/context.py +356 -0
  394. aria_code/packages/aria_services/context_checkpoints.py +157 -0
  395. aria_code/packages/aria_services/data.py +11 -0
  396. aria_code/packages/aria_services/provider_health.py +304 -0
  397. aria_code/packages/aria_services/references.py +247 -0
  398. aria_code/packages/aria_services/registry.py +249 -0
  399. aria_code/packages/aria_services/research_protocol.py +137 -0
  400. aria_code/packages/aria_services/research_quality.py +186 -0
  401. aria_code/packages/aria_services/settings.py +160 -0
  402. aria_code/packages/aria_services/usage.py +151 -0
  403. aria_code/packages/aria_skills/__init__.py +46 -0
  404. aria_code/packages/aria_skills/catalog.py +149 -0
  405. aria_code/packages/aria_skills/loader.py +455 -0
  406. aria_code/packages/aria_skills/registry.py +84 -0
  407. aria_code/packages/aria_tools/__init__.py +5 -0
  408. aria_code/packages/aria_tools/financial/__init__.py +5 -0
  409. aria_code/packages/aria_tools/financial/_paths.py +92 -0
  410. aria_code/packages/aria_tools/registry.py +129 -0
  411. aria_code/packages/quant_engine/__init__.py +33 -0
  412. aria_code/packages/quant_engine/_namespace.py +24 -0
  413. aria_code/packages/quant_engine/backtest/__init__.py +10 -0
  414. aria_code/packages/quant_engine/backtest/core.py +53 -0
  415. aria_code/packages/quant_engine/backtest/engine.py +102 -0
  416. aria_code/packages/quant_engine/portfolio/__init__.py +9 -0
  417. aria_code/packages/quant_engine/portfolio/optimizer.py +85 -0
  418. aria_code/packages/quant_engine/sports/__init__.py +76 -0
  419. aria_code/packages/quant_engine/sports/calibrator.py +354 -0
  420. aria_code/packages/quant_engine/sports/dixon_coles.py +234 -0
  421. aria_code/packages/quant_engine/sports/elo.py +300 -0
  422. aria_code/packages/quant_engine/sports/form.py +188 -0
  423. aria_code/packages/quant_engine/sports/h2h.py +195 -0
  424. aria_code/packages/quant_engine/sports/predictor.py +312 -0
  425. aria_code/packages/quant_engine/sports/tracker.py +665 -0
  426. aria_code/packages/quant_engine/stochastic/__init__.py +31 -0
  427. aria_code/packages/quant_engine/stochastic/gbm_enhanced.py +195 -0
  428. aria_code/packages/quant_engine/stochastic/ito_calculus.py +477 -0
  429. aria_code/packages/quant_engine/stochastic/kelly_criterion.py +181 -0
  430. aria_code/packages/quant_engine/stochastic/monte_carlo_advanced.py +95 -0
  431. aria_code/packages/quant_engine/stochastic/options_pricing.py +576 -0
  432. aria_code/packages/quant_engine/stochastic/stochastic_processes.py +90 -0
  433. aria_code/packs/__init__.py +85 -0
  434. aria_code/packs/base.py +168 -0
  435. aria_code/packs/finance/__init__.py +250 -0
  436. aria_code/packs/healthcare/__init__.py +40 -0
  437. aria_code/packs/logistics/__init__.py +171 -0
  438. aria_code/packs/payments/__init__.py +139 -0
  439. aria_code/packs/realty/__init__.py +190 -0
  440. aria_code/packs/registry.py +202 -0
  441. aria_code/packs/rules.py +90 -0
  442. aria_code/plan_utils.py +194 -0
  443. aria_code/plugin_loader.py +328 -0
  444. aria_code/portfolio_ledger.py +4 -0
  445. aria_code/preview_server.py +449 -0
  446. aria_code/privacy/__init__.py +5 -0
  447. aria_code/privacy/feedback.py +123 -0
  448. aria_code/project_review.py +278 -0
  449. aria_code/project_review_api.py +235 -0
  450. aria_code/project_review_server.py +18 -0
  451. aria_code/project_tools.py +4 -0
  452. aria_code/providers/__init__.py +30 -0
  453. aria_code/providers/google_video_provider.py +256 -0
  454. aria_code/providers/llm/__init__.py +19 -0
  455. aria_code/providers/llm/anthropic.py +184 -0
  456. aria_code/providers/llm/arthera_gateway.py +90 -0
  457. aria_code/providers/llm/autoconfig.py +213 -0
  458. aria_code/providers/llm/base.py +139 -0
  459. aria_code/providers/llm/custom.py +158 -0
  460. aria_code/providers/llm/ollama.py +137 -0
  461. aria_code/providers/llm/openai_compat.py +350 -0
  462. aria_code/providers/llm/registry.py +457 -0
  463. aria_code/providers/local_image_provider.py +202 -0
  464. aria_code/providers/local_llm_provider.py +549 -0
  465. aria_code/providers/ollama_models.py +79 -0
  466. aria_code/providers/openai_params.py +32 -0
  467. aria_code/providers/tool_messages.py +100 -0
  468. aria_code/realty_data_tools.py +4 -0
  469. aria_code/report_exporters.py +150 -0
  470. aria_code/report_generator.py +1764 -0
  471. aria_code/review_service.py +497 -0
  472. aria_code/runtime/__init__.py +176 -0
  473. aria_code/runtime/acceptance.py +632 -0
  474. aria_code/runtime/agent_loop.py +1851 -0
  475. aria_code/runtime/agent_profiles.py +75 -0
  476. aria_code/runtime/approval.py +71 -0
  477. aria_code/runtime/baseline.py +219 -0
  478. aria_code/runtime/budget.py +232 -0
  479. aria_code/runtime/checkpoints.py +481 -0
  480. aria_code/runtime/consult.py +65 -0
  481. aria_code/runtime/contract.py +282 -0
  482. aria_code/runtime/delivery.py +432 -0
  483. aria_code/runtime/events.py +113 -0
  484. aria_code/runtime/gateway.py +167 -0
  485. aria_code/runtime/lsp.py +484 -0
  486. aria_code/runtime/native_index.py +153 -0
  487. aria_code/runtime/orchestrator.py +55 -0
  488. aria_code/runtime/processes.py +343 -0
  489. aria_code/runtime/project_graph.py +614 -0
  490. aria_code/runtime/repo_map.py +712 -0
  491. aria_code/runtime/research_bundle.py +105 -0
  492. aria_code/runtime/review.py +269 -0
  493. aria_code/runtime/run_state.py +127 -0
  494. aria_code/runtime/run_store.py +522 -0
  495. aria_code/runtime/scoped_runs.py +113 -0
  496. aria_code/runtime/self_healing.py +422 -0
  497. aria_code/runtime/semantic_diff.py +171 -0
  498. aria_code/runtime/subagent.py +721 -0
  499. aria_code/runtime/symbol_edit.py +117 -0
  500. aria_code/runtime/task_brief.py +46 -0
  501. aria_code/runtime/task_context.py +145 -0
  502. aria_code/runtime/task_ledger.py +108 -0
  503. aria_code/runtime/task_orchestrator.py +90 -0
  504. aria_code/runtime/task_outcome.py +33 -0
  505. aria_code/runtime/task_verification.py +266 -0
  506. aria_code/runtime/task_worktree.py +448 -0
  507. aria_code/runtime/tool_executor.py +329 -0
  508. aria_code/runtime/tool_policy.py +107 -0
  509. aria_code/runtime/transactions.py +216 -0
  510. aria_code/runtime/windows_job.py +115 -0
  511. aria_code/runtime/workflows.py +222 -0
  512. aria_code/runtime/worktrees.py +215 -0
  513. aria_code/runway_video_client.py +4 -0
  514. aria_code/safety/__init__.py +27 -0
  515. aria_code/safety/client_isolation.py +178 -0
  516. aria_code/safety/permissions.py +339 -0
  517. aria_code/safety/risk.py +699 -0
  518. aria_code/safety/sandbox.py +148 -0
  519. aria_code/safety/service.py +102 -0
  520. aria_code/service_endpoints.py +14 -0
  521. aria_code/setup_wizard.py +684 -0
  522. aria_code/spreadsheet_tools.py +4 -0
  523. aria_code/strategy_vault.py +4 -0
  524. aria_code/tools/__init__.py +0 -0
  525. aria_code/tools/artifact_tools.py +252 -0
  526. aria_code/tools/broker_tools.py +92 -0
  527. aria_code/tools/build_quant_engine.py +97 -0
  528. aria_code/tools/code_audit_tools.py +192 -0
  529. aria_code/tools/computer_use_tools.py +509 -0
  530. aria_code/tools/data_analysis_tools.py +831 -0
  531. aria_code/tools/enterprise_finance_tools.py +202 -0
  532. aria_code/tools/extended_tools.py +240 -0
  533. aria_code/tools/file_analysis_tools.py +880 -0
  534. aria_code/tools/image_gen_tools.py +114 -0
  535. aria_code/tools/local_finance_tools.py +3488 -0
  536. aria_code/tools/logistics_carriers.py +11 -0
  537. aria_code/tools/logistics_inventory.py +11 -0
  538. aria_code/tools/logistics_io.py +11 -0
  539. aria_code/tools/logistics_tenancy.py +11 -0
  540. aria_code/tools/logistics_tools.py +11 -0
  541. aria_code/tools/macro_tools.py +412 -0
  542. aria_code/tools/notification_tools.py +249 -0
  543. aria_code/tools/project_tools.py +525 -0
  544. aria_code/tools/realty_data_tools.py +662 -0
  545. aria_code/tools/spreadsheet_tools.py +399 -0
  546. aria_code/tools/stripe_tools.py +115 -0
  547. aria_code/tools/video_tools.py +500 -0
  548. aria_code/training/__init__.py +1 -0
  549. aria_code/training/compare.py +117 -0
  550. aria_code/training/prelude_commands.py +111 -0
  551. aria_code/training/prelude_eval.py +390 -0
  552. aria_code/training/prelude_real.py +183 -0
  553. aria_code/training/prelude_train.py +248 -0
  554. aria_code/training/sft_dataset.py +230 -0
  555. aria_code/training/trajectory_dataset.py +263 -0
  556. aria_code/ui/__init__.py +105 -0
  557. aria_code/ui/banner.py +404 -0
  558. aria_code/ui/completer.py +571 -0
  559. aria_code/ui/console.py +285 -0
  560. aria_code/ui/input_box.py +505 -0
  561. aria_code/ui/mentions.py +206 -0
  562. aria_code/ui/picker.py +248 -0
  563. aria_code/ui/render/__init__.py +11 -0
  564. aria_code/ui/render/actions.py +297 -0
  565. aria_code/ui/render/finance.py +1732 -0
  566. aria_code/ui/render/market.py +253 -0
  567. aria_code/ui/render/output.py +954 -0
  568. aria_code/ui/render/responsive.py +75 -0
  569. aria_code/ui/render/team.py +367 -0
  570. aria_code/ui/robot.py +239 -0
  571. aria_code/ui/startup_dashboard.py +110 -0
  572. aria_code/video_analysis.py +147 -0
  573. aria_code/video_editor.py +518 -0
  574. aria_code/video_workflow/__init__.py +8 -0
  575. aria_code/video_workflow/__main__.py +61 -0
  576. aria_code/video_workflow/engines/__init__.py +18 -0
  577. aria_code/video_workflow/engines/base.py +69 -0
  578. aria_code/video_workflow/engines/custom_model.py +204 -0
  579. aria_code/video_workflow/engines/google_veo.py +94 -0
  580. aria_code/video_workflow/engines/local_engine.py +71 -0
  581. aria_code/video_workflow/engines/registry.py +98 -0
  582. aria_code/video_workflow/google_models.py +278 -0
  583. aria_code/video_workflow/music/__init__.py +5 -0
  584. aria_code/video_workflow/music/foley_service.py +132 -0
  585. aria_code/video_workflow/music/service.py +212 -0
  586. aria_code/video_workflow/pipeline.py +620 -0
  587. aria_code/video_workflow/plan.py +202 -0
  588. aria_code/video_workflow/session.py +297 -0
  589. aria_code/workspace/__init__.py +6 -0
  590. aria_code/workspace/files.py +219 -0
  591. aria_code/workspace/verify.py +167 -0
  592. aria_code/workspace_changes.py +199 -0
  593. aria_code/workspace_service.py +196 -0
  594. aria_code/workspace_tools.py +150 -0
  595. aria_code-0.167.0.dist-info/METADATA +330 -0
  596. aria_code-0.167.0.dist-info/RECORD +601 -0
  597. aria_code-0.167.0.dist-info/WHEEL +5 -0
  598. aria_code-0.167.0.dist-info/entry_points.txt +5 -0
  599. aria_code-0.167.0.dist-info/licenses/LICENSE +201 -0
  600. aria_code-0.167.0.dist-info/licenses/NOTICE +49 -0
  601. aria_code-0.167.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,279 @@
1
+ """
2
+ agents/financial/catalyst.py — 催化剂检测 Agent
3
+ ================================================
4
+ 识别近期/即将到来的价格催化剂:财报日、股息除权、
5
+ 分析师评级变化、大宗交易/大股东增减持。
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import logging
11
+ from datetime import datetime, timedelta, timezone
12
+ from typing import Any, Dict, List, Optional
13
+
14
+ from ..base import BaseAgent, AgentResult
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class CatalystAgent(BaseAgent):
20
+
21
+ name = "catalyst"
22
+ description = "催化剂检测 — 财报日、股息除权、分析师评级变化"
23
+
24
+ _SYSTEM = (
25
+ "You are an event-driven equity analyst. Analyze the upcoming and recent "
26
+ "catalysts for a stock: earnings dates, ex-dividend dates, analyst rating "
27
+ "changes, and insider activity. Assess whether these catalysts are "
28
+ "likely to be POSITIVE (price-driving), NEUTRAL, or NEGATIVE. "
29
+ "Focus on timing: catalysts within 14 days are high-impact. "
30
+ "Conclude with: POSITIVE / NEUTRAL / NEGATIVE"
31
+ )
32
+
33
+ async def fetch_data(self, symbol: str) -> Dict[str, Any]:
34
+ data = await super().fetch_data(symbol)
35
+ catalysts: Dict[str, Any] = {}
36
+
37
+ try:
38
+ import yfinance as yf
39
+ ticker = yf.Ticker(symbol)
40
+
41
+ # 1. Earnings calendar
42
+ try:
43
+ cal = ticker.calendar
44
+ if cal is not None:
45
+ if hasattr(cal, "to_dict"):
46
+ cal = cal.to_dict()
47
+ if isinstance(cal, dict):
48
+ for k in ("Earnings Date", "earnings_date", "earningsDate"):
49
+ v = cal.get(k)
50
+ if v:
51
+ catalysts["earnings_date"] = str(v[0] if isinstance(v, list) else v)
52
+ break
53
+ except Exception as e:
54
+ logger.debug("[catalyst] calendar fetch %s: %s", symbol, e)
55
+
56
+ # 2. Recent analyst recommendations
57
+ try:
58
+ recs = ticker.recommendations
59
+ if recs is not None and not recs.empty:
60
+ recs = recs.sort_index(ascending=False)
61
+ recent_recs = recs.head(5)
62
+ rec_list = []
63
+ for ts, row in recent_recs.iterrows():
64
+ rec_list.append({
65
+ "date": str(ts)[:10],
66
+ "firm": str(row.get("Firm", row.get("firm", ""))),
67
+ "grade": str(row.get("To Grade", row.get("toGrade", row.get("action", "")))),
68
+ "prev": str(row.get("From Grade", row.get("fromGrade", ""))),
69
+ "action": str(row.get("Action", row.get("action", ""))),
70
+ })
71
+ catalysts["recommendations"] = rec_list
72
+ except Exception as e:
73
+ logger.debug("[catalyst] recs fetch %s: %s", symbol, e)
74
+
75
+ # 3. Upcoming dividend
76
+ try:
77
+ info = ticker.info or {}
78
+ ex_div = info.get("exDividendDate")
79
+ div_rate = info.get("dividendRate") or info.get("trailingAnnualDividendRate")
80
+ if ex_div:
81
+ from datetime import date
82
+ ex_date = datetime.fromtimestamp(ex_div, tz=timezone.utc).date()
83
+ days_to_exdiv = (ex_date - date.today()).days
84
+ catalysts["ex_dividend"] = {
85
+ "date": str(ex_date),
86
+ "days_away": days_to_exdiv,
87
+ "annual_rate": div_rate,
88
+ }
89
+ except Exception as e:
90
+ logger.debug("[catalyst] dividend fetch %s: %s", symbol, e)
91
+
92
+ # 4. Short interest (proxy for contrarian catalyst)
93
+ try:
94
+ info = ticker.info or {}
95
+ short_ratio = info.get("shortRatio")
96
+ short_pct = info.get("shortPercentOfFloat")
97
+ if short_ratio or short_pct:
98
+ catalysts["short_interest"] = {
99
+ "ratio": short_ratio,
100
+ "pct_float": short_pct,
101
+ }
102
+ except Exception as e:
103
+ logger.debug("[catalyst] short interest %s: %s", symbol, e)
104
+
105
+ except Exception as e:
106
+ logger.debug("[catalyst] yfinance init %s: %s", symbol, e)
107
+
108
+ data["catalysts"] = catalysts
109
+ return data
110
+
111
+ async def analyze(self, symbol: str, data: Dict[str, Any]) -> AgentResult:
112
+ catalysts = data.get("catalysts", {})
113
+ quote = data.get("quote", {})
114
+ price = quote.get("price", 0)
115
+
116
+ if not catalysts:
117
+ return AgentResult(
118
+ agent=self.name, symbol=symbol,
119
+ analysis=f"{symbol}: 未获取到催化剂数据。",
120
+ confidence=0.3, signal="HOLD",
121
+ key_points=["无近期催化剂数据"],
122
+ )
123
+
124
+ catalyst_block = _format_catalysts(catalysts)
125
+ urgency = _assess_urgency(catalysts)
126
+
127
+ prompt = (
128
+ f"Stock: {symbol} Price: {price}\n\n"
129
+ f"Catalysts:\n{catalyst_block}\n\n"
130
+ "Evaluate:\n"
131
+ "1. Most impactful upcoming catalyst and timing\n"
132
+ "2. Analyst sentiment trend (upgrades vs downgrades)\n"
133
+ "3. Event-driven trade setup (if any)\n"
134
+ "4. Risk of negative surprise\n"
135
+ "5. Conclude: POSITIVE / NEUTRAL / NEGATIVE"
136
+ )
137
+
138
+ analysis = await self._call_llm(self._SYSTEM, prompt, max_tokens=450)
139
+ if not analysis:
140
+ analysis = _template_analysis(symbol, catalysts, urgency)
141
+
142
+ signal, confidence = _derive_signal(analysis, catalysts, urgency)
143
+ key_points = _build_key_points(catalysts, urgency)
144
+
145
+ return AgentResult(
146
+ agent=self.name, symbol=symbol,
147
+ analysis=analysis,
148
+ confidence=confidence,
149
+ signal=signal,
150
+ key_points=key_points,
151
+ data_used=catalysts,
152
+ )
153
+
154
+
155
+ # ── Helpers ───────────────────────────────────────────────────────────────────
156
+
157
+ def _format_catalysts(c: Dict) -> str:
158
+ lines = []
159
+
160
+ if "earnings_date" in c:
161
+ ed = c["earnings_date"]
162
+ try:
163
+ ed_dt = datetime.fromisoformat(str(ed).split()[0])
164
+ days = (ed_dt.date() - datetime.today().date()).days
165
+ timing = f"({days}天后)" if days >= 0 else f"({-days}天前)"
166
+ except Exception:
167
+ timing = ""
168
+ lines.append(f"财报日: {ed}{timing}")
169
+
170
+ if "ex_dividend" in c:
171
+ d = c["ex_dividend"]
172
+ days_away = d.get("days_away", 999)
173
+ rate = d.get("annual_rate", "")
174
+ rate_str = f" 年化股息 {rate:.2f}" if rate else ""
175
+ lines.append(f"除息日: {d.get('date','')}({days_away}天后){rate_str}")
176
+
177
+ if "recommendations" in c:
178
+ for r in c["recommendations"][:3]:
179
+ action = r.get("action", "").upper()
180
+ firm = r.get("firm", "")
181
+ grade = r.get("grade", "")
182
+ prev = r.get("prev", "")
183
+ change = f"{prev} → {grade}" if prev and prev != grade else grade
184
+ lines.append(f"分析师评级: [{r.get('date','')}] {firm} {action} {change}")
185
+
186
+ if "short_interest" in c:
187
+ si = c["short_interest"]
188
+ ratio = si.get("ratio")
189
+ pct = si.get("pct_float")
190
+ parts = []
191
+ if ratio: parts.append(f"空头比率 {ratio:.1f}x")
192
+ if pct: parts.append(f"流通股空仓 {pct*100:.1f}%")
193
+ if parts: lines.append(f"空头数据: {', '.join(parts)}")
194
+
195
+ return "\n".join(lines) or "无催化剂数据"
196
+
197
+
198
+ def _assess_urgency(c: Dict) -> str:
199
+ if "earnings_date" in c:
200
+ try:
201
+ ed_dt = datetime.fromisoformat(str(c["earnings_date"]).split()[0])
202
+ days = (ed_dt.date() - datetime.today().date()).days
203
+ if 0 <= days <= 7:
204
+ return "high"
205
+ if 0 <= days <= 14:
206
+ return "medium"
207
+ except Exception:
208
+ pass
209
+ exdiv = c.get("ex_dividend", {})
210
+ if 0 <= exdiv.get("days_away", 999) <= 5:
211
+ return "high"
212
+ return "low"
213
+
214
+
215
+ def _derive_signal(analysis: str, c: Dict, urgency: str) -> tuple[str, float]:
216
+ text = analysis.upper()
217
+ recs = c.get("recommendations", [])
218
+ upgrades = sum(1 for r in recs if "UPGRAD" in r.get("action", "").upper())
219
+ downgrades = sum(1 for r in recs if "DOWNGRAD" in r.get("action", "").upper())
220
+
221
+ if "POSITIVE" in text:
222
+ conf = 0.65 if urgency == "high" else 0.55
223
+ return "BUY", conf
224
+ if "NEGATIVE" in text:
225
+ conf = 0.65 if urgency == "high" else 0.55
226
+ return "SELL", conf
227
+
228
+ if upgrades > downgrades:
229
+ return "BUY", 0.5
230
+ if downgrades > upgrades:
231
+ return "SELL", 0.5
232
+ return "HOLD", 0.4
233
+
234
+
235
+ def _build_key_points(c: Dict, urgency: str) -> List[str]:
236
+ points = []
237
+ if "earnings_date" in c:
238
+ try:
239
+ ed_dt = datetime.fromisoformat(str(c["earnings_date"]).split()[0])
240
+ days = (ed_dt.date() - datetime.today().date()).days
241
+ points.append(f"财报日在 {days} 天后" if days >= 0 else f"财报 {-days} 天前已公布")
242
+ except Exception:
243
+ points.append(f"财报日: {c['earnings_date']}")
244
+ if "ex_dividend" in c:
245
+ d = c["ex_dividend"]
246
+ points.append(f"除息日 {d.get('date','')}({d.get('days_away','')}天)")
247
+ recs = c.get("recommendations", [])
248
+ if recs:
249
+ latest = recs[0]
250
+ points.append(f"最新评级: {latest.get('firm','')} {latest.get('grade','')}")
251
+ if urgency == "high":
252
+ points.append("⚡ 高优先级催化剂(7天内)")
253
+ return points[:5]
254
+
255
+
256
+ def _template_analysis(symbol: str, c: Dict, urgency: str) -> str:
257
+ parts = []
258
+ if "earnings_date" in c:
259
+ try:
260
+ ed_dt = datetime.fromisoformat(str(c["earnings_date"]).split()[0])
261
+ days = (ed_dt.date() - datetime.today().date()).days
262
+ parts.append(f"财报日在 {days} 天{'后' if days >= 0 else '前'}")
263
+ except Exception:
264
+ parts.append(f"财报日: {c['earnings_date']}")
265
+ recs = c.get("recommendations", [])
266
+ upgrades = sum(1 for r in recs if "UPGRAD" in r.get("action", "").upper())
267
+ downgrades = sum(1 for r in recs if "DOWNGRAD" in r.get("action", "").upper())
268
+ if upgrades or downgrades:
269
+ parts.append(f"近期评级: {upgrades}次升级 / {downgrades}次降级")
270
+ if "ex_dividend" in c:
271
+ d = c["ex_dividend"]
272
+ parts.append(f"除息日: {d.get('date','')}({d.get('days_away','')}天)")
273
+
274
+ sentiment = "POSITIVE" if upgrades > downgrades else ("NEGATIVE" if downgrades > upgrades else "NEUTRAL")
275
+ return (
276
+ f"{symbol} 催化剂摘要:\n"
277
+ + "\n".join(f" • {p}" for p in parts)
278
+ + f"\n结论:{sentiment}"
279
+ )
@@ -0,0 +1,175 @@
1
+ """
2
+ agents/financial/corporate_finance.py — Corporate Finance & Financial Statement Diagnosis Agent
3
+ ==============================================================================================
4
+ Enterprise Financial Analysis Agent:
5
+ 1. Three-Statement Health Audit (P&L, Balance Sheet, Cash Flow)
6
+ 2. Dupont 3-Factor & 5-Factor Decomposition (Profitability, Efficiency, Leverage)
7
+ 3. Working Capital & Cash Conversion Cycle (DSO, DIO, DPO, CCC)
8
+ 4. Solvency, Liquidity & Altman Z-Score Health Evaluation
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import json
14
+ import logging
15
+ from typing import Any, Callable, Dict, List, Optional
16
+
17
+ from ..base import BaseAgent, AgentResult
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+
22
+ class CorporateFinanceAgent(BaseAgent):
23
+ name = "corporate_finance"
24
+ description = "企业财务报表体检智能体 — 负责三张表联动诊断、杜邦分析拆解与营运资本效率分析"
25
+
26
+ def __init__(
27
+ self,
28
+ llm_provider=None,
29
+ data_router=None,
30
+ on_token: Optional[Callable[[str], None]] = None,
31
+ on_thought: Optional[Callable[[str], None]] = None,
32
+ on_tool_start: Optional[Callable[[str, Dict], None]] = None,
33
+ on_tool_end: Optional[Callable[[str, Any], None]] = None,
34
+ lang: str = "zh",
35
+ ) -> None:
36
+ super().__init__(
37
+ llm_provider=llm_provider,
38
+ data_router=data_router,
39
+ on_token=on_token,
40
+ on_thought=on_thought,
41
+ on_tool_start=on_tool_start,
42
+ on_tool_end=on_tool_end,
43
+ lang=lang,
44
+ )
45
+
46
+ async def analyze(self, symbol: str, data: Dict[str, Any]) -> AgentResult:
47
+ """
48
+ Analyze enterprise financial statements.
49
+ """
50
+ company_name = symbol or data.get("company_name", "Enterprise")
51
+ income_raw = data.get("income_statement", {})
52
+ balance_raw = data.get("balance_sheet", {})
53
+ cashflow_raw = data.get("cashflow", {})
54
+
55
+ from aria_code.packages.aria_tools.financial._paths import ensure_arthera_root
56
+ ensure_arthera_root()
57
+
58
+ # Try to use Arthera CorporateFinanceService
59
+ try:
60
+ from packages.contracts.corporate_finance_models import (
61
+ BalanceSheetData,
62
+ CashflowData,
63
+ IncomeStatementData,
64
+ )
65
+ from packages.quant_engine.services.corporate_finance_service import CorporateFinanceService
66
+
67
+ service = CorporateFinanceService()
68
+ income = IncomeStatementData(
69
+ period=income_raw.get("period", "Current-FY"),
70
+ revenue=float(income_raw.get("revenue", 10000000.0)),
71
+ cost_of_goods_sold=float(income_raw.get("cost_of_goods_sold", income_raw.get("cogs", 6000000.0))),
72
+ gross_profit=float(income_raw.get("gross_profit", 0.0)),
73
+ operating_expenses=float(income_raw.get("operating_expenses", income_raw.get("opex", 2000000.0))),
74
+ operating_income=float(income_raw.get("operating_income", 0.0)),
75
+ net_income=float(income_raw.get("net_income", 1600000.0)),
76
+ )
77
+ balance = BalanceSheetData(
78
+ period=balance_raw.get("period", "Current-FY"),
79
+ cash_and_equivalents=float(balance_raw.get("cash_and_equivalents", balance_raw.get("cash", 3000000.0))),
80
+ accounts_receivable=float(balance_raw.get("accounts_receivable", balance_raw.get("ar", 1500000.0))),
81
+ inventory=float(balance_raw.get("inventory", 1000000.0)),
82
+ current_assets=float(balance_raw.get("current_assets", 0.0)),
83
+ total_assets=float(balance_raw.get("total_assets", 0.0)),
84
+ accounts_payable=float(balance_raw.get("accounts_payable", balance_raw.get("ap", 800000.0))),
85
+ current_liabilities=float(balance_raw.get("current_liabilities", 0.0)),
86
+ total_liabilities=float(balance_raw.get("total_liabilities", 0.0)),
87
+ total_equity=float(balance_raw.get("total_equity", 0.0)),
88
+ )
89
+ cashflow = CashflowData(
90
+ period=cashflow_raw.get("period", "Current-FY"),
91
+ operating_cash_flow=float(cashflow_raw.get("operating_cash_flow", cashflow_raw.get("ocf", 1800000.0))),
92
+ capital_expenditures=float(cashflow_raw.get("capital_expenditures", cashflow_raw.get("capex", 500000.0))),
93
+ free_cash_flow=float(cashflow_raw.get("free_cash_flow", 0.0)),
94
+ )
95
+
96
+ diag = service.analyze_company_financials(company_name, income, balance, cashflow)
97
+ diag_dict = diag.to_dict()
98
+
99
+ except Exception as exc:
100
+ logger.debug(f"Arthera finance service not imported, using local fallback: {exc}")
101
+ diag_dict = self._local_fallback(company_name, income_raw, balance_raw, cashflow_raw)
102
+
103
+ dupont = diag_dict.get("dupont", {})
104
+ wc = diag_dict.get("working_capital", {})
105
+ gross_m = diag_dict.get("gross_margin_pct", 0.0)
106
+ net_m = diag_dict.get("net_margin_pct", 0.0)
107
+ z_score = diag_dict.get("altman_z_score", 3.0)
108
+ solvency = diag_dict.get("solvency_risk", "SAFE")
109
+ strengths = diag_dict.get("key_strengths", [])
110
+ risks = diag_dict.get("key_risks", [])
111
+ recs = diag_dict.get("strategic_recommendations", [])
112
+
113
+ analysis_text = (
114
+ f"### 📑 企业财务报表体检诊断报告: {company_name}\n\n"
115
+ f"• **盈利能力指标**: 毛利率 `{gross_m}%` | 净利率 `{net_m}%` | 杜邦 ROE `{dupont.get('roe', 0)}%`\n"
116
+ f"• **营运资本周转**: 现金周转周期(CCC) `{wc.get('cash_conversion_cycle_days', 0)}` 天 (DSO: `{wc.get('dso_days', 0)}`d, DIO: `{wc.get('dio_days', 0)}`d, DPO: `{wc.get('dpo_days', 0)}`d)\n"
117
+ f"• **偿债与流动性**: 流动比率 `{wc.get('current_ratio', 1.0)}x` | 速动比率 `{wc.get('quick_ratio', 1.0)}x` | Altman Z-Score `{z_score}` ({solvency})\n\n"
118
+ f"**💡 财务核心优势**:\n"
119
+ + ("\n".join(f"- {s}" for s in strengths) if strengths else "- 财务基本面稳健。")
120
+ + "\n\n"
121
+ f"**⚠️ 潜在风险点**:\n"
122
+ + ("\n".join(f"- {r}" for r in risks) if risks else "- 无重大财务结构异常。")
123
+ + "\n\n"
124
+ f"**🎯 经营与财资建议**:\n"
125
+ + ("\n".join(f"- {rc}" for rc in recs) if recs else "- 维持当前营运资本节奏。")
126
+ )
127
+
128
+ signal = "STRONG_BUY" if solvency == "SAFE" and dupont.get("roe", 0) > 15.0 else ("HOLD" if solvency == "GREY_ZONE" else "BUY")
129
+
130
+ return AgentResult(
131
+ agent=self.name,
132
+ symbol=company_name,
133
+ analysis=analysis_text,
134
+ confidence=0.94,
135
+ signal=signal,
136
+ key_points=[
137
+ f"ROE: {dupont.get('roe', 0)}% (Net Margin {net_m}%)",
138
+ f"CCC: {wc.get('cash_conversion_cycle_days', 0)} days",
139
+ f"Solvency Status: {solvency} (Z-Score {z_score})",
140
+ ],
141
+ data_used=diag_dict,
142
+ provenance=["dupont-decomposition", "working-capital-engine", "solvency-z-score"],
143
+ )
144
+
145
+ def _local_fallback(self, company_name, income, balance, cashflow) -> Dict[str, Any]:
146
+ rev = float(income.get("revenue", 10000000.0))
147
+ cogs = float(income.get("cost_of_goods_sold", income.get("cogs", 6000000.0)))
148
+ net = float(income.get("net_income", 1500000.0))
149
+ assets = float(balance.get("total_assets", 8000000.0))
150
+ equity = float(balance.get("total_equity", 5000000.0))
151
+ gross = max(0.0, rev - cogs)
152
+ return {
153
+ "company_name": company_name,
154
+ "gross_margin_pct": round((gross / max(1.0, rev)) * 100.0, 1),
155
+ "net_margin_pct": round((net / max(1.0, rev)) * 100.0, 1),
156
+ "dupont": {
157
+ "roe": round((net / max(1.0, equity)) * 100.0, 1),
158
+ "net_profit_margin": round((net / max(1.0, rev)) * 100.0, 1),
159
+ "asset_turnover": round(rev / max(1.0, assets), 2),
160
+ "equity_multiplier": round(assets / max(1.0, equity), 2),
161
+ },
162
+ "working_capital": {
163
+ "dso_days": 45.0,
164
+ "dio_days": 60.0,
165
+ "dpo_days": 35.0,
166
+ "cash_conversion_cycle_days": 70.0,
167
+ "current_ratio": 2.1,
168
+ "quick_ratio": 1.5,
169
+ },
170
+ "altman_z_score": 3.2,
171
+ "solvency_risk": "SAFE",
172
+ "key_strengths": ["毛利稳定", "流动性充足"],
173
+ "key_risks": [],
174
+ "strategic_recommendations": ["保持健康的营运资金周转"],
175
+ }
@@ -0,0 +1,224 @@
1
+ """
2
+ agents/financial/debate.py — 信号争议调解 Agent
3
+ ================================================
4
+ 当多个 Agent 出现真实分歧(看涨 vs 看跌)时,
5
+ DebateAgent 作为"裁判"对冲突进行分析,输出综合判断。
6
+ 不独立运行,由 AgentTeam 在检测到分歧时自动触发。
7
+
8
+ 2026-08 领域词汇修正:这个 agent 原本把金融的 BUY/HOLD/SELL 硬编码在
9
+ system prompt、信号解析和模板兜底里,但 AgentTeam 对**所有**领域都会在
10
+ 信号冲突时触发它——实测跑 warehouse 团队(GOOD/WATCH/CONCERN/SEVERE)
11
+ 时,它往结果里塞了一个 "HOLD",正是 signal_scheme.py 开头警告过的那种
12
+ "借用金融词汇表达完全不同含义"。表决层没被污染(SignalScheme.vote()
13
+ 会过滤掉不在本领域词表里的信号),但报告界面上会多出一张语义不搭的卡片,
14
+ 而且裁判意见实际上没参与最终结论 —— 等于白跑一趟。
15
+
16
+ 现在 team.py 会把当前领域的 SignalScheme 通过 data["signal_scheme"]
17
+ 传进来,本文件所有词汇都从 scheme 里取。不传时默认 FINANCIAL_SCHEME,
18
+ 所以单独调用 DebateAgent 的既有金融调用方行为完全不变。
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import logging
24
+ from typing import Any, Dict, List
25
+
26
+ from ..base import BaseAgent, AgentResult
27
+ from ..signal_scheme import FINANCIAL_SCHEME, SignalScheme
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+
32
+ class DebateAgent(BaseAgent):
33
+
34
+ name = "debate"
35
+ description = "信号争议调解 — 当多 Agent 信号冲突时自动触发,输出裁判视角"
36
+
37
+ _SYSTEM_FINANCIAL = (
38
+ "You are a senior investment committee chair mediating a dispute between "
39
+ "analysts who have conflicting views on a stock. Your role is to:\n"
40
+ "1. Identify the core disagreement\n"
41
+ "2. Evaluate which side has stronger evidence\n"
42
+ "3. Determine the dominant factor (macro vs technical vs fundamental)\n"
43
+ "4. Provide a nuanced resolution that acknowledges both sides\n"
44
+ "5. Conclude with a clear signal: {vocabulary} and the primary reason\n"
45
+ "Be direct. Avoid empty hedging. Make a call."
46
+ )
47
+
48
+ _SYSTEM_GENERIC = (
49
+ "You are the senior reviewer mediating a dispute between specialist "
50
+ "analysts who reached conflicting conclusions about the same subject. "
51
+ "Your role is to:\n"
52
+ "1. Identify the core disagreement\n"
53
+ "2. Evaluate which side has stronger evidence\n"
54
+ "3. Determine which dimension dominates the overall assessment\n"
55
+ "4. Provide a nuanced resolution that acknowledges both sides\n"
56
+ "5. Conclude with a clear signal: {vocabulary} and the primary reason\n"
57
+ "Be direct. Avoid empty hedging. Make a call."
58
+ )
59
+
60
+ def _system_prompt(self, scheme: SignalScheme) -> str:
61
+ # 只有金融领域保留"投资委员会主席"这个具体身份设定;其它领域用中性
62
+ # 措辞——让仓储/地产的裁判自称投资委员会主席,会把 LLM 往错误的
63
+ # 推理框架上带(比如去权衡"要不要建仓"而不是"这个仓库健不健康")。
64
+ template = self._SYSTEM_FINANCIAL if scheme.name == "financial" else self._SYSTEM_GENERIC
65
+ return template.format(vocabulary=" / ".join(_ranked_vocabulary(scheme)))
66
+
67
+ async def fetch_data(self, symbol: str) -> Dict[str, Any]:
68
+ return await super().fetch_data(symbol)
69
+
70
+ async def analyze(self, symbol: str, data: Dict[str, Any]) -> AgentResult:
71
+ conflicting: List[Dict] = data.get("conflicting", [])
72
+ scheme: SignalScheme = data.get("signal_scheme") or FINANCIAL_SCHEME
73
+
74
+ if not conflicting:
75
+ return AgentResult(
76
+ agent=self.name, symbol=symbol,
77
+ analysis="无冲突结果可调解。",
78
+ confidence=0.3, signal=scheme.neutral_default,
79
+ key_points=["无需调解"],
80
+ )
81
+
82
+ debate_block = _format_conflict(conflicting, scheme)
83
+ vocabulary = " / ".join(_ranked_vocabulary(scheme))
84
+ subject_line = f"Stock: {symbol}" if scheme.name == "financial" else f"Subject: {symbol}"
85
+ dominant_q = (
86
+ "What is the dominant factor driving the stock right now? "
87
+ if scheme.name == "financial"
88
+ else "Which dimension dominates the overall assessment right now? "
89
+ )
90
+
91
+ prompt = (
92
+ f"{subject_line}\n\n"
93
+ f"Conflicting Analyst Views:\n{debate_block}\n\n"
94
+ "Mediate this dispute. Which view is more compelling and why? "
95
+ f"{dominant_q}"
96
+ f"End with: Signal: {vocabulary} — [primary reason in one line]"
97
+ )
98
+
99
+ analysis = await self._call_llm(self._system_prompt(scheme), prompt, max_tokens=600)
100
+ if not analysis:
101
+ analysis = _template_resolution(symbol, conflicting, scheme)
102
+
103
+ signal = _extract_signal(analysis, scheme)
104
+ confidence = _estimate_confidence(conflicting)
105
+ key_points = _build_key_points(conflicting, analysis, scheme)
106
+
107
+ return AgentResult(
108
+ agent=self.name, symbol=symbol,
109
+ analysis=analysis,
110
+ confidence=confidence,
111
+ signal=signal,
112
+ key_points=key_points,
113
+ data_used={"conflict_count": len(conflicting)},
114
+ )
115
+
116
+
117
+ # ── Helpers ───────────────────────────────────────────────────────────────────
118
+
119
+ def _ranked_vocabulary(scheme: SignalScheme) -> List[str]:
120
+ """按分数从高到低列出该领域的信号词,供 prompt 展示。"""
121
+ return [name for name, _ in sorted(scheme.scores.items(), key=lambda kv: -kv[1])]
122
+
123
+
124
+ def _format_conflict(results: List[Dict], scheme: SignalScheme = FINANCIAL_SCHEME) -> str:
125
+ lines = []
126
+ for r in results:
127
+ agent = r.get("agent", "unknown")
128
+ signal = r.get("signal", scheme.neutral_default)
129
+ conf = r.get("confidence", 0)
130
+ pts = r.get("key_points", [])
131
+ summary = "; ".join(pts[:3]) if pts else r.get("analysis", "")[:150]
132
+ lines.append(
133
+ f" [{agent.upper()}] Signal: {signal} (conf {conf:.0%})\n"
134
+ f" Key points: {summary}"
135
+ )
136
+ return "\n".join(lines)
137
+
138
+
139
+ def _extract_signal(analysis: str, scheme: SignalScheme = FINANCIAL_SCHEME) -> str:
140
+ """从裁判文本里解析出本领域词汇表中的信号。
141
+
142
+ 长词优先匹配(STRONG_BUY 必须排在 BUY 前面,否则 "STRONG_BUY" 会被
143
+ "BUY" 的前缀判定抢先命中;这是原实现手写四个 if 的顺序想表达的意思,
144
+ 改成按长度排序后对任意领域词汇表都成立,不用每加一个领域重写一遍)。
145
+ """
146
+ text = analysis.upper()
147
+ vocabulary = sorted(scheme.scores, key=len, reverse=True)
148
+
149
+ for marker in ("SIGNAL: ", "SIGNAL:", "CONCLUSION:", "CONCLUSION: "):
150
+ idx = text.find(marker)
151
+ if idx != -1:
152
+ remainder = text[idx + len(marker):].strip()
153
+ for name in vocabulary:
154
+ if remainder.startswith(name.upper()):
155
+ return name
156
+
157
+ # 没有显式 marker 时的兜底:只在文本里恰好出现一个方向的词汇时才采信,
158
+ # 出现多个方向说明裁判没给出明确结论,退回中性值而不是猜。
159
+ positives = [s for s in scheme.positive_signals if s.upper() in text]
160
+ negatives = [s for s in scheme.negative_signals if s.upper() in text]
161
+ if positives and not negatives:
162
+ return max(positives, key=lambda s: scheme.scores.get(s, 0))
163
+ if negatives and not positives:
164
+ return min(negatives, key=lambda s: scheme.scores.get(s, 0))
165
+ return scheme.neutral_default
166
+
167
+
168
+ def _estimate_confidence(results: List[Dict]) -> float:
169
+ if not results:
170
+ return 0.4
171
+ confs = [r.get("confidence", 0.5) for r in results if r.get("confidence")]
172
+ avg = sum(confs) / len(confs) if confs else 0.5
173
+ return round(min(avg * 0.9, 0.75), 2)
174
+
175
+
176
+ def _side_labels(scheme: SignalScheme) -> tuple[str, str]:
177
+ """(正面阵营, 负面阵营) 的中文标签。金融叫多空,其它领域这么叫没有意义
178
+ ——仓储团队里没有"看跌方",只有"报告健康"和"报告有问题"的两拨 agent。"""
179
+ if scheme.name == "financial":
180
+ return "看涨方", "看跌方"
181
+ return "正面评估", "负面评估"
182
+
183
+
184
+ def _split_sides(results: List[Dict], scheme: SignalScheme) -> tuple[List[Dict], List[Dict]]:
185
+ positive = [r for r in results if r.get("signal") in scheme.positive_signals]
186
+ negative = [r for r in results if r.get("signal") in scheme.negative_signals]
187
+ return positive, negative
188
+
189
+
190
+ def _build_key_points(
191
+ results: List[Dict], analysis: str, scheme: SignalScheme = FINANCIAL_SCHEME
192
+ ) -> List[str]:
193
+ positive, negative = _split_sides(results, scheme)
194
+ pos_label, neg_label = _side_labels(scheme)
195
+ points = []
196
+ if positive:
197
+ points.append(f"{pos_label}: {', '.join(r['agent'] for r in positive)}")
198
+ if negative:
199
+ points.append(f"{neg_label}: {', '.join(r['agent'] for r in negative)}")
200
+ points.append("DebateAgent 已介入调解")
201
+ points.append(f"裁判结论: {_extract_signal(analysis, scheme)}")
202
+ return points
203
+
204
+
205
+ def _template_resolution(
206
+ symbol: str, results: List[Dict], scheme: SignalScheme = FINANCIAL_SCHEME
207
+ ) -> str:
208
+ positive, negative = _split_sides(results, scheme)
209
+ pos_label, neg_label = _side_labels(scheme)
210
+
211
+ best = max(scheme.scores, key=lambda s: scheme.scores[s])
212
+ worst = min(scheme.scores, key=lambda s: scheme.scores[s])
213
+ if len(positive) > len(negative):
214
+ resolution = f"{best} — 多数{pos_label}信号占优"
215
+ elif len(negative) > len(positive):
216
+ resolution = f"{worst} — 多数{neg_label}信号占优"
217
+ else:
218
+ resolution = f"{scheme.neutral_default} — 双方力量均衡,建议观望"
219
+ return (
220
+ f"{symbol} 信号冲突调解报告\n"
221
+ f"{pos_label}: {', '.join(r['agent'] for r in positive) or '无'}\n"
222
+ f"{neg_label}: {', '.join(r['agent'] for r in negative) or '无'}\n"
223
+ f"裁判结论: Signal: {resolution}"
224
+ )