Files

175 lines
7.3 KiB
Python

# -*- coding: utf-8 -*-
"""
财务风控节点
审查维度:研发资本化操纵、客户/供应商集中度、应收账款质量、现金流
"""
import json
from .base_agent import BaseAgent
FIN_SYSTEM_PROMPT = """你是一名精通科创板审计规则的注册会计师(CPA),同时是金融风控专家。
你的任务是基于提供的企业财务数据,从财务角度穿透审查以下风险:
1. 研发资本化操纵风险:研发资本化率是否异常,是否存在美化利润嫌疑
2. 客户/供应商集中风险:前五大客户/供应商占比是否过高
3. 应收账款质量:应收账款周转率是否异常,是否存在坏账风险
4. 现金流健康度:经营现金流是否能覆盖运营需求
评估标准参考:
- 科创板企业研发资本化率超过30%需重点关注
- 前五大客户占比超过50%存在集中风险
- 应收账款周转率低于4次/年需关注回款能力
- 经营现金流/营收比低于0.5需关注持续经营能力
请输出JSON格式:
{
"agent": "财务风控节点",
"rd_capitalization_risk": {"score": 0-100, "level": "高/中/低", "detail": "..."},
"concentration_risk": {"score": 0-100, "level": "高/中/低", "detail": "..."},
"receivable_risk": {"score": 0-100, "level": "高/中/低", "detail": "..."},
"cashflow_risk": {"score": 0-100, "level": "高/中/低", "detail": "..."},
"overall_fin_risk": {"score": 0-100, "level": "高/中/低"},
"key_findings": ["..."],
"recommendations": ["..."]
}"""
class FinanceAgent(BaseAgent):
"""财务风控节点"""
def __init__(self):
super().__init__(
name="财务风控节点",
system_prompt=FIN_SYSTEM_PROMPT,
role_icon="👔",
)
def evaluate(self, company_data: dict) -> dict:
"""执行财务风险评估"""
prompt = self._build_prompt(company_data)
result = self.infer_json(prompt)
if result.get("parse_error"):
result = self._rule_based_evaluation(company_data)
result["agent"] = "财务风控节点"
result["icon"] = self.role_icon
return result
def _build_prompt(self, company_data: dict) -> str:
financials = company_data.get("financials", {})
return f"""请对以下科创企业进行财务风险穿透审查:
企业名称:{company_data.get('short_name', '未知')}
行业:{company_data.get('industry', '未知')}
财务核心指标:
- 营业收入: {financials.get('revenue_2024', 0):,.0f}
- 净利润: {financials.get('net_profit_2024', 0):,.0f}
- 研发费用: {financials.get('rd_expense_2024', 0):,.0f}
- 研发资本化率: {financials.get('rd_capitalization_rate', 0):.1%}
- 研发/营收比: {financials.get('rd_revenue_ratio', 0):.1%}
- 前五大客户占比: {financials.get('top5_customer_ratio', 0):.1%}
- 前五大供应商占比: {financials.get('top5_supplier_ratio', 0):.1%}
- 应收账款周转率: {financials.get('receivable_turnover', 0):.1f} 次/年
- 经营现金流比率: {financials.get('cash_flow_ratio', 0):.2f}
请输出严格的JSON评估结果。"""
def _rule_based_evaluation(self, company_data: dict) -> dict:
"""基于规则的财务风险评估"""
fin = company_data.get("financials", {})
# 1. 研发资本化操纵风险
cap_rate = fin.get("rd_capitalization_rate", 0)
if cap_rate >= 0.4:
rd_score = 90
rd_detail = f"研发资本化率高达{cap_rate:.0%},严重怀疑美化利润"
elif cap_rate >= 0.3:
rd_score = 70
rd_detail = f"研发资本化率{cap_rate:.0%},超过行业警戒线(30%),需重点审查"
elif cap_rate >= 0.15:
rd_score = 45
rd_detail = f"研发资本化率{cap_rate:.0%},处于中等水平,建议关注趋势"
elif cap_rate > 0:
rd_score = 25
rd_detail = f"研发资本化率{cap_rate:.0%},处于合理范围"
else:
rd_score = 10
rd_detail = "研发费用全部费用化处理,财务政策审慎"
# 2. 集中度风险
customer_ratio = fin.get("top5_customer_ratio", 0)
supplier_ratio = fin.get("top5_supplier_ratio", 0)
max_concentration = max(customer_ratio, supplier_ratio)
if max_concentration >= 0.8:
conc_score = 90
conc_detail = f"前五大客户占比{customer_ratio:.0%},供应商占比{supplier_ratio:.0%},集中度极高"
elif max_concentration >= 0.6:
conc_score = 70
conc_detail = f"前五大客户占比{customer_ratio:.0%},供应商占比{supplier_ratio:.0%},集中度偏高"
elif max_concentration >= 0.4:
conc_score = 45
conc_detail = f"前五大客户占比{customer_ratio:.0%},供应商占比{supplier_ratio:.0%},中等集中度"
else:
conc_score = 20
conc_detail = f"客户和供应商分布较为分散"
# 3. 应收账款风险
turnover = fin.get("receivable_turnover", 8)
if turnover < 3:
recv_score = 80
recv_detail = f"应收账款周转率仅{turnover:.1f}次/年,回款能力极差"
elif turnover < 5:
recv_score = 55
recv_detail = f"应收账款周转率{turnover:.1f}次/年,回款速度偏慢"
elif turnover < 8:
recv_score = 30
recv_detail = f"应收账款周转率{turnover:.1f}次/年,回款能力尚可"
else:
recv_score = 15
recv_detail = f"应收账款周转率{turnover:.1f}次/年,回款能力良好"
# 4. 现金流风险
cf_ratio = fin.get("cash_flow_ratio", 1.0)
if cf_ratio < 0.5:
cf_score = 80
cf_detail = f"经营现金流比率仅{cf_ratio:.2f},存在持续经营风险"
elif cf_ratio < 0.8:
cf_score = 55
cf_detail = f"经营现金流比率{cf_ratio:.2f},现金流偏紧"
elif cf_ratio < 1.2:
cf_score = 30
cf_detail = f"经营现金流比率{cf_ratio:.2f},基本健康"
else:
cf_score = 15
cf_detail = f"经营现金流比率{cf_ratio:.2f},现金流充裕"
overall = int(rd_score * 0.30 + conc_score * 0.30 +
recv_score * 0.20 + cf_score * 0.20)
findings = [rd_detail, conc_detail]
if recv_score >= 50:
findings.append(recv_detail)
if cf_score >= 50:
findings.append(cf_detail)
return {
"rd_capitalization_risk": {"score": rd_score, "level": self._level(rd_score), "detail": rd_detail},
"concentration_risk": {"score": conc_score, "level": self._level(conc_score), "detail": conc_detail},
"receivable_risk": {"score": recv_score, "level": self._level(recv_score), "detail": recv_detail},
"cashflow_risk": {"score": cf_score, "level": self._level(cf_score), "detail": cf_detail},
"overall_fin_risk": {"score": overall, "level": self._level(overall)},
"key_findings": findings,
"recommendations": ["关注研发资本化率变化趋势", "降低客户集中度风险"],
}
@staticmethod
def _level(score: int) -> str:
if score >= 70:
return "高"
elif score >= 40:
return "中"
return "低"