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,414 @@
1
+ """
2
+ brokers/config.py — 券商配置加载与管理
3
+ ========================================
4
+ 配置文件位置:~/.aria-code/brokers.json(或由 ARIA_HOME 环境变量覆盖)
5
+
6
+ 示例配置::
7
+
8
+ {
9
+ "brokers": [
10
+ {
11
+ "id": "xt_main",
12
+ "type": "xtquant",
13
+ "label": "中信主账户",
14
+ "account_id": "1234567890",
15
+ "default": true
16
+ },
17
+ {
18
+ "id": "ibkr_us",
19
+ "type": "ibkr",
20
+ "label": "盈透美股",
21
+ "host": "127.0.0.1",
22
+ "port": 7496,
23
+ "client_id": 1
24
+ },
25
+ {
26
+ "id": "alpaca_paper",
27
+ "type": "alpaca",
28
+ "label": "Alpaca 模拟盘",
29
+ "api_key": "PKxxx",
30
+ "api_secret": "xxx",
31
+ "paper": true
32
+ },
33
+ {
34
+ "id": "futu_hk",
35
+ "type": "futu",
36
+ "label": "富途港股",
37
+ "host": "127.0.0.1",
38
+ "port": 11111,
39
+ "market": "HK"
40
+ },
41
+ {
42
+ "id": "tiger_us",
43
+ "type": "tiger",
44
+ "label": "老虎美股",
45
+ "tiger_id": "xxx",
46
+ "private_key_path": "~/.aria-code/tiger_rsa.pem",
47
+ "account": "xxx"
48
+ },
49
+ {
50
+ "id": "longbridge_cn",
51
+ "type": "longbridge",
52
+ "label": "长桥A股",
53
+ "app_key": "xxx",
54
+ "app_secret": "xxx",
55
+ "access_token": "xxx"
56
+ }
57
+ ]
58
+ }
59
+
60
+ 支持的 type 值:
61
+ paper 本地仿盘账户(无真实券商连接)
62
+ xtquant 迅投(中信、华鑫、浙商等)
63
+ easytrader easytrader(同花顺、通达信、华泰、国君)
64
+ futu 富途牛牛 OpenAPI(港股/美股/A股)
65
+ tiger 老虎证券 OpenAPI(美股/港股/A股)
66
+ longbridge 长桥证券 OpenAPI(港股/美股/A股)
67
+ ibkr Interactive Brokers TWS/Gateway
68
+ alpaca Alpaca Markets(美股,支持模拟盘)
69
+ webull Webull(美股)
70
+ """
71
+
72
+ from __future__ import annotations
73
+
74
+ import json
75
+ import os
76
+ from pathlib import Path
77
+ from typing import Any, Dict, List, Optional
78
+ from aria_code.packages.aria_core.paths import aria_home
79
+
80
+
81
+ def _resolve_aria_home() -> Path:
82
+ """Resolve the Aria config directory (same logic as aria_cli.py).
83
+
84
+ Priority:
85
+ 1. ARIA_HOME env var (explicit override)
86
+ 2. ~/.arthera — legacy path, kept for backward compat if it exists
87
+ 3. ~/.aria-code — default for fresh installs
88
+ """
89
+ if "ARIA_HOME" in os.environ:
90
+ return Path(os.environ["ARIA_HOME"]).expanduser()
91
+ legacy = aria_home()
92
+ if legacy.exists():
93
+ return legacy
94
+ return Path.home() / ".aria-code"
95
+
96
+
97
+ BROKERS_CONFIG_PATH = _resolve_aria_home() / "brokers.json"
98
+
99
+
100
+ # ── 读写工具 ───────────────────────────────────────────────────────────────────
101
+
102
+ def load_config() -> Dict[str, Any]:
103
+ """加载 brokers.json,文件不存在时返回空 {"brokers": []}。"""
104
+ if not BROKERS_CONFIG_PATH.exists():
105
+ return {"brokers": []}
106
+ try:
107
+ with open(BROKERS_CONFIG_PATH, encoding="utf-8") as f:
108
+ return json.load(f)
109
+ except Exception:
110
+ return {"brokers": []}
111
+
112
+
113
+ def save_config(cfg: Dict[str, Any]) -> None:
114
+ """保存配置到 brokers.json(0600,仅本人可读)。
115
+
116
+ 这个文件存的是券商密码 / api_secret / access_token —— 本仓库里价值最高的
117
+ 凭据。此前它按进程 umask 写出,通常是 0644,同机器上任何账号可读。
118
+ """
119
+ from aria_code.packages.aria_core.secure_file import write_secret_json
120
+
121
+ write_secret_json(BROKERS_CONFIG_PATH, cfg)
122
+
123
+
124
+ def list_broker_configs() -> List[Dict[str, Any]]:
125
+ """返回所有已配置的券商列表。"""
126
+ return load_config().get("brokers", [])
127
+
128
+
129
+ def get_broker_config(broker_id: str) -> Optional[Dict[str, Any]]:
130
+ """根据 id 查找某个券商配置。"""
131
+ for b in list_broker_configs():
132
+ if b.get("id") == broker_id:
133
+ return b
134
+ return None
135
+
136
+
137
+ def get_default_broker_config() -> Optional[Dict[str, Any]]:
138
+ """返回标记了 default=true 的券商,或第一个。"""
139
+ brokers = list_broker_configs()
140
+ if not brokers:
141
+ return None
142
+ for b in brokers:
143
+ if b.get("default"):
144
+ return b
145
+ return brokers[0]
146
+
147
+
148
+ def add_broker_config(cfg: Dict[str, Any]) -> None:
149
+ """新增一条券商配置(id 重复时覆盖)。"""
150
+ data = load_config()
151
+ brokers = data.get("brokers", [])
152
+ brokers = [b for b in brokers if b.get("id") != cfg.get("id")]
153
+ brokers.append(cfg)
154
+ data["brokers"] = brokers
155
+ save_config(data)
156
+
157
+
158
+ def remove_broker_config(broker_id: str) -> bool:
159
+ """删除某个券商配置,返回 True 表示找到并删除。"""
160
+ data = load_config()
161
+ before = len(data.get("brokers", []))
162
+ data["brokers"] = [b for b in data.get("brokers", []) if b.get("id") != broker_id]
163
+ if len(data["brokers"]) < before:
164
+ save_config(data)
165
+ return True
166
+ return False
167
+
168
+
169
+ def set_default_broker(broker_id: str) -> bool:
170
+ """设置默认券商。"""
171
+ data = load_config()
172
+ found = False
173
+ for b in data.get("brokers", []):
174
+ if b.get("id") == broker_id:
175
+ b["default"] = True
176
+ found = True
177
+ else:
178
+ b.pop("default", None)
179
+ if found:
180
+ save_config(data)
181
+ return found
182
+
183
+
184
+ # ── 聊天内确认下单开关 ──────────────────────────────────────────────────────────
185
+ # 默认关闭,且只能在终端里手动开启(见 apps/cli/commands/broker_cmds.py 的
186
+ # `/trade allow-chat-confirm <broker_id>`——那条命令本身要求真人在终端里
187
+ # 原样重新输入这个券商的 id(不是 y/yes)才会调用 set_chat_confirm_enabled)。
188
+ # 这个开关本身永远不能通过 MCP/聊天打开,只能被查询和使用——打开这道门的
189
+ # 动作必须发生在终端键盘前,跟 /trade confirm 那道"真正下单"的门是同一个
190
+ # 安全等级。见 packages/aria_mcp/server.py 的 _call_broker_confirm_order。
191
+
192
+ def is_chat_confirm_enabled(broker_id: str) -> bool:
193
+ """某个券商是否已经被用户在终端里显式开启了'聊天内确认下单'。"""
194
+ cfg = get_broker_config(broker_id)
195
+ return bool(cfg and cfg.get("chat_confirm_enabled") is True)
196
+
197
+
198
+ def set_chat_confirm_enabled(broker_id: str, enabled: bool) -> bool:
199
+ """开启/关闭某个券商的'聊天内确认下单'。返回 True 表示找到并设置成功。
200
+
201
+ 调用方(`/broker allow-chat-confirm`)负责在调用这个函数之前,先让
202
+ 真人在终端里做一次明确、不容易误触的确认——这个函数本身不做任何
203
+ 额外确认,只是纯粹的配置读写。"""
204
+ data = load_config()
205
+ found = False
206
+ for b in data.get("brokers", []):
207
+ if b.get("id") == broker_id:
208
+ b["chat_confirm_enabled"] = bool(enabled)
209
+ found = True
210
+ break
211
+ if found:
212
+ save_config(data)
213
+ return found
214
+
215
+
216
+ # ── 配置校验 ──────────────────────────────────────────────────────────────────
217
+
218
+ # 每种 type 必需的字段
219
+ _REQUIRED_FIELDS: Dict[str, List[str]] = {
220
+ "paper": [],
221
+ "xtquant": ["account_id"],
222
+ "easytrader": ["broker_name"],
223
+ "futu": ["host", "port"], # FutuOpenD must be running locally
224
+ "tiger": ["tiger_id", "private_key_path", "account"],
225
+ "longbridge": ["app_key", "app_secret", "access_token"],
226
+ "ibkr": ["host", "port"], # TWS/Gateway host:port required
227
+ "alpaca": ["api_key", "api_secret"],
228
+ "webull": ["username", "password"], # read-only, still needs credentials
229
+ "trading212": ["api_key"],
230
+ }
231
+
232
+ _TYPE_LABELS: Dict[str, str] = {
233
+ "paper": "Aria 本地仿盘账户",
234
+ "xtquant": "迅投 XTQuant(中信/华鑫/浙商等)",
235
+ "easytrader": "EasyTrader(同花顺/通达信/华泰/国君)",
236
+ "futu": "富途牛牛 OpenAPI",
237
+ "tiger": "老虎证券 OpenAPI",
238
+ "longbridge": "长桥证券 OpenAPI",
239
+ "ibkr": "Interactive Brokers TWS/Gateway",
240
+ "alpaca": "Alpaca Markets(美股 / 模拟盘)",
241
+ "webull": "Webull(美股)",
242
+ "trading212": "Trading212(英国 Invest/ISA)",
243
+ }
244
+
245
+
246
+ _RECOMMENDED_FIELDS: Dict[str, List[str]] = {
247
+ "paper": ["starting_cash", "currency"],
248
+ "futu": ["market"],
249
+ "ibkr": ["client_id"],
250
+ "alpaca": ["paper"],
251
+ }
252
+
253
+
254
+ def validate_broker_config(cfg: Dict[str, Any]) -> List[str]:
255
+ """校验券商配置,返回错误列表(空列表=通过)。
256
+
257
+ Warnings (prefixed with '⚠ ') are non-fatal but worth showing.
258
+ """
259
+ errors: List[str] = []
260
+ if not cfg.get("id"):
261
+ errors.append("缺少 'id' 字段")
262
+ if not cfg.get("label"):
263
+ errors.append("⚠ 建议设置 'label' 字段(账户显示名称)")
264
+ broker_type = cfg.get("type", "")
265
+ if not broker_type:
266
+ errors.append("缺少 'type' 字段")
267
+ elif broker_type not in _REQUIRED_FIELDS:
268
+ errors.append(f"不支持的 type: {broker_type!r} (支持: {', '.join(_REQUIRED_FIELDS)})")
269
+ else:
270
+ for req in _REQUIRED_FIELDS[broker_type]:
271
+ if not cfg.get(req):
272
+ errors.append(f"{broker_type} 缺少必需字段: '{req}'")
273
+ for rec in _RECOMMENDED_FIELDS.get(broker_type, []):
274
+ if not cfg.get(rec):
275
+ errors.append(f"⚠ {broker_type} 建议设置 '{rec}' 字段")
276
+ return errors
277
+
278
+
279
+ def supported_broker_types() -> Dict[str, str]:
280
+ """返回所有支持的券商类型 {type: 描述}。"""
281
+ return dict(_TYPE_LABELS)
282
+
283
+
284
+ # ── 生成配置模板 ──────────────────────────────────────────────────────────────
285
+
286
+ _TEMPLATES: Dict[str, Dict[str, Any]] = {
287
+ "paper": {
288
+ "id": "paper_main",
289
+ "type": "paper",
290
+ "label": "Aria 仿盘账户",
291
+ "mode": "paper",
292
+ "starting_cash": 100000,
293
+ "currency": "USD",
294
+ "default": True,
295
+ "_comment": "本地仿盘账户,不连接真实券商;订单写入 ~/.arthera/paper_ledger.json"
296
+ },
297
+ "xtquant": {
298
+ "id": "xt_main",
299
+ "type": "xtquant",
300
+ "label": "中信主账户",
301
+ "mode": "read_only",
302
+ "allow_live_trade": False,
303
+ "require_confirm": True,
304
+ "account_id": "YOUR_ACCOUNT_ID",
305
+ "default": True,
306
+ "_comment": "需安装 xtquant: pip install xtquant (仅 Windows/Linux)"
307
+ },
308
+ "easytrader": {
309
+ "id": "ht_main",
310
+ "type": "easytrader",
311
+ "label": "华泰账户",
312
+ "mode": "read_only",
313
+ "allow_live_trade": False,
314
+ "require_confirm": True,
315
+ "broker_name": "huatai",
316
+ "exe_path": "C:\\华泰证券\\xiadan.exe",
317
+ "_comment": "broker_name 可选: huatai/guojun/ths/tdx/yh/zszq/xq"
318
+ },
319
+ "futu": {
320
+ "id": "futu_hk",
321
+ "type": "futu",
322
+ "label": "富途港股",
323
+ "mode": "read_only",
324
+ "allow_live_trade": False,
325
+ "require_confirm": True,
326
+ "host": "127.0.0.1",
327
+ "port": 11111,
328
+ "market": "HK",
329
+ "_comment": "需安装 futu-api: pip install futu-api 并启动富途 OpenD"
330
+ },
331
+ "tiger": {
332
+ "id": "tiger_us",
333
+ "type": "tiger",
334
+ "label": "老虎美股",
335
+ "mode": "read_only",
336
+ "allow_live_trade": False,
337
+ "require_confirm": True,
338
+ "tiger_id": "YOUR_TIGER_ID",
339
+ "private_key_path": "~/.aria-code/tiger_rsa.pem",
340
+ "account": "YOUR_ACCOUNT",
341
+ "_comment": "需安装 tigeropen: pip install tigeropen"
342
+ },
343
+ "longbridge": {
344
+ "id": "lb_cn",
345
+ "type": "longbridge",
346
+ "label": "长桥A股",
347
+ "mode": "read_only",
348
+ "allow_live_trade": False,
349
+ "require_confirm": True,
350
+ "app_key": "YOUR_APP_KEY",
351
+ "app_secret": "YOUR_APP_SECRET",
352
+ "access_token": "YOUR_ACCESS_TOKEN",
353
+ "_comment": "需安装 longbridge: pip install longbridge"
354
+ },
355
+ "ibkr": {
356
+ "id": "ibkr_us",
357
+ "type": "ibkr",
358
+ "label": "盈透美股",
359
+ "mode": "read_only",
360
+ "allow_live_trade": False,
361
+ "require_confirm": True,
362
+ "host": "127.0.0.1",
363
+ "port": 7496,
364
+ "client_id": 1,
365
+ "_comment": "需安装 ib_insync: pip install ib_insync 并启动 TWS/Gateway"
366
+ },
367
+ "alpaca": {
368
+ "id": "alpaca_paper",
369
+ "type": "alpaca",
370
+ "label": "Alpaca 模拟盘",
371
+ "mode": "paper",
372
+ "allow_live_trade": False,
373
+ "require_confirm": True,
374
+ "api_key": "YOUR_API_KEY",
375
+ "api_secret": "YOUR_API_SECRET",
376
+ "paper": True,
377
+ "_comment": "需安装 alpaca-py: pip install alpaca-py"
378
+ },
379
+ "webull": {
380
+ "id": "webull_us",
381
+ "type": "webull",
382
+ "label": "Webull 美股",
383
+ "mode": "read_only",
384
+ "allow_live_trade": False,
385
+ "require_confirm": True,
386
+ "username": "YOUR_EMAIL_OR_PHONE",
387
+ "password": "YOUR_PASSWORD",
388
+ "device_id": "",
389
+ "_comment": "需安装 webull: pip install webull"
390
+ },
391
+ "trading212": {
392
+ "id": "trading212_uk",
393
+ "type": "trading212",
394
+ "label": "Trading212 英国账户",
395
+ "mode": "read_only",
396
+ "allow_live_trade": False,
397
+ "require_confirm": True,
398
+ "api_key": "YOUR_API_KEY",
399
+ "base_url": "https://live.trading212.com/api/v0",
400
+ "_comment": "无需额外 SDK(直接 REST)。practice 账户把 base_url 换成 https://demo.trading212.com/api/v0。仅支持限价单。"
401
+ },
402
+ }
403
+
404
+
405
+ def get_config_template(broker_type: str) -> Optional[Dict[str, Any]]:
406
+ """返回指定券商类型的配置模板。"""
407
+ import copy
408
+ tmpl = _TEMPLATES.get(broker_type)
409
+ return copy.deepcopy(tmpl) if tmpl else None
410
+
411
+
412
+ def print_all_templates() -> str:
413
+ """返回所有配置模板的 JSON 字符串(用于 /broker init 命令)。"""
414
+ return json.dumps({"brokers": list(_TEMPLATES.values())}, ensure_ascii=False, indent=2)
@@ -0,0 +1,5 @@
1
+ from .ibkr_broker import IBKRBroker
2
+ from .alpaca_broker import AlpacaBroker
3
+ from .webull_broker import WebullBroker
4
+
5
+ __all__ = ["IBKRBroker", "AlpacaBroker", "WebullBroker"]
@@ -0,0 +1,183 @@
1
+ """
2
+ brokers/intl/alpaca_broker.py — Alpaca Markets 适配器
3
+ ======================================================
4
+ 支持市场:美股(实盘 + 模拟盘)
5
+
6
+ 安装:pip install alpaca-py
7
+ 文档:https://docs.alpaca.markets/
8
+
9
+ 配置示例::
10
+
11
+ {
12
+ "id": "alpaca_paper",
13
+ "type": "alpaca",
14
+ "label": "Alpaca 模拟盘",
15
+ "api_key": "PKxxx",
16
+ "api_secret": "xxx",
17
+ "paper": true
18
+ }
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ from typing import Any, Dict, List
24
+
25
+ from ..base import BrokerBase, AccountInfo, Position, Order, OrderResult
26
+
27
+
28
+ class AlpacaBroker(BrokerBase):
29
+ broker_type = "alpaca"
30
+ broker_name = "Alpaca Markets"
31
+ market = "US"
32
+
33
+ def __init__(self, broker_id: str, config: Dict[str, Any]):
34
+ super().__init__(broker_id, config)
35
+ self._api_key = config.get("api_key", "")
36
+ self._api_secret = config.get("api_secret", "")
37
+ self._paper = bool(config.get("paper", False))
38
+ self._trading = None
39
+
40
+ def connect(self) -> bool:
41
+ try:
42
+ from alpaca.trading.client import TradingClient
43
+ except ImportError:
44
+ raise ImportError("alpaca-py 未安装。请运行: pip install alpaca-py")
45
+
46
+ try:
47
+ client = TradingClient(self._api_key, self._api_secret, paper=self._paper)
48
+ client.get_account() # 测试连通性
49
+ self._trading = client
50
+ self._connected = True
51
+ return True
52
+ except Exception as e:
53
+ raise RuntimeError(f"Alpaca 连接失败: {e}") from e
54
+
55
+ def account_info(self) -> AccountInfo:
56
+ self._require_connected()
57
+ try:
58
+ a = self._trading.get_account()
59
+ except Exception as e:
60
+ raise RuntimeError(f"Alpaca 账户查询失败: {e}") from e
61
+
62
+ equity = float(getattr(a, "equity", 0))
63
+ cash = float(getattr(a, "cash", 0))
64
+ mv = float(getattr(a, "long_market_value", 0)) - float(getattr(a, "short_market_value", 0))
65
+ pnl = float(getattr(a, "unrealized_pl", 0))
66
+ return AccountInfo(
67
+ broker_id=self.broker_id,
68
+ broker_type=self.broker_type,
69
+ label=self.label,
70
+ account_id=str(getattr(a, "account_number", getattr(a, "id", ""))),
71
+ currency="USD",
72
+ total_assets=equity,
73
+ cash=cash,
74
+ market_value=mv,
75
+ pnl_today=float(getattr(a, "unrealized_pl", 0)),
76
+ pnl_total=pnl,
77
+ extra={"buying_power": float(getattr(a, "buying_power", 0)),
78
+ "paper": self._paper},
79
+ )
80
+
81
+ def positions(self) -> List[Position]:
82
+ self._require_connected()
83
+ try:
84
+ raw = self._trading.get_all_positions()
85
+ except Exception as e:
86
+ raise RuntimeError(f"Alpaca 持仓查询失败: {e}") from e
87
+
88
+ result = []
89
+ for p in (raw or []):
90
+ sym = str(getattr(p, "symbol", ""))
91
+ qty = float(getattr(p, "qty", 0))
92
+ avail = float(getattr(p, "qty_available", qty))
93
+ cost = float(getattr(p, "avg_entry_price", 0))
94
+ price = float(getattr(p, "current_price", 0))
95
+ mv = float(getattr(p, "market_value", 0))
96
+ pnl = float(getattr(p, "unrealized_pl", 0))
97
+ pnl_pct = float(getattr(p, "unrealized_plpc", 0)) * 100
98
+ result.append(Position(
99
+ symbol=sym, name=sym,
100
+ quantity=qty, available_qty=avail,
101
+ cost_price=cost, current_price=price,
102
+ market_value=mv, pnl=pnl, pnl_pct=pnl_pct,
103
+ currency="USD", market="us",
104
+ ))
105
+ return result
106
+
107
+ def orders(self, status: str = "all", limit: int = 50) -> List[Order]:
108
+ self._require_connected()
109
+ try:
110
+ from alpaca.trading.requests import GetOrdersRequest
111
+ from alpaca.trading.enums import QueryOrderStatus
112
+ qstatus = {
113
+ "open": QueryOrderStatus.OPEN,
114
+ "filled": QueryOrderStatus.CLOSED,
115
+ "cancelled": QueryOrderStatus.CLOSED,
116
+ }.get(status, QueryOrderStatus.ALL)
117
+ raw = self._trading.get_orders(GetOrdersRequest(status=qstatus, limit=limit))
118
+ except Exception as e:
119
+ raise RuntimeError(f"Alpaca 订单查询失败: {e}") from e
120
+
121
+ result = []
122
+ for o in (raw or []):
123
+ side = "buy" if str(getattr(o, "side", "")).lower() == "buy" else "sell"
124
+ mapped = _alpaca_order_status(str(getattr(o, "status", "")))
125
+ if status not in ("all",) and mapped != status:
126
+ continue
127
+ result.append(Order(
128
+ order_id=str(getattr(o, "id", "")),
129
+ symbol=str(getattr(o, "symbol", "")),
130
+ name=str(getattr(o, "symbol", "")),
131
+ side=side,
132
+ order_type=str(getattr(o, "order_type", "limit")).lower(),
133
+ quantity=float(getattr(o, "qty", 0) or 0),
134
+ filled_qty=float(getattr(o, "filled_qty", 0) or 0),
135
+ price=float(getattr(o, "limit_price", 0) or 0),
136
+ avg_price=float(getattr(o, "filled_avg_price", 0) or 0),
137
+ status=mapped,
138
+ created_at=str(getattr(o, "created_at", "")),
139
+ currency="USD",
140
+ ))
141
+ return result
142
+
143
+ def place_order(self, symbol: str, side: str, quantity: float,
144
+ order_type: str = "limit", price: float = 0.0, **kwargs) -> OrderResult:
145
+ self._require_connected()
146
+ try:
147
+ from alpaca.trading.requests import MarketOrderRequest, LimitOrderRequest
148
+ from alpaca.trading.enums import OrderSide, TimeInForce
149
+ alpaca_side = OrderSide.BUY if side == "buy" else OrderSide.SELL
150
+ if order_type == "market":
151
+ req = MarketOrderRequest(
152
+ symbol=symbol, qty=quantity, side=alpaca_side, time_in_force=TimeInForce.DAY)
153
+ else:
154
+ req = LimitOrderRequest(
155
+ symbol=symbol, qty=quantity, side=alpaca_side,
156
+ limit_price=price, time_in_force=TimeInForce.DAY)
157
+ o = self._trading.submit_order(req)
158
+ return OrderResult(success=True, order_id=str(o.id), broker_id=self.broker_id)
159
+ except Exception as e:
160
+ return OrderResult(success=False, message=str(e), broker_id=self.broker_id)
161
+
162
+ def cancel_order(self, order_id: str) -> bool:
163
+ self._require_connected()
164
+ try:
165
+ self._trading.cancel_order_by_id(order_id)
166
+ return True
167
+ except Exception:
168
+ return False
169
+
170
+ def _require_connected(self):
171
+ if not self._connected or not self._trading:
172
+ raise RuntimeError("Alpaca 未连接,请先调用 connect()")
173
+
174
+
175
+ def _alpaca_order_status(raw: str) -> str:
176
+ raw = raw.lower()
177
+ if raw == "filled":
178
+ return "filled"
179
+ if raw == "partially_filled":
180
+ return "partial"
181
+ if raw in ("canceled", "cancelled", "expired", "rejected"):
182
+ return "cancelled"
183
+ return "open"