aria-code 4.1.3__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 (284) hide show
  1. agents/__init__.py +32 -0
  2. agents/base.py +190 -0
  3. agents/deep/__init__.py +37 -0
  4. agents/deep/calibration_loop.py +144 -0
  5. agents/deep/critic.py +125 -0
  6. agents/deep/deepen.py +193 -0
  7. agents/deep/models.py +149 -0
  8. agents/deep/pipeline.py +164 -0
  9. agents/deep/quant_fusion.py +192 -0
  10. agents/deep/themes.py +95 -0
  11. agents/deep/tiers.py +106 -0
  12. agents/financial/__init__.py +10 -0
  13. agents/financial/catalyst.py +279 -0
  14. agents/financial/debate.py +145 -0
  15. agents/financial/earnings.py +303 -0
  16. agents/financial/fundamental.py +159 -0
  17. agents/financial/macro.py +99 -0
  18. agents/financial/news.py +207 -0
  19. agents/financial/risk.py +132 -0
  20. agents/financial/sector.py +279 -0
  21. agents/financial/synthesis.py +274 -0
  22. agents/financial/technical.py +258 -0
  23. agents/portfolio_agent.py +333 -0
  24. agents/realty/__init__.py +62 -0
  25. agents/realty/asset_diagnosis.py +150 -0
  26. agents/realty/business_match.py +165 -0
  27. agents/realty/cashflow_verify.py +208 -0
  28. agents/realty/contract_rules.py +209 -0
  29. agents/realty/energy_anomaly.py +188 -0
  30. agents/realty/exit_settlement.py +207 -0
  31. agents/realty/fulfillment_risk.py +205 -0
  32. agents/realty/ops_optimize.py +159 -0
  33. agents/realty/revenue_share.py +214 -0
  34. agents/registry.py +144 -0
  35. agents/sports/__init__.py +0 -0
  36. agents/sports/football_agent.py +169 -0
  37. agents/team.py +289 -0
  38. aliyun_data_client.py +660 -0
  39. apps/README.md +12 -0
  40. apps/__init__.py +2 -0
  41. apps/channels/README.md +15 -0
  42. apps/cli/README.md +13 -0
  43. apps/cli/__init__.py +2 -0
  44. apps/cli/bootstrap.py +99 -0
  45. apps/cli/codegen_paths.py +29 -0
  46. apps/cli/commands/__init__.py +16 -0
  47. apps/cli/commands/analysis_cmds.py +288 -0
  48. apps/cli/commands/backtest_cmds.py +1887 -0
  49. apps/cli/commands/broker_cmds.py +1154 -0
  50. apps/cli/commands/business_workflow_cmds.py +289 -0
  51. apps/cli/commands/catalog.py +84 -0
  52. apps/cli/commands/data_cmds.py +405 -0
  53. apps/cli/commands/diagnostic_cmds.py +179 -0
  54. apps/cli/commands/diagnostic_ops_cmds.py +696 -0
  55. apps/cli/commands/finance_render.py +12 -0
  56. apps/cli/commands/market.py +399 -0
  57. apps/cli/commands/market_cmds.py +1276 -0
  58. apps/cli/commands/market_context.py +425 -0
  59. apps/cli/commands/market_render.py +7 -0
  60. apps/cli/commands/model_cmds.py +1579 -0
  61. apps/cli/commands/ops_cmds.py +668 -0
  62. apps/cli/commands/portfolio_cmds.py +962 -0
  63. apps/cli/commands/report.py +377 -0
  64. apps/cli/commands/scaffold_templates.py +617 -0
  65. apps/cli/commands/session_cmds.py +179 -0
  66. apps/cli/commands/session_ux_cmds.py +280 -0
  67. apps/cli/commands/team.py +588 -0
  68. apps/cli/commands/team_render.py +8 -0
  69. apps/cli/commands/ui_cmds.py +358 -0
  70. apps/cli/commands/workflow_cmds.py +279 -0
  71. apps/cli/commands/workspace_cmds.py +1414 -0
  72. apps/cli/config_paths.py +70 -0
  73. apps/cli/config_store.py +61 -0
  74. apps/cli/deterministic.py +122 -0
  75. apps/cli/direct.py +48 -0
  76. apps/cli/github_app_auth.py +135 -0
  77. apps/cli/handlers/__init__.py +11 -0
  78. apps/cli/handlers/broker_handlers.py +122 -0
  79. apps/cli/handlers/chart_handlers.py +1309 -0
  80. apps/cli/handlers/market_handlers.py +2509 -0
  81. apps/cli/handlers/realty_handlers.py +114 -0
  82. apps/cli/handlers/strategy_advice.py +82 -0
  83. apps/cli/hooks.py +180 -0
  84. apps/cli/i18n.py +284 -0
  85. apps/cli/intent.py +136 -0
  86. apps/cli/intent_router.py +217 -0
  87. apps/cli/lifecycle_hooks.py +48 -0
  88. apps/cli/main.py +29 -0
  89. apps/cli/market_metadata.py +135 -0
  90. apps/cli/market_universe.py +265 -0
  91. apps/cli/message_processing.py +257 -0
  92. apps/cli/plan_mode.py +139 -0
  93. apps/cli/plotly_html.py +15 -0
  94. apps/cli/prediction_feedback.py +202 -0
  95. apps/cli/preflight.py +497 -0
  96. apps/cli/project_aria.py +60 -0
  97. apps/cli/prompts/__init__.py +0 -0
  98. apps/cli/prompts/coding.py +658 -0
  99. apps/cli/prompts/system_prompts.py +531 -0
  100. apps/cli/prompts/ui.py +434 -0
  101. apps/cli/providers/__init__.py +1 -0
  102. apps/cli/providers/base.py +271 -0
  103. apps/cli/providers/chat_routing.py +80 -0
  104. apps/cli/providers/llm/__init__.py +1 -0
  105. apps/cli/providers/llm/ollama_stream.py +1170 -0
  106. apps/cli/providers/llm/sse_stream.py +216 -0
  107. apps/cli/providers/runtime_bridge.py +185 -0
  108. apps/cli/runtime_consumer.py +489 -0
  109. apps/cli/session_export.py +87 -0
  110. apps/cli/session_jsonl.py +207 -0
  111. apps/cli/session_store.py +112 -0
  112. apps/cli/todo_tracker.py +190 -0
  113. apps/cli/tools/__init__.py +40 -0
  114. apps/cli/tools/context.py +46 -0
  115. apps/cli/tools/file_tools.py +112 -0
  116. apps/cli/tools/market_tools.py +549 -0
  117. apps/cli/tools/notebook_tools.py +111 -0
  118. apps/cli/tools/system_tools.py +669 -0
  119. apps/cli/tools/write_tools.py +715 -0
  120. apps/cli/tradingview_bridge.py +434 -0
  121. apps/cli/update_check.py +152 -0
  122. apps/cli/utils/__init__.py +0 -0
  123. apps/cli/utils/market_detect.py +1578 -0
  124. apps/daemon/README.md +14 -0
  125. apps/vscode/README.md +115 -0
  126. apps/vscode/package.json +70 -0
  127. aria_cli.py +11636 -0
  128. aria_code-4.1.3.dist-info/METADATA +952 -0
  129. aria_code-4.1.3.dist-info/RECORD +284 -0
  130. aria_code-4.1.3.dist-info/WHEEL +5 -0
  131. aria_code-4.1.3.dist-info/entry_points.txt +2 -0
  132. aria_code-4.1.3.dist-info/licenses/LICENSE +121 -0
  133. aria_code-4.1.3.dist-info/top_level.txt +50 -0
  134. aria_daemon.py +1295 -0
  135. aria_feishu_bot.py +1359 -0
  136. aria_relay_client.py +182 -0
  137. aria_relay_server.py +405 -0
  138. aria_telegram_bot.py +202 -0
  139. ariarc.py +328 -0
  140. artifacts.py +491 -0
  141. backtest_report.py +472 -0
  142. brokers/__init__.py +72 -0
  143. brokers/base.py +207 -0
  144. brokers/capabilities.py +264 -0
  145. brokers/cn/__init__.py +10 -0
  146. brokers/cn/easytrader_broker.py +193 -0
  147. brokers/cn/futu_broker.py +194 -0
  148. brokers/cn/longbridge_broker.py +190 -0
  149. brokers/cn/tiger_broker.py +196 -0
  150. brokers/cn/xtquant_broker.py +175 -0
  151. brokers/config.py +364 -0
  152. brokers/intl/__init__.py +5 -0
  153. brokers/intl/alpaca_broker.py +183 -0
  154. brokers/intl/ibkr_broker.py +215 -0
  155. brokers/intl/webull_broker.py +156 -0
  156. brokers/paper_broker.py +259 -0
  157. brokers/planning.py +296 -0
  158. brokers/registry.py +181 -0
  159. brokers/trading.py +237 -0
  160. change_store.py +127 -0
  161. command_safety.py +19 -0
  162. computer_use_tools.py +504 -0
  163. dashboard_generator.py +578 -0
  164. data_analysis_tools.py +808 -0
  165. data_cleaner.py +483 -0
  166. data_service.py +481 -0
  167. datasources/__init__.py +23 -0
  168. datasources/base.py +166 -0
  169. datasources/router.py +221 -0
  170. datasources/sources/__init__.py +15 -0
  171. datasources/sources/akshare_source.py +269 -0
  172. datasources/sources/alpha_vantage_source.py +202 -0
  173. datasources/sources/edgar_source.py +218 -0
  174. datasources/sources/finnhub_source.py +197 -0
  175. datasources/sources/fred_source.py +219 -0
  176. datasources/sources/tushare_source.py +141 -0
  177. datasources/sources/web_scraper_source.py +278 -0
  178. datasources/sources/world_bank_source.py +205 -0
  179. datasources/sources/yfinance_source.py +152 -0
  180. demo_player.py +204 -0
  181. doctor.py +508 -0
  182. file_analysis_tools.py +734 -0
  183. finance_formulas.py +389 -0
  184. football_data_client.py +1670 -0
  185. intent_classifier.py +358 -0
  186. local_finance_tools.py +3221 -0
  187. local_llm_provider.py +552 -0
  188. macro_tools.py +368 -0
  189. market_data_client.py +1899 -0
  190. mcp_client.py +506 -0
  191. memory_manager.py +245 -0
  192. model_capability.py +416 -0
  193. notification_tools.py +248 -0
  194. packages/__init__.py +23 -0
  195. packages/aria_agents/__init__.py +5 -0
  196. packages/aria_agents/manifest.py +69 -0
  197. packages/aria_core/__init__.py +34 -0
  198. packages/aria_core/architecture.py +192 -0
  199. packages/aria_core/export.py +124 -0
  200. packages/aria_core/manifest.py +65 -0
  201. packages/aria_infra/__init__.py +15 -0
  202. packages/aria_infra/arthera.py +52 -0
  203. packages/aria_infra/doctor.py +246 -0
  204. packages/aria_infra/product.py +37 -0
  205. packages/aria_mcp/__init__.py +25 -0
  206. packages/aria_mcp/bridge.py +38 -0
  207. packages/aria_mcp/config.py +97 -0
  208. packages/aria_mcp/tools.py +61 -0
  209. packages/aria_sdk/__init__.py +19 -0
  210. packages/aria_sdk/client.py +396 -0
  211. packages/aria_sdk/providers.py +70 -0
  212. packages/aria_sdk/streaming.py +73 -0
  213. packages/aria_sdk/types.py +86 -0
  214. packages/aria_services/__init__.py +55 -0
  215. packages/aria_services/context.py +258 -0
  216. packages/aria_services/data.py +11 -0
  217. packages/aria_services/provider_health.py +189 -0
  218. packages/aria_services/registry.py +213 -0
  219. packages/aria_services/usage.py +138 -0
  220. packages/aria_skills/__init__.py +5 -0
  221. packages/aria_skills/registry.py +59 -0
  222. packages/aria_tools/__init__.py +5 -0
  223. packages/aria_tools/registry.py +128 -0
  224. packages/quant_engine/__init__.py +6 -0
  225. packages/quant_engine/sports/__init__.py +72 -0
  226. packages/quant_engine/sports/calibrator.py +353 -0
  227. packages/quant_engine/sports/dixon_coles.py +234 -0
  228. packages/quant_engine/sports/elo.py +299 -0
  229. packages/quant_engine/sports/form.py +188 -0
  230. packages/quant_engine/sports/h2h.py +195 -0
  231. packages/quant_engine/sports/ml_model.py +354 -0
  232. packages/quant_engine/sports/predictor.py +311 -0
  233. packages/quant_engine/sports/tracker.py +664 -0
  234. packages/quant_engine/stochastic/__init__.py +27 -0
  235. packages/quant_engine/stochastic/gbm_enhanced.py +195 -0
  236. packages/quant_engine/stochastic/ito_calculus.py +477 -0
  237. packages/quant_engine/stochastic/kelly_criterion.py +181 -0
  238. packages/quant_engine/stochastic/monte_carlo_advanced.py +95 -0
  239. packages/quant_engine/stochastic/options_pricing.py +573 -0
  240. packages/quant_engine/stochastic/stochastic_processes.py +90 -0
  241. plan_utils.py +194 -0
  242. plugin_loader.py +328 -0
  243. portfolio_ledger.py +262 -0
  244. privacy/__init__.py +5 -0
  245. privacy/feedback.py +123 -0
  246. project_tools.py +525 -0
  247. providers/__init__.py +30 -0
  248. providers/llm/__init__.py +19 -0
  249. providers/llm/anthropic.py +184 -0
  250. providers/llm/base.py +139 -0
  251. providers/llm/ollama.py +128 -0
  252. providers/llm/openai_compat.py +282 -0
  253. providers/llm/registry.py +358 -0
  254. realty_data_tools.py +659 -0
  255. report_generator.py +1314 -0
  256. runtime/__init__.py +103 -0
  257. runtime/agent_loop.py +1183 -0
  258. runtime/approval.py +51 -0
  259. runtime/events.py +102 -0
  260. runtime/gateway.py +128 -0
  261. runtime/lsp.py +346 -0
  262. runtime/subagent.py +258 -0
  263. runtime/tool_executor.py +104 -0
  264. runtime/tool_policy.py +106 -0
  265. safety/__init__.py +21 -0
  266. safety/permissions.py +275 -0
  267. setup_wizard.py +653 -0
  268. strategy_vault.py +420 -0
  269. ui/__init__.py +100 -0
  270. ui/banner.py +310 -0
  271. ui/completer.py +391 -0
  272. ui/console.py +271 -0
  273. ui/image_render.py +243 -0
  274. ui/input_box.py +376 -0
  275. ui/picker.py +195 -0
  276. ui/render/__init__.py +11 -0
  277. ui/render/finance.py +1480 -0
  278. ui/render/market.py +225 -0
  279. ui/render/output.py +681 -0
  280. ui/render/team.py +346 -0
  281. ui/robot.py +235 -0
  282. workspace/__init__.py +6 -0
  283. workspace/files.py +170 -0
  284. workspace/verify.py +113 -0
