關於文章訂閱
文章 >我作了一個財報網站 (November 08, 2025)
English | 中文

我作了一個財報網站

Part 2 - 如何處理財報資料
November 08, 2025

Building a Finance Website |1200|630

我建立了一個名為 myfinsight.com 的網站,提供各家美國上市公司的財務報表與視覺化。 本系列文章將探討如何向美國證券交易委員會 (SEC) 查詢盈利報告、如何將數據發佈到網站, Mailchimp 電子報, 以及社交平台 XThreads.

在上一篇文章中,我們討論了如何獲取公司的財務數據。在本文中,我們將討論如何解析(處理)財務數據。讓我們首先看看 Meta 截至 2025 年 6 月 30 日季度期間的收入表: Meta財報 |900|Meta財報

一份收入表(或稱損益表)通常包含「營收」(或「收入」)、「成本與費用」和「淨利」(或「淨收入」)。在所有的財務報告中,收入表通常是對大多數人來說最容易理解的。正如您在表格中可以輕易看到的,淨利就是營收減去成本和稅項。

現在您可能會問,有什麼需要解析(處理)的呢?我們難道不就是下載表格、上傳到雲端,然後在網站上提供服務嗎?如果您只是想獲得像 Yahoo Finance 網站那樣的數字,那麼您說得對:複製並貼上這些數字就夠了。然而,我們不僅想要這些數字,我們還想要深入的見解。例如,淨利的增長率是多少?那麼我們就必須確保在我們的資料庫中,來自所有不同季度報告的淨利都使用相同的名稱進行「標記」,這樣我們才能查詢它們並計算出差異。

我們可能還想將營收來源視覺化。Meta 的主要營收來源是什麼?哪個國家的銷量最多?因此,我們也需要理解表格中數字之間的關係。

Meta財報 |600|Meta財報

如果我們可以推導並解析(處理)出表格中所有的數學關係,那麼我們就可以繪製出如下圖所示的圖表,來展示營收從何而來以及流向何處。這比表格中的數字更容易理解。

Meta財報視覺化 |900|Meta財報視覺化

好的,現在我們知道必須以某種方式解析數據才能獲得財務見解,那我們可以直接請 AI 來完成嗎?是的,我們可以,而且大多數時候 AI 都能做得很好。然而,我選擇不這樣做,原因有以下幾點:

  1. 我比較拮据,沒有那麼多錢支付 token 費用。 每季度有數千家上市公司提交報告。我不打算在一個業餘愛好的項目上花費太多資金。
  2. 很難控制 AI 輸出的品質。 如果輸出是錯誤的或出現了「幻覺」,您要如何進行偵錯(除錯)?使用 AI 來解析具有絕對正確答案、零誤差範圍且不容許創造性的財務數據或數學計算是很有挑戰性的。隨著 AI 模型的日益發展,將大部分業務邏輯委託給第三方也是有風險的。
  3. 幸運的是,正如我們將在下面看到的,提交的財務數據本身已經是一種結構良好的 XML 格式,我們可以輕鬆地從中提取數學關係。

取得數學關係

正如在上一篇文章中所提到的,數學關係可以從 EX-101.CAL 檔案中找到。對於收入表(損益表): Meta’s income statement |900|Meta’s income statement

從檔案中解析出的對應數學結構是:

Meta’s income statement |400|Meta’s income statement

這是一個樹狀結構,其中每個頂層元素都連接到一個或多個子元素。如果您仔細觀察,它幾乎就像一個倒置的表格,淨利在頂部,而營收在底部。

為了方便起見,我們可以將上述樹狀圖轉換為以下文本格式:

(us-gaap:NetIncomeLoss) weight: 1.0
 | (us-gaap:IncomeTaxExpenseBenefit) weight: -1.0
 | (us-gaap:IncomeLossFromContinuingOperations) weight: 1.0
 | | (us-gaap:NonoperatingIncomeExpense) weight: 1.0
 | | (us-gaap:OperatingIncomeLoss) weight: 1.0
 | | | (us-gaap:CostsAndExpenses) weight: -1.0
 | | | | (us-gaap:CostOfRevenue) weight: 1.0
 | | | | (us-gaap:GeneralAndAdministrativeExpense) weight: 1.0
 | | | | (us-gaap:ResearchAndDevelopmentExpense) weight: 1.0
 | | | | (us-gaap:SellingAndMarketingExpense) weight: 1.0
 | | | (us-gaap:Revenue) weight: 1.0

在這個表示法中,| 符號表示節點或元素的深度。元素 "us-gaap:NetIncomeLoss" 的深度為 0,因為它前面沒有 | 符號。元素 "us-gaap:IncomeTaxExpenseBenefit" 和 "us-gaap:IncomeLossFromContinuingOperations" 的深度為 1,因為它們前面有一個 | 符號。如同在樹狀結構中,深度為 0 的元素連接到深度為 1 的元素,即根元素 us-gaap:NetIncomeLoss 連接到 us-gaap:IncomeTaxExpenseBenefit 和 us-gaap:IncomeLossFromContinuingOperations。

這個樹狀結構中的連接告訴我們元素之間的數學關係。元素 "us-gaap:IncomeTaxExpenseBenefit" 和 "us-gaap:IncomeLossFromContinuingOperations" 都對根元素 us-gaap:NetIncomeLoss 有貢獻,因為它們彼此相連。我們還可以發現 us-gaap:IncomeTaxExpenseBenefit 的權重是 -1,意味著負向貢獻。因此,從這個關係中我們知道:

us-gaap:NetIncomeLoss = us-gaap:IncomeLossFromContinuingOperations - us-gaap:IncomeTaxExpenseBenefit

您可能會想知道前綴 "us-gaap" 是什麼。「us-gaap」前綴表示這些元素,例如 "us-gaap:NetIncomeLoss",是來自 US GAAP 財務報告分類標準(GAAP 代表「一般公認會計原則」)的標準元素之一。由於這些標準元素被不同的公司廣泛使用,因此您很有可能從不同公司的文件中找到 "us-gaap:NetIncomeLoss",從而非常容易地在公司之間進行比較。請注意,如果有標準元素,也可能存在非標準元素。例如,Netflix 的財務報告中包含 "nflx:ContentAssets",它指的是該公司許可和自行製作的電影和節目的庫存,這些庫存被記錄在資產負債表上作為資產。這種類型的資產對 Netflix 來說是獨一無二的,因此該公司需要創建自己的元素來表示此類資產。

填充數值

如上一篇文章所述,數值可以在 XML 檔案中找到。透過在檔案中查找樹狀結構中的每個元素,我們可以得到類似以下的結構:

 $18337 (us-gaap:NetIncomeLoss) w:1.0
 | $2197 (us-gaap:IncomeTaxExpenseBenefit) w:-1.0
 | $20534 (us-gaap:IncomeLossFromContinuingOperations) w:1.0
 | | $93 (us-gaap:NonoperatingIncomeExpense) w:1.0
 | | $20441  (us-gaap:OperatingIncomeLoss) w:1.0
 | | | $27075 (us-gaap:CostsAndExpenses) w:-1.0
 | | | | $2663 (us-gaap:GeneralAndAdministrativeExpense) w:1.0
 | | | | $2979 (us-gaap:SellingAndMarketingExpense) w:1.0
 | | | | $12942 (us-gaap:ResearchAndDevelopmentExpense) w:1.0
 | | | | $8491 (us-gaap:CostOfRevenue) w:1.0
 | | | $47516  (us-gaap:Revenue) w:1.0

我們用 "w" 替換了 "weight"(權重)來縮短表達式。檢查數字是否正確很容易。例如,us-gaap:CostsAndExpenses 有四個子項目;成本和費用必須是它們數值的總和,即:

$27075 = $2663 + $2979 + $12942 + $8491

填充標籤

猜測這些元素是什麼並不難。例如,us-gaap:CostOfRevenue 顯然是「營收成本」。然而,有些時候並不容易理解;例如,us-gaap:IncomeTaxesPaidNet。因此,我們需要找到每個元素的文字或標籤。我們要查看的檔案是 EX-101.LAB,這在上一篇文章中也有討論過。在填充文字後,我們得到:

 $18337 Net income, w:1.0
 | $2197 Provision for income taxes, w:-1.0
 | $20534 Income before provision for income taxes, w:1.0
 | | $93 Interest and other income, net, w:1.0
 | | $20441 Income (loss) from operations, w:1.0
 | | | $27075 Total costs and expenses, w:-1.0
 | | | | $2663 General and administrative, w:1.0
 | | | | $2979 Marketing and sales, w:1.0
 | | | | $12942 Research and development, w:1.0
 | | | | $8491 Cost of revenue, w:1.0
 | | | $47516 Revenue, w:1.0

數據結構

既然財務文件已經是樹狀結構,我們在處理數據時也應該使用這種數據結構。在上面我們討論了很多關於「元素」的內容。這些元素本質上就是樹狀數據結構中的「節點」。每個節點都應具備 GAAP 標籤(即 us-gaap:NetIncomeLoss 這樣的代碼)、人類可讀的文本(即名稱或說明),以及它的數值。我們可以用 Python 定義這個節點,如下所示:

@dataclasses.dataclass
class Node:
    text: str
    label: str
    value: float
    weight: float
    to_nodes: list["Node"]

where to_nodes lists the node’s child nodes. For example, in the above Meta’s income statement, we have

tax = Node(
    "Provision for income taxes",
    "us-gaap:IncomeTaxExpenseBenefit",
    2197,
    -1.0,
    []
    )
income_lose = Node(
    "Income before provision for income taxes",
    "us-gaap:IncomeLossFromContinuingOperations",
    20534,
    1.0,
    []
)
net_income = Node(
    "Net income",
    "us-gaap:NetIncomeLoss",
    18337,
    1.0,
    [tax, income_lose]
)

其中 to_nodes 列出了該節點的子節點。例如,在上面 Meta 的收入表中,我們有:

由於節點 net_income 有兩個子節點:tax(權重為 -1)和 income_lose,我們可以推導出等式 net_income = income_lose - tax.

有了 Node 這個類別,就可以非常容易地繪製樹狀結構並推導出其他數學關係。

最後說明

我展示了一個非常簡化的財務文件視圖。在一個真正的文件中,還有很多我沒有在這裡提及的數據。例如,一個數值通常有一個單位。淨銷售額 $18337 實際上是以百萬為單位。一個數值也可以有維度(dimension)。淨銷售額可以在一個「國家」維度下有多個數值。有興趣的讀者可以查閱 https://www.xbrl.org 了解財務文件的結構,以及像 https://xbrl.us/data-rule 這樣的規則,以獲取有關財務文件的指南。


訂閱阿丹的電子報

科技 & 我的動態