「鈔能力養成指北」:開年變富第一步,從科學記賬開始

語言: CN / TW / HK

寫在前面: 面對全面放開後多樣的消費機會,開發者們如何在保障品質生活的同時,藉助開源工具,全面、科學地規劃和管理個人財務,把握資金動向,避開消費陷阱?

LigaAI 特邀我司 Nerd4me 大佬分享其個人財務管理經驗,系列共分「概念篇」和「實戰篇」。本篇「實戰篇」,將展開介紹開發者如何使用 Beancount 系統且便捷地記賬。

Beancount 是一個基於純文字的開源記賬軟體,提供了一系列開箱即用的命令列工具,以及一套簡潔、實用且美觀的 Web UI。

其核心記賬邏輯是「複式記賬法」,即每一筆交易至少關聯兩個交易賬戶,一借一貸,數額相等。特別的是, 複式記賬法規定「收入為負,支出為正」 —— 在《「鈔能力養成指北」前傳》中,我們也詳細解釋了這點,大家可以按需補課。

👉新手指南:Why Beancount?

市面上有非常多成熟、知名的記賬工具,為什麼我仍強烈推薦使用 Beancount?出於以下幾點考慮:

  1. Beancount 採用改良版的複式記賬方案,「正負」代替「借貸」 對非會計專業的朋友更友好;

  2. 可直接在本地執行。相比基於雲端的工具,資料安全更有保障,無需擔心個人賬務洩漏;

  3. 純文字檔案管理賬目,便於記錄和儲存。 基於 Beancount 語法生成的檔案,很容易閱讀;

  4. 提供完整的命令列工具集和視覺化工具 Fava(內含大量財報模板),支援基於類 SQL 查詢,可輕鬆生成各種複雜的報表資料;

  5. 賬本既是使用者的輸入檔案,也是軟體的「資料庫」,可實現資料和工具的「無痛搬家」

Beancount 是 Ledger-Like 家族的傑出成員。對比背靠 C++ 的 Ledger,基於 Python 的 Beancount 應用輕便,新增外掛或二次開發更簡單;多貨幣支援等豐富而強大的功能,能夠很好地覆蓋各種記賬、查賬場景。

事實上,Beancount 並不知道什麼是「貨幣」。它只是記錄了「通貨 Commodity」的變化,而通貨完全由使用者定義。 因此,Beancount 可以記錄含貨幣在內任何東西的變化,如年假天數、股票、航空里程、信用卡積分……

當然,也可以用來數豆子——這也是「Beancount」名字的由來 >A<

👉 英勇黃銅:基本環境搭建

邁出「Beancount 記賬」的第一步,需要安裝 Python3 環境和對應包。

pip install beancount fava

使用下列命令,生成一個官方提供的示例。

bean-example > example.beancount

通過 fava 命令執行 Web UI 。預設情況下的 Web UI 會執行在 http://localhost:5000 中。

fava -H 0.0.0.0 example.beancount

👉 不屈白銀:Beancount 語法入門

環境搭建後,我們需要製作賬本來承載賬目資訊。Beancount 作者在 Beancount User's Manual 中提供了非常詳盡的使用說明,大家可以根據實際需求自行建立。

下面以《「鈔能力養成指北」前傳》中「老王煎餅攤」為例,逐步演示如何使用 Beancount 編寫賬本並製成報表。

1. 製作賬本

新建一個純文字檔案並儲存為 laowang.bean。在任意文字編輯器開啟,只需簡單兩步就能完成賬本內容的編寫。

第一步:設立交易賬戶

使用  open  命令設立交易賬戶,語法結構為開戶時間 open 賬戶型別:賬戶名稱 貨幣型別;備註

其中,開戶時間應早於該賬戶關聯的首筆交易產生的時間;同時,在複式記賬法中,交易賬戶分為五大型別:

  • Assets - 資產類賬戶:現金、存款、基金、股票、房子、車子、借出賬款等;

  • Liabilities - 負債類賬戶:信用卡、貸款、花唄、向他人借款等;

  • Income - 收入類賬戶:工資、獎金、專利、投資收益等;

  • Expenses - 費用類賬戶:衣食住行等一切花銷、過年發出的紅包等;

  • Equity - 權益類賬戶:記賬前已有的資產或負債,一般在賬戶初始化時設定。