@@ -0,0 +1,205 @@
1
+ """
2
+ agents/realty/fulfillment_risk.py — 履约风控 Agent
3
+ ===================================================
4
+ 监控合同履约和资金风险,生成风险等级和处置建议。
5
+
6
+ 输入数据(data dict keys):
7
+ invoices — 账单列表(应收/实收/逾期情况)
8
+ contract_rules — 合同规则(保底/保证金/结算周期等)
9
+ cashflow_status — 最新流水核验状态
10
+ account_changes — 收款账户变更记录
11
+ compliance_flags— 合规预警标志(私自换码/改业态等)
12
+
13
+ 输出:
14
+ analysis — 风险报告
15
+ signal — BUY=低风险 / HOLD=中等风险 / SELL=高风险 / STRONG_SELL=极高风险
16
+ key_points — 风险事项清单(按级别)
17
+ """
18
+ from __future__ import annotations
19
+
20
+ from typing import Any, Dict, List
21
+ from ..base import BaseAgent, AgentResult
22
+
23
+
24
+ class FulfillmentRiskAgent(BaseAgent):
25
+ name = "fulfillment_risk"
26
+ description = "履约风控:监控逾期/保底/保证金/私账/业态合规,生成风险等级和处置建议"
27
+
28
+ _SYSTEM = (
29
+ "你是一名专业的不动产合同履约风险管理专家。\n"
30
+ "请对履约风险评估结果进行分析:\n"
31
+ " 1. 逾期风险:账单逾期天数、逾期金额、逾期频次\n"
32
+ " 2. 保底风险:实际流水是否持续低于保底标准\n"
33
+ " 3. 保证金风险:保证金余额是否充足(低于1个月保底需预警)\n"
34
+ " 4. 资金风险:是否存在私自更换收款码、现金比例过高\n"
35
+ " 5. 合规风险:是否擅自改变业态、违规装修、无照经营\n"
36
+ " 6. 综合风险等级:[低] / [中] / [高] / [极高]\n"
37
+ " 7. 处置建议:催缴/整改通知/保证金扣除/退出清算(分级建议)"
38
+ )
39
+
40
+ async def analyze(self, symbol: str, data: Dict[str, Any]) -> AgentResult:
41
+ invoices = data.get("invoices", [])
42
+ rules = data.get("contract_rules", {})
43
+ cf_status = data.get("cashflow_status", {})
44
+ acct_chg = data.get("account_changes", [])
45
+ flags = data.get("compliance_flags", [])
46
+
47
+ risk = _assess_risk(invoices, rules, cf_status, acct_chg, flags)
48
+
49
+ user_prompt = (
50
+ f"履约风险评估:\n"
51
+ f" 逾期账单: {risk['overdue_count']}张 逾期金额: {risk['overdue_amount']:,.2f}元\n"
52
+ f" 最长逾期: {risk['max_overdue_days']}天\n"
53
+ f" 保底覆盖率: {risk['guaranteed_coverage_pct']:.1f}%(近3期平均)\n"
54
+ f" 保证金余额: {risk['deposit_balance']:,.2f}元 "
55
+ f" 要求: {risk['deposit_required']:,.2f}元\n"
56
+ f" 账户变更记录: {len(acct_chg)}次\n"
57
+ f" 合规标志: {', '.join(flags) or '无'}\n\n"
58
+ f"风险事项({risk['risk_count']}项):\n"
59
+ + "\n".join(f" [{item['level']}] {item['desc']}" for item in risk["risk_items"])
60
+ + "\n\n请完成风险报告并给出处置建议。"
61
+ )
62
+
63
+ analysis = await self._call_llm(self._SYSTEM, user_prompt, max_tokens=700)
64
+ if not analysis:
65
+ analysis = _template_risk_report(risk, rules)
66
+
67
+ signal = _risk_signal(risk)
68
+ confidence = _risk_confidence(risk, invoices)
69
+ key_points = _risk_key_points(risk)
70
+
71
+ return AgentResult(
72
+ agent = self.name,
73
+ symbol = symbol,
74
+ analysis = analysis,
75
+ confidence = confidence,
76
+ signal = signal,
77
+ key_points = key_points,
78
+ data_used = {"risk_assessment": risk},
79
+ )
80
+
81
+
82
+ # ── 风险评估逻辑 ──────────────────────────────────────────────────────────────
83
+
84
+ def _assess_risk(
85
+ invoices: List[Dict], rules: Dict, cf: Dict,
86
+ acct_changes: List[Dict], flags: List[str],
87
+ ) -> Dict:
88
+ guaranteed = rules.get("guaranteed_monthly", 0)
89
+ deposit_req = rules.get("deposit_amount", 0)
90
+ deposit_bal = rules.get("deposit_balance", deposit_req) # 当前余额
91
+
92
+ risk_items: List[Dict] = []
93
+
94
+ # 1. 逾期账单分析
95
+ overdue = [inv for inv in invoices if inv.get("status") in ("overdue", "逾期")]
96
+ overdue_amount = sum(inv.get("amount", 0) - inv.get("paid", 0) for inv in overdue)
97
+ max_overdue_days = max((inv.get("overdue_days", 0) for inv in overdue), default=0)
98
+
99
+ if overdue_amount > 0:
100
+ level = "极高" if max_overdue_days > 60 else ("高" if max_overdue_days > 30 else "中")
101
+ risk_items.append({"level": level,
102
+ "desc": f"共{len(overdue)}张账单逾期,金额{overdue_amount:,.2f}元,最长{max_overdue_days}天"})
103
+
104
+ # 2. 保底覆盖率(取近几期)
105
+ recent_revenues = [inv.get("revenue", 0) for inv in invoices[-3:] if inv.get("revenue")]
106
+ if recent_revenues and guaranteed > 0:
107
+ avg_coverage = sum(r / guaranteed * 100 for r in recent_revenues) / len(recent_revenues)
108
+ if avg_coverage < 60:
109
+ risk_items.append({"level": "高",
110
+ "desc": f"近{len(recent_revenues)}期流水平均仅覆盖保底{avg_coverage:.1f}%"})
111
+ elif avg_coverage < 80:
112
+ risk_items.append({"level": "中",
113
+ "desc": f"近期流水覆盖保底{avg_coverage:.1f}%,持续偏低"})
114
+ else:
115
+ avg_coverage = 100.0
116
+
117
+ # 3. 保证金不足
118
+ if deposit_req > 0 and deposit_bal < deposit_req * 0.5:
119
+ risk_items.append({"level": "高",
120
+ "desc": f"保证金余额{deposit_bal:,.0f}元不足要求{deposit_req:,.0f}元的50%"})
121
+ elif deposit_req > 0 and deposit_bal < deposit_req:
122
+ risk_items.append({"level": "中",
123
+ "desc": f"保证金余额{deposit_bal:,.0f}元低于合同要求{deposit_req:,.0f}元"})
124
+
125
+ # 4. 账户变更
126
+ if len(acct_changes) > 0:
127
+ unauth = [c for c in acct_changes if not c.get("approved")]
128
+ if unauth:
129
+ risk_items.append({"level": "极高",
130
+ "desc": f"发现{len(unauth)}次未授权收款账户变更,疑似私账行为"})
131
+ else:
132
+ risk_items.append({"level": "低",
133
+ "desc": f"共{len(acct_changes)}次账户变更,已审批"})
134
+
135
+ # 5. 流水核验异常
136
+ cf_signal = cf.get("signal", "")
137
+ if cf_signal in ("SELL", "STRONG_SELL"):
138
+ risk_items.append({"level": "高",
139
+ "desc": f"流水核验异常({cf.get('anomaly_summary','')}),需稽查"})
140
+
141
+ # 6. 合规标志
142
+ for flag in flags:
143
+ risk_items.append({"level": "高", "desc": f"合规违规: {flag}"})
144
+
145
+ return {
146
+ "overdue_count": len(overdue),
147
+ "overdue_amount": overdue_amount,
148
+ "max_overdue_days": max_overdue_days,
149
+ "guaranteed_coverage_pct": avg_coverage,
150
+ "deposit_balance": deposit_bal,
151
+ "deposit_required": deposit_req,
152
+ "risk_items": risk_items,
153
+ "risk_count": len(risk_items),
154
+ "has_extreme_risk": any(r["level"] == "极高" for r in risk_items),
155
+ "has_high_risk": any(r["level"] == "高" for r in risk_items),
156
+ }
157
+
158
+
159
+ def _risk_signal(risk: Dict) -> str:
160
+ if risk.get("has_extreme_risk"): return "STRONG_SELL"
161
+ if risk.get("has_high_risk"): return "SELL"
162
+ mid_count = sum(1 for r in risk.get("risk_items", []) if r["level"] == "中")
163
+ if mid_count >= 2: return "SELL"
164
+ if mid_count >= 1: return "HOLD"
165
+ return "BUY"
166
+
167
+
168
+ def _risk_confidence(risk: Dict, invoices: List) -> float:
169
+ data_points = sum([
170
+ 1 if invoices else 0,
171
+ 1 if risk.get("deposit_required", 0) > 0 else 0,
172
+ 1 if risk.get("guaranteed_coverage_pct", 100) < 100 else 0,
173
+ ])
174
+ return round(0.6 + 0.1 * data_points, 2)
175
+
176
+
177
+ def _risk_key_points(risk: Dict) -> List[str]:
178
+ pts = []
179
+ if risk["overdue_amount"] > 0:
180
+ pts.append(f"逾期金额: {risk['overdue_amount']:,.2f}元(最长{risk['max_overdue_days']}天)")
181
+ pts.append(f"保底覆盖率: {risk['guaranteed_coverage_pct']:.1f}%")
182
+ pts.append(f"保证金: {risk['deposit_balance']:,.2f}/{risk['deposit_required']:,.2f}元")
183
+ for item in [r for r in risk["risk_items"] if r["level"] in ("极高", "高")][:2]:
184
+ pts.append(f"[{item['level']}风险] {item['desc'][:50]}")
185
+ return pts[:5]
186
+
187
+
188
+ def _template_risk_report(risk: Dict, rules: Dict) -> str:
189
+ level_map = {True: "极高", False: ""}
190
+ overall = "极高" if risk["has_extreme_risk"] else ("高" if risk["has_high_risk"] else
191
+ ("中" if risk["risk_count"] > 0 else "低"))
192
+ return (
193
+ f"履约风控报告(模板):\n"
194
+ f" 综合风险等级: {overall}\n"
195
+ f" 逾期账单: {risk['overdue_count']}张 逾期金额: {risk['overdue_amount']:,.2f}元\n"
196
+ f" 最长逾期天数: {risk['max_overdue_days']}天\n"
197
+ f" 保底覆盖率: {risk['guaranteed_coverage_pct']:.1f}%\n"
198
+ f" 保证金: {risk['deposit_balance']:,.2f}/{risk['deposit_required']:,.2f}元\n"
199
+ f" 风险事项 ({risk['risk_count']}项):\n"
200
+ + "\n".join(f" [{r['level']}] {r['desc']}" for r in risk["risk_items"])
201
+ + f"\n 处置建议: "
202
+ + ("立即启动退出清算程序" if overall == "极高" else
203
+ "发出整改通知,7日内未整改启动违约程序" if overall == "高" else
204
+ "发出催缴通知,持续监控" if overall == "中" else "保持正常监控")
205
+ )
@@ -0,0 +1,159 @@
1
+ """
2
+ agents/realty/ops_optimize.py — 运营提升 Agent
3
+ ===============================================
4
+ 分析坪效、客流、商品排行、活动效果,提出经营优化建议。
5
+
6
+ 输入数据(data dict keys):
7
+ project_info — 项目基本信息(面积/业态/开业时间)
8
+ performance_data — 经营绩效数据(坪效/客流/流水趋势/商品排行)
9
+ marketing_data — 营销活动数据(会员/优惠券/外卖/团购)
10
+ peer_benchmarks — 同业基准数据(可选)
11
+
12
+ 输出:
13
+ analysis — 运营优化建议
14
+ signal — BUY=经营健康/高潜力 / HOLD=有改善空间 / SELL=经营不佳需干预
15
+ key_points — Top3 优化建议
16
+ """
17
+ from __future__ import annotations
18
+
19
+ from typing import Any, Dict, List
20
+ from ..base import BaseAgent, AgentResult
21
+
22
+
23
+ class OpsOptimizeAgent(BaseAgent):
24
+ name = "ops_optimize"
25
+ description = "运营提升:分析坪效/客流/营销效果,提出招商补位和经营优化建议"
26
+
27
+ _SYSTEM = (
28
+ "你是一名资深的商业空间运营顾问,专注于帮助经营方提升业绩。\n"
29
+ "请基于以下经营数据给出针对性的优化建议:\n"
30
+ " 1. 坪效分析(当前坪效 vs 行业基准,提升空间)\n"
31
+ " 2. 客流优化(高峰时段利用率、低谷期激活策略)\n"
32
+ " 3. 商品/品类优化(畅销/滞销商品,品类结构调整)\n"
33
+ " 4. 营销活动效果评估(会员召回、优惠券核销率、外卖占比)\n"
34
+ " 5. 营业时间优化建议\n"
35
+ " 6. 招商补位建议(空置面积是否可引入互补业态)\n"
36
+ " 7. 优先级最高的3项具体可执行建议(含预期效果)"
37
+ )
38
+
39
+ async def analyze(self, symbol: str, data: Dict[str, Any]) -> AgentResult:
40
+ project = data.get("project_info", {})
41
+ perf = data.get("performance_data", {})
42
+ marketing= data.get("marketing_data", {})
43
+ bench = data.get("peer_benchmarks", {})
44
+
45
+ metrics = _calc_metrics(project, perf, marketing, bench)
46
+
47
+ user_prompt = (
48
+ f"项目信息:{project.get('name','未命名')} "
49
+ f"({project.get('area',0)}m² {project.get('business_type','未知业态')})\n"
50
+ f"开业: {project.get('open_date','未知')}\n\n"
51
+ f"经营绩效:\n"
52
+ f" 月均流水: {perf.get('monthly_revenue',0):,.2f}元\n"
53
+ f" 坪效: {metrics['revenue_per_sqm']:.1f}元/m²/月 行业基准: {bench.get('revenue_per_sqm',300):.1f}\n"
54
+ f" 日均客流: {perf.get('daily_visits',0):.0f}人次 转化率: {metrics['conversion_rate']:.1%}\n"
55
+ f" 会员复购率: {marketing.get('member_repurchase_pct',0):.1f}%\n"
56
+ f" 外卖收入占比: {metrics['delivery_pct']:.1f}%\n"
57
+ f" 优惠券核销率: {marketing.get('coupon_redemption_pct',0):.1f}%\n\n"
58
+ f"Top10商品: {perf.get('top_products', [])[:5]}\n"
59
+ f"垫底商品: {perf.get('bottom_products', [])[:3]}\n\n"
60
+ "请给出运营优化建议。"
61
+ )
62
+
63
+ analysis = await self._call_llm(self._SYSTEM, user_prompt, max_tokens=700)
64
+ if not analysis:
65
+ analysis = _template_ops(metrics, perf, marketing, bench)
66
+
67
+ signal = _ops_signal(metrics, bench)
68
+ confidence = _ops_confidence(perf, marketing)
69
+ key_points = _ops_key_points(metrics, perf, marketing, bench)
70
+
71
+ return AgentResult(
72
+ agent = self.name,
73
+ symbol = symbol,
74
+ analysis = analysis,
75
+ confidence = confidence,
76
+ signal = signal,
77
+ key_points = key_points,
78
+ data_used = {"metrics": metrics},
79
+ )
80
+
81
+
82
+ # ── 辅助逻辑 ──────────────────────────────────────────────────────────────────
83
+
84
+ def _calc_metrics(project: Dict, perf: Dict, marketing: Dict, bench: Dict) -> Dict:
85
+ area = project.get("area", 1)
86
+ revenue = perf.get("monthly_revenue", 0)
87
+ visits = perf.get("daily_visits", 0) * 30
88
+ orders = perf.get("monthly_orders", 0)
89
+ delivery = marketing.get("delivery_revenue", 0)
90
+
91
+ return {
92
+ "revenue_per_sqm": revenue / area if area else 0,
93
+ "conversion_rate": orders / visits if visits else 0,
94
+ "delivery_pct": delivery / revenue * 100 if revenue else 0,
95
+ "bench_psm": bench.get("revenue_per_sqm", 300),
96
+ "psm_gap_pct": (revenue / area - bench.get("revenue_per_sqm", 300))
97
+ / bench.get("revenue_per_sqm", 300) * 100 if area else 0,
98
+ }
99
+
100
+
101
+ def _ops_signal(metrics: Dict, bench: Dict) -> str:
102
+ psm = metrics.get("revenue_per_sqm", 0)
103
+ bench_psm = metrics.get("bench_psm", 300)
104
+ if bench_psm <= 0: return "HOLD"
105
+ ratio = psm / bench_psm
106
+ if ratio >= 1.2: return "BUY"
107
+ if ratio >= 0.8: return "HOLD"
108
+ if ratio >= 0.5: return "SELL"
109
+ return "STRONG_SELL"
110
+
111
+
112
+ def _ops_confidence(perf: Dict, marketing: Dict) -> float:
113
+ has = sum([
114
+ 1 if perf.get("monthly_revenue") else 0,
115
+ 1 if perf.get("daily_visits") else 0,
116
+ 1 if marketing.get("member_count") else 0,
117
+ 1 if perf.get("top_products") else 0,
118
+ ])
119
+ return round(0.5 + 0.1 * has, 2)
120
+
121
+
122
+ def _ops_key_points(metrics: Dict, perf: Dict, marketing: Dict, bench: Dict) -> List[str]:
123
+ pts = []
124
+ psm = metrics.get("revenue_per_sqm", 0)
125
+ bench_psm = metrics.get("bench_psm", 300)
126
+
127
+ pts.append(f"坪效: {psm:.1f}元/m²/月 行业基准: {bench_psm:.1f} 差距: {metrics['psm_gap_pct']:+.1f}%")
128
+ pts.append(f"转化率: {metrics['conversion_rate']:.1%} 外卖占比: {metrics['delivery_pct']:.1f}%")
129
+
130
+ if psm < bench_psm * 0.7:
131
+ pts.append("坪效显著低于基准,建议重新评估业态或开展营销活动")
132
+ if marketing.get("coupon_redemption_pct", 50) < 20:
133
+ pts.append("优惠券核销率低,营销触达效果需改善")
134
+ if marketing.get("member_repurchase_pct", 0) < 30:
135
+ pts.append("会员复购率偏低,建议加强会员运营和精准推送")
136
+ return pts[:5]
137
+
138
+
139
+ def _template_ops(metrics: Dict, perf: Dict, marketing: Dict, bench: Dict) -> str:
140
+ psm = metrics.get("revenue_per_sqm", 0)
141
+ bench_psm = metrics.get("bench_psm", 300)
142
+ gap = metrics.get("psm_gap_pct", 0)
143
+
144
+ recs = []
145
+ if psm < bench_psm:
146
+ recs.append("1. 引入高客单价品类或体验型业态,提升坪效")
147
+ if metrics.get("delivery_pct", 0) < 20:
148
+ recs.append("2. 开通美团/饿了么外卖渠道,提高营业时段覆盖")
149
+ if marketing.get("member_count", 0) < 500:
150
+ recs.append("3. 启动会员招募计划,目标500+活跃会员")
151
+ recs.append("4. 分析低峰时段,设计限时优惠活动激活非高峰客流")
152
+
153
+ return (
154
+ f"运营提升建议(模板):\n"
155
+ f" 坪效: {psm:.1f}元/m²/月({'+' if gap >= 0 else ''}{gap:.1f}% vs 行业)\n"
156
+ f" 转化率: {metrics['conversion_rate']:.1%} 外卖占比: {metrics['delivery_pct']:.1f}%\n\n"
157
+ f"优化建议:\n"
158
+ + "\n".join(f" {r}" for r in recs)
159
+ )
@@ -0,0 +1,214 @@
1
+ """
2
+ agents/realty/revenue_share.py — 分账规则 Agent
3
+ ================================================
4
+ 根据合同规则和实际流水,计算各方收益并生成分账配置建议。
5
+
6
+ 输入数据(data dict keys):
7
+ contract_rules — 合同规则(保底/分润比例/阶梯/服务费/风险准备金等)
8
+ transaction_data — 本期实际流水数据(总流水/支付渠道明细/退款等)
9
+ accounts — 各方收款账户信息(可选,用于分账配置验证)
10
+
11
+ 输出:
12
+ analysis — 分账计算说明文本
13
+ signal — BUY=分账正常 / HOLD=有补足情况 / SELL=流水严重不足
14
+ key_points — 各方金额摘要
15
+ data_used — 包含 split_result(可直接入库)
16
+ """
17
+ from __future__ import annotations
18
+
19
+ from decimal import Decimal, ROUND_HALF_UP
20
+ from typing import Any, Dict, List
21
+ from ..base import BaseAgent, AgentResult
22
+
23
+
24
+ class RevenueShareAgent(BaseAgent):
25
+ name = "revenue_share"
26
+ description = "分账规则:根据合同和实际流水计算各方应得金额,生成分账配置建议"
27
+
28
+ _SYSTEM = (
29
+ "你是一名分账与财务核算专家,专注于不动产经营权共创模式下的收益分配。\n"
30
+ "请对分账计算结果进行解读和说明:\n"
31
+ " 1. 说明本期各方应得金额的计算过程(分润基数→分润金额→保底补足→扣除项)\n"
32
+ " 2. 分析流水与保底的差距,判断经营状态(正常/偏低/严重不足)\n"
33
+ " 3. 如有阶梯分成被触发,解释阶梯规则的执行情况\n"
34
+ " 4. 给出本期结算的注意事项或风险提示\n"
35
+ " 5. 对下期经营给出1-2条改善建议"
36
+ )
37
+
38
+ async def analyze(self, symbol: str, data: Dict[str, Any]) -> AgentResult:
39
+ rules = data.get("contract_rules", {})
40
+ txn = data.get("transaction_data", {})
41
+ accts = data.get("accounts", {})
42
+
43
+ split = _calculate_split(rules, txn)
44
+
45
+ user_prompt = (
46
+ f"本期分账计算结果:\n"
47
+ f" 实际总流水: {split['gross_revenue']:,.2f}元\n"
48
+ f" 参与分润流水: {split['net_revenue']:,.2f}元\n"
49
+ f" 保底金额: {split['guaranteed']:,.2f}元\n"
50
+ f" 分润比例: {split['share_pct']}%\n"
51
+ f" 资产方分润金额: {split['owner_share']:,.2f}元\n"
52
+ f" 保底补足金额: {split['top_up']:,.2f}元(需经营方补缴)\n"
53
+ f" 资产方实得: {split['owner_total']:,.2f}元\n"
54
+ f" 平台服务费: {split['platform_fee']:,.2f}元\n"
55
+ f" 风险准备金: {split['risk_reserve']:,.2f}元\n"
56
+ f" 经营方实得: {split['operator_net']:,.2f}元\n"
57
+ f" 结算周期: {rules.get('settlement_cycle','月结')}\n\n"
58
+ f"合同规则: 保底{rules.get('guaranteed_monthly',0):,}元/月, "
59
+ f"流水分润{rules.get('revenue_share_pct',0)}%, "
60
+ f"平台{rules.get('platform_fee_pct',5)}%, "
61
+ f"风险准备金{rules.get('risk_reserve_pct',3)}%\n\n"
62
+ "请对以上分账结果进行解读和说明。"
63
+ )
64
+
65
+ analysis = await self._call_llm(self._SYSTEM, user_prompt, max_tokens=600)
66
+ if not analysis:
67
+ analysis = _template_split_analysis(split, rules)
68
+
69
+ signal = _split_signal(split)
70
+ confidence = 0.95 # 分账计算是确定性逻辑,置信度高
71
+ key_points = _split_key_points(split)
72
+
73
+ return AgentResult(
74
+ agent = self.name,
75
+ symbol = symbol,
76
+ analysis = analysis,
77
+ confidence = confidence,
78
+ signal = signal,
79
+ key_points = key_points,
80
+ data_used = {"split_result": split, "contract_rules": rules},
81
+ )
82
+
83
+
84
+ # ── 核心计算逻辑(Decimal精度) ────────────────────────────────────────────────
85
+
86
+ def _calculate_split(rules: Dict, txn: Dict) -> Dict:
87
+ """
88
+ 分账计算(精确到分)
89
+
90
+ 分配顺序:
91
+ 1. 从总流水中扣除: 平台服务费 + 风险准备金 + 退款
92
+ 2. 剩余净流水 vs 分润基数 → 计算资产方分润
93
+ 3. 资产方分润 vs 保底 → 计算保底补足
94
+ 4. 经营方实得 = 净流水 - 资产方总收益 - 平台费 - 风险准备金
95
+ """
96
+ D = Decimal
97
+
98
+ gross = D(str(txn.get("gross_revenue", 0)))
99
+ refunds = D(str(txn.get("refunds", 0)))
100
+ guaranteed = D(str(rules.get("guaranteed_monthly", 0)))
101
+ share_pct = D(str(rules.get("revenue_share_pct", 0))) / D("100")
102
+ base_revenue = D(str(rules.get("revenue_share_base", 0)))
103
+ platform_pct = D(str(rules.get("platform_fee_pct", 5))) / D("100")
104
+ reserve_pct = D(str(rules.get("risk_reserve_pct", 3))) / D("100")
105
+
106
+ # 各扣除项
107
+ net_revenue = gross - refunds
108
+ platform_fee = (net_revenue * platform_pct).quantize(D("0.01"), ROUND_HALF_UP)
109
+ risk_reserve = (net_revenue * reserve_pct).quantize(D("0.01"), ROUND_HALF_UP)
110
+ distributable = net_revenue - platform_fee - risk_reserve
111
+
112
+ # 资产方分润(超出分润基数部分 * 分润比例)
113
+ shareable_revenue = max(D("0"), distributable - base_revenue)
114
+ owner_share = (shareable_revenue * share_pct).quantize(D("0.01"), ROUND_HALF_UP)
115
+
116
+ # 保底补足(若分润不足保底,经营方须补足)
117
+ top_up = max(D("0"), guaranteed - owner_share)
118
+
119
+ owner_total = owner_share + top_up
120
+ operator_net = distributable - owner_total
121
+
122
+ # 阶梯分成(如有)
123
+ tiered_triggered = _apply_tiered(rules.get("tiered_rules", []), net_revenue)
124
+
125
+ return {
126
+ "gross_revenue": float(gross),
127
+ "refunds": float(refunds),
128
+ "net_revenue": float(net_revenue),
129
+ "platform_fee": float(platform_fee),
130
+ "risk_reserve": float(risk_reserve),
131
+ "distributable": float(distributable),
132
+ "guaranteed": float(guaranteed),
133
+ "share_pct": float(rules.get("revenue_share_pct", 0)),
134
+ "owner_share": float(owner_share),
135
+ "top_up": float(top_up),
136
+ "owner_total": float(owner_total),
137
+ "operator_net": float(operator_net),
138
+ "tiered_triggered": tiered_triggered,
139
+ }
140
+
141
+
142
+ def _apply_tiered(tiered_rules: List[Dict], revenue: Decimal) -> List[Dict]:
143
+ """计算触发的阶梯分成规则"""
144
+ triggered = []
145
+ for rule in tiered_rules:
146
+ threshold = Decimal(str(rule.get("threshold", 0)))
147
+ pct = rule.get("pct", 0)
148
+ if revenue >= threshold:
149
+ triggered.append({"threshold": float(threshold), "pct": pct,
150
+ "status": "triggered"})
151
+ else:
152
+ triggered.append({"threshold": float(threshold), "pct": pct,
153
+ "status": "not_triggered"})
154
+ return triggered
155
+
156
+
157
+ def _split_signal(split: Dict) -> str:
158
+ net = split.get("net_revenue", 0)
159
+ guaranteed = split.get("guaranteed", 0)
160
+ op_net = split.get("operator_net", 0)
161
+
162
+ if guaranteed <= 0: return "HOLD"
163
+ coverage = net / guaranteed if guaranteed else 0
164
+ if coverage >= 2.0 and op_net > 0: return "BUY"
165
+ if coverage >= 1.0 and op_net > 0: return "HOLD"
166
+ if op_net > 0 and coverage >= 0.5: return "SELL" # 经营方能勉强覆盖
167
+ return "STRONG_SELL" # 经营方净收入为负或流水极低
168
+
169
+
170
+ def _split_status(split: Dict) -> str:
171
+ """根据分账结果给出人读友好状态描述"""
172
+ top_up = split.get("top_up", 0)
173
+ op_net = split.get("operator_net", 0)
174
+ guaranteed = split.get("guaranteed", 0)
175
+ if top_up == 0:
176
+ return "流水分润超过保底,经营状况良好"
177
+ if op_net >= guaranteed * 0.5:
178
+ return "保底兜底生效(属正常),经营方净收入尚可"
179
+ if op_net > 0:
180
+ return "保底兜底生效,经营方净收入偏低,建议持续关注"
181
+ return "经营方净收入为负,无法自覆保底,需紧急处置"
182
+
183
+
184
+ def _split_key_points(split: Dict) -> List[str]:
185
+ pts = []
186
+ pts.append(f"本期总流水: {split['gross_revenue']:,.2f}元")
187
+ pts.append(f"资产方实得: {split['owner_total']:,.2f}元"
188
+ + (f"(含补足{split['top_up']:,.2f}元)" if split['top_up'] > 0 else ""))
189
+ pts.append(f"经营方实得: {split['operator_net']:,.2f}元")
190
+ pts.append(f"平台服务费: {split['platform_fee']:,.2f}元 风险准备金: {split['risk_reserve']:,.2f}元")
191
+ if split.get("top_up", 0) > 0:
192
+ pts.append(f"保底补足: {split['top_up']:,.2f}元(需经营方在结算日前缴纳)")
193
+ return pts
194
+
195
+
196
+ def _template_split_analysis(split: Dict, rules: Dict) -> str:
197
+ top_up_line = (
198
+ "保底补足: {:,.2f}元(须补缴)".format(split['top_up'])
199
+ if split['top_up'] > 0 else "流水覆盖保底,无需补足"
200
+ )
201
+ return (
202
+ f"分账计算说明(模板):\n"
203
+ f" 本期总流水: {split['gross_revenue']:,.2f}元 退款: {split['refunds']:,.2f}元\n"
204
+ f" 净流水: {split['net_revenue']:,.2f}元\n"
205
+ f" 平台服务费 ({rules.get('platform_fee_pct',5)}%): -{split['platform_fee']:,.2f}元\n"
206
+ f" 风险准备金 ({rules.get('risk_reserve_pct',3)}%): -{split['risk_reserve']:,.2f}元\n"
207
+ f" 可分配金额: {split['distributable']:,.2f}元\n"
208
+ f" 资产方分润: {split['owner_share']:,.2f}元\n"
209
+ f" 保底收益: {split['guaranteed']:,.2f}元\n"
210
+ f" {top_up_line}\n"
211
+ f" 资产方实得: {split['owner_total']:,.2f}元\n"
212
+ f" 经营方实得: {split['operator_net']:,.2f}元\n"
213
+ f" 状态: {_split_status(split)}"
214
+ )