aria-code 0.52.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (478) hide show
  1. aria_code/__init__.py +42 -0
  2. aria_code/_version.py +20 -0
  3. aria_code/adk_apps/__init__.py +1 -0
  4. aria_code/adk_apps/aria_code_review/__init__.py +1 -0
  5. aria_code/adk_apps/aria_code_review/agent.py +32 -0
  6. aria_code/adk_apps/aria_research/__init__.py +1 -0
  7. aria_code/adk_apps/aria_research/agent.py +31 -0
  8. aria_code/agents/__init__.py +34 -0
  9. aria_code/agents/base.py +318 -0
  10. aria_code/agents/code_review.py +200 -0
  11. aria_code/agents/deep/__init__.py +37 -0
  12. aria_code/agents/deep/calibration_loop.py +144 -0
  13. aria_code/agents/deep/critic.py +125 -0
  14. aria_code/agents/deep/deepen.py +193 -0
  15. aria_code/agents/deep/models.py +149 -0
  16. aria_code/agents/deep/pipeline.py +164 -0
  17. aria_code/agents/deep/quant_fusion.py +192 -0
  18. aria_code/agents/deep/themes.py +95 -0
  19. aria_code/agents/deep/tiers.py +106 -0
  20. aria_code/agents/engineering/__init__.py +14 -0
  21. aria_code/agents/engineering/coder.py +222 -0
  22. aria_code/agents/engineering/tester.py +145 -0
  23. aria_code/agents/financial/__init__.py +21 -0
  24. aria_code/agents/financial/cashflow_burn.py +119 -0
  25. aria_code/agents/financial/catalyst.py +279 -0
  26. aria_code/agents/financial/corporate_finance.py +175 -0
  27. aria_code/agents/financial/debate.py +224 -0
  28. aria_code/agents/financial/earnings.py +303 -0
  29. aria_code/agents/financial/fundamental.py +191 -0
  30. aria_code/agents/financial/macro.py +99 -0
  31. aria_code/agents/financial/news.py +207 -0
  32. aria_code/agents/financial/risk.py +165 -0
  33. aria_code/agents/financial/sector.py +279 -0
  34. aria_code/agents/financial/strategist.py +121 -0
  35. aria_code/agents/financial/stripe_revenue.py +127 -0
  36. aria_code/agents/financial/synthesis.py +274 -0
  37. aria_code/agents/financial/technical.py +258 -0
  38. aria_code/agents/orchestrator.py +44 -0
  39. aria_code/agents/portfolio_agent.py +363 -0
  40. aria_code/agents/realty/__init__.py +62 -0
  41. aria_code/agents/realty/asset_diagnosis.py +152 -0
  42. aria_code/agents/realty/business_match.py +166 -0
  43. aria_code/agents/realty/cashflow_verify.py +209 -0
  44. aria_code/agents/realty/contract_rules.py +210 -0
  45. aria_code/agents/realty/energy_anomaly.py +189 -0
  46. aria_code/agents/realty/exit_settlement.py +208 -0
  47. aria_code/agents/realty/fulfillment_risk.py +206 -0
  48. aria_code/agents/realty/ops_optimize.py +160 -0
  49. aria_code/agents/realty/revenue_share.py +215 -0
  50. aria_code/agents/registry.py +158 -0
  51. aria_code/agents/signal_scheme.py +111 -0
  52. aria_code/agents/sports/__init__.py +0 -0
  53. aria_code/agents/sports/football_agent.py +197 -0
  54. aria_code/agents/supervisor.py +113 -0
  55. aria_code/agents/team.py +492 -0
  56. aria_code/agents/warehouse/__init__.py +25 -0
  57. aria_code/agents/warehouse/contracts.py +26 -0
  58. aria_code/agents/warehouse/dashboard.py +155 -0
  59. aria_code/agents/warehouse/fulfillment_leadtime.py +95 -0
  60. aria_code/agents/warehouse/inbound_exceptions.py +25 -0
  61. aria_code/agents/warehouse/inventory_health.py +24 -0
  62. aria_code/agents/warehouse/local_run.py +71 -0
  63. aria_code/agents/warehouse/local_snapshot.py +132 -0
  64. aria_code/agents/warehouse/logistics_cost.py +84 -0
  65. aria_code/agents/warehouse/logistics_sync.py +21 -0
  66. aria_code/agents/warehouse/workflow.py +31 -0
  67. aria_code/aliyun_data_client.py +4 -0
  68. aria_code/apps/README.md +12 -0
  69. aria_code/apps/__init__.py +2 -0
  70. aria_code/apps/channels/README.md +15 -0
  71. aria_code/apps/channels/__init__.py +17 -0
  72. aria_code/apps/channels/intake.py +92 -0
  73. aria_code/apps/channels/registry.py +95 -0
  74. aria_code/apps/channels/tradingview.py +94 -0
  75. aria_code/apps/cli/README.md +13 -0
  76. aria_code/apps/cli/__init__.py +2 -0
  77. aria_code/apps/cli/_optional.py +120 -0
  78. aria_code/apps/cli/bootstrap.py +145 -0
  79. aria_code/apps/cli/broker_render.py +206 -0
  80. aria_code/apps/cli/codegen_paths.py +29 -0
  81. aria_code/apps/cli/commands/__init__.py +16 -0
  82. aria_code/apps/cli/commands/_business_render.py +78 -0
  83. aria_code/apps/cli/commands/_ui.py +71 -0
  84. aria_code/apps/cli/commands/analysis_cmds.py +369 -0
  85. aria_code/apps/cli/commands/ashare_prediction_cmds.py +327 -0
  86. aria_code/apps/cli/commands/auth_cmds.py +239 -0
  87. aria_code/apps/cli/commands/backtest_cmds.py +2543 -0
  88. aria_code/apps/cli/commands/broker_cmds.py +1234 -0
  89. aria_code/apps/cli/commands/business_workflow_cmds.py +319 -0
  90. aria_code/apps/cli/commands/canvas_cmds.py +77 -0
  91. aria_code/apps/cli/commands/catalog.py +87 -0
  92. aria_code/apps/cli/commands/core_cmds.py +2520 -0
  93. aria_code/apps/cli/commands/data_cmds.py +457 -0
  94. aria_code/apps/cli/commands/diagnostic_cmds.py +230 -0
  95. aria_code/apps/cli/commands/diagnostic_ops_cmds.py +813 -0
  96. aria_code/apps/cli/commands/file_cmds.py +312 -0
  97. aria_code/apps/cli/commands/finance_service_cmds.py +60 -0
  98. aria_code/apps/cli/commands/fx_commodity_cmds.py +123 -0
  99. aria_code/apps/cli/commands/market.py +434 -0
  100. aria_code/apps/cli/commands/market_cmds.py +1381 -0
  101. aria_code/apps/cli/commands/market_context.py +425 -0
  102. aria_code/apps/cli/commands/market_render.py +7 -0
  103. aria_code/apps/cli/commands/model_cmds.py +2153 -0
  104. aria_code/apps/cli/commands/ops_cmds.py +721 -0
  105. aria_code/apps/cli/commands/orchestrator_cmds.py +179 -0
  106. aria_code/apps/cli/commands/pdf_export_cmds.py +125 -0
  107. aria_code/apps/cli/commands/portfolio_cmds.py +1278 -0
  108. aria_code/apps/cli/commands/report.py +437 -0
  109. aria_code/apps/cli/commands/scaffold_templates.py +617 -0
  110. aria_code/apps/cli/commands/session_cmds.py +236 -0
  111. aria_code/apps/cli/commands/session_ux_cmds.py +359 -0
  112. aria_code/apps/cli/commands/team.py +669 -0
  113. aria_code/apps/cli/commands/team_render.py +8 -0
  114. aria_code/apps/cli/commands/ui_cmds.py +401 -0
  115. aria_code/apps/cli/commands/warehouse_cmds.py +79 -0
  116. aria_code/apps/cli/commands/workflow_cmds.py +480 -0
  117. aria_code/apps/cli/commands/workspace_cmds.py +1494 -0
  118. aria_code/apps/cli/config_paths.py +73 -0
  119. aria_code/apps/cli/config_store.py +78 -0
  120. aria_code/apps/cli/constants.py +88 -0
  121. aria_code/apps/cli/context.py +34 -0
  122. aria_code/apps/cli/deterministic.py +191 -0
  123. aria_code/apps/cli/direct.py +48 -0
  124. aria_code/apps/cli/finance_service_catalog.py +111 -0
  125. aria_code/apps/cli/football_reports.py +231 -0
  126. aria_code/apps/cli/github_app_auth.py +135 -0
  127. aria_code/apps/cli/google_login.py +196 -0
  128. aria_code/apps/cli/handlers/__init__.py +11 -0
  129. aria_code/apps/cli/handlers/broker_handlers.py +122 -0
  130. aria_code/apps/cli/handlers/chart_handlers.py +1309 -0
  131. aria_code/apps/cli/handlers/market_handlers.py +2513 -0
  132. aria_code/apps/cli/handlers/realty_handlers.py +114 -0
  133. aria_code/apps/cli/handlers/sports_handlers.py +22 -0
  134. aria_code/apps/cli/handlers/strategy_advice.py +82 -0
  135. aria_code/apps/cli/helpers.py +302 -0
  136. aria_code/apps/cli/hooks.py +180 -0
  137. aria_code/apps/cli/i18n.py +297 -0
  138. aria_code/apps/cli/intent.py +136 -0
  139. aria_code/apps/cli/intent_router.py +276 -0
  140. aria_code/apps/cli/intent_signals.py +344 -0
  141. aria_code/apps/cli/lifecycle_hooks.py +48 -0
  142. aria_code/apps/cli/local_tool_schemas.py +536 -0
  143. aria_code/apps/cli/main.py +29 -0
  144. aria_code/apps/cli/market_metadata.py +135 -0
  145. aria_code/apps/cli/market_universe.py +487 -0
  146. aria_code/apps/cli/message_processing.py +310 -0
  147. aria_code/apps/cli/model_catalog.py +620 -0
  148. aria_code/apps/cli/pdf_report.py +977 -0
  149. aria_code/apps/cli/plan_mode.py +139 -0
  150. aria_code/apps/cli/plotly_html.py +15 -0
  151. aria_code/apps/cli/prediction_feedback.py +202 -0
  152. aria_code/apps/cli/preflight.py +502 -0
  153. aria_code/apps/cli/project_aria.py +60 -0
  154. aria_code/apps/cli/prompt_assembly.py +59 -0
  155. aria_code/apps/cli/prompts/__init__.py +0 -0
  156. aria_code/apps/cli/prompts/coding.py +53 -0
  157. aria_code/apps/cli/prompts/select.py +142 -0
  158. aria_code/apps/cli/prompts/system_prompts.py +552 -0
  159. aria_code/apps/cli/prompts/ui.py +436 -0
  160. aria_code/apps/cli/provider_endpoints.py +237 -0
  161. aria_code/apps/cli/provider_keys.py +73 -0
  162. aria_code/apps/cli/providers/__init__.py +1 -0
  163. aria_code/apps/cli/providers/base.py +521 -0
  164. aria_code/apps/cli/providers/chat_routing.py +128 -0
  165. aria_code/apps/cli/providers/collaboration.py +98 -0
  166. aria_code/apps/cli/providers/llm/__init__.py +1 -0
  167. aria_code/apps/cli/providers/llm/offline_responses.py +68 -0
  168. aria_code/apps/cli/providers/llm/ollama_stream.py +1594 -0
  169. aria_code/apps/cli/providers/llm/response_cache.py +60 -0
  170. aria_code/apps/cli/providers/llm/sse_stream.py +257 -0
  171. aria_code/apps/cli/providers/runtime_bridge.py +353 -0
  172. aria_code/apps/cli/providers/vertexai_stream.py +316 -0
  173. aria_code/apps/cli/runtime_consumer.py +657 -0
  174. aria_code/apps/cli/sandbox.py +32 -0
  175. aria_code/apps/cli/session_export.py +120 -0
  176. aria_code/apps/cli/session_jsonl.py +208 -0
  177. aria_code/apps/cli/session_store.py +112 -0
  178. aria_code/apps/cli/skills_catalog.py +273 -0
  179. aria_code/apps/cli/todo_tracker.py +190 -0
  180. aria_code/apps/cli/tool_executor.py +823 -0
  181. aria_code/apps/cli/tool_registry.py +34 -0
  182. aria_code/apps/cli/tool_scope.py +106 -0
  183. aria_code/apps/cli/tools/__init__.py +40 -0
  184. aria_code/apps/cli/tools/context.py +46 -0
  185. aria_code/apps/cli/tools/file_tools.py +180 -0
  186. aria_code/apps/cli/tools/market_tools.py +620 -0
  187. aria_code/apps/cli/tools/notebook_tools.py +111 -0
  188. aria_code/apps/cli/tools/system_tools.py +726 -0
  189. aria_code/apps/cli/tools/write_tools.py +845 -0
  190. aria_code/apps/cli/tradingview_bridge.py +529 -0
  191. aria_code/apps/cli/turn_planning.py +137 -0
  192. aria_code/apps/cli/update_check.py +153 -0
  193. aria_code/apps/cli/utils/__init__.py +0 -0
  194. aria_code/apps/cli/utils/market_detect.py +1597 -0
  195. aria_code/apps/daemon/README.md +14 -0
  196. aria_code/apps/vscode/README.md +115 -0
  197. aria_code/apps/vscode/package.json +70 -0
  198. aria_code/aria_cli.py +6743 -0
  199. aria_code/aria_daemon.py +1398 -0
  200. aria_code/aria_feishu_bot.py +1423 -0
  201. aria_code/aria_mcp_server.py +7 -0
  202. aria_code/aria_relay_client.py +4 -0
  203. aria_code/aria_relay_server.py +490 -0
  204. aria_code/aria_telegram_bot.py +202 -0
  205. aria_code/ariarc.py +385 -0
  206. aria_code/artifacts.py +581 -0
  207. aria_code/backtest_engine.py +4 -0
  208. aria_code/backtest_report.py +4 -0
  209. aria_code/brokers/__init__.py +78 -0
  210. aria_code/brokers/automation.py +193 -0
  211. aria_code/brokers/base.py +231 -0
  212. aria_code/brokers/capabilities.py +264 -0
  213. aria_code/brokers/cn/__init__.py +10 -0
  214. aria_code/brokers/cn/easytrader_broker.py +193 -0
  215. aria_code/brokers/cn/futu_broker.py +194 -0
  216. aria_code/brokers/cn/longbridge_broker.py +190 -0
  217. aria_code/brokers/cn/tiger_broker.py +196 -0
  218. aria_code/brokers/cn/xtquant_broker.py +225 -0
  219. aria_code/brokers/config.py +414 -0
  220. aria_code/brokers/intl/__init__.py +5 -0
  221. aria_code/brokers/intl/alpaca_broker.py +183 -0
  222. aria_code/brokers/intl/ibkr_broker.py +215 -0
  223. aria_code/brokers/intl/trading212_broker.py +183 -0
  224. aria_code/brokers/intl/webull_broker.py +156 -0
  225. aria_code/brokers/paper_broker.py +266 -0
  226. aria_code/brokers/planning.py +296 -0
  227. aria_code/brokers/registry.py +213 -0
  228. aria_code/brokers/trading.py +267 -0
  229. aria_code/canva_client.py +4 -0
  230. aria_code/change_store.py +127 -0
  231. aria_code/clients/__init__.py +0 -0
  232. aria_code/clients/aliyun_data_client.py +660 -0
  233. aria_code/clients/aria_relay_client.py +182 -0
  234. aria_code/clients/canva_client.py +284 -0
  235. aria_code/clients/figma_client.py +100 -0
  236. aria_code/clients/football_data_client.py +1671 -0
  237. aria_code/clients/kling_video_client.py +182 -0
  238. aria_code/clients/market_data_client.py +1976 -0
  239. aria_code/clients/openai_image_client.py +242 -0
  240. aria_code/clients/runway_video_client.py +157 -0
  241. aria_code/clients/warehouse_erp_client.py +105 -0
  242. aria_code/cloud_memory.py +181 -0
  243. aria_code/command_safety.py +19 -0
  244. aria_code/computer_use_tools.py +4 -0
  245. aria_code/dashboard_generator.py +579 -0
  246. aria_code/data_analysis_tools.py +4 -0
  247. aria_code/data_cleaner.py +483 -0
  248. aria_code/data_service.py +513 -0
  249. aria_code/datasources/__init__.py +23 -0
  250. aria_code/datasources/base.py +166 -0
  251. aria_code/datasources/router.py +253 -0
  252. aria_code/datasources/sources/__init__.py +15 -0
  253. aria_code/datasources/sources/akshare_source.py +269 -0
  254. aria_code/datasources/sources/alpha_vantage_source.py +203 -0
  255. aria_code/datasources/sources/edgar_source.py +219 -0
  256. aria_code/datasources/sources/finnhub_source.py +198 -0
  257. aria_code/datasources/sources/fred_source.py +223 -0
  258. aria_code/datasources/sources/tushare_source.py +143 -0
  259. aria_code/datasources/sources/web_scraper_source.py +278 -0
  260. aria_code/datasources/sources/world_bank_source.py +206 -0
  261. aria_code/datasources/sources/yfinance_source.py +152 -0
  262. aria_code/demo_player.py +207 -0
  263. aria_code/doctor.py +813 -0
  264. aria_code/domain/__init__.py +0 -0
  265. aria_code/domain/backtest_engine.py +354 -0
  266. aria_code/domain/backtest_report.py +472 -0
  267. aria_code/domain/finance_formulas.py +389 -0
  268. aria_code/domain/portfolio_ledger.py +307 -0
  269. aria_code/domain/strategy_vault.py +421 -0
  270. aria_code/evals/__init__.py +37 -0
  271. aria_code/evals/harness.py +598 -0
  272. aria_code/evals/runner.py +238 -0
  273. aria_code/external_agent_runner.py +115 -0
  274. aria_code/figma_client.py +4 -0
  275. aria_code/file_analysis_tools.py +4 -0
  276. aria_code/finance_formulas.py +4 -0
  277. aria_code/football_data_client.py +4 -0
  278. aria_code/image_gen_tools.py +4 -0
  279. aria_code/intent_classifier.py +386 -0
  280. aria_code/kling_video_client.py +4 -0
  281. aria_code/licensing.py +151 -0
  282. aria_code/local_finance_tools.py +4 -0
  283. aria_code/local_image_provider.py +4 -0
  284. aria_code/local_llm_provider.py +4 -0
  285. aria_code/macro_tools.py +4 -0
  286. aria_code/markdown_pdf.py +289 -0
  287. aria_code/market_data_client.py +4 -0
  288. aria_code/mcp_client.py +639 -0
  289. aria_code/memory_manager.py +246 -0
  290. aria_code/model_capability.py +486 -0
  291. aria_code/notification_tools.py +4 -0
  292. aria_code/openai_image_client.py +4 -0
  293. aria_code/packages/__init__.py +23 -0
  294. aria_code/packages/adk_bridge/__init__.py +11 -0
  295. aria_code/packages/adk_bridge/code_review_tools.py +49 -0
  296. aria_code/packages/adk_bridge/market_tools.py +125 -0
  297. aria_code/packages/aria_agents/__init__.py +5 -0
  298. aria_code/packages/aria_agents/manifest.py +78 -0
  299. aria_code/packages/aria_core/__init__.py +34 -0
  300. aria_code/packages/aria_core/architecture.py +269 -0
  301. aria_code/packages/aria_core/export.py +147 -0
  302. aria_code/packages/aria_core/manifest.py +65 -0
  303. aria_code/packages/aria_core/paths.py +57 -0
  304. aria_code/packages/aria_core/secure_file.py +68 -0
  305. aria_code/packages/aria_infra/__init__.py +15 -0
  306. aria_code/packages/aria_infra/arthera.py +52 -0
  307. aria_code/packages/aria_infra/doctor.py +246 -0
  308. aria_code/packages/aria_infra/product.py +40 -0
  309. aria_code/packages/aria_mcp/__init__.py +25 -0
  310. aria_code/packages/aria_mcp/bridge.py +201 -0
  311. aria_code/packages/aria_mcp/circuit.py +82 -0
  312. aria_code/packages/aria_mcp/config.py +111 -0
  313. aria_code/packages/aria_mcp/installer.py +95 -0
  314. aria_code/packages/aria_mcp/server.py +1550 -0
  315. aria_code/packages/aria_mcp/tools.py +81 -0
  316. aria_code/packages/aria_sdk/__init__.py +19 -0
  317. aria_code/packages/aria_sdk/client.py +396 -0
  318. aria_code/packages/aria_sdk/providers.py +70 -0
  319. aria_code/packages/aria_sdk/streaming.py +79 -0
  320. aria_code/packages/aria_sdk/types.py +86 -0
  321. aria_code/packages/aria_services/__init__.py +92 -0
  322. aria_code/packages/aria_services/cache.py +60 -0
  323. aria_code/packages/aria_services/context.py +356 -0
  324. aria_code/packages/aria_services/context_checkpoints.py +157 -0
  325. aria_code/packages/aria_services/data.py +11 -0
  326. aria_code/packages/aria_services/provider_health.py +268 -0
  327. aria_code/packages/aria_services/references.py +247 -0
  328. aria_code/packages/aria_services/registry.py +249 -0
  329. aria_code/packages/aria_services/research_protocol.py +57 -0
  330. aria_code/packages/aria_services/research_quality.py +186 -0
  331. aria_code/packages/aria_services/settings.py +157 -0
  332. aria_code/packages/aria_services/usage.py +151 -0
  333. aria_code/packages/aria_skills/__init__.py +46 -0
  334. aria_code/packages/aria_skills/catalog.py +149 -0
  335. aria_code/packages/aria_skills/loader.py +455 -0
  336. aria_code/packages/aria_skills/registry.py +84 -0
  337. aria_code/packages/aria_tools/__init__.py +5 -0
  338. aria_code/packages/aria_tools/financial/__init__.py +8 -0
  339. aria_code/packages/aria_tools/financial/_paths.py +130 -0
  340. aria_code/packages/aria_tools/financial/compliance.py +31 -0
  341. aria_code/packages/aria_tools/financial/factors.py +33 -0
  342. aria_code/packages/aria_tools/financial/risk_tools.py +33 -0
  343. aria_code/packages/aria_tools/financial/strategy.py +31 -0
  344. aria_code/packages/aria_tools/registry.py +128 -0
  345. aria_code/packages/quant_engine/__init__.py +34 -0
  346. aria_code/packages/quant_engine/_namespace.py +62 -0
  347. aria_code/packages/quant_engine/backtest/__init__.py +14 -0
  348. aria_code/packages/quant_engine/backtest/core.py +53 -0
  349. aria_code/packages/quant_engine/backtest/engine.py +96 -0
  350. aria_code/packages/quant_engine/portfolio/__init__.py +13 -0
  351. aria_code/packages/quant_engine/portfolio/optimizer.py +85 -0
  352. aria_code/packages/quant_engine/sports/__init__.py +80 -0
  353. aria_code/packages/quant_engine/sports/calibrator.py +354 -0
  354. aria_code/packages/quant_engine/sports/dixon_coles.py +234 -0
  355. aria_code/packages/quant_engine/sports/elo.py +300 -0
  356. aria_code/packages/quant_engine/sports/form.py +188 -0
  357. aria_code/packages/quant_engine/sports/h2h.py +195 -0
  358. aria_code/packages/quant_engine/sports/ml_model.py +377 -0
  359. aria_code/packages/quant_engine/sports/predictor.py +312 -0
  360. aria_code/packages/quant_engine/sports/tracker.py +665 -0
  361. aria_code/packages/quant_engine/stochastic/__init__.py +35 -0
  362. aria_code/packages/quant_engine/stochastic/gbm_enhanced.py +195 -0
  363. aria_code/packages/quant_engine/stochastic/ito_calculus.py +477 -0
  364. aria_code/packages/quant_engine/stochastic/kelly_criterion.py +181 -0
  365. aria_code/packages/quant_engine/stochastic/monte_carlo_advanced.py +95 -0
  366. aria_code/packages/quant_engine/stochastic/options_pricing.py +576 -0
  367. aria_code/packages/quant_engine/stochastic/stochastic_processes.py +90 -0
  368. aria_code/packs/__init__.py +85 -0
  369. aria_code/packs/base.py +168 -0
  370. aria_code/packs/finance/__init__.py +250 -0
  371. aria_code/packs/logistics/__init__.py +169 -0
  372. aria_code/packs/payments/__init__.py +139 -0
  373. aria_code/packs/realty/__init__.py +190 -0
  374. aria_code/packs/registry.py +202 -0
  375. aria_code/packs/rules.py +90 -0
  376. aria_code/plan_utils.py +194 -0
  377. aria_code/plugin_loader.py +328 -0
  378. aria_code/portfolio_ledger.py +4 -0
  379. aria_code/preview_server.py +449 -0
  380. aria_code/privacy/__init__.py +5 -0
  381. aria_code/privacy/feedback.py +123 -0
  382. aria_code/project_review.py +278 -0
  383. aria_code/project_review_api.py +235 -0
  384. aria_code/project_review_server.py +18 -0
  385. aria_code/project_tools.py +4 -0
  386. aria_code/providers/__init__.py +30 -0
  387. aria_code/providers/llm/__init__.py +19 -0
  388. aria_code/providers/llm/anthropic.py +184 -0
  389. aria_code/providers/llm/autoconfig.py +213 -0
  390. aria_code/providers/llm/base.py +139 -0
  391. aria_code/providers/llm/custom.py +158 -0
  392. aria_code/providers/llm/ollama.py +129 -0
  393. aria_code/providers/llm/openai_compat.py +313 -0
  394. aria_code/providers/llm/registry.py +444 -0
  395. aria_code/providers/local_image_provider.py +202 -0
  396. aria_code/providers/local_llm_provider.py +589 -0
  397. aria_code/realty_data_tools.py +4 -0
  398. aria_code/report_exporters.py +150 -0
  399. aria_code/report_generator.py +1764 -0
  400. aria_code/runtime/__init__.py +169 -0
  401. aria_code/runtime/acceptance.py +481 -0
  402. aria_code/runtime/agent_loop.py +1520 -0
  403. aria_code/runtime/approval.py +57 -0
  404. aria_code/runtime/budget.py +232 -0
  405. aria_code/runtime/checkpoints.py +432 -0
  406. aria_code/runtime/crash_report.py +174 -0
  407. aria_code/runtime/events.py +113 -0
  408. aria_code/runtime/gateway.py +150 -0
  409. aria_code/runtime/lsp.py +484 -0
  410. aria_code/runtime/orchestrator.py +55 -0
  411. aria_code/runtime/repo_map.py +700 -0
  412. aria_code/runtime/run_state.py +127 -0
  413. aria_code/runtime/run_store.py +450 -0
  414. aria_code/runtime/self_healing.py +422 -0
  415. aria_code/runtime/subagent.py +547 -0
  416. aria_code/runtime/task_ledger.py +86 -0
  417. aria_code/runtime/task_orchestrator.py +90 -0
  418. aria_code/runtime/tool_executor.py +217 -0
  419. aria_code/runtime/tool_policy.py +107 -0
  420. aria_code/runtime/worktrees.py +215 -0
  421. aria_code/runway_video_client.py +4 -0
  422. aria_code/safety/__init__.py +23 -0
  423. aria_code/safety/permissions.py +306 -0
  424. aria_code/safety/service.py +102 -0
  425. aria_code/setup_wizard.py +673 -0
  426. aria_code/spreadsheet_tools.py +4 -0
  427. aria_code/strategy_vault.py +4 -0
  428. aria_code/tools/__init__.py +0 -0
  429. aria_code/tools/artifact_tools.py +252 -0
  430. aria_code/tools/broker_tools.py +92 -0
  431. aria_code/tools/build_quant_engine.py +97 -0
  432. aria_code/tools/code_audit_tools.py +192 -0
  433. aria_code/tools/computer_use_tools.py +504 -0
  434. aria_code/tools/data_analysis_tools.py +809 -0
  435. aria_code/tools/enterprise_finance_tools.py +156 -0
  436. aria_code/tools/extended_tools.py +240 -0
  437. aria_code/tools/file_analysis_tools.py +885 -0
  438. aria_code/tools/image_gen_tools.py +114 -0
  439. aria_code/tools/local_finance_tools.py +3417 -0
  440. aria_code/tools/logistics_tools.py +135 -0
  441. aria_code/tools/macro_tools.py +369 -0
  442. aria_code/tools/notification_tools.py +249 -0
  443. aria_code/tools/project_tools.py +525 -0
  444. aria_code/tools/realty_data_tools.py +659 -0
  445. aria_code/tools/spreadsheet_tools.py +388 -0
  446. aria_code/tools/stripe_tools.py +115 -0
  447. aria_code/ui/__init__.py +105 -0
  448. aria_code/ui/banner.py +508 -0
  449. aria_code/ui/completer.py +501 -0
  450. aria_code/ui/console.py +281 -0
  451. aria_code/ui/image_render.py +243 -0
  452. aria_code/ui/input_box.py +488 -0
  453. aria_code/ui/picker.py +201 -0
  454. aria_code/ui/render/__init__.py +11 -0
  455. aria_code/ui/render/finance.py +1705 -0
  456. aria_code/ui/render/market.py +225 -0
  457. aria_code/ui/render/output.py +775 -0
  458. aria_code/ui/render/responsive.py +75 -0
  459. aria_code/ui/render/team.py +354 -0
  460. aria_code/ui/robot.py +235 -0
  461. aria_code/ui/startup_dashboard.py +109 -0
  462. aria_code/utils/vscode_uri.py +37 -0
  463. aria_code/video_analysis.py +147 -0
  464. aria_code/video_editor.py +271 -0
  465. aria_code/workspace/__init__.py +6 -0
  466. aria_code/workspace/files.py +193 -0
  467. aria_code/workspace/verify.py +113 -0
  468. aria_code/workspace_changes.py +199 -0
  469. aria_code/workspace_context.py +233 -0
  470. aria_code/workspace_service.py +196 -0
  471. aria_code/workspace_tools.py +150 -0
  472. aria_code-0.52.0.dist-info/METADATA +237 -0
  473. aria_code-0.52.0.dist-info/RECORD +478 -0
  474. aria_code-0.52.0.dist-info/WHEEL +5 -0
  475. aria_code-0.52.0.dist-info/entry_points.txt +3 -0
  476. aria_code-0.52.0.dist-info/licenses/LICENSE +201 -0
  477. aria_code-0.52.0.dist-info/licenses/NOTICE +49 -0
  478. aria_code-0.52.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,617 @@