1970-01-01 open Income:Sales CNY
1970-01-01 open Assets:Bank:Saving:ICBC CNY
1970-01-01 open Assets:Fixed CNY ;固定資產
1970-01-01 open Liabilities:CreditCard:ICBC CNY
1970-01-01 open Expenses:Food CNY

第二步:編寫交易記錄

Beancount 是複式記賬工具,其賬目分錄至少包含三行資訊:交易詳情、支出詳情和收入詳情。

交易詳情記錄了交易時間、收款人資訊和交易備註,格式為 YYYY-MM-DD */! "" ""

  • */! 」為對賬識別符號: * 表示該交易已確認,! 表示該交易存疑/待確認。
  • 雙引號中的為選填內容,分別記錄「收款人 Payee」和「交易備註 Narration」。

支出/收入詳情記錄出/進賬的賬戶名稱、交易數額和貨幣型別,出賬為負,進賬為正,正負金額相加為零。

2023-01-01 * "xx公司" "購買裝置"
  Assets:Bank:Saving:ICBC      -1,000.00 CNY
  Assets:Fixed                  1,000.00 CNY

2023-01-01 * "採購食材"
  Liabilities:CreditCard:ICBC   -500.00 CNY
  Expenses:Food                  500.00 CNY

把「老王煎餅攤」的賬本補充完整,就會得到下面這個 laowang.bean 檔案。

1970-01-01 open Income:Sales CNY
1970-01-01 open Assets:Bank:Saving:ICBC CNY
1970-01-01 open Assets:Fixed CNY ;固定資產
1970-01-01 open Liabilities:CreditCard:ICBC CNY
1970-01-01 open Expenses:Food CNY

2023-01-01 * "xx公司" "購買裝置"
  Assets:Bank:Saving:ICBC      -1,000.00 CNY
  Assets:Fixed                  1,000.00 CNY

2023-01-01 * "採購食材"
  Liabilities:CreditCard:ICBC   -500.00 CNY
  Expenses:Food                  500.00 CNY

2023-01-02 * "煎餅銷售收入"
  Income:Sales                -1,000.00 CNY
  Assets:Bank:Saving:ICBC      1,000.00 CNY

2023-01-02 * "質量問題食材退貨"
  Expenses:Food                 -100.00 CNY
  Liabilities:CreditCard:ICBC    100.00 CNY

2. 生成財務報表

使用 Beancount 命令列工具集中的 bean-report 命令,可以實現各類財務報表的自動生成。

比如, income 子命令能生成損益表,balsheet 可以統計資產負債情況,balances 用於查詢各賬戶餘額等。

(BEANCOUNT) bean-report laowang.bean balances
Assets:Bank:Saving:ICBC
Assets:Fixed                   1000.00 CNY
Equity
Expenses:Food                   400.00 CNY
Income:Sales                  -1000.00 CNY
Liabilities:CreditCard:ICBC    -400.00 CNY

賬戶餘額表指出,老王持有 1,000 元的固定資產、在食材上花費 400 元、煎餅營業收入 1,000 元、信用卡欠款 400 元。

對許多非技術背景的朋友來說,用命令列呈現的資料有點不太好閱讀。沒關係,Beancount 自己會出手:Beancount 為我們提供了一個視覺化工具 Fava

安裝 Fava 後,使用 fava laowang.bean 命令啟動 Web UI 服務。在瀏覽器中開啟 http://localhost:5000/,就可以獲得表格式的報表資料。

👉 榮耀黃金:進階場景說明

在現實生活中,除了「一對一」交易,我們還會遇到很多涉及多個賬戶的「一對多」和「多對多」的情況。下面幾個場景展示了 Beancount 和複式記賬法在處理複雜交易方面的優勢。

場景 1 :發工資

應聘談薪,我們關心「稅前工資」和「到手工資」。那麼,每月發放的工資、獎金,繳納的五險一金和個人所得稅等費用,在 Beancount 中應該如何入賬呢?

2023-01-10 * "Some Company" "💰工資2022-12"
  Income:SomeCompany:Salary           -20,000.00 CNY ;應發工資
  Income:SomeCompany:Benefits            -500.00 CNY ;節日福利
  Income:SomeCompany:HousingFund       -2,000.00 CNY ;住房公積金單位扣除
  Assets:Government:HousingFund         4,000.00 CNY ;住房公積金繳納
  Expenses:Government:SocialSecurity    1,500.00 CNY ;社保繳納
  Expenses:Government:IncomeTax         3,000.00 CNY ;個稅繳納
  Assets:Bank:Saving:ICBC              14,000.00 CNY ;實發工資

