mobile wallpaper 1
mobile wallpaper 2
mobile wallpaper 3
mobile wallpaper 4
1925 字
5 分钟
两天,给财报实验室补上「行业」这条骨架
2026-10-24

这两天没加新功能,都在补一件事:让「行业」真正参与分析,而不只是个标签。

以前所有公司都走同一套判断逻辑,看毛利率、看负债率、看周转天数。问题是这些阈值本来就不通用——零售的 30% 负债率算健康,房企的 30% 等于没借钱。同一把尺子量所有人,结论必然是错的。

👉 进入财报实验室#


一、先有骨架:10 个组 + 20 个门类#

行业分类做成了两层:

层内容用途
行业组10 个(制造、零售、地产、金融…)决定用哪套分析模板
国标门类20 个(A 农林牧渔 → T 国际组织)对外可对齐 GB/T 4754

识别路径按可信度排:人工指定 > 代码映射表 > PDF 正文 > 公司名关键词。

后面这层「门类」是今天才补的。之前拿 20 个门类名字去跑,只认得出 13 个——M(科研)、N(水利环境)、O(居民服务)、Q(卫生)、R(文体)、S(公共管理)全部落空,因为它们只存在于服务业的中类里,没写进组识别的关键词表。

补完之后:

  • 门类 → 组识别:19 / 20(T 国际组织不认,A 股没这种公司)
  • 门类代码:20 / 20,每家公司的结果里都带 section

现在确认页可以直接选字母:

A · 农、林、牧、渔业
C · 制造业
M · 科学研究和技术服务业

选完自动映射回行业组,页面显示「服务业 · 第三产业 · 门类 M」。

二、模板外置:阈值不该写死在代码里#

原先判断逻辑是 if 毛利率 < 0.1: ...,散在几百行里。改一个阈值要动代码、跑测试、重启服务。

现在全部搬进 JSON:

{
"id": "inventory_heavy",
"angle": "库存型",
"when": [{ "metric": "存货周转天数", "op": ">=", "value": 180 }],
"text": "存货周转 <b>{存货周转天数}</b> 天:货压在仓库里..."
}

规则引擎支持 >= > <= < == != exists truthy,文案里能直接引用指标并指定格式(百分比 / 亿元 / 天数 / 倍数)。行业模板用 extends 继承通用规则,只写差异部分。

一个副作用:配置坏了程序不会崩,会回退到旧逻辑并打警告——宁可分析得糙一点,也不能让整份年报解析失败。

三、识别 PDF 正文:从 60% 到能用#

代码映射表覆盖不到的公司,只能去年报正文里找「所属行业」这类句子。

第一版扫前 15 页,50 份抽样只认出 60%。漏掉的原因很朴素:有的公司把行业信息写在第 21 页。

改成两遍扫描(15 页 → 30 页)就上去了。同时还修了几个假阳性:

  • 「1、新一代信息技术产业」→ 序号开头的句子不算
  • 「集成电路作为信息技术产业」→ 泛指句式不算
  • 「金融等众多行业」→ 带「等」的泛指不算

现在这条路是 60% 召回、0 错误——宁可认不出,也不要认错。

四、金融三业:报表结构完全不同#

制造业那套解析器遇到银行直接崩:银行没有「营业成本」,保险没有「毛利」,证券的科目名是另一套。

所以单独写了金融解析器,按三个行业各自的恒等式校验:

行业恒等式
银行8 条(资产=负债+权益、利息净收入拆分…)
证券8 条
保险5 条(保险不查收入拆分)

结果是银行 8/8、证券 8/8、保险里的人寿 5/5 全部通过。平安卡在一个 5,815 元的差额上,至今没修——差一分钱都不出页,这是有意的。

五、诊断:从「三个数」到「为什么亏」#

最初的分析输出是这样的:

毛利率 33.48%、净利率 -8.44%、期间费用率 73.76%

三个数字摆出来,读者还得自己算哪个是主因。现在的输出是结论先行:

收入同比 17.06% 到 6.62 亿元,仍亏 0.56 亿元——毛利撑不住费用。毛利 2.21 亿、期间费用 4.88 亿。

判断「为什么亏」的规则改过一次。第一版按固定顺序试:负毛利 → 费用吞噬 → 减值 → 投资。结果福星股份亏 41.82 亿,被判成「费用吞噬」——因为毛利确实覆盖不了费用(缺口 2.64 亿),可真正的窟窿是 25.48 亿减值。

改成按占比判:费用缺口、减值、投资亏损,谁占亏损额比例最大,谁就是主因。现在福星是「减值拖累型」,岩山科技是「费用吞噬型」(毛利 2.21 亿 vs 费用 4.88 亿),各归各位。

六、全量回测:61 份年报#

这两天最重要的一个数字,是拿 61 份真实年报跑了一遍完整链路:

指标结果
样本61 份
通过57 份(93.4%)
修完权益校正58 份(95.1%)
剩余失败3 份(各差百万到千万级)

失败的全被恒等式拦下来了,没有一份错误页面流出去。

最值得说的一个 bug:山子高科差了 63 亿。查下来是「所有者权益」抓到了权益变动表里的同名行(74.83 亿),而资产负债表里归母 11.59 + 少数 0.01 = 11.60 亿,正好等于资产 108.85 − 负债 97.25。

修法是:当归母+少数与「资产−负债」一致、却与已解析的权益不符时,用前者覆盖。两个来源交叉验证,比任何单点解析都可靠。

七、顺手把界面换了#

原来是蓝粉渐变的 SaaS 风,看久了和「财报」这件事不太搭。换成了一套更安静的语言:暖石色背景、单一青色强调、1px 细线做结构、标题用细字重。

改的不只是颜色:

  • 控制台上传时显示真实百分比进度,解析时显示已用时间(30–60 秒不让你干等)
  • /admin 收进后台——经 Cloudflare 隧道访问一律 404,只能本机直连
  • 年报页的「两年对比」「关键比率」加了图:一个同比变化率横条,一个按单位拆开的分组条形(比率和天数不能画在同一根轴上,否则流动比率 0.83 会被压成一条线)

八、还没做完的#

  • 教育、医疗、环保公用三个细分模板刚写完,阈值是行业常识 + 单一样本定的,等真实年报来打脸
  • 中天精装差 36.5 万、平安差 5,815 元,都是小数目但没修
  • 厦门银行的 PDF 文本层是散的,暂时解析不了

两天下来最大的感受:财报分析的可信度不来自模型多聪明,来自每一处都能被验证。资产必须等于负债加权益,现金流必须首尾闭合,差一分钱就拒绝出页——这条规则救回来的错误,比任何算法优化都多。

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

两天,给财报实验室补上「行业」这条骨架
https://star-fall.159911.xyz/posts/caiwu-industry/
作者
星落
发布于
2026-10-24
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录

star-fall のcafe 加载中…