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,432 @@
1
+ """Context builders for market-analysis commands."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import logging
7
+ import re
8
+ import time
9
+ from typing import Any, Callable, Optional
10
+
11
+ from aria_code.apps.cli.prompts.system_prompts import build_response_style_rule
12
+
13
+
14
+ TA_SESSION_CACHE: dict[str, dict[str, Any]] = {}
15
+ TA_SESSION_CACHE_TTL = 600
16
+
17
+
18
+ def context_has_price(context: str) -> bool:
19
+ """Whether an /analyze context carries a fetched price — the header line
20
+ build_analyze_context writes as "- Price: 333.69" ("- 价格: 333.69")."""
21
+ return re.search(r"^- (?:Price|价格): \d", context or "", re.MULTILINE) is not None
22
+
23
+
24
+ def _cached_ta(symbol: str) -> dict[str, Any]:
25
+ cached = TA_SESSION_CACHE.get(symbol)
26
+ if cached and (time.time() - float(cached.get("ts", 0))) < TA_SESSION_CACHE_TTL:
27
+ return {**(cached.get("data") or {}), "_cached": True}
28
+ return {}
29
+
30
+
31
+ def _store_ta(symbol: str, data: dict[str, Any]) -> None:
32
+ if data.get("success"):
33
+ TA_SESSION_CACHE[symbol] = {"data": data, "ts": time.time()}
34
+
35
+
36
+ def build_analyze_prompt(symbol: str, context: str, is_cn: bool, response_lang: str | None = None) -> str:
37
+ """Build the LLM prompt for /analyze from a prepared market context."""
38
+
39
+ symbol = symbol.upper()
40
+ lang = response_lang if response_lang in ("zh", "en") else ("zh" if is_cn else "en")
41
+ _no_explain = (
42
+ "注意:如某字段数据缺失,请直接省略该项,不要写'数据缺失'或'未提供'的说明文字。"
43
+ "对于无数据的章节整体跳过即可。\n"
44
+ if lang == "zh" else
45
+ "Note: If any data field is missing, skip that item entirely. Do not write 'data unavailable' or explain why it is missing.\n"
46
+ )
47
+ if lang == "zh":
48
+ return (
49
+ f"{context}\n\n"
50
+ f"{build_response_style_rule('zh')}"
51
+ f"请对以上 {symbol} 进行综合分析,包括:\n"
52
+ f"1. 技术面分析(趋势判断、支撑/阻力、指标信号)\n"
53
+ f"2. 基本面评估(估值合理性、盈利能力)\n"
54
+ f"3. 风险提示(简要 2-3 条)\n"
55
+ f"4. 综合建议(操作方向 + 关键价位参考)\n"
56
+ f"\n{_no_explain}"
57
+ )
58
+ return (
59
+ f"{context}\n\n"
60
+ f"{build_response_style_rule('en')}"
61
+ f"Please provide a comprehensive analysis of {symbol}, covering:\n"
62
+ f"1. Technical analysis (trend, support/resistance, indicator signals)\n"
63
+ f"2. Fundamentals (valuation, profitability — only if data is available)\n"
64
+ f"3. Risk assessment (2-3 key points)\n"
65
+ f"4. Summary outlook with key price levels\n"
66
+ f"\n{_no_explain}"
67
+ )
68
+
69
+
70
+ async def build_analyze_context(
71
+ symbol: str,
72
+ is_cn: bool,
73
+ *,
74
+ has_mdc: bool = False,
75
+ get_mdc: Callable[[], Any] | None = None,
76
+ ashare_name_lookup: Callable[[str], str | None] | None = None,
77
+ has_brokers: bool = False,
78
+ get_broker_registry: Callable[[], Any] | None = None,
79
+ logger: logging.Logger | None = None,
80
+ ) -> str:
81
+ """Fetch real market data and build a structured LLM context."""
82
+
83
+ log = logger or logging.getLogger(__name__)
84
+ loop = asyncio.get_event_loop()
85
+ ctx_lines: list[str] = [f"## {symbol} 市场数据" if is_cn else f"## {symbol} Market Data"]
86
+
87
+ quote: dict[str, Any] = {}
88
+ technical: dict[str, Any] = {}
89
+ quality: dict[str, Any] = {}
90
+
91
+ # ── Primary: cloud DataService bundle ────────────────────────────────────
92
+ try:
93
+ from packages.aria_services import data as service_data
94
+ try:
95
+ from datasources.router import get_router as get_data_router
96
+ router = get_data_router()
97
+ except Exception:
98
+ router = None
99
+ bundle = await loop.run_in_executor(
100
+ None,
101
+ lambda: service_data.DataService(router=router).bundle(
102
+ symbol, history_days=370, technical_days=120,
103
+ ),
104
+ )
105
+ quote = bundle.quote or {}
106
+ technical = bundle.technical or {}
107
+ quality = dict(bundle.quality or {})
108
+ if not quality.get("providers") and getattr(bundle, "provider_chain", None):
109
+ quality["providers"] = list(getattr(bundle, "provider_chain", []) or [])
110
+ if not quality.get("missing_fields") and getattr(bundle, "missing_fields", None):
111
+ quality["missing_fields"] = list(getattr(bundle, "missing_fields", []) or [])
112
+ _store_ta(symbol, technical)
113
+ except Exception as exc:
114
+ log.debug("analyze data service failed for %s: %s", symbol, exc)
115
+
116
+ # ── Fallback 1: market data client ────────────────────────────────────────
117
+ if not quote and has_mdc and get_mdc:
118
+ try:
119
+ mdc = get_mdc()
120
+ raw_q = await loop.run_in_executor(None, mdc.quote, symbol)
121
+ if raw_q:
122
+ quote = raw_q if isinstance(raw_q, dict) else (raw_q.to_dict() if hasattr(raw_q, "to_dict") else vars(raw_q))
123
+ if quote.get("price"):
124
+ raw_ta = await loop.run_in_executor(None, mdc.technical_indicators, symbol, 120)
125
+ if isinstance(raw_ta, dict) and raw_ta.get("success"):
126
+ technical = raw_ta
127
+ _store_ta(symbol, technical)
128
+ else:
129
+ technical = _cached_ta(symbol)
130
+ except Exception:
131
+ technical = _cached_ta(symbol)
132
+
133
+ # ── Fallback 2: DataRouter (yfinance direct) ─────────────────────────────
134
+ if not quote or not quote.get("price"):
135
+ try:
136
+ from datasources.router import DataRouter
137
+ router_direct = DataRouter()
138
+ raw_q = await loop.run_in_executor(None, router_direct.quote, symbol)
139
+ if raw_q:
140
+ quote = raw_q.to_dict() if hasattr(raw_q, "to_dict") else vars(raw_q)
141
+ except Exception as exc:
142
+ log.debug("DataRouter.quote fallback failed for %s: %s", symbol, exc)
143
+
144
+ # If no technical from above, try cached
145
+ if not technical:
146
+ technical = _cached_ta(symbol)
147
+
148
+ if quality:
149
+ ctx_lines.append(f"\n### {'数据质量' if is_cn else 'Data Quality'}")
150
+ status = quality.get("status")
151
+ if status:
152
+ ctx_lines.append(f"- {'状态' if is_cn else 'Status'}: {status}")
153
+ providers = quality.get("providers") or []
154
+ if providers:
155
+ ctx_lines.append(f"- {'数据源' if is_cn else 'Providers'}: {', '.join(map(str, providers))}")
156
+ missing = quality.get("missing_fields") or []
157
+ if missing:
158
+ ctx_lines.append(f"- {'缺失字段' if is_cn else 'Missing fields'}: {', '.join(map(str, missing))}")
159
+ warnings = quality.get("warnings") or []
160
+ if warnings:
161
+ ctx_lines.append(f"- {'警告' if is_cn else 'Warnings'}: {'; '.join(map(str, warnings[:3]))}")
162
+
163
+ # ── Price / header line ───────────────────────────────────────────────────
164
+ price = quote.get("price") if quote else None
165
+ change_pct = quote.get("change_pct") if quote else None
166
+ name = (quote.get("name") or symbol) if quote else symbol
167
+
168
+ if price and float(price) == 0.0:
169
+ price = None # treat 0 as missing
170
+
171
+ if is_cn and (not name or name == symbol or str(name).isascii()):
172
+ try:
173
+ cn_name = ashare_name_lookup(symbol) if ashare_name_lookup else None
174
+ if cn_name:
175
+ name = cn_name
176
+ except Exception as exc:
177
+ log.debug("ashare name lookup failed for %s: %s", symbol, exc)
178
+
179
+ if price:
180
+ chg_str = f"{float(change_pct):+.2f}%" if change_pct is not None else ""
181
+ header = f"- 价格: {float(price):.2f}" if is_cn else f"- Price: {float(price):.2f}"
182
+ if chg_str:
183
+ header += f" ({chg_str})"
184
+ if name and name != symbol:
185
+ header += f" [{name}]"
186
+ ctx_lines.append(header)
187
+ # 52-week range
188
+ h52 = quote.get("high_52w", 0)
189
+ l52 = quote.get("low_52w", 0)
190
+ if h52 and l52 and float(h52) > 0:
191
+ ctx_lines.append(
192
+ f"- 52周区间: {float(l52):.2f} — {float(h52):.2f}"
193
+ if is_cn else
194
+ f"- 52-week range: {float(l52):.2f} — {float(h52):.2f}"
195
+ )
196
+ else:
197
+ ctx_lines.append(
198
+ "- 价格: 获取失败(稍后重试或配置数据服务 key)"
199
+ if is_cn else
200
+ "- Price: unavailable (configure a data service key via /apikey)"
201
+ )
202
+
203
+ # ── Technical indicators ──────────────────────────────────────────────────
204
+ rsi = technical.get("rsi")
205
+ macd_hist= technical.get("macd_hist")
206
+ ma20 = technical.get("ma20")
207
+ ma60 = technical.get("ma60")
208
+ bb_upper = technical.get("bb_upper")
209
+ bb_lower = technical.get("bb_lower")
210
+
211
+ has_tech = any(v is not None for v in (rsi, macd_hist, ma20))
212
+ if has_tech:
213
+ ctx_lines.append(f"\n### {'技术指标' if is_cn else 'Technical Indicators'}")
214
+ if rsi is not None:
215
+ rsi_desc = ("超买" if rsi > 70 else "超卖" if rsi < 30 else "中性") if is_cn else (
216
+ "Overbought" if rsi > 70 else "Oversold" if rsi < 30 else "Neutral")
217
+ ctx_lines.append(f"- RSI (14): {rsi:.1f} [{rsi_desc}]")
218
+ if macd_hist is not None:
219
+ trend = ("多头 Bullish" if macd_hist > 0 else "空头 Bearish") if is_cn else (
220
+ "Bullish" if macd_hist > 0 else "Bearish")
221
+ ctx_lines.append(f"- MACD 柱状图: {macd_hist:.4f} [{trend}]" if is_cn else
222
+ f"- MACD histogram: {macd_hist:.4f} [{trend}]")
223
+ if ma20 and price:
224
+ rel = ("上方 ↑" if float(price) > ma20 else "下方 ↓") if is_cn else (
225
+ "above ↑" if float(price) > ma20 else "below ↓")
226
+ ctx_lines.append(f"- MA20: {ma20:.2f} [价格在{rel}]" if is_cn else
227
+ f"- MA20: {ma20:.2f} [Price {rel}]")
228
+ if ma60 and price:
229
+ rel = ("上方 ↑" if float(price) > ma60 else "下方 ↓") if is_cn else (
230
+ "above ↑" if float(price) > ma60 else "below ↓")
231
+ ctx_lines.append(f"- MA60: {ma60:.2f} [价格在{rel}]" if is_cn else
232
+ f"- MA60: {ma60:.2f} [Price {rel}]")
233
+ if bb_upper and bb_lower:
234
+ ctx_lines.append(f"- 布林带: {bb_lower:.2f} — {bb_upper:.2f}" if is_cn else
235
+ f"- Bollinger Bands: {bb_lower:.2f} — {bb_upper:.2f}")
236
+ if technical.get("_cached"):
237
+ ctx_lines.append(" [以上技术指标来自缓存]" if is_cn else " [Technical data from session cache]")
238
+
239
+ # ── Support / resistance (computed from history) ──────────────────────────
240
+ await _append_support_resistance(ctx_lines, symbol, is_cn, price, ma20, ma60, bb_upper, bb_lower, loop, log)
241
+
242
+ # ── Fundamentals ──────────────────────────────────────────────────────────
243
+ await _append_fundamentals(ctx_lines, symbol, is_cn, loop, log, quote)
244
+
245
+ # ── Broker position ───────────────────────────────────────────────────────
246
+ _append_broker_position(
247
+ ctx_lines, symbol, is_cn,
248
+ has_brokers=has_brokers, get_broker_registry=get_broker_registry, logger=log,
249
+ )
250
+
251
+ return "\n".join(ctx_lines)
252
+
253
+
254
+ async def _append_support_resistance(
255
+ ctx_lines: list[str],
256
+ symbol: str,
257
+ is_cn: bool,
258
+ price: Optional[float],
259
+ ma20: Optional[float],
260
+ ma60: Optional[float],
261
+ bb_upper: Optional[float],
262
+ bb_lower: Optional[float],
263
+ loop,
264
+ log: logging.Logger,
265
+ ) -> None:
266
+ """Compute support/resistance from price history and key MAs."""
267
+ levels: dict[str, list[float]] = {"support": [], "resistance": []}
268
+
269
+ try:
270
+ from datasources.router import DataRouter
271
+ hist_result = await loop.run_in_executor(None, DataRouter().history, symbol, 90)
272
+ if hist_result and hist_result.data is not None and not hist_result.data.empty:
273
+ df = hist_result.data
274
+ close_col = next((c for c in df.columns if "close" in c.lower()), None)
275
+ high_col = next((c for c in df.columns if "high" in c.lower()), None)
276
+ low_col = next((c for c in df.columns if "low" in c.lower()), None)
277
+
278
+ if close_col and len(df) >= 10:
279
+ closes = df[close_col].dropna()
280
+ highs = df[high_col].dropna() if high_col else closes
281
+ lows = df[low_col].dropna() if low_col else closes
282
+
283
+ # Rolling 10-day swing highs (local maxima)
284
+ for i in range(5, len(highs) - 5):
285
+ window = highs.iloc[i-5:i+5]
286
+ if float(highs.iloc[i]) == float(window.max()):
287
+ levels["resistance"].append(float(highs.iloc[i]))
288
+ # Rolling 10-day swing lows (local minima)
289
+ for i in range(5, len(lows) - 5):
290
+ window = lows.iloc[i-5:i+5]
291
+ if float(lows.iloc[i]) == float(window.min()):
292
+ levels["support"].append(float(lows.iloc[i]))
293
+ except Exception as exc:
294
+ log.debug("support/resistance history failed for %s: %s", symbol, exc)
295
+
296
+ # Add MA lines as dynamic support/resistance
297
+ if price:
298
+ p = float(price)
299
+ if ma20:
300
+ (levels["support"] if p > ma20 else levels["resistance"]).append(ma20)
301
+ if ma60:
302
+ (levels["support"] if p > ma60 else levels["resistance"]).append(ma60)
303
+ # Bollinger bands
304
+ if bb_lower:
305
+ levels["support"].append(bb_lower)
306
+ if bb_upper:
307
+ levels["resistance"].append(bb_upper)
308
+
309
+ if levels["support"] or levels["resistance"]:
310
+ ctx_lines.append(f"\n### {'关键价位' if is_cn else 'Key Price Levels'}")
311
+
312
+ # Pick the 3 nearest support levels below price
313
+ sup = sorted(set(round(v, 2) for v in levels["support"] if v < p), reverse=True)[:3]
314
+ # Pick the 3 nearest resistance levels above price
315
+ res = sorted(set(round(v, 2) for v in levels["resistance"] if v > p))[:3]
316
+
317
+ if sup:
318
+ sup_str = " / ".join(f"{v:.2f}" for v in sup)
319
+ ctx_lines.append(f"- 支撑位: {sup_str}" if is_cn else f"- Support: {sup_str}")
320
+ if res:
321
+ res_str = " / ".join(f"{v:.2f}" for v in res)
322
+ ctx_lines.append(f"- 阻力位: {res_str}" if is_cn else f"- Resistance: {res_str}")
323
+
324
+
325
+ async def _append_fundamentals(
326
+ ctx_lines: list[str],
327
+ symbol: str,
328
+ is_cn: bool,
329
+ loop,
330
+ log: logging.Logger,
331
+ quote: dict[str, Any],
332
+ ) -> None:
333
+ fund_lines: list[str] = []
334
+
335
+ # Try DataRouter (yfinance / alpha_vantage / edgar chain)
336
+ try:
337
+ from datasources.router import DataRouter
338
+ fund = await loop.run_in_executor(None, DataRouter().fundamentals, symbol)
339
+ if fund:
340
+ def _row(label_cn: str, label_en: str, val: Optional[float], fmt: str = ".2f") -> None:
341
+ if val is not None and val != 0.0:
342
+ formatted = f"{val:{fmt}}"
343
+ fund_lines.append(f"- {label_cn}: {formatted}" if is_cn else f"- {label_en}: {formatted}")
344
+
345
+ _row("市盈率 (TTM)", "P/E ratio (TTM)", fund.pe_ttm)
346
+ _row("市净率", "Price-to-Book", fund.pb)
347
+ _row("ROE", "Return on Equity", fund.roe, ".2f")
348
+ _row("营收增速", "Revenue Growth (YoY)", fund.revenue_growth, ".2f")
349
+ _row("净利增速", "Earnings Growth (YoY)", fund.net_profit_growth, ".2f")
350
+ _row("股息率", "Dividend Yield", fund.dividend_yield, ".2f")
351
+
352
+ # Market cap: format nicely (USD or CNY)
353
+ if fund.total_mv and fund.total_mv > 0:
354
+ mv = fund.total_mv
355
+ if mv >= 1e12:
356
+ mv_str = f"{mv/1e12:.2f}T"
357
+ elif mv >= 1e9:
358
+ mv_str = f"{mv/1e9:.2f}B"
359
+ elif mv >= 1e8:
360
+ mv_str = f"{mv/1e8:.2f}亿" if is_cn else f"{mv/1e9:.2f}B"
361
+ else:
362
+ mv_str = f"{mv:,.0f}"
363
+ fund_lines.append(f"- 总市值: {mv_str}" if is_cn else f"- Market Cap: {mv_str}")
364
+
365
+ if fund.source:
366
+ fund_lines.append(f" [数据源: {fund.source}]" if is_cn else f" [source: {fund.source}]")
367
+ except Exception as exc:
368
+ log.debug("fundamentals fetch failed for %s: %s", symbol, exc)
369
+
370
+ # Also try quote-level PE/PB if fundamentals didn't yield anything
371
+ if not fund_lines and quote:
372
+ pe = quote.get("pe_ttm", 0)
373
+ pb = quote.get("pb", 0)
374
+ if pe and float(pe) > 0:
375
+ fund_lines.append(f"- 市盈率 (TTM): {float(pe):.2f}" if is_cn else f"- P/E ratio (TTM): {float(pe):.2f}")
376
+ if pb and float(pb) > 0:
377
+ fund_lines.append(f"- 市净率: {float(pb):.2f}" if is_cn else f"- Price-to-Book: {float(pb):.2f}")
378
+
379
+ if fund_lines:
380
+ ctx_lines.append(f"\n### {'基本面' if is_cn else 'Fundamentals'}")
381
+ ctx_lines.extend(fund_lines)
382
+
383
+
384
+ def _append_broker_position(
385
+ ctx_lines: list[str],
386
+ symbol: str,
387
+ is_cn: bool,
388
+ *,
389
+ has_brokers: bool,
390
+ get_broker_registry: Callable[[], Any] | None,
391
+ logger: logging.Logger,
392
+ ) -> None:
393
+ if not has_brokers or not get_broker_registry:
394
+ return
395
+ try:
396
+ registry = get_broker_registry()
397
+ broker = registry.active()
398
+ if not broker or not broker.is_connected:
399
+ return
400
+ positions = broker.positions()
401
+ symbol_norm = symbol.lstrip("0").upper()
402
+ match = None
403
+ for position in positions:
404
+ pos_symbol = str(position.symbol or "").lstrip("0").upper()
405
+ if pos_symbol == symbol_norm or pos_symbol.startswith(symbol_norm) or symbol_norm.startswith(pos_symbol):
406
+ match = position
407
+ break
408
+ ctx_lines.append(f"\n### {'我的持仓' if is_cn else 'Your Position'}")
409
+ if not match:
410
+ ctx_lines.append(f"- 当前未持有此股 [{broker.label}]" if is_cn else f"- Not currently held [{broker.label}]")
411
+ return
412
+ qty = getattr(match, "quantity", None) or getattr(match, "qty", None)
413
+ cost = getattr(match, "cost_price", None) or getattr(match, "avg_cost", None)
414
+ pnl = getattr(match, "pnl", None)
415
+ pnl_pct = getattr(match, "pnl_pct", None)
416
+ market_value = getattr(match, "market_value", None)
417
+ ctx_lines.append(f"- 持有: 是 [{broker.label}]" if is_cn else f"- Held: Yes [{broker.label}]")
418
+ if qty is not None:
419
+ ctx_lines.append(f"- 持仓量: {qty:,}" if is_cn else f"- Quantity: {qty:,}")
420
+ if cost is not None:
421
+ ctx_lines.append(f"- 成本价: {cost:.3f}" if is_cn else f"- Avg Cost: {cost:.3f}")
422
+ if market_value is not None:
423
+ ctx_lines.append(f"- 市值: {market_value:,.2f}" if is_cn else f"- Market Value: {market_value:,.2f}")
424
+ if pnl is not None and pnl_pct is not None:
425
+ sign = "+" if pnl >= 0 else ""
426
+ ctx_lines.append(
427
+ f"- 浮动盈亏: {sign}{pnl:,.2f} ({sign}{pnl_pct:.2f}%)"
428
+ if is_cn else
429
+ f"- Unrealized P&L: {sign}{pnl:,.2f} ({sign}{pnl_pct:.2f}%)"
430
+ )
431
+ except Exception as exc:
432
+ logger.debug("broker position lookup failed for %s: %s", symbol, exc)
@@ -0,0 +1,7 @@
1
+ """Backwards-compatibility shim — canonical code lives in ui/render/market.py."""
2
+ from aria_code.ui.render.market import * # noqa: F401, F403
3
+ from aria_code.ui.render.market import (
4
+ print_quote_result, print_ta_result,
5
+ render_quote_plain, render_ta_plain,
6
+ compact_quote_market_cap,
7
+ )