不難看出,複式記賬法的優勢之一是能夠清晰地展示同一筆交易中,資金在各個賬戶之間的流動關係,反映資金運動的來龍去脈。

場景 2 :記錄房產

對於房產、車輛等固定資產,我們不只關心其購入時的價值,也同樣在乎其後續的升/貶值情況,即當前市場估值

Beancount 不預先定義任何貨幣,我們可以建立人民幣 CNY 的變種貨幣 CNY.UNVEST,賦予房子一個人民幣變種價格(即估值價格)

這樣,在以人民幣 CNY 展示總資產時,我們既能在價格頁檢視房子的當前市值估值,也不會影響總資產的統計。

;建立房產貨幣
2018-06-01 commodity HOUSE.ABC
  name: "房產名稱"
2018-06-01 open Assets:Property:CS:ABC HOUSE.ABC

;房產購買
2018-06-01 * "XX地產" "房產名稱"
  Assets:Property:CS:ABC                        1 HOUSE.ABC {2,000,000.00 CNY} ;房產購買價格
  Assets:Bank:Saving:ICBC              600,000.00 CNY ;首付款
  Liabilities:Bank:BOC:MortgageLoan  1,400,000.00 CNY ;抵押貸款

;房產價格
2018-06-01 price HOUSE.ABC 2,000,000.00 CNY ;買入成本
2018-06-01 price HOUSE.ABC 2,000,000.00 CNY.UNVEST ;估值價格
2023-01-17 price HOUSE.ABC 2,500,000.00 CNY.UNVEST ;估值價格

場景 3 :AA 制消費分攤

AA 制的費用分攤、信用卡分期還款等交易記賬是典型的「一對多」場景。

小紅和小明外出吃飯一共花費 500 元,由小紅先行支付;小明幾天後想起,將 AA 的費用轉賬還給小紅。在小紅的賬本中,這筆錢應該這樣記錄:

2023-01-13 * "xx 飯店" "和小明吃飯"
  Assets:VA:Wechat              -500.00 CNY ;微信零錢付款
  Expenses:Food:DiningOut        250.00 CNY ;AA我(小紅)的一半
  Assets:Receivables:Xiao-Ming   250.00 CNY ;AA小明的一半

2023-01-17 * "小明" "AA吃飯收款"
  Assets:VA:Wechat               250.00 CNY
  Assets:Receivables:Xiao-Ming  -250.00 CNY

場景 4 :貨幣轉換

出入境限制全面放開,許多好友也都選擇出國遊玩散心。在消費記賬時,Beancount 如何處理不同貨幣之間的匯率轉化關係?

在登記交易時,使用 @@ 即可連線兩種互相轉換的貨幣。本例中,信用卡支出的 650 元人民幣正是由 100 美元轉換而來。

2023-01-17 * "在免稅店買東西"
 Assets:Cash                                 -200.00 USD ;現金支付
 Liabilities:CreditCard:ICBC                 -650.00 CNY @@ 100.00 USD ;信用卡付款
 Expenses:Clothing:Pants                     +150.00 USD
 Expenses:Clothing:Shoes                     +150.00 USD

場景 5 :使用 DSL 進行復雜查詢

除了 bean-report 命令外,Beancount 還提供 bean-query 工具,支援 SQL 語句查詢,以滿足更復雜的資料統計。感興趣的朋友可以在 Beancount – Query Language 文件中瞭解。

這裡分享一下讓 Beancount 回答「我都在哪些加油站加過幾次油」的操作指令。

👉 超凡大師:最佳實踐分享

看到這裡的朋友們,恭喜你們已經學會了 Beancount 複式記賬的常用語法和操作。它們可以滿足生活中絕大多數消費和交易的記賬需求。下面分享的是一些個人實踐的經驗總結,希望能更好地幫你開啟「Beancount 之旅」。

1. 賬本編輯器的選擇

我選擇 VSCode 作為賬本檔案編輯器,搭配 Lencerf/vscode-beancount 外掛一起使用,可以自動為 .bean 或者 .beancount 檔案加上語法高亮、補全賬戶名,還可以實現金額資料的自動對齊。

