非创新型公司年度经营复盘(ROIC × g 骨架)
这个 skill 是干嘛的?一句话版
给一家"生意模式已经定型"的公司做年度体检——用两个数字当骨架: ROIC(投进去的钱一年挣回百分之几,回答"这门生意好不好")和 g(收入还在不在增长,回答"这门生意还在不在长"),然后把这两个数字一层层拆开, 最后用一张 T 字表看钱是怎么在这两者之间流转的。
产出是一份六章的年度经营复盘报告 —— 最终只交付一个 HTML 文件(六章合一、表格全内联)。
用户 2026-09-22 明确要求:不再输出 PDF、不再单独交付 CSV 与分章子表 HTML。 三个脚本(第一 / 四 / 五章)的产物算中间产物,落临时目录即可,不要复制进交付目录。
什么时候会想到用它
- 你拿到一家制造业 / CXO / 器械 / 消费公司,想系统性地把它过去 10 年的经营捋一遍
- 你想知道"这家公司 ROIC 从 20% 掉到 12%,到底是卖得便宜了还是资产变重了"
- 你想知道"收入涨了这么多,是哪块业务、哪个区域在涨"
- 你想知道"这些年挣的钱和融的钱,都投到哪去了"
- 你要给一家公司写年度复盘,但不想每次都从零想结构
什么时候不要用: 如果这家公司是创新药或早期 biotech——它的钱今天花出去,收入要等 5–10 年、 还取决于临床成败。这时候 ROIC 必然难看、g 也预测不了,这套框架会给出错误的结论。 遇到这种情况请直接说明不适用。
它长什么样(六章骨架)
一、现象描述 ← 十二项指标逐年排一张表(全自动)
收入 / 增长 / 扣非归母 / 增长 / ROIC剔商誉 / ROIC含商誉 / 总资产 / 增长
/ 员工总数 / 员工增长 / 当年股价涨跌幅 / 重大事件
▲ 表格分上下两段:上面是「年度段」(到最近一个完整财年)
下面是「季度段」(最近 6 个单季,看最新颗粒度)
二、拆解收入增长 ← 拆 g(半自动 + 人工)
2.1 增长阶段:分几个阶段看
2.2 业务拆解:哪个业务在长(年度 + 末尾一列最新半年报)
2.3 区域拆解:哪个区域在长(年度 + 末尾一列最新半年报)
2.4 逐年原因:年报 + 卖方点评 + 电话会纪要(年层 + 季层)
2.5 前瞻指标:未来 g 会怎样(年层看可不可信,季层看现在指向哪)
三、特殊项目 ← 有就写,没有就不写(人工,绝不编造)
capex(走单季)/ 在手订单 / 管线数 / 第二增长曲线……
(来源:年报 + 每年年报后的卖方点评 + 电话会纪要)
四、ROIC 两层拆解 ← 拆 ROIC(全自动,调 roic-decomp)
4.1 主表
4.2 从表里看趋势和原因
4.3 落到业务层面解释
五、资金来源与运用 ← T 字表(全自动,调 sources-uses)
钱从哪来 → 分红回购 + 资产增加,两边必须相等
六、概括性总结 ← 人工
它解决的核心问题
一家公司值不值得看,本质上就看两件事:
钱投进去,回报高不高? → ROIC
这门生意还在不在变大? → g
但只看到这两个数字没用。真正的洞察来自拆开看:
- ROIC 掉了 → 是"卖得便宜了"(净利率)还是"资产变重了"(周转率)?
- g 下来了 → 是所有业务一起慢,还是主力业务见顶、新业务没接上?
- 钱一直投 → 是在增强未来的 ROIC 和 g,还是在摊薄它们?
跟其他 skill 的关系
这个 skill 是总装车间,不是新机器。它把已有的四个 skill 串起来:
| 章节 | 调用谁 |
|---|---|
| 第一章 | 本 skill 自己的脚本 |
| 第四章 | roic-decomp(ROIC 两层拆解) |
| 第五章 | sources-uses(资金来源与运用) |
| 第三章部分 | capex-revenue-analysis(capex 与收入关系) |
所以不要重复造轮子——第四、五章直接调它们的脚本,口径天然一致。
容易忘的二十一个点
-
第一章第 5、6 列并列(ROIC 剔商誉 / 含商誉)不是冗余 ——两个数的差距本身就说明问题:差距大 = 大量并购商誉在拖累真实回报。
-
第一章第 7、8 列并列(总资产 / 总资产增长)也不是冗余 ——总资产增速 vs 收入增速就是 ROIC 的前哨。 资产涨得比收入快,ROIC 迟早掉;资产不涨收入还在涨,ROIC 会升。 看这两个数就能提前一两年看出 ROIC 要往哪走。
-
第二章业务拆解的披露口径会变 ——公司换个分部口径,数字就断了。不同口径必须分开成表并标注年份, 硬拼成一条连续曲线会得到错误结论。
-
2.4 / 2.5 / 第三章不要只翻年报 ——年报是"公司想让你看到的原因",卖方点评和电话会纪要是"市场追问出来的原因"。 每年年报后(3–5 月)券商都会发事件点评(本地在
外部研究/), 电话会纪要在跟踪纪要/。这三处都要过一遍。 2.5 只收"每年都常规披露的"(连续 ≥3 年、口径一致、领先收入 1–4 季度), 一次性的单年数据只能当 2.4 的佐证。 -
拿点评/纪要里的"观点"当"事实"写进报告是大忌 ——只写公司方明确说的、或点评里引用的公司披露数字。 分析师自己的推测要么不写,要么标"某券商认为…"。无出处宁可留白。
-
第三章"没有就不写" ——公司没有连续披露的特殊项目时,这一章直接省略。 不要为了结构完整而凑数,这是硬约束。
-
T 字表必须左右布局,不能上下两张表 ——第五章的"钱从哪来"和"钱去哪了"要左右并排(CSS grid + 中间竖分隔线), 不要输出成源在上、运用在下两张独立表。这是用户明确纠正过的地方:"样子很丑"。
-
员工数只能从大智慧 F10 拿,而且只有最近 10 年 ——akshare / 东财 / 同花顺都没有员工人数。 F10 的「员工构成」表不是
<table>是<dl>,用 table 正则抓会静默返回空。 做"上市以来"复盘时早期为空是正常的,需用--emp-csv补。 -
第一章的表是"两段拼起来的",不是一张连续表 ——上面是年度段(一行一年,一直到最近一个完整财年), 下面是季度段(最近 6 个单季)。 为什么这么设计:年报是一年一次的,等最新年报出来时,最近半年的经营变化已经"过期"了。 接上 6 个单季,就能看到最新的颗粒度。 两段是上下拼接,季度段不替代年度段,年度段最后一行也不换成半年报。
-
季度段的增长率是"同比",不是"环比" ——2026Q1 对比 2025Q1,不是对比 2025Q4。 制造业季节性极强,用环比会把淡季读成下滑。 普洛实测:2026Q1 收入同比 −10.4%,环比却是 +21.1%——同一个数,两个相反的结论。
quarterly.py已按同比实现。 -
季度段的末行是"官方累计值",不是单季加总 ——末行给半年报/年报披露的累计值。 单季加总会和它差一点(年末调整、重述、合并范围变化)。 实测对账:2026Q1 单季 24.47 + Q2 单季 23.76 = 48.23 = 半年报累计 48.23 ✓ 有差异时脚本会打
[info],以披露值为准。 -
季度段的 ROIC 和员工数两列留空是故意的 ——ROIC 是年度概念(分母是期初期末均值),单季年化会失真、且和年度段不可比; 员工数半年报/季报根本不披露,只有年报有。 这两列保留但填「—」,是为了让季度段和年度段在视觉上对齐, 读者一眼知道"这两项季度没有",而不是以为漏了。
-
2.2 / 2.3 的分部数据只能到"最新半年报",做不出季度段 ——这不是取数偷懒,是信息披露制度:分部(主营业务构成) 只有半年报和年报披露,一季报/三季报根本不披。 实测 24 个报告期全部是
06-30或12-31,没有例外。 所以这两节的表 = 年度列 + 末尾追加一列最新半年报。 追加那一列注意三点:标"H1 单季值(未年化)"、不比大小只比占比、占比重算。 -
capex 是唯一该走单季的运营指标 ——在手订单、客户数、产能利用率大多是半年/年才披露一次, 但 capex 是现金流量表科目,季报就有,所以走单季。 用
CONSTRUCT_LONG_ASSET字段,与收入对照时必须用滚动 4 季(TTM)比值, 比单季绝对值会误判(单季大额投入看起来像"扩张",其实可能只是某基地一次性付款)。 -
2.4 / 2.5 也是"年层 + 季层"两段 ——和第一章同一个思路:年层看趋势,季层看最新。 季层的"原因"比年层难拿(季报的经营讨论只有几段), 拿不到就只写数据变化,不要硬编原因——这条比年层更要守。
-
第 11 列「当年股价涨跌幅」讲的是"市场当时认没认" ——它是后复权的年末÷上年末(不复权会把送转/分红的除权跳空算成暴跌)。 上市首年基数用上市首日收盘(标
*),末年未结束就按 YTD(标YTD), 上市前年份填「—」(公司没上市,不是取数失败,绝不手填)。 它的价值在于和基本面背离的地方:英科医疗 2021 年收入还在 +17.4%、 ROIC 仍有 119%,股价却已经 −46.5% —— 市场比财报早一年看到周期顶。 -
季度接口不一定回溯到公司最早年份,早期年份要走"年度利润表"兜底 ——季度接口的回溯深度因公司而异(药明到 2017Q1,英科医疗只到 2016Q3)。 某年季度记录不足 4 条时,按季度加总会把半年当全年 (英科 2016:真实 11.83 亿,加总只有 6.4 亿,不报错、表格也看不出异常)。 所以脚本对这类年份整行改取年度利润表接口。 另外首年缺上一年末资产负债表时,该年 ROIC 留空即可,不要为了凑数改成期末 IC ——那会破坏与其它年份的可比性。
-
股价那一列会"静默缺",靠缓存兜底 ——东财 K 线接口会被代理间歇性挡住(同一天 17:03 通、18:00 连报 ProxyError, 重试 8 次全败),届时第 11 列整列变空。 脚本现在会在成功时写一份
<输出目录>/price_{6位数字代码}.csv, 接口不通时自动读回并打印[info] 改用缓存(已结束年份的值不会变)。 这两个文件名都必须用 6 位数字代码(price_300677.csv、events_300677.csv), 写成price_SZ300677.csv会静默找不到。事件文本里含英文逗号(如7,292.948) 要加引号,否则会被截断。 -
拼总报告时不要直接内联三份自动产出的 CSS ——第一章、第四章、第五章各带一份 CSS,都有
table/th,td/thead th这类通用选择器,直接拼会互相覆盖(ROIC 表的深蓝表头被现象表样式顶掉)。 要把每份 CSS 的每个选择器加.chN前缀做作用域化,表格包进<div class="chN">。 打印时还要加-webkit-print-color-adjust:exact(保底色)、thead{display:table-header-group}(长表跨页重复表头), 并显式重设.tacc{display:flex!important}——否则 A4 会把 T 字表压成上下布局。 -
交付物只有一份 HTML,别多给 ——用户 2026-09-22 明确要求「以后只生成一个 html 文件就行了,别的不用了」。 以前会顺手把 PDF、现象表 CSV、现象表 HTML、ROIC 拆解 HTML、T 字表 HTML 全复制到 交付目录(一次 6 个文件),现在只放一个
{公司}_{6位代码}_年度经营复盘_{起}_{止}.html。 三个脚本的产物落临时目录即可;但不要删——verify.py与正文数字溯源都靠它。 PDF 只在用户明确要求时才做。 -
左侧目录必须由正文锚点自动生成,别手写 ——报告的左边有一条 fixed 目录栏(
222px,滚动时高亮当前章节)。 它是读长报告的唯一导航,所以外观已固化成外壳,不要再每次现写:templates/report_shell.html(CSS + 目录容器 + scrollspy)+scripts/shell.py(render()拼装、build_nav()生成目录、check_anchors()查断链)。 为什么必须自动:第三章「没有就不写」是硬约束,删章时手写目录极易漏删锚点 → 点进去跳到页首。build_nav()扫正文实际锚点生成,删章即消失。 锚点约定:c0摘要 /c1–c6章 /ap附录 /cN-M二级;h3有标题能自动取名,div类锚点必须手写data-nav="文案"才进目录。 两个不能删的断点:980px 隐藏目录;@media print里必须同时写.wrap{display:block}+nav{display:none},否则打印只印出左半页。 填外壳一律str.replace(),不能.format()(CSS 大括号会 KeyError)。
怎么跑
$PY = "<本机 Python 解释器,见 ENV.local.md>"
$SK = "$env:USERPROFILE\.workbuddy\skills"
# 第一章:十二项指标表(全自动;员工数自动走大智慧 F10)—— 产物是中间产物,不交付
& $PY "$SK\non-innovative-annual-review\scripts\annual_review.py" SH603259 2014 2025
# 默认 = 年度段 + 季度段(最近 6 个单季)
# F10 只有最近 10 年,更早年份用 --emp-csv 传补(列:年份,员工数)
# 不想抓员工数时加 --no-emp
# 季度段行数可调:--quarters 8
# 只要年度段(不抓季度):--no-quarters
# 第四章:ROIC 两层拆解
& $PY "$SK\roic-decomp\scripts\roic_decomp.py" SH603259 2014 2015 ... 2025
# 第五章:资金来源与运用
& $PY "$SK\sources-uses\scripts\t_account.py" SH603259 2014 2025
# 重大事件(可选):在临时目录放一个 events_603259.csv
# 三列:年份,事件,类型
# 类型 = 定稿(已核实) / 草稿(检索来的,脚本自动加 [草稿] 前缀提醒你还没核实)
# 交付:把三块自动表格按作用域内联进六章模板(正文存成 body.html),
# 再用固化外壳合成 —— 目录会自动生成并校验断链,只把这一份 HTML 放交付目录
& $PY "$SK\non-innovative-annual-review\scripts\shell.py" `
--title "药明康德(603259)经营复盘 2014–2025" `
--body-file "<临时目录>\body.html" --out "<交付目录>\药明康德_603259_年度经营复盘_2014_2025.html"
# 也可以从旧报告重排:--from-report <旧报告>.html --out <新报告>.html
# 只看目录不写文件: --title T --body-file <临时目录>\body.html --out x --nav-only
# (PDF 仅在用户明确要求时才导)
# 自检(改过 skill 后跑一下)
& $PY "$SK\non-innovative-annual-review\scripts\verify.py" --full
注意:用哪个 Python 解释器、里面有没有 akshare,看同目录的 ENV.local.md——
那是每台机器各一份的本地配置(本机用的是托管 venv,里面装了 akshare)。
不要在 README 里写死解释器版本:2026-09-22 发现这里曾写着「必须用系统 Python 3.14,
托管版 3.13 没装 akshare」,与 ENV.local.md 直接矛盾——机器相关的东西一律只写在 ENV.local.md。
输出长什么样
- 第一章:一张 HTML 表,分上下两段
- 年度段:一行一年,十二列 (收入 / 收入增长 / 扣非归母 / 扣非增长 / ROIC剔商誉 / ROIC含商誉 / 总资产 / 总资产增长 / 员工总数 / 员工总数增长 / 当年股价涨跌幅 / 重大事件)
- 季度段:最近 6 个单季 + 1 行官方累计值(高亮) (同比口径;ROIC 两列、员工两列、股价一列填「—」)
- 增长与股价涨跌幅为正标红、为负标绿(A 股习惯),底部自动附口径说明
- 第四、五章:各自 skill 的 HTML 产物(中间产物,不交付)
- 交付给用户的只有一份文件:
{公司}_{6位代码}_年度经营复盘_{起}_{止}.html——六章合一, 三块自动表格按.ch1/.ch4/.ch5作用域内联
一句话记忆
ROIC 说好不好,g 说长不长;第二章拆 g,第四章拆 ROIC,第五章看钱怎么在中间流转。
总资产涨得比收入快 → ROIC 要掉;这是最早能看到的预警。
第一章的表是两段拼的:年度段看趋势,季度段看最新——季度段同比,别用环比。
创新药别用——人家投入在今天,收入在很远的未来。
Scan to join WeChat group