財務分析有一句被引用到磨出包漿的話:利潤是觀點,現金是事實。賬面利潤經過應計會計的多層估計——壞帳準備怎麼提、存貨怎麼計價、研發支出算費用還是資產、折舊年限取多長——每一層估計都是管理層的判斷空間。判斷空間大不等於有問題,但判斷空間的方向長期一致地偏向「讓利潤更好看」時,問題就大了。而現金流量表相對難以美化,因為現金的收付有銀行流水作外部證據。
這篇文章做三件事:第一,把三張報表的勾稽關係寫成可機械驗證的公式——數字先「對得上」,才談得上分析;第二,給出現金流品質的檢查構面與一張紅旗速查表(訊號→該查哪個科目→怎麼驗證);第三,示範把這些檢查寫成可自動執行的規則引擎,接到你的年報抽取管道上。文中所有數字均為教學用假設值,公司均為虛構,與任何真實公司無關;紅旗訊號只是複核線索,不構成對任何公司的判斷。財報數據怎麼從 PDF 變成結構化 JSON,見 300 頁年報轉結構化 JSON,本篇假設你已經有那層管道。
一、三表勾稽:先確認數字「對得上」
三張報表不是三份獨立文件,而是同一套帳的三個視圖,彼此有硬性勾稽關係。這些關係是免費的機械驗證——抽取管道輸出的數據如果勾稽不過,要麼是抽取錯(OCR 錯位、單位搞混、欄位對錯),要麼是報表本身有值得深挖的地方。無論哪種,都必須先處理再分析。
核心勾稽公式(允許容差,超差必須有解釋項):
現金勾稽:
期末現金 = 期初現金 + 經營活動淨現金流 + 投資活動淨現金流
+ 融資活動淨現金流 ± 匯率變動影響
保留盈餘勾稽:
期末保留盈餘 = 期初保留盈餘 + 本期淨利 − 宣告股利 ± 其他權益變動
(注意口徑:歸屬母公司淨利 vs 全口徑淨利,差額是非控股權益損益)
固定資產滾動勾稽:
期末不動產廠房設備 ≈ 期初 + 本期購置(CapEx)− 折舊
− 處置帳面價值 ± 減值 ± 匯率換算
(真實年報還有重估、轉列持有待售等項目,容差外的差額要逐項對到附註)
債務勾稽:
計息債務的增減 ↔ 現金流量表融資活動中的借款/還款項目
利息費用(損益表)↔ 利息付現(現金流量表附註)——差異來自應計與資本化利息
工程上把這四組勾稽寫成斷言,容差設為抽取值的可容忍誤差(例如報表單位的四捨五入範圍)。勾稽失敗的處理流程:先懷疑抽取(回查原頁),再懷疑口徑(合併範圍變動、處置子公司),最後才是「報表本身對不上」——那是重大發現,要單獨記錄。這一步同時是抽取品質的守門員:機器讀財報的錯誤模式與工具選型見 機器怎麼讀懂財報 與 PaddleOCR 抽取港股年報。
二、現金轉換率:第一個體檢指標
最粗但最有效的指標:經營現金流與淨利的比值,逐年看、看趨勢,不看單年。
現金轉換率 = 經營活動淨現金流 ÷ 淨利(口徑全程一致,建議用全口徑)
自由現金流 FCF = 經營活動淨現金流 − 資本支出
判讀邏輯:
- 單年背離正常:營運資本有時間性(大單預收、年末集中回款),一年偏低說明不了什麼
- 持續單向背離是訊號:淨利年年增長、現金轉換率年年下滑,代表利潤越來越「紙面化」
- 背離要分解歸因:現金流量表間接法本身就是一張「淨利→現金」的調節表,逐項看差異來自折舊攤提(非現金費用,正常)、營運資本變動(要追查)、還是其他項目(要讀附註)
乙公司(虛構,教學假設值,單位:百萬)的五年序列:
| 年度 | Y1 | Y2 | Y3 | Y4 | Y5 |
|---|---|---|---|---|---|
| 淨利 | 100 | 120 | 145 | 175 | 210 |
| 經營現金流 | 90 | 100 | 95 | 80 | 60 |
| 現金轉換率 | 0.90 | 0.83 | 0.66 | 0.46 | 0.29 |
| 淨利增速 | — | 20.0% | 20.8% | 20.7% | 20.0% |
這是一家損益表漂亮得整齊的公司:淨利每年增長約兩成。但現金轉換率五年內跌到不足三成——每 1 元賬面利潤只收到 0.29 元經營現金。錢去哪了?下一步就是拆營運資本。
三、營運資本紅旗:應收帳款、存貨與應付帳款
應收帳款:收入是真的收到了嗎
DSO(應收帳款週轉天數)= 應收帳款 ÷ 期間收入 × 期間天數
核心比較:應收帳款增速 vs 收入增速
乙公司的應收帳款(教學假設值):
| 年度 | Y1 | Y2 | Y3 | Y4 | Y5 |
|---|---|---|---|---|---|
| 收入 | 1,000 | 1,150 | 1,300 | 1,450 | 1,600 |
| 應收帳款 | 200 | 260 | 350 | 480 | 650 |
| 應收增速 | — | 30.0% | 34.6% | 37.1% | 35.4% |
| DSO(天) | 73.0 | 82.5 | 98.3 | 120.8 | 148.3 |
收入增速逐年放緩(15%→10%),應收帳款增速卻維持在 30% 以上——應收增速是收入增速的三倍,DSO 五年翻倍。這個組合的典型解釋只有幾種:放寬信用政策換收入(提前確認的風險上升)、 channel stuffing(向渠道壓貨)、客戶品質惡化(回款能力下降)、或收入本身激進確認。哪一種都需要查附註:帳齡結構是否惡化、壞帳準備計提比率是否不升反降、期後回款情況、收入確認政策有沒有變更。
存貨:成本有沒有被留在資產負債表上
DIO(存貨週轉天數)= 存貨 ÷ 期間銷貨成本 × 期間天數
紅旗組合:DIO 持續拉長 + 毛利率不降反升 + 存貨跌價準備比率下降
乙公司存貨(教學假設值):Y1→Y5 分別為 150、190、250、330、440,銷貨成本 700→1,100,DIO 從 78 天拉到 146 天;同期毛利率反而從 30.0% 微升到 31.2%。存貨堆積通常意味著成本應該被結轉進損益表卻被留在資產負債表上——若跌價準備沒有同步加提,毛利率就是虛的。驗證方法:查存貨明細(原材料/在製品/製成品哪部分堆積)、跌價準備的計提政策與實際比率、存貨帳齡、以及毛利率與同口徑同業的偏離。
應付帳款:往上游藏的利潤
DPO(應付帳款週轉天數)突然拉長有兩種解釋:對上游議價力增強(好事),或刻意拖付款製造經營現金流(壞事,且不可持續——供應商遲早收緊信用)。區分方法:看應付增速是否遠超採購增速、有沒有供應商糾紛或票據逾期的披露、經營現金流的改善是否恰好只來自應付增加。
四、資本化支出:「費用」與「資產」的邊界遊戲
應計操縱裡最隱蔽的一類,發生在「這筆支出算當期費用還是資本化為資產」的邊界上:
| 手法 | 利潤表效果 | 資產負債表效果 | 檢查訊號 | 該查哪裡 |
|---|---|---|---|---|
| 研發支出資本化比率突升 | 當期費用減少、利潤上升 | 無形資產增加 | 資本化比率與自身歷史及同業慣例的偏離;攤銷年限是否偏長 | 會計政策附註、無形資產變動表 |
| 利息資本化 | 財務費用下降 | 在建工程/資產成本增加 | 資本化利息金額與在建工程規模是否匹配 | 借款費用附註 |
| 折舊/攤提年限拉長 | 當期折舊減少 | 資產淨值偏高 | 會計估計變更披露;變更時點是否恰好在本業轉弱時 | 會計估計變更附註、固定資產明細 |
| 減值「一次洗澡」後輕裝上陣 | 未來折舊攤提變輕 | 資產帳面大幅下調 | 大額減值後的年份利潤「奇蹟式」改善 | 減值測試假設(折現率、增長率)披露 |
判讀原則:資本化本身不是錯,方向一致性才是訊號。一家公司如果在業績壓力最大的年份恰好更改估計、恰好提高資本化比率、恰好減少減值計提,每個動作單獨看都有理由,連起來看就是一張完整的圖。規則引擎要做的就是自動把這些「各自合理」的動作放到同一張時間軸上。
五、紅旗訊號速查表
把前面各節收斂成一張可直接落地的檢查表(訊號→該查哪個科目→怎麼驗證):
| 紅旗訊號 | 該查哪個科目/附註 | 怎麼驗證 |
|---|---|---|
| 現金轉換率持續下滑 | 現金流量表間接法調節項 | 逐年分解淨利與 OCF 的差異來源,定位最大調節項 |
| 應收增速遠超收入增速 | 應收帳款附註:帳齡、壞帳準備 | 帳齡是否拉長、準備比率是否下降、期後回款抽查 |
| 收入期末集中 | 分部/季度數據、應收明細 | 末季收入佔比異常、期後退貨與紅字沖銷 |
| 存貨堆積+毛利率上升 | 存貨附註:明細、跌價準備 | NRV 測試、存貨帳齡、成本結轉方法有無變更 |
| 研發資本化比率突升 | 無形資產變動表、會計政策附註 | 與歷史及同口徑同業比較;攤銷年限合理性 |
| 折舊年限拉長 | 會計估計變更披露 | 重算變更對當期折舊的影響金額 |
| 投資/其他現金流項目鉅額 | 現金流量表附註拆解 | 追蹤資金流向:是否變相流向關聯方 |
| 權益法收益大但無現金股利 | 聯營合營附註、股利記錄 | 收益是否只是「紙面富貴」,被投資方自身現金流狀況 |
| 關聯交易金額或佔比異常 | 關聯方附註 | 交易必要性、定價依據、資金是否閉環回流 |
| 繳稅現金遠低於賬面所得稅費用 | 稅項附註、遞延所得稅變動表 | 稅收優惠的可持續性;遞延所得稅資產的確認依據 |
| FCF 連續為負但賬面獲利 | 資本支出明細 | 區分擴張性(可論證)與維持性 CapEx;擴張是否有對應產能與訂單 |
使用紀律有兩條。第一,紅旗不等於結論:每個訊號都只是「該去翻哪頁附註」的路標,翻完附註仍然可能找到完全正當的解釋。第二,單訊號不定罪,組合訊號才立案:上面乙公司的例子之所以典型,是因為淨利高增、應收堆積、存貨堆積、現金轉換率崩塌四個訊號同時出現且方向一致。
六、把檢查寫成可自動執行的規則引擎
人工翻附註不可規模化,但把檢查固化成規則,就能對每一家進入研究視野的公司自動跑一遍體檢。規則的統一格式:
from dataclasses import dataclass
from typing import Literal
@dataclass
class Rule:
id: str
metric: str # 計算哪個指標
condition: str # 觸發條件(參數化,禁止寫死「行業平均」)
severity: Literal["info", "warn", "block"]
where_to_look: str # 紅旗指向的科目/附註
how_to_verify: str # 人工複核步驟
RULES = [
Rule("CQ-001", "cash_conversion",
"ocf_to_ni < 0.5 for 2 consecutive years",
"warn", "現金流量表間接法調節項",
"逐年分解淨利與 OCF 差異,定位最大調節項"),
Rule("CQ-002", "ar_vs_revenue",
"ar_growth - revenue_growth > params['ar_gap_pp'] for 2 years",
"warn", "應收帳款附註(帳齡、壞帳準備)",
"檢查帳齡結構、準備比率趨勢、期後回款"),
Rule("CQ-003", "inventory_buildup",
"dio_increase > params['dio_days'] and gross_margin_rising",
"warn", "存貨附註(明細、跌價準備)",
"NRV 測試、存貨帳齡、成本結轉方法變更"),
Rule("CQ-004", "articulation_fail",
"any tie-out check exceeds tolerance",
"block", "先回查抽取原頁,再查合併範圍",
"勾稽不過禁止進入品質分析"),
]
# 參數是「可校準的默認值」,不是普世真理(教學用默認,實際以公司歷史分布校準)
DEFAULT_PARAMS = {"ar_gap_pp": 15.0, "dio_days": 20.0}
三個設計決策值得說明。第一,severity 分級:block 級(勾稽失敗)直接攔截,品質分析不許開始;warn 級產出紅旗清單供人工複核;info 級只記錄。第二,閾值參數化:不硬編碼任何「行業標準值」——不同行業、不同商業模式的正常週轉天數差異極大,閾值應該用公司自身歷史分布加可配置偏移來校準,上表的默認參數只是教學起點。第三,輸出必須帶指針:每面紅旗都要附上觸發它的原始數值、期間、來源頁碼,複核者十秒內能翻到原文。沒有指針的紅旗等於新的噪音源。
七、AI 會在這裡出錯:符號、口徑與編造
把這套檢查交給 AI Agent 執行時,高頻錯誤模式:
| AI 的典型錯誤 | 說明 | 驗證機制 |
|---|---|---|
| 間接法符號搞反 | 應收增加是現金流出(減項),模型常寫成加項 | 用勾稽斷言反查:調整後的調節項加總必須等於 OCF 與淨利之差 |
| 淨利口徑混用 | 歸母淨利與全口徑淨利混著算現金轉換率 | 指標定義中固定口徑,schema 欄位顯式區分 |
| 把政策變更當異常 | 會計準則轉換(如租賃資本化)引起的機械性變化被報成紅旗 | 規則引擎先比對披露的會計政策變更清單,命中則降級為 info |
| 附註缺失時編造 | 帳齡、跌價準備等附註數據抽不到時,憑「合理估計」補數 | 硬性規則:附註字段抽不到就輸出 null+「附註缺失」標記,禁止估計 |
| 半年報天數錯配 | 用 365 天去除半年數據,DSO/DIO 直接翻倍 | period 欄位帶期間天數,公式從 period 取數而非寫死 |
| 把紅旗當結論輸出 | 「該公司存在利潤操縱」這類斷言 | 輸出模板只允許「訊號+指針+待驗證項」,定性判斷留給人 |
最後一條是立場問題,值得單獨強調:紅旗清單的輸出格式本身要防止 AI 下定性結論。訊號、指針、待驗證項三段式,就是逼著系統停在「這裡值得看」而不是跳到「這裡有問題」。AI 越權下結論的行為模式與約束方法,本站有專文分析:LLM Agent 自主繞過流程約束的實證分析。
整條檢查線的驗證閉環:勾稽先行(不對帳就攔截)→ 指標機械計算(公式帶口徑)→ 紅旗帶指針(可十秒回查原文)→ 人工複核(紅旗是線索不是判決)→ 複核結果回寫(校準參數與規則版本)。把這個閉環升級成系統級的多層門控,見 自建投研系統。
下一步
- 300 頁年報轉結構化 JSON:本篇規則引擎的輸入從哪來
- 可比公司分析自動化:現金流品質檢查同時是 comps 樣本的準入過濾——品質不過關的公司不該進比較表
- DCF 假設與敏感度分析:現金流品質決定 FCF 預測的可信度,兩篇互為前提
- 機器怎麼讀懂財報:抽取層的方法論與錯誤模式