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,315 @@
1
+ """
2
+ agents/financial/earnings.py — 财报解读 Agent
3
+ =============================================
4
+ 分析最近一期财报:EPS/营收 beat or miss、同比/环比变化、
5
+ 指引调整及市场反应。在财报发布后 5 天内尤为有效。
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import logging
11
+ from datetime import datetime, timedelta
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 EarningsAgent(BaseAgent):
20
+
21
+ name = "earnings"
22
+ description = "财报解读 — EPS/营收 beat or miss、同比增速、指引变化"
23
+
24
+ _SYSTEM = (
25
+ "You are a financial analyst specializing in earnings analysis. "
26
+ "Evaluate the most recent quarterly earnings report:\n"
27
+ "1. Was it a beat or miss on EPS and revenue?\n"
28
+ "2. How does this compare to prior quarters (trend)?\n"
29
+ "3. Was guidance raised, lowered, or maintained?\n"
30
+ "4. What is the market likely to do with this information?\n"
31
+ "5. Conclude: STRONG_BEAT / BEAT / IN_LINE / MISS / STRONG_MISS\n"
32
+ "Map to signal: BEAT/STRONG_BEAT→BUY, IN_LINE→HOLD, MISS/STRONG_MISS→SELL"
33
+ )
34
+
35
+ async def fetch_data(self, symbol: str) -> Dict[str, Any]:
36
+ data = await super().fetch_data(symbol)
37
+ earnings: Dict[str, Any] = {}
38
+
39
+ try:
40
+ import yfinance as yf
41
+ ticker = yf.Ticker(symbol)
42
+
43
+ # 1. Quarterly earnings history
44
+ try:
45
+ qe = ticker.quarterly_earnings
46
+ if qe is not None and not qe.empty:
47
+ rows = []
48
+ for ts, row in qe.sort_index(ascending=False).head(4).iterrows():
49
+ rows.append({
50
+ "period": str(ts)[:10],
51
+ "actual_eps": _safe_float(row.get("Earnings")),
52
+ "est_eps": _safe_float(row.get("Estimate", row.get("EPS Estimate"))),
53
+ "revenue": _safe_float(row.get("Revenue")),
54
+ "rev_estimate": _safe_float(row.get("Revenue Estimate")),
55
+ })
56
+ earnings["quarterly_eps"] = rows
57
+ except Exception as e:
58
+ logger.debug("[earnings] quarterly_earnings %s: %s", symbol, e)
59
+
60
+ # 2. Earnings dates
61
+ try:
62
+ ed = ticker.earnings_dates
63
+ if ed is not None and not ed.empty:
64
+ recent = ed.sort_index(ascending=False).head(2)
65
+ dates = []
66
+ for ts, row in recent.iterrows():
67
+ reported_eps = _safe_float(row.get("Reported EPS", row.get("EPS")))
68
+ est_eps = _safe_float(row.get("EPS Estimate"))
69
+ if reported_eps is not None:
70
+ beat = reported_eps - est_eps if est_eps is not None else None
71
+ dates.append({
72
+ "date": str(ts)[:10],
73
+ "reported_eps": reported_eps,
74
+ "estimated_eps": est_eps,
75
+ "beat_by": round(beat, 4) if beat is not None else None,
76
+ "pct_surprise": round(beat / abs(est_eps) * 100, 1)
77
+ if (beat is not None and est_eps and est_eps != 0) else None,
78
+ })
79
+ earnings["recent_reports"] = dates
80
+ except Exception as e:
81
+ logger.debug("[earnings] earnings_dates %s: %s", symbol, e)
82
+
83
+ # 3. Revenue trend (quarterly income)
84
+ try:
85
+ qs = ticker.quarterly_financials
86
+ if qs is not None and not qs.empty:
87
+ rev_row = None
88
+ for label in ("Total Revenue", "Revenue", "Net Revenue"):
89
+ if label in qs.index:
90
+ rev_row = qs.loc[label]
91
+ break
92
+ if rev_row is not None:
93
+ revs = []
94
+ for ts, val in rev_row.sort_index(ascending=False).head(4).items():
95
+ revs.append({"period": str(ts)[:10], "revenue": _safe_float(val)})
96
+ earnings["revenue_trend"] = revs
97
+ except Exception as e:
98
+ logger.debug("[earnings] quarterly_financials %s: %s", symbol, e)
99
+
100
+ # 4. Stock price reaction (compare price before/after earnings)
101
+ try:
102
+ recent = earnings.get("recent_reports", [])
103
+ if recent:
104
+ from datetime import date
105
+ report_date_str = recent[0].get("date", "")
106
+ if report_date_str:
107
+ hist = ticker.history(start=report_date_str, period="5d")
108
+ if not hist.empty and len(hist) >= 2:
109
+ open_price = float(hist["Open"].iloc[0])
110
+ close_price = float(hist["Close"].iloc[-1])
111
+ earnings["price_reaction_pct"] = round(
112
+ (close_price - open_price) / open_price * 100, 2
113
+ )
114
+ except Exception as e:
115
+ logger.debug("[earnings] price_reaction %s: %s", symbol, e)
116
+
117
+ except Exception as e:
118
+ logger.debug("[earnings] yfinance init %s: %s", symbol, e)
119
+
120
+ data["earnings"] = earnings
121
+ return data
122
+
123
+ async def analyze(self, symbol: str, data: Dict[str, Any]) -> AgentResult:
124
+ earnings = data.get("earnings", {})
125
+ quote = data.get("quote", {})
126
+ price = quote.get("price", 0)
127
+
128
+ if not earnings:
129
+ return AgentResult(
130
+ agent=self.name, symbol=symbol,
131
+ analysis=(f"{symbol}: 未获取到财报数据。" if str(self.lang).startswith("zh")
132
+ else f"{symbol}: no earnings data."),
133
+ confidence=0.3, signal="HOLD",
134
+ key_points=["无财报数据" if str(self.lang).startswith("zh") else "no earnings data"],
135
+ )
136
+
137
+ earnings_block = _format_earnings(earnings)
138
+ most_recent = earnings.get("recent_reports", [{}])[0] if earnings.get("recent_reports") else {}
139
+ beat_miss_summary = _assess_beat_miss(most_recent, earnings)
140
+
141
+ prompt = (
142
+ f"Stock: {symbol} Price: {price}\n\n"
143
+ f"Earnings Data:\n{earnings_block}\n\n"
144
+ f"Initial Assessment: {beat_miss_summary}\n\n"
145
+ "Provide detailed earnings analysis:\n"
146
+ "1. Most recent quarter: beat or miss? By how much?\n"
147
+ "2. Revenue & EPS trend direction (improving / deteriorating / stable)\n"
148
+ "3. Likely market interpretation\n"
149
+ "4. Conclude: STRONG_BEAT / BEAT / IN_LINE / MISS / STRONG_MISS"
150
+ )
151
+
152
+ analysis = await self._call_llm(self._SYSTEM, prompt, max_tokens=500)
153
+ if not analysis:
154
+ analysis = _template_analysis(symbol, earnings, most_recent, beat_miss_summary, lang=self.lang)
155
+
156
+ signal, confidence = _derive_signal(analysis, most_recent, earnings)
157
+ key_points = _build_key_points(earnings, most_recent, signal, lang=self.lang)
158
+
159
+ return AgentResult(
160
+ agent=self.name, symbol=symbol,
161
+ analysis=analysis,
162
+ confidence=confidence,
163
+ signal=signal,
164
+ key_points=key_points,
165
+ data_used={
166
+ "beat_miss": beat_miss_summary,
167
+ "pct_surprise": most_recent.get("pct_surprise"),
168
+ "price_reaction_pct": earnings.get("price_reaction_pct"),
169
+ },
170
+ )
171
+
172
+
173
+ # ── Helpers ───────────────────────────────────────────────────────────────────
174
+
175
+ def _safe_float(val) -> Optional[float]:
176
+ try:
177
+ v = float(val)
178
+ return None if (v != v) else v # NaN check
179
+ except (TypeError, ValueError):
180
+ return None
181
+
182
+
183
+ def _format_earnings(e: Dict) -> str:
184
+ lines = []
185
+ recent = e.get("recent_reports", [])
186
+ if recent:
187
+ lines.append("Recent Reports:")
188
+ for r in recent[:2]:
189
+ act = r.get("reported_eps")
190
+ est = r.get("estimated_eps")
191
+ sup = r.get("pct_surprise")
192
+ lines.append(
193
+ f" {r.get('date','')} EPS: actual {act} est {est} "
194
+ f"surprise {sup:+.1f}%" if sup else
195
+ f" {r.get('date','')} EPS: actual {act} est {est}"
196
+ )
197
+
198
+ rx = e.get("price_reaction_pct")
199
+ if rx is not None:
200
+ lines.append(f"Post-earnings price reaction: {rx:+.1f}%")
201
+
202
+ qt = e.get("quarterly_eps", [])
203
+ if qt:
204
+ lines.append("Quarterly EPS (last 4):")
205
+ for q in qt[:4]:
206
+ ep = q.get("actual_eps")
207
+ lines.append(f" {q.get('period','')} EPS: {ep}")
208
+
209
+ rev = e.get("revenue_trend", [])
210
+ if rev:
211
+ lines.append("Revenue Trend (last 4 quarters):")
212
+ prev = None
213
+ for r in rev[:4]:
214
+ rv = r.get("revenue")
215
+ growth = ""
216
+ if rv and prev:
217
+ g = (rv - prev) / abs(prev) * 100
218
+ growth = f" {g:+.1f}% QoQ"
219
+ lines.append(f" {r.get('period','')} {_fmt_num(rv)}{growth}")
220
+ prev = rv
221
+
222
+ return "\n".join(lines) or "无财报数据"
223
+
224
+
225
+ def _fmt_num(v) -> str:
226
+ if v is None: return "N/A"
227
+ if abs(v) >= 1e9: return f"${v/1e9:.2f}B"
228
+ if abs(v) >= 1e6: return f"${v/1e6:.1f}M"
229
+ return f"{v:.4f}"
230
+
231
+
232
+ def _assess_beat_miss(most_recent: Dict, earnings: Dict) -> str:
233
+ sup = most_recent.get("pct_surprise")
234
+ if sup is None:
235
+ return "无充分数据判断"
236
+ if sup >= 10: return f"大幅超预期 +{sup:.1f}%"
237
+ if sup >= 3: return f"超预期 +{sup:.1f}%"
238
+ if sup >= -3: return f"基本符合预期 {sup:+.1f}%"
239
+ if sup >= -10: return f"略低预期 {sup:.1f}%"
240
+ return f"大幅低于预期 {sup:.1f}%"
241
+
242
+
243
+ def _derive_signal(analysis: str, most_recent: Dict, earnings: Dict) -> tuple[str, float]:
244
+ text = analysis.upper()
245
+ sup = most_recent.get("pct_surprise")
246
+ rx = earnings.get("price_reaction_pct")
247
+
248
+ if "STRONG_BEAT" in text:
249
+ return "BUY", 0.75
250
+ if "STRONG_MISS" in text:
251
+ return "SELL", 0.75
252
+ if "BEAT" in text and "MISS" not in text:
253
+ conf = 0.65 if (rx and rx > 2) else 0.55
254
+ return "BUY", conf
255
+ if "MISS" in text and "BEAT" not in text:
256
+ conf = 0.65 if (rx and rx < -2) else 0.55
257
+ return "SELL", conf
258
+
259
+ # Fallback to raw surprise
260
+ if sup is not None:
261
+ if sup >= 10: return "BUY", 0.70
262
+ if sup >= 3: return "BUY", 0.55
263
+ if sup <= -10: return "SELL", 0.70
264
+ if sup <= -3: return "SELL", 0.55
265
+
266
+ return "HOLD", 0.40
267
+
268
+
269
+ def _build_key_points(earnings: Dict, most_recent: Dict, signal: str, lang: str = "zh") -> List[str]:
270
+ zh = str(lang).lower().startswith("zh")
271
+ pts = []
272
+ sup = most_recent.get("pct_surprise")
273
+ if sup is not None:
274
+ if zh:
275
+ pts.append(f"EPS 超预期 {sup:+.1f}%" if sup >= 0 else f"EPS 低于预期 {sup:.1f}%")
276
+ else:
277
+ pts.append(f"EPS beat by {sup:+.1f}%" if sup >= 0 else f"EPS missed by {sup:.1f}%")
278
+ rx = earnings.get("price_reaction_pct")
279
+ if rx is not None:
280
+ pts.append(f"财报后股价反应: {rx:+.1f}%" if zh else f"post-earnings move {rx:+.1f}%")
281
+ rev = earnings.get("revenue_trend", [])
282
+ if len(rev) >= 2:
283
+ v0 = rev[0].get("revenue")
284
+ v1 = rev[1].get("revenue")
285
+ if v0 and v1:
286
+ qoq = (v0 - v1) / abs(v1) * 100
287
+ pts.append(f"营收环比 {qoq:+.1f}%" if zh else f"revenue {qoq:+.1f}% q/q")
288
+ pts.append(f"财报信号: {signal}" if zh else f"earnings signal: {signal}")
289
+ return pts[:5]
290
+
291
+
292
+ def _template_analysis(symbol: str, earnings: Dict, most_recent: Dict, summary: str, lang: str = "zh") -> str:
293
+ sup = most_recent.get("pct_surprise")
294
+ if sup is not None:
295
+ if sup >= 10: verdict = "STRONG_BEAT"
296
+ elif sup >= 3: verdict = "BEAT"
297
+ elif sup >= -3: verdict = "IN_LINE"
298
+ elif sup >= -10:verdict = "MISS"
299
+ else: verdict = "STRONG_MISS"
300
+ else:
301
+ verdict = "IN_LINE"
302
+
303
+ if not str(lang).lower().startswith("zh"):
304
+ return (
305
+ f"{symbol} earnings (template):\n"
306
+ f"First read: {summary}\n"
307
+ f"Rating: {verdict}\n"
308
+ f"Suggested signal: {'BUY' if 'BEAT' in verdict else ('SELL' if 'MISS' in verdict else 'HOLD')}"
309
+ )
310
+ return (
311
+ f"{symbol} 财报解读(模板):\n"
312
+ f"初步判断:{summary}\n"
313
+ f"财报评级:{verdict}\n"
314
+ f"建议信号:{'BUY' if 'BEAT' in verdict else ('SELL' if 'MISS' in verdict else 'HOLD')}"
315
+ )
@@ -0,0 +1,178 @@
1
+ """
2
+ agents/financial/fundamental.py — 基本面分析 Agent
3
+ ====================================================
4
+ 分析:PE/PB/ROE、营收增速、竞争壁垒、估值水位。
5
+ """
6
+ from __future__ import annotations
7
+ from typing import Any, Dict, List, Optional
8
+ from ..base import BaseAgent, AgentResult
9
+
10
+
11
+ class FundamentalAgent(BaseAgent):
12
+ name = "fundamental"
13
+ description = "基本面分析:估值/ROE/竞争优势/财务健康"
14
+
15
+ _SYSTEM = (
16
+ "You are a fundamental equity analyst. Evaluate: PE/PB valuation levels "
17
+ "(vs historical range and sector peers), ROE quality, revenue growth, "
18
+ "balance sheet health, and competitive moat. "
19
+ "Be data-driven. End with: UNDERVALUED / FAIRLY_VALUED / OVERVALUED."
20
+ )
21
+
22
+ async def fetch_data(self, symbol: str) -> Dict[str, Any]:
23
+ data = await super().fetch_data(symbol)
24
+ if self.data:
25
+ try:
26
+ f = self.data.fundamentals(symbol)
27
+ if f:
28
+ data["fundamentals"] = {
29
+ "pe_ttm": f.pe_ttm,
30
+ "pb": f.pb,
31
+ "roe": f.roe,
32
+ "revenue_growth": f.revenue_growth,
33
+ "dividend_yield": f.dividend_yield,
34
+ "source": f.source,
35
+ }
36
+ except Exception:
37
+ pass
38
+ return data
39
+
40
+ async def analyze(self, symbol: str, data: Dict[str, Any]) -> AgentResult:
41
+ quote = data.get("quote", {})
42
+ fund = data.get("fundamentals", {})
43
+ price = _num_or_none(quote.get("price"))
44
+ # Accept both schemas: the agent's own fetch_data (pe_ttm/pb) AND the
45
+ # shared team data bundle (pe_ratio/pb_ratio from finnhub/yahoo).
46
+ pe = _num_or_none(
47
+ fund.get("pe_ttm") or fund.get("pe_ratio") or fund.get("pe")
48
+ or quote.get("pe_ttm") or quote.get("pe_ratio")
49
+ )
50
+ pb = _num_or_none(
51
+ fund.get("pb") or fund.get("pb_ratio")
52
+ or quote.get("pb") or quote.get("pb_ratio")
53
+ )
54
+ roe = _num_or_none(fund.get("roe"))
55
+ rev_g = _num_or_none(fund.get("revenue_growth") or fund.get("rev_growth"))
56
+ div_y = _num_or_none(fund.get("dividend_yield"))
57
+
58
+ fund_str = (
59
+ f" PE(TTM): {_fmt_num(pe, 1, 'x')}\n"
60
+ f" PB: {_fmt_num(pb, 2, 'x')}\n"
61
+ f" ROE: {_fmt_num(roe, 1, '%')}\n"
62
+ f" Revenue growth: {_fmt_num(rev_g, 1, '%')}\n"
63
+ f" Dividend yield: {_fmt_num(div_y, 2, '%')}"
64
+ ) if pe or pb else " (fundamental data unavailable)"
65
+
66
+ prompt = (
67
+ f"Stock: {symbol} Price: {price}\n"
68
+ f"Fundamentals:\n{fund_str}\n\n"
69
+ "Evaluate:\n"
70
+ "1. Valuation (PE/PB vs historical/sector)\n"
71
+ "2. Profitability quality (ROE trend)\n"
72
+ "3. Growth outlook (revenue/earnings)\n"
73
+ "4. Balance sheet and dividend\n"
74
+ "5. Competitive moat\n"
75
+ "Conclusion: UNDERVALUED / FAIRLY_VALUED / OVERVALUED\n\n"
76
+ "Data limits: use only the financial fields supplied above. No historical series, peer "
77
+ "panel or factor validation report is connected here; do not claim those comparisons "
78
+ "or tests were run. If a valuation or financial field is missing, identify it as unavailable."
79
+ )
80
+
81
+ analysis = await self._call_llm(self._SYSTEM, prompt, max_tokens=500, quote=quote)
82
+ if not analysis:
83
+ analysis = _template_fundamental(symbol, pe, pb, roe, rev_g, lang=self.lang)
84
+
85
+ signal = _extract_signal(analysis, pe or 0)
86
+ confidence = _calc_confidence(pe or 0, pb or 0, roe or 0)
87
+ key_points = _extract_key_points(analysis)
88
+
89
+ return AgentResult(
90
+ agent=self.name, symbol=symbol,
91
+ analysis=analysis, confidence=confidence,
92
+ signal=signal, key_points=key_points,
93
+ data_used={"pe": pe, "pb": pb, "roe": roe},
94
+ )
95
+
96
+
97
+ def _num_or_none(value: Any) -> Optional[float]:
98
+ try:
99
+ if value is None:
100
+ return None
101
+ out = float(value)
102
+ return out if out != 0 else None
103
+ except (TypeError, ValueError):
104
+ return None
105
+
106
+
107
+ def _fmt_num(value: Optional[float], digits: int = 1, suffix: str = "") -> str:
108
+ if value is None:
109
+ return "数据不足"
110
+ return f"{value:.{digits}f}{suffix}"
111
+
112
+
113
+ def _extract_signal(text: str, pe: float = 0) -> str:
114
+ t = text.upper()
115
+ if "UNDERVALUED" in t or "低估" in t: return "BUY"
116
+ if "OVERVALUED" in t or "高估" in t: return "SELL"
117
+ # PE 辅助判断
118
+ if pe > 0:
119
+ if pe < 15: return "BUY"
120
+ if pe > 50: return "SELL"
121
+ return "HOLD"
122
+
123
+
124
+ def _calc_confidence(pe: float, pb: float, roe: float) -> float:
125
+ if pe <= 0 and pb <= 0 and roe == 0:
126
+ return 0.4 # 无数据,低置信度
127
+ score = 0.5
128
+ if pe > 0:
129
+ if pe < 15: score += 0.15
130
+ elif pe < 25: score += 0.05
131
+ elif pe > 50: score -= 0.15
132
+ if roe > 20: score += 0.15
133
+ elif roe > 10: score += 0.05
134
+ return round(min(0.95, max(0.2, score)), 2)
135
+
136
+
137
+ def _extract_key_points(text: str) -> List[str]:
138
+ points = []
139
+ for line in text.split("\n"):
140
+ line = line.strip()
141
+ if line.startswith(("1.", "2.", "3.", "4.", "5.", "•", "-", "·")) and len(line) > 5:
142
+ points.append(line.lstrip("1234567890.-•· "))
143
+ return points[:4]
144
+
145
+
146
+ def _template_fundamental(symbol: str, pe: Optional[float], pb: Optional[float],
147
+ roe: Optional[float], rev_g: Optional[float], lang: str = "zh") -> str:
148
+ if not str(lang).lower().startswith("zh"):
149
+ if not pe or pe <= 0:
150
+ valuation, conclusion = "not enough data", "DATA_LIMITED"
151
+ elif pe < 15:
152
+ valuation, conclusion = "undervalued", "UNDERVALUED"
153
+ elif pe > 40:
154
+ valuation, conclusion = "overvalued", "OVERVALUED"
155
+ else:
156
+ valuation, conclusion = "fairly valued", "FAIRLY_VALUED"
157
+ return (
158
+ f"{symbol} fundamentals (template):\n"
159
+ f"• Valuation: PE={_fmt_num(pe, 1, 'x')} PB={_fmt_num(pb, 2, 'x')} → {valuation}\n"
160
+ f"• Profitability: ROE={_fmt_num(roe, 1, '%')} revenue growth={_fmt_num(rev_g, 1, '%')}\n"
161
+ "• Missing figures are not zeros; check against the filings and peers\n"
162
+ f"• Conclusion: {conclusion}"
163
+ )
164
+ if not pe or pe <= 0:
165
+ valuation, conclusion = "数据不足", "DATA_LIMITED"
166
+ elif pe < 15:
167
+ valuation, conclusion = "低估", "UNDERVALUED"
168
+ elif pe > 40:
169
+ valuation, conclusion = "高估", "OVERVALUED"
170
+ else:
171
+ valuation, conclusion = "合理", "FAIRLY_VALUED"
172
+ return (
173
+ f"{symbol} 基本面分析(模板):\n"
174
+ f"• 估值:PE={_fmt_num(pe, 1, 'x')} PB={_fmt_num(pb, 2, 'x')} → {valuation}\n"
175
+ f"• 盈利能力:ROE={_fmt_num(roe, 1, '%')} 营收增速={_fmt_num(rev_g, 1, '%')}\n"
176
+ "• 基本面数据不足时,不应把缺失值当作 0;建议结合财报和行业对比复核\n"
177
+ f"• 结论: {conclusion}"
178
+ )
@@ -0,0 +1,111 @@
1
+ """
2
+ agents/financial/macro.py — 宏观环境 Agent
3
+ ===========================================
4
+ 分析:利率环境、汇率、行业周期、政策面、大盘趋势。
5
+ """
6
+ from __future__ import annotations
7
+ from typing import Any, Dict, List
8
+ from ..base import BaseAgent, AgentResult
9
+
10
+
11
+ class MacroAgent(BaseAgent):
12
+ name = "macro"
13
+ description = "宏观分析:利率/汇率/政策/大盘趋势"
14
+
15
+ _SYSTEM = (
16
+ "You are a macro strategist covering China and global markets. "
17
+ "Focus on: interest rate environment, USD/CNY trend, sector cycle, "
18
+ "regulatory policy, and market sentiment. Be concise and data-driven. "
19
+ "End with: TAILWIND / NEUTRAL / HEADWIND for the given stock."
20
+ )
21
+
22
+ async def fetch_data(self, symbol: str) -> Dict[str, Any]:
23
+ data = await super().fetch_data(symbol)
24
+ # 尝试拉取指数数据作为大盘参考
25
+ if self.data:
26
+ for idx in ["000001", "399006"]: # 上证 + 创业板
27
+ try:
28
+ q = self.data.quote(idx)
29
+ if q:
30
+ data.setdefault("indices", {})[idx] = q.to_dict()
31
+ except Exception:
32
+ pass
33
+ return data
34
+
35
+ async def analyze(self, symbol: str, data: Dict[str, Any]) -> AgentResult:
36
+ quote = data.get("quote", {})
37
+ indices = data.get("indices", {})
38
+
39
+ idx_summary = ""
40
+ for code, q in indices.items():
41
+ name = {"000001": "上证", "399006": "创业板"}.get(code, code)
42
+ idx_summary += f" {name}: {q.get('price',0):.2f} {q.get('change_pct',0):+.2f}%\n"
43
+
44
+ prompt = (
45
+ f"Symbol: {symbol}\n"
46
+ f"Market Indices:\n{idx_summary or ' (unavailable)'}\n\n"
47
+ "Analyze the macroeconomic backdrop for this stock:\n"
48
+ "1. Current rate/liquidity environment (PBOC stance)\n"
49
+ "2. Sector regulatory environment (any recent policies)\n"
50
+ "3. Market sentiment and positioning\n"
51
+ "4. Key macro risks to watch\n"
52
+ "Conclusion: TAILWIND / NEUTRAL / HEADWIND"
53
+ )
54
+
55
+ analysis = await self._call_llm(self._SYSTEM, prompt, max_tokens=500, quote=quote)
56
+ if not analysis:
57
+ analysis = _template_macro(symbol, indices, lang=self.lang)
58
+
59
+ signal = _extract_signal(analysis)
60
+ key_points = _extract_key_points(analysis)
61
+
62
+ return AgentResult(
63
+ agent=self.name, symbol=symbol,
64
+ analysis=analysis, confidence=0.65,
65
+ signal=signal, key_points=key_points,
66
+ data_used={"indices": indices},
67
+ )
68
+
69
+
70
+ def _extract_signal(text: str) -> str:
71
+ t = text.upper()
72
+ if "TAILWIND" in t or "看多" in t: return "BUY"
73
+ if "HEADWIND" in t or "看空" in t: return "SELL"
74
+ return "HOLD"
75
+
76
+
77
+ def _extract_key_points(text: str) -> List[str]:
78
+ points = []
79
+ for line in text.split("\n"):
80
+ line = line.strip()
81
+ if line.startswith(("1.", "2.", "3.", "4.", "•", "-", "·")) and len(line) > 5:
82
+ points.append(line.lstrip("1234567890.-•· "))
83
+ return points[:4]
84
+
85
+
86
+ _IDX_NAMES = {"000001": "上证", "399006": "创业板"}
87
+
88
+ def _template_macro(symbol: str, indices: Dict, lang: str = "zh") -> str:
89
+ """Without a model: the index moves, and nothing claimed beyond them.
90
+
91
+ This stated "当前货币政策偏宽松,流动性充裕" (policy loose, liquidity
92
+ ample) as fact — a macro view with no data behind it.
93
+ """
94
+ zh = str(lang).lower().startswith("zh")
95
+ idx_str = ("、" if zh else ", ").join(
96
+ f"{_IDX_NAMES.get(k, k) if zh else k} {v.get('change_pct', 0):+.2f}%"
97
+ for k, v in indices.items()
98
+ ) if indices else ("指数数据不可用" if zh else "index data unavailable")
99
+ if not zh:
100
+ return (
101
+ f"{symbol} macro (template):\n"
102
+ f"• Market indices: {idx_str}\n"
103
+ "• Policy and liquidity were not assessed (no model analysis)\n"
104
+ "• Conclusion: NEUTRAL"
105
+ )
106
+ return (
107
+ f"{symbol} 宏观分析(模板):\n"
108
+ f"• 市场指数: {idx_str}\n"
109
+ "• 未评估货币政策与流动性(无模型分析)\n"
110
+ "• 结论: NEUTRAL"
111
+ )