1
+ # Auto-extracted from aria_cli.py (SlashCommands._SCAFFOLD_TEMPLATES)
2
+
3
+ SCAFFOLD_TEMPLATES = {
4
+ "quant": {
5
+ "desc": "量化策略项目(数据层 / 信号层 / 回测引擎 / 报告)",
6
+ "dirs": ["data/raw", "data/processed", "strategy", "backtest", "report", "tests"],
7
+ "files": {
8
+ "requirements.txt": "akshare\nyfinance\npandas\nnumpy\nmatplotlib\nscipy\n",
9
+ "data/fetcher.py": '''\
10
+ """数据获取层:akshare A股 / yfinance 美股,带本地 CSV 缓存。"""
11
+ import os, pathlib
12
+ import akshare as ak
13
+ import yfinance as yf
14
+ import pandas as pd
15
+
16
+ CACHE = pathlib.Path(__file__).parent / "processed"
17
+ CACHE.mkdir(exist_ok=True)
18
+
19
+ def fetch_ashare(symbol: str, start: str, end: str, adjust: str = "qfq") -> pd.DataFrame:
20
+ cache_f = CACHE / f"{symbol}_{adjust}.csv"
21
+ if cache_f.exists():
22
+ df = pd.read_csv(cache_f, index_col=0, parse_dates=True)
23
+ if str(df.index[-1].date()) >= end:
24
+ return df
25
+ df = ak.stock_zh_a_hist(symbol=symbol, period="daily",
26
+ start_date=start.replace("-",""),
27
+ end_date=end.replace("-",""), adjust=adjust)
28
+ df = df.rename(columns={"日期":"Date","开盘":"Open","最高":"High",
29
+ "最低":"Low","收盘":"Close","成交量":"Volume"})
30
+ df["Date"] = pd.to_datetime(df["Date"])
31
+ df = df.set_index("Date").sort_index()
32
+ df.to_csv(cache_f)
33
+ return df
34
+
35
+ def fetch_us(symbol: str, period: str = "2y") -> pd.DataFrame:
36
+ return yf.Ticker(symbol).history(period=period, auto_adjust=True)[
37
+ ["Open","High","Low","Close","Volume"]]
38
+ ''',
39
+ "strategy/base.py": '''\
40
+ """抽象策略基类:子类只需实现 generate_signals()。"""
41
+ from abc import ABC, abstractmethod
42
+ import pandas as pd
43
+
44
+ class Strategy(ABC):
45
+ name: str = "base"
46
+
47
+ @abstractmethod
48
+ def generate_signals(self, df: pd.DataFrame) -> pd.Series:
49
+ """返回 +1(做多)/ -1(做空)/ 0(空仓)的 Series,与 df.index 对齐。"""
50
+ ...
51
+ ''',
52
+ "strategy/dual_ma.py": '''\
53
+ """双均线策略:短期 MA 上穿长期 MA 买入,下穿卖出。"""
54
+ import pandas as pd
55
+ from .base import Strategy
56
+
57
+ class DualMA(Strategy):
58
+ name = "dual_ma"
59
+
60
+ def __init__(self, fast: int = 5, slow: int = 20):
61
+ self.fast = fast
62
+ self.slow = slow
63
+
64
+ def generate_signals(self, df: pd.DataFrame) -> pd.Series:
65
+ close = df["Close"]
66
+ fast_ma = close.rolling(self.fast).mean()
67
+ slow_ma = close.rolling(self.slow).mean()
68
+ sig = pd.Series(0, index=df.index)
69
+ sig[fast_ma > slow_ma] = 1
70
+ sig[fast_ma < slow_ma] = -1
71
+ # 只在交叉时换仓(减少换手)
72
+ return sig.diff().fillna(0).clip(-1, 1).cumsum().clip(-1, 1)
73
+ ''',
74
+ "strategy/__init__.py": "from .dual_ma import DualMA\n",
75
+ "backtest/engine.py": '''\
76
+ """向量化回测引擎,含 A股交易成本。"""
77
+ import pandas as pd
78
+ import numpy as np
79
+
80
+ # A股交易成本:双边手续费 0.025%×2 + 印花税 0.05%(卖出)+ 滑点 0.1%
81
+ A_SHARE_COST = 0.025/100 * 2 + 0.05/100 + 0.1/100
82
+
83
+ def backtest(df: pd.DataFrame, signals: pd.Series,
84
+ cost_rate: float = A_SHARE_COST,
85
+ initial_capital: float = 1_000_000) -> pd.DataFrame:
86
+ """
87
+ df : OHLCV DataFrame(index=DatetimeIndex)
88
+ signals : +1 做多 / -1 做空 / 0 空仓
89
+ 返回含 equity_curve 和各日 pnl 的 DataFrame
90
+ """
91
+ ret = df["Close"].pct_change()
92
+ pos = signals.shift(1).fillna(0) # 信号次日执行
93
+ turnover = pos.diff().abs().fillna(0)
94
+ strat_ret = pos * ret - turnover * cost_rate
95
+ bnh_ret = ret.copy()
96
+
97
+ cum_strat = (1 + strat_ret).cumprod() * initial_capital
98
+ cum_bnh = (1 + bnh_ret).cumprod() * initial_capital
99
+
100
+ result = pd.DataFrame({
101
+ "strategy": cum_strat, "buy_hold": cum_bnh,
102
+ "daily_ret": strat_ret, "position": pos,
103
+ })
104
+
105
+ # 统计指标
106
+ ann = 252
107
+ sharpe = strat_ret.mean() / strat_ret.std() * np.sqrt(ann) if strat_ret.std() else 0
108
+ max_dd = (cum_strat / cum_strat.cummax() - 1).min()
109
+ total_r = cum_strat.iloc[-1] / initial_capital - 1
110
+ ann_r = (1 + total_r) ** (ann / len(result)) - 1
111
+ wins = (strat_ret[pos.shift(-1) != pos] > 0).mean()
112
+
113
+ result.attrs = dict(sharpe=round(sharpe,2), max_drawdown=round(max_dd,4),
114
+ total_return=round(total_r,4), annual_return=round(ann_r,4),
115
+ win_rate=round(wins,4))
116
+ return result
117
+ ''',
118
+ "backtest/__init__.py": "from .engine import backtest\n",
119
+ "report/plot.py": '''\
120
+ """生成净值曲线 + 回撤图,保存为 PNG。"""
121
+ import matplotlib
122
+ matplotlib.use("Agg")
123
+ import matplotlib.pyplot as plt
124
+ import matplotlib.gridspec as gridspec
125
+ import pandas as pd
126
+ import pathlib
127
+
128
+ OUT = pathlib.Path(__file__).parent / "output"
129
+ OUT.mkdir(exist_ok=True)
130
+
131
+ def plot_result(result: pd.DataFrame, title: str = "Backtest") -> pathlib.Path:
132
+ fig = plt.figure(figsize=(12, 7), facecolor="#0d1117")
133
+ gs = gridspec.GridSpec(2, 1, height_ratios=[3,1], hspace=0.08)
134
+
135
+ ax1 = fig.add_subplot(gs[0])
136
+ ax1.plot(result.index, result["strategy"], color="#3fb950", lw=1.5, label="Strategy")
137
+ ax1.plot(result.index, result["buy_hold"], color="#58a6ff", lw=1.0, label="Buy & Hold", alpha=0.7)
138
+ ax1.set_facecolor("#161b22"); ax1.tick_params(colors="#8b949e"); ax1.legend(facecolor="#21262d", edgecolor="#30363d", labelcolor="#e6edf3")
139
+ ax1.set_title(title, color="#e6edf3", fontsize=13)
140
+ for spine in ax1.spines.values(): spine.set_color("#30363d")
141
+
142
+ dd = result["strategy"] / result["strategy"].cummax() - 1
143
+ ax2 = fig.add_subplot(gs[1], sharex=ax1)
144
+ ax2.fill_between(result.index, dd, 0, color="#f85149", alpha=0.6)
145
+ ax2.set_facecolor("#161b22"); ax2.tick_params(colors="#8b949e")
146
+ ax2.set_ylabel("Drawdown", color="#8b949e", fontsize=9)
147
+ for spine in ax2.spines.values(): spine.set_color("#30363d")
148
+
149
+ a = result.attrs
150
+ fig.text(0.12, 0.02, f"Annual {a.get('annual_return',0):.1%} Sharpe {a.get('sharpe',0):.2f} MaxDD {a.get('max_drawdown',0):.1%} Win {a.get('win_rate',0):.1%}", color="#8b949e", fontsize=9)
151
+
152
+ out_f = OUT / f"{title.replace(' ','_')}.png"
153
+ plt.savefig(out_f, dpi=130, bbox_inches="tight", facecolor=fig.get_facecolor())
154
+ plt.close(fig)
155
+ print(f"图表已保存: {out_f}")
156
+ return out_f
157
+ ''',
158
+ "report/__init__.py": "from .plot import plot_result\n",
159
+ "main.py": '''\
160
+ """运行量化策略回测的主入口。"""
161
+ import sys, pathlib
162
+ sys.path.insert(0, str(pathlib.Path(__file__).parent))
163
+
164
+ from data.fetcher import fetch_ashare
165
+ from strategy import DualMA
166
+ from backtest import backtest
167
+ from report import plot_result
168
+ from datetime import datetime, timedelta
169
+
170
+ SYMBOL = "600519" # 贵州茅台(示例)
171
+ END = datetime.now().strftime("%Y-%m-%d")
172
+ START = (datetime.now() - timedelta(days=730)).strftime("%Y-%m-%d")
173
+
174
+ print(f"抓取 {SYMBOL} 数据 {START} → {END}...")
175
+ df = fetch_ashare(SYMBOL, START, END)
176
+ print(f"共 {len(df)} 条 K线")
177
+
178
+ strategy = DualMA(fast=5, slow=20)
179
+ signals = strategy.generate_signals(df)
180
+ result = backtest(df, signals)
181
+
182
+ a = result.attrs
183
+ print(f"\n===== 回测结果 ({SYMBOL} · 双均线5/20) =====")
184
+ print(f"总收益: {a['total_return']:.2%}")
185
+ print(f"年化收益: {a['annual_return']:.2%}")
186
+ print(f"夏普比率: {a['sharpe']:.2f}")
187
+ print(f"最大回撤: {a['max_drawdown']:.2%}")
188
+ print(f"胜率: {a['win_rate']:.2%}")
189
+
190
+ plot_result(result, f"{SYMBOL}_DualMA")
191
+ ''',
192
+ "tests/test_strategy.py": '''\
193
+ """基础单元测试:策略信号生成 + 回测引擎。"""
194
+ import sys, pathlib
195
+ sys.path.insert(0, str(pathlib.Path(__file__).parent.parent))
196
+ import pandas as pd
197
+ import numpy as np
198
+ from strategy import DualMA
199
+ from backtest import backtest
200
+
201
+ def _make_df(n=100):
202
+ dates = pd.date_range("2024-01-01", periods=n)
203
+ close = pd.Series(100 + np.cumsum(np.random.randn(n)), index=dates)
204
+ return pd.DataFrame({"Open":close,"High":close*1.01,"Low":close*0.99,"Close":close,"Volume":1e6})
205
+
206
+ def test_signal_shape():
207
+ df = _make_df()
208
+ sig = DualMA(fast=5,slow=20).generate_signals(df)
209
+ assert len(sig) == len(df)
210
+ assert set(sig.unique()).issubset({-1,0,1})
211
+
212
+ def test_backtest_runs():
213
+ df = _make_df()
214
+ sig = DualMA().generate_signals(df)
215
+ res = backtest(df, sig)
216
+ assert "strategy" in res.columns
217
+ assert res.attrs.get("sharpe") is not None
218
+
219
+ if __name__ == "__main__":
220
+ test_signal_shape(); test_backtest_runs(); print("All tests passed.")
221
+ ''',
222
+ },
223
+ },
224
+ "analysis": {
225
+ "desc": "数据分析项目(数据加载 / 清洗 / 可视化 / 报告)",
226
+ "dirs": ["data/raw", "data/processed", "src", "output", "notebooks"],
227
+ "files": {
228
+ "requirements.txt": "pandas\nnumpy\nmatplotlib\nseaborn\nopenpyxl\nyfinance\n",
229
+ "src/loader.py": '''\
230
+ """数据加载工具:支持 CSV / Excel / yfinance。"""
231
+ import pandas as pd, pathlib, yfinance as yf
232
+
233
+ DATA = pathlib.Path(__file__).parent.parent / "data"
234
+
235
+ def load_csv(filename: str, **kw) -> pd.DataFrame:
236
+ return pd.read_csv(DATA / "raw" / filename, **kw)
237
+
238
+ def load_excel(filename: str, sheet=0, **kw) -> pd.DataFrame:
239
+ return pd.read_excel(DATA / "raw" / filename, sheet_name=sheet, **kw)
240
+
241
+ def load_stock(symbol: str, period: str = "1y") -> pd.DataFrame:
242
+ df = yf.Ticker(symbol).history(period=period, auto_adjust=True, progress=False)
243
+ return df[["Open","High","Low","Close","Volume"]]
244
+
245
+ def save_processed(df: pd.DataFrame, name: str) -> pathlib.Path:
246
+ out = DATA / "processed" / name
247
+ df.to_csv(out); return out
248
+ ''',
249
+ "src/analyzer.py": '''\
250
+ """常用分析函数:描述统计 / 相关性 / 滚动指标。"""
251
+ import pandas as pd, numpy as np
252
+
253
+ def describe_df(df: pd.DataFrame) -> pd.DataFrame:
254
+ return df.describe().round(4)
255
+
256
+ def correlation_matrix(df: pd.DataFrame) -> pd.DataFrame:
257
+ return df.corr().round(4)
258
+
259
+ def rolling_stats(series: pd.Series, window: int = 20) -> pd.DataFrame:
260
+ return pd.DataFrame({
261
+ "mean": series.rolling(window).mean(),
262
+ "std": series.rolling(window).std(),
263
+ "zscore": (series - series.rolling(window).mean()) / series.rolling(window).std(),
264
+ })
265
+
266
+ def annualized_return(series: pd.Series) -> float:
267
+ ret = series.pct_change().dropna()
268
+ return float((1 + ret.mean()) ** 252 - 1)
269
+
270
+ def max_drawdown(series: pd.Series) -> float:
271
+ return float((series / series.cummax() - 1).min())
272
+ ''',
273
+ "src/visualizer.py": '''\
274
+ """可视化工具:折线图 / 直方图 / 热力图。"""
275
+ import matplotlib
276
+ matplotlib.use("Agg")
277
+ import matplotlib.pyplot as plt
278
+ import seaborn as sns
279
+ import pandas as pd, pathlib
280
+
281
+ OUT = pathlib.Path(__file__).parent.parent / "output"
282
+ OUT.mkdir(exist_ok=True)
283
+ plt.style.use("dark_background")
284
+
285
+ def plot_series(series: pd.Series, title: str = "", filename: str = "plot.png") -> pathlib.Path:
286
+ fig, ax = plt.subplots(figsize=(11,4), facecolor="#0d1117")
287
+ ax.plot(series.index, series.values, color="#58a6ff", lw=1.2)
288
+ ax.set_title(title, color="#e6edf3"); ax.set_facecolor("#161b22")
289
+ for sp in ax.spines.values(): sp.set_color("#30363d")
290
+ ax.tick_params(colors="#8b949e")
291
+ out = OUT / filename
292
+ plt.savefig(out, dpi=130, bbox_inches="tight", facecolor=fig.get_facecolor())
293
+ plt.close(); return out
294
+
295
+ def plot_heatmap(df: pd.DataFrame, title: str = "Correlation", filename: str = "heatmap.png") -> pathlib.Path:
296
+ fig, ax = plt.subplots(figsize=(8,6), facecolor="#0d1117")
297
+ sns.heatmap(df, annot=True, fmt=".2f", cmap="RdYlGn", ax=ax,
298
+ linewidths=0.3, linecolor="#30363d", cbar_kws={"shrink":0.7})
299
+ ax.set_title(title, color="#e6edf3"); ax.tick_params(colors="#8b949e")
300
+ out = OUT / filename
301
+ plt.savefig(out, dpi=130, bbox_inches="tight", facecolor=fig.get_facecolor())
302
+ plt.close(); return out
303
+ ''',
304
+ "main.py": '''\
305
+ """数据分析项目入口示例。"""
306
+ import sys, pathlib
307
+ sys.path.insert(0, str(pathlib.Path(__file__).parent))
308
+ from src.loader import load_stock
309
+ from src.analyzer import describe_df, correlation_matrix, annualized_return, max_drawdown
310
+ from src.visualizer import plot_series
311
+
312
+ # 示例:分析多支股票
313
+ SYMBOLS = ["AAPL","MSFT","NVDA"]
314
+ closes = {}
315
+ for sym in SYMBOLS:
316
+ df = load_stock(sym, period="1y")
317
+ closes[sym] = df["Close"]
318
+ print(f"{sym}: 年化收益 {annualized_return(df['Close']):.2%} 最大回撤 {max_drawdown(df['Close']):.2%}")
319
+
320
+ import pandas as pd
321
+ closes_df = pd.DataFrame(closes)
322
+ print("\n相关性矩阵:")
323
+ print(correlation_matrix(closes_df))
324
+
325
+ plot_series(closes_df["AAPL"], "AAPL Close Price", "aapl_close.png")
326
+ print("图表已保存到 output/")
327
+ ''',
328
+ },
329
+ },
330
+ "fastapi": {
331
+ "desc": "FastAPI 金融数据 API 服务(行情 / 技术指标 / 基本面)",
332
+ "dirs": ["app/routers", "app/schemas", "app/services", "tests"],
333
+ "files": {
334
+ "requirements.txt": "fastapi\nuvicorn[standard]\nyfinance\nrequests\npandas\nnumpy\n",
335
+ "app/__init__.py": "",
336
+ "app/main.py": '''\
337
+ """FastAPI 主应用入口。"""
338
+ from fastapi import FastAPI
339
+ from app.routers import market, health
340
+
341
+ app = FastAPI(title="Aria Finance API", version="1.0.0",
342
+ description="金融行情与分析 REST API")
343
+
344
+ app.include_router(health.router)
345
+ app.include_router(market.router, prefix="/market", tags=["market"])
346
+
347
+ if __name__ == "__main__":
348
+ import uvicorn
349
+ uvicorn.run("app.main:app", host="0.0.0.0", port=8000, reload=True)
350
+ ''',
351
+ "app/routers/__init__.py": "",
352
+ "app/routers/health.py": '''\
353
+ from fastapi import APIRouter
354
+ from datetime import datetime
355
+
356
+ router = APIRouter()
357
+
358
+ @router.get("/health")
359
+ def health_check():
360
+ return {"status": "ok", "timestamp": datetime.now().isoformat()}
361
+ ''',
362
+ "app/routers/market.py": '''\
363
+ """行情路由:报价 / 历史 K 线 / 技术指标。"""
364
+ from fastapi import APIRouter, HTTPException, Query
365
+ from app.services.market_service import get_quote, get_history, get_technicals
366
+
367
+ router = APIRouter()
368
+
369
+ @router.get("/quote/{symbol}")
370
+ def quote(symbol: str):
371
+ data = get_quote(symbol.upper())
372
+ if not data:
373
+ raise HTTPException(status_code=404, detail=f"No data for {symbol}")
374
+ return data
375
+
376
+ @router.get("/history/{symbol}")
377
+ def history(symbol: str, period: str = Query("3mo", description="1mo/3mo/6mo/1y/2y")):
378
+ records = get_history(symbol.upper(), period)
379
+ return {"symbol": symbol.upper(), "period": period, "data": records}
380
+
381
+ @router.get("/technicals/{symbol}")
382
+ def technicals(symbol: str):
383
+ return get_technicals(symbol.upper())
384
+ ''',
385
+ "app/services/__init__.py": "",
386
+ "app/services/market_service.py": '''\
387
+ """市场数据服务层(基于 yfinance)。"""
388
+ import yfinance as yf
389
+ import pandas as pd, numpy as np
390
+ from typing import Optional
391
+
392
+ def get_quote(symbol: str) -> Optional[dict]:
393
+ try:
394
+ t = yf.Ticker(symbol)
395
+ info = t.info or {}
396
+ price = info.get("currentPrice") or info.get("regularMarketPrice")
397
+ if not price:
398
+ hist = t.history(period="1d", auto_adjust=True)
399
+ price = float(hist["Close"].iloc[-1]) if not hist.empty else None
400
+ return {
401
+ "symbol": symbol,
402
+ "price": price,
403
+ "prev_close": info.get("previousClose"),
404
+ "open": info.get("open"),
405
+ "day_high": info.get("dayHigh"),
406
+ "day_low": info.get("dayLow"),
407
+ "volume": info.get("volume"),
408
+ "market_cap": info.get("marketCap"),
409
+ "pe_ratio": info.get("trailingPE"),
410
+ "name": info.get("longName", symbol),
411
+ "currency": info.get("currency", "USD"),
412
+ }
413
+ except Exception:
414
+ return None
415
+
416
+ def get_history(symbol: str, period: str = "3mo") -> list:
417
+ try:
418
+ df = yf.Ticker(symbol).history(period=period, auto_adjust=True)
419
+ df = df.reset_index()
420
+ df["Date"] = df["Date"].dt.strftime("%Y-%m-%d")
421
+ return df[["Date","Open","High","Low","Close","Volume"]].round(4).to_dict(orient="records")
422
+ except Exception:
423
+ return []
424
+
425
+ def get_technicals(symbol: str) -> dict:
426
+ try:
427
+ df = yf.Ticker(symbol).history(period="6mo", auto_adjust=True)
428
+ close = df["Close"]
429
+ rsi_period = 14
430
+ delta = close.diff()
431
+ gain = delta.clip(lower=0).rolling(rsi_period).mean()
432
+ loss = (-delta.clip(upper=0)).rolling(rsi_period).mean()
433
+ rs = gain / loss
434
+ rsi = float((100 - 100 / (1 + rs)).iloc[-1])
435
+ ema12 = close.ewm(span=12).mean()
436
+ ema26 = close.ewm(span=26).mean()
437
+ macd = ema12 - ema26
438
+ signal = macd.ewm(span=9).mean()
439
+ return {
440
+ "symbol": symbol,
441
+ "rsi": round(rsi, 2),
442
+ "macd": round(float(macd.iloc[-1]), 4),
443
+ "macd_signal": round(float(signal.iloc[-1]), 4),
444
+ "ma20": round(float(close.rolling(20).mean().iloc[-1]), 2),
445
+ "ma60": round(float(close.rolling(60).mean().iloc[-1]), 2),
446
+ "bb_upper": round(float(close.rolling(20).mean().iloc[-1] + 2*close.rolling(20).std().iloc[-1]), 2),
447
+ "bb_lower": round(float(close.rolling(20).mean().iloc[-1] - 2*close.rolling(20).std().iloc[-1]), 2),
448
+ }
449
+ except Exception as e:
450
+ return {"error": str(e)}
451
+ ''',
452
+ "tests/test_api.py": '''\
453
+ """API 单元测试(不启动服务器)。"""
454
+ import sys, pathlib
455
+ sys.path.insert(0, str(pathlib.Path(__file__).parent.parent))
456
+ from fastapi.testclient import TestClient
457
+ from app.main import app
458
+
459
+ client = TestClient(app)
460
+
461
+ def test_health():
462
+ r = client.get("/health")
463
+ assert r.status_code == 200
464
+ assert r.json()["status"] == "ok"
465
+
466
+ def test_quote_valid():
467
+ r = client.get("/market/quote/AAPL")
468
+ assert r.status_code == 200
469
+ data = r.json()
470
+ assert "price" in data
471
+ assert data["symbol"] == "AAPL"
472
+
473
+ def test_history():
474
+ r = client.get("/market/history/AAPL?period=1mo")
475
+ assert r.status_code == 200
476
+ assert len(r.json()["data"]) > 0
477
+
478
+ if __name__ == "__main__":
479
+ test_health(); test_quote_valid(); test_history(); print("All tests passed.")
480
+ ''',
481
+ "run.py": '''\
482
+ """启动 FastAPI 开发服务器。"""
483
+ import uvicorn
484
+ uvicorn.run("app.main:app", host="0.0.0.0", port=8000, reload=True)
485
+ ''',
486
+ },
487
+ },
488
+ "dashboard": {
489
+ "desc": "Plotly Dash 交互式金融看板",
490
+ "dirs": ["assets", "components", "data"],
491
+ "files": {
492
+ "requirements.txt": "dash\nplotly\nyfinance\npandas\nnumpy\n",
493
+ "components/__init__.py": "",
494
+ "components/chart.py": '''\
495
+ """K线图 + 均线组件。"""
496
+ import yfinance as yf
497
+ import plotly.graph_objects as go
498
+ from plotly.subplots import make_subplots
499
+ import pandas as pd, numpy as np
500
+
501
+ def build_candlestick(symbol: str, period: str = "6mo") -> go.Figure:
502
+ df = yf.Ticker(symbol).history(period=period, auto_adjust=True)
503
+ df["MA20"] = df["Close"].rolling(20).mean()
504
+ df["MA60"] = df["Close"].rolling(60).mean()
505
+
506
+ fig = make_subplots(rows=2, cols=1, shared_xaxes=True,
507
+ row_heights=[0.75,0.25], vertical_spacing=0.03)
508
+ fig.add_trace(go.Candlestick(
509
+ x=df.index, open=df["Open"], high=df["High"],
510
+ low=df["Low"], close=df["Close"], name="K线",
511
+ increasing_line_color="#3fb950", decreasing_line_color="#f85149"
512
+ ), row=1, col=1)
513
+ fig.add_trace(go.Scatter(x=df.index, y=df["MA20"], name="MA20",
514
+ line=dict(color="#58a6ff", width=1)), row=1, col=1)
515
+ fig.add_trace(go.Scatter(x=df.index, y=df["MA60"], name="MA60",
516
+ line=dict(color="#e3b341", width=1)), row=1, col=1)
517
+ fig.add_trace(go.Bar(x=df.index, y=df["Volume"], name="成交量",
518
+ marker_color="#30363d"), row=2, col=1)
519
+ fig.update_layout(
520
+ template="plotly_dark", plot_bgcolor="#0d1117", paper_bgcolor="#010409",
521
+ title=f"{symbol} | {period}", height=600,
522
+ xaxis_rangeslider_visible=False,
523
+ legend=dict(bgcolor="#161b22", bordercolor="#30363d"),
524
+ )
525
+ return fig
526
+ ''',
527
+ "app.py": '''\
528
+ """Dash 交互式金融看板主应用。"""
529
+ import dash
530
+ from dash import dcc, html, Input, Output, State
531
+ from components.chart import build_candlestick
532
+ import yfinance as yf
533
+
534
+ app = dash.Dash(__name__, title="Aria Dashboard")
535
+
536
+ PERIODS = ["1mo","3mo","6mo","1y","2y","5y"]
537
+
538
+ app.layout = html.Div([
539
+ html.Div([
540
+ html.H1("Aria 金融看板", style={"color":"#e6edf3","fontSize":"22px","fontWeight":"700","margin":"0"}),
541
+ html.Div([
542
+ dcc.Input(id="symbol-input", value="AAPL", type="text", debounce=True,
543
+ placeholder="输入股票代码",
544
+ style={"background":"#161b22","color":"#e6edf3","border":"1px solid #30363d",
545
+ "borderRadius":"6px","padding":"8px 12px","width":"160px","marginRight":"8px"}),
546
+ dcc.Dropdown(id="period-dd", options=[{"label":p,"value":p} for p in PERIODS],
547
+ value="6mo", clearable=False,
548
+ style={"width":"100px","background":"#161b22","color":"#0d1117"}),
549
+ ], style={"display":"flex","alignItems":"center","gap":"8px"}),
550
+ ], style={"display":"flex","justifyContent":"space-between","alignItems":"center",
551
+ "padding":"16px 24px","borderBottom":"1px solid #21262d","background":"#010409"}),
552
+
553
+ dcc.Loading(dcc.Graph(id="main-chart", style={"height":"600px"}),
554
+ color="#58a6ff"),
555
+
556
+ html.Div(id="stats-row", style={"display":"flex","gap":"10px",
557
+ "padding":"12px 24px","background":"#010409"}),
558
+ ], style={"background":"#010409","minHeight":"100vh","fontFamily":"-apple-system,sans-serif"})
559
+
560
+ @app.callback(
561
+ [Output("main-chart","figure"), Output("stats-row","children")],
562
+ [Input("symbol-input","value"), Input("period-dd","value")],
563
+ prevent_initial_call=False,
564
+ )
565
+ def update_chart(symbol, period):
566
+ if not symbol:
567
+ return dash.no_update, dash.no_update
568
+ symbol = symbol.strip().upper()
569
+ fig = build_candlestick(symbol, period)
570
+ try:
571
+ info = yf.Ticker(symbol).info or {}
572
+ price = info.get("currentPrice") or info.get("regularMarketPrice","—")
573
+ mktcap = info.get("marketCap")
574
+ pe = info.get("trailingPE","—")
575
+ name = info.get("longName", symbol)
576
+ mktcap_s = f"${mktcap/1e9:.1f}B" if mktcap else "—"
577
+ except Exception:
578
+ name,price,mktcap_s,pe = symbol,"—","—","—"
579
+
580
+ def kpi(label, val):
581
+ return html.Div([
582
+ html.Div(label, style={"fontSize":"11px","color":"#8b949e","marginBottom":"4px"}),
583
+ html.Div(str(val), style={"fontSize":"18px","fontWeight":"700","color":"#e6edf3"}),
584
+ ], style={"background":"#161b22","border":"1px solid #30363d","borderRadius":"8px",
585
+ "padding":"12px 16px","minWidth":"120px"})
586
+
587
+ stats = [kpi("公司", name[:20]), kpi("现价", price),
588
+ kpi("市值", mktcap_s), kpi("市盈率", pe)]
589
+ return fig, stats
590
+
591
+ if __name__ == "__main__":
592
+ app.run(debug=True, host="0.0.0.0", port=8050)
593
+ ''',
594
+ "README.md": '''\
595
+ # Aria Dashboard
596
+
597
+ 交互式金融看板(Plotly Dash)。
598
+
599
+ ## 启动
600
+
601
+ ```bash
602
+ pip install -r requirements.txt
603
+ python app.py
604
+ ```
605
+
606
+ 浏览器访问 http://localhost:8050
607
+
608
+ ## 功能
609
+
610
+ - K线图 + 成交量(MA20/MA60)
611
+ - 多周期切换(1mo 到 5y)
612
+ - 基本面 KPI(市值、市盈率)
613
+ ''',
614
+ },
615
+ },
616
+ }
617
+