具體的配置操作請檢視作者在 Github 上提供的幫助文件瞭解。

2. 賬戶開戶日期的設立

前面提到,交易賬戶的開設日期應早於該賬戶首筆交易產生的時間。這裡也補充一些比較有意思的開戶事件,供諸位參考。

  • Expenses 賬戶可以使用自己的出生日期作為開戶日期;
  • Income 賬戶可以按來源分類後再選擇日期,如 Income:SomeCompany:Salary 的開戶時間是該公司的入職日期;
  • Assets 和 Liabilities 賬戶中的借/貸記卡的開設日期,與銀行的開戶日期保持一致。

3. 分割賬本檔案結構

記賬是一個長期習慣,但是隨著時間累積,賬本檔案越變越大,只在一個檔案中編寫和記錄就會變得極其不便。

因此,在建立賬本時,我們可以提前規劃賬本分類,使用 Beancount 的 include 語法對賬本進行結構分割。這樣就可以在一個 Beancount 檔案中包含其他的檔案,就像下面這樣:

.
├── 2022
│   ├── 09.bean
│   ├── 10.bean
│   ├── 11.bean
│   ├── 12.bean
│   ├── __index.bean
│   ├── creditcard.bean
│   ├── event.bean
│   ├── forecast.bean
│   ├── income.bean
│   ├── loan.bean
│   └── transfer.bean
├── 2023
│   ├── 01.bean
│   ├── __index.bean
│   ├── forecast.bean
│   ├── income.bean
│   ├── insurance.bean
│   ├── loan.bean
│   └── transfer.bean
├── account
│   ├── __index.bean
│   ├── assets.bean
│   ├── equity.bean
│   ├── expenses.bean
│   ├── income.bean
│   └── liabilities.bean
├── commodity
│   ├── __index.bean
│   └── fund.bean
├── doc
│   └── __index.bean
└── main.bean

4. 定期對賬

賬本的定期對賬(或稱定期斷言,Balance Assertion)就像寫程式碼時的「Ctrl + S」或「Command + S」,無事發生自動隱形,關鍵時刻出手「救命」。

斷言就是告訴 Beancount,在某個日期前,這個賬戶有多少餘額(設值為 A) 。如果 Beancount 計算的該時間點前的交易餘額 B,與餘額 A 不相等,那它就會報錯。此時,我們只需檢查兩次斷言日期之間的交易,就能快速定位錯賬。

使用 balance 命令標記某個日期前的賬戶餘額(區分 bean-report 命令中的 balance 子命令),讓 Beancount 自動核對賬本中的賬戶餘額是否與實際金額相等。

2023-01-01 balance Assets:Bank:Saving:ICBC 10,000.00 CNY

需要注意,斷言宣告的是所給日期開始前的餘額,即當日的交易不算在內。也就是說,上面的斷言表示,在 2023 年元旦前,即截止至 2022 年 12 月 31 日,工商銀行儲蓄賬戶餘額為 10,000 元。

👉後記

在 wzyboy 的《Beancount——命令行復式簿記》一文中,我第一次瞭解到「記賬神器 Beancount」;2022 年 9  月前後,我正式使用 Beancount 管理個人財務。如今睡前開啟 VSCode 記錄當天的資金變動,已經成為固定活動,而在每日的記賬、查賬中,我也獲益良多。

本文分享的 Beancount 入門級操作指令,可以滿足(個人)日常記賬的簡單需求;Beancount 還有許多證券投資、基金淨值更新等高階應用,大家可以自行挖寶~

新的一年,堅持記賬,搞錢發財!


編者語:# 程式設計之外 是 LigaAI 開設的全新欄目。在這裡,我們將與開發者朋友們一起發現和分享生活中的「技術時刻」,並通過極具創意與實用的「生活程式碼」,感受「技術改善生活」的真諦。如果你也對「程式碼提升幸福感」感興趣,歡迎關注 LigaAI@oschina

LigaAI 是新一代智慧研發協作平臺,我們關注研發協作與效率,重視開發者個人的價值創造。往期文章中,我們分享了許多敏捷開發、專案管理、個人成長與提升的文章,歡迎朋友們閱讀交流。

體驗新一代智慧研發協作,請 點選這裡 展開了解。LigaAI 助力開發者揚帆遠航,期待與你一路同行!