跳转到主要内容

Beancount是什么:纯文本复式记账

Beancount是面向股票、加密货币和日常账目的纯文本复式记账——它是什么,以及为什么工程师使用它。详见正文说明。详见正文说明。详见正文说明。

本指南整合了使用强大、开源的纯文本记账工具 Beancount 进行纯文本会计的最佳实践。它涵盖了基础理念、从基础到高级的语法、复杂资产的实际案例研究,以及长期账本管理策略。

第一部分:"为什么" —— 智能簿记的基础

在深入探讨"怎么做"之前,理解"为什么"至关重要。有效的簿记是个人财务管理的基础,也是通往财务清晰和自由之路的必要一步。

超越支出追踪:通往财务清晰之路

简单的支出追踪应用告诉你钱花在了哪里。一个健壮的会计系统告诉你这些,以及更多:它提供了你财务状况的完整图景,包括你的净资产、现金流以及投资表现。首要目标是可观测性——获得对财务生活清晰、数据驱动的理解,这让你能够做出明智的决策、评估风险,并朝着退休等长期目标努力。

为什么要复式记账?平衡系统的力量

与单式记账(简单的支出清单)不同,复式记账法将每笔交易记录为至少两个账户之间的价值流动。其核心原则是基本会计等式:

资产=负债+权益(净资产)\text{资产} = \text{负债} + \text{权益(净资产)}

这个系统确保你的账簿始终保持平衡,大大减少了错误。它通过生成如资产负债表(你拥有和欠什么)和损益表(你赚了什么和花了什么)等关键报告,提供了完整的财务图景。

第二部分:Beancount 入门

Beancount 是一个基于 Python 的强大工具,用于纯文本会计。

在 Beancount.io 上首次体验 Fava

Beancount.io 提供了一个强大的环境,它将 Beancount 引擎与移动应用(iOS, Android)和网络应用Fava(一个出色的基于网络的账本可视化界面)相结合。无需安装。当你使用该平台时,你直接与你的账本文件(例如,main.bean)的文本编辑器交互,并看到 Fava 生成的报告实时更新。

Fava 将你编写的纯文本转化为交互式图表、财务报表和可筛选的交易列表,让你清晰地看到你的财务报告。

或从终端开始使用bea

如果你更愿意在shell环境中工作,bea就是Beancount.io的命令行工具。无需账户:使用brew install bex-co/tap/beauv tool install beancount-io即可安装,它能创建、验证、查询并报告相同的纯文本文件。CLI快速入门能让你在几分钟内建立第一个账本,而使用bea的第一个月则带你端到端地完成整个月的结算。

五种核心账户类型

Beancount 使用五种顶级账户类型,它们构成了账本的结构:

账户类型描述典型余额
资产你拥有的(现金、银行账户、投资、房产)。正数
负债你欠的(信用卡债务、贷款、抵押贷款)。负数
收入钱的来源(工资、奖金、利息)。负数
费用钱的去向(食物、租金、旅行、税费)。正数
权益你的净资产;用于初始余额。负数

Beancount 等式

Beancount 强制执行其自身版本的会计等式,其中整个账本中所有分录的总和等于零:

资产+费用+负债+收入+权益=0\text{资产} + \text{费用} + \text{负债} + \text{收入} + \text{权益} = 0

这就是为什么按照惯例,收入负债权益账户持有负值——它们是增加你的资产费用的资金的_来源_。

第三部分:Beancount 的语言 —— 核心语法

Beancount 中的所有条目都是以日期开头的指令

定义账户(open)和商品

在使用一个账户之前,你必须使用 open 指令声明它。你还可以选择指定它将持有的货币或"商品"。

; YYYY-MM-DD open Account:Name [Commodity1, Commodity2, ...]
2020-01-01 open Assets:Bank:US:Chase:Checking      USD
2020-01-01 open Liabilities:CreditCard:US:Discover USD
2020-01-01 open Expenses:Food:Groceries
2020-01-01 open Income:Salary:Google

商品可以是现实世界的货币(例如,USDJPY)或你定义的任何自定义单位,如航空里程(MILES_UA)或股票代码(HOOL)。

记录你的第一笔交易(*

交易是最常见的条目。它们以日期、标志(* 表示完整交易,! 表示不完整交易)、可选收款人和描述开头。后面每一行(缩进两个空格)都是一个账户的"分录"。

; YYYY-MM-DD * "Payee" "Description"
;   Account1      Amount Commodity
;   Account2     -Amount Commodity
 
2024-07-28 * "Trader Joe's" "Weekly groceries"
  Expenses:Food:Groceries     125.50 USD
  Liabilities:CreditCard:US:Discover  -125.50 USD

为了方便,如果一笔交易只有两个分录,你可以省略第二行的金额,Beancount 会自动计算。

2024-07-28 * "Trader Joe's" "Weekly groceries"
  Expenses:Food:Groceries     125.50 USD
  Liabilities:CreditCard:US:Discover

交易级别平衡: 更重要的是,在日常使用中,每一笔单独的交易也必须平衡——单笔交易内所有分录的总和必须为零。如果交易不平衡,Beancount 会显示如下错误:

Beancount 错误提示

处理多货币交易(@@@)

Beancount 擅长多货币会计。

  • 使用 @ 指定每单位换算价格。
  • 使用 @@ 指定换算的总成本。
; Buying a flight in EUR with a USD card
2024-08-01 * "Lufthansa" "Flight to Berlin"
  Expenses:Travel:Flights      500.00 EUR @@ 545.00 USD  ; 500 EUR cost me 545 USD in total
  Liabilities:CreditCard:US:Discover  -545.00 USD

第四部分:确保准确性 —— 对账的艺术

维护准确账本的一个关键实践是定期对账。这涉及将 Beancount 账本中的余额与金融机构的官方对账单进行比较。

使用余额断言(balance)自动化检查

balance 指令是进行自动检查的主要工具。你断言在某个日期,一个账户有特定余额。如果计算出的余额与断言不匹配,Beancount 将报错。这对于快速定位错误非常宝贵。

注意: 余额断言检查的是指定日期_开始时_(在该日任何交易之前)的账户状态。

; From your monthly credit card statement
2024-08-01 balance Liabilities:CreditCard:US:Discover  -1432.78 USD

关联支持文件(document)

你可以链接到外部文件,如银行对账单或收据,创建可审计的跟踪记录。Fava 使这些链接可点击。

2024-08-01 document Liabilities:CreditCard:US:Discover "statements/discover-2024-07.pdf"

纠正错误和初始化余额

当你开始账本或发现无法追踪的差异时,你需要进行调整。标准做法是使用一个特殊的 权益 账户。

; Initializing a cash account when starting your ledger
2020-01-01 * "Initial Balance" "Setting up cash account"
  Assets:Cash:Wallet           200.00 USD
  Equity:Opening-Balances     -200.00 USD

Equity:Opening-Balances 账户持有从未知或外部来源进入账本的金额。

对于精确差异不重要的快速修复,pad 指令可以自动调整账户余额以满足后续的 balance 断言,并将差额计入权益账户。请谨慎使用,因为它可能掩盖更大的问题。显式调整通常更安全。

第五部分:高级和现实交易模式

追踪债务:管理应收和应付

复式记账非常适合追踪别人欠你的钱(Assets:Receivables)或你欠别人的钱(Liabilities:Payable)。

示例: 你为团体聚餐支付了 90 美元,你的朋友 Bob 欠你他的 45 美元份额。

  1. 记录初始费用和应收款:

    2024-08-05 * "Dinner Place" "Dinner with Bob"
      Expenses:Food:Restaurant          45.00 USD  ; Your share
      Assets:Receivables:Bob            45.00 USD  ; Bob owes you
      Assets:Bank:US:Chase:Checking    -90.00 USD
  2. 当 Bob 还你钱时:

    2024-08-06 * "Bob" "Paid me back for dinner"
      Assets:Bank:US:Chase:Checking     45.00 USD
      Assets:Receivables:Bob           -45.00 USD

Assets:Receivables:Bob 账户现在为零,你的账簿完美平衡。

资产与费用:购车与折旧

像汽车这样的大额购买不是简单的费用;它是获得一项随时间贬值(折旧)的资产。

  1. 将购买记录为资产:

    2023-01-15 * "Toyota Dealer" "Purchase of a new car"
      Assets:Car:ToyotaCamry         30000.00 USD
      Assets:Bank:US:Chase:Checking -30000.00 USD
  2. 记录年度折旧: 假设你估计汽车每年贬值 3,000 美元。年底,你将其记录为费用。

    2023-12-31 * "Depreciation" "Annual car value depreciation"
      Expenses:Depreciation:Car      3000.00 USD
      Assets:Car:ToyotaCamry        -3000.00 USD

在此条目之后,你的 Assets:Car:ToyotaCamry 账户正确反映了汽车的新价值(27,000 美元),并且你已将当年的使用成本作为费用正确核算。

第六部分:深入探讨 —— 建模复杂的现实世界资产

案例研究 1:房地产会计

房子通常是你最大的资产和负债。以下是如何建模。

  1. 创建账户和自定义商品:

    2022-01-01 commodity HOUSE_123MAIN
      name: "Property at 123 Main St"
    2022-01-01 open Assets:Property:Home:123Main        HOUSE_123MAIN
    2022-01-01 open Liabilities:Mortgage:HomeLoan       USD
    2022-01-01 open Expenses:Home:Interest
    2022-01-01 open Expenses:Home:PropertyTax
  2. 记录购买: 假设你用 10 万美元首付和 40 万美元贷款购买了一栋 50 万美元的房子。

    2022-03-15 * "Settlement Company" "Purchase of 123 Main St"
      Assets:Property:Home:123Main          1 HOUSE_123MAIN {500000.00 USD}
      Assets:Bank:DownPayment          -100000.00 USD
      Liabilities:Mortgage:HomeLoan    -400000.00 USD
  3. 记录每月按揭付款: 你的每月付款包括本金(减少负债)和利息(一项费用)。

    2022-04-01 * "Mortgage Bank" "Monthly Mortgage Payment"
      Liabilities:Mortgage:HomeLoan      800.00 USD   ; Principal
      Expenses:Home:Interest            1200.00 USD   ; Interest
      Assets:Bank:US:Chase:Checking    -2000.00 USD
  4. 追踪增值(未实现收益): 房子的市场价值会变化。为了在不影响你的官方净资产(因为收益在出售前未实现)的情况下追踪这一点,你可以使用带有"虚拟"货币的价格指令。

    ; The purchase price is the real cost basis
    2022-03-15 price HOUSE_123MAIN   500000.00 USD
     
    ; An updated market estimate is an unrealized gain
    2024-01-01 price HOUSE_123MAIN   550000.00 USD.UNREALIZED

这允许你在 Fava 的图表中看到预估价值,而不会不当夸大你的资产负债表。

探索一个包含按揭跟踪、折旧和房产出售的实时房地产示例账本:

在新标签页中打开 房地产示例账本

案例研究 2:跟踪限制性股票单位(RSUs)

RSU 是一种常见的股权补偿形式。对它们进行会计处理涉及跟踪初始授予、归属事件和预扣税款。

  1. 初始设置: 为已归属(HOOL)和未归属(HOOL.UNVEST)的股票以及后续条目涉及的所有账户创建商品。预先声明所有这些都是为了使下面的两笔交易能够独立加载。

    2021-01-01 commodity HOOL
    2021-01-01 commodity HOOL.UNVEST
    2021-01-01 open Assets:Brokerage:Etrade:HOOL          HOOL
    2021-01-01 open Assets:Grant:Unvested                 HOOL.UNVEST
    2021-01-01 open Income:Grant:Awards                   HOOL.UNVEST
    2021-01-01 open Expenses:Grant:Vested                 HOOL.UNVEST
    2021-01-01 open Income:Salary:Hooli:RSU               USD
    2021-01-01 open Expenses:Taxes:Federal                USD
    2021-01-01 open Expenses:Taxes:State                  USD
  2. 记录初始授予: 此交易显示总授予额进入一个未归属资产账户。目前还没有应税项目,所以整个条目以跟踪商品 HOOL.UNVEST 计价。

    2021-02-01 * "Hooli" "Initial RSU Grant"
      Assets:Grant:Unvested        1000 HOOL.UNVEST
      Income:Grant:Awards         -1000 HOOL.UNVEST
  3. 记录归属事件: 这是关键交易。当股份归属时,你确认收入,雇主预扣股份以支付税款,你保留剩余部分。假设 100 股以每股 150.00 美元归属,因此:

    • 总薪酬:100 × $150.00 = $15,000.00
    • 预扣用于纳税的股份:40 × $150.00 = $6,000.00(联邦 $4,800.00 + 州 $1,200.00)
    • 你保留的股份:60 × $150.00 = $9,000.00 的成本基础
    • 给你的现金:$0.00 — 全部预扣税以股份支付

    这些金额构成该条目,并且它们相互平衡:$6,000.00 的税款加上 $9,000.00 的保留股票恰好等于 $15,000.00 的收入。

    2022-02-01 * "Hooli" "RSU Vesting Event"
      ; Ordinary income: 100 shares * $150.00
      Income:Salary:Hooli:RSU                   -15000.00 USD
      ; Tax withheld, funded by 40 of the 100 shares (40 * $150.00 = $6,000.00)
      Expenses:Taxes:Federal                      4800.00 USD
      Expenses:Taxes:State                        1200.00 USD
      ; The 60 shares you keep, at their $150.00 vesting-day basis
      Assets:Brokerage:Etrade:HOOL                  60 HOOL {150.00 USD}
      ; Retire the 100 unvested units the grant was tracking
      Assets:Grant:Unvested                       -100 HOOL.UNVEST
      Expenses:Grant:Vested                        100 HOOL.UNVEST

这个单一的、平衡的交易模拟了整个事件:未归属的授予减少,收入被确认,税款被预扣,60 股净归属股份以正确的成本基础出现在你的经纪账户中,用于未来的资本收益计算。

有两个细节值得复制到你自己的账本中。首先,逐账户记录预扣税,而不是让一个包罗万象的平衡账户吸收它——如果联邦和州的条目之和与预扣股份的价值不符,交易将无法平衡,Beancount 会告诉你。其次,不要在各分录之间留空行:空行会结束交易,Beancount 会对后续分录报告语法错误。

如果你的雇主在公开市场上出售预扣的股份,而不是按归属价格收回,那么该出售是单独的交易——减少 Assets:Brokerage:Etrade:HOOL 以换取现金——而出售价格与 $150.00 基础之间的任何差额都是小额资本收益或损失。将其排除在归属条目之外。

第七部分:账本项目管理

随着账本的增长,组织性变得关键。

使用版本控制(Git)保护你的数据

由于你的账本是文本文件,它非常适合使用 Git 进行版本控制。这给了你所有更改的完整历史,保护你免受意外删除或错误的影响。警告: 你的财务数据高度敏感。在 GitHub/GitLab 等服务上使用私有仓库,或自己托管。

使用标签(#)和链接(^)组织

Beancount 提供了两种在账户之外对交易进行分组的方法:

  • 标签(#): 用于事件或项目。例如,你可以筛选与特定旅行相关的所有交易。 2024-07-20 * "酒店" "维也纳" #trip-europe-2024
  • 链接(^): 用于连接在不同时间发生的财务相关交易,例如现金取款和相关的银行费用。

结构化文件的可扩展策略(include)

单个巨大的文件难以管理。使用 include 指令将你的账本拆分为多个文件main.bean:

; Main ledger file
 
; Global options
option "title" "My Personal Ledger"
option "operating_currency" "USD"
 
; Include account declarations and other files
include "accounts.bean"
include "years/2023.bean"
include "years/2024.bean"
include "events/trip-europe-2024.bean"

一个健壮的组织策略,按优先级排序:

  1. 按事件: 为主要的、独立的事件创建一个单独的文件(例如,trip-europe-2024.bean)。
  2. 按类别/收款人: 对于高度规律、重复的交易,如水电费或工资,将它们分组到自己的文件中(例如,recurring-rent.bean)。
  3. 按账户: 对于与特定账户紧密耦合的交易(利息、费用、信用卡支付),考虑使用账户特定文件。
  4. 按日期: 对于所有其他一般交易,按年份(2024.bean)或月份(2024/07.bean)简单拆分是有效的。

第八部分:结论

Beancount 学习曲线陡峭,但回报是无可匹敌的力量、灵活性和对财务数据的控制。通过拥抱复式记账的原则和 Beancount 提供的实用工具,你可以从简单的费用追踪走向一个完整、准确、有洞察力的个人财务管理体系。你的账本成为一个永久的、私密的、宝贵的资产,用于理解你的过去和规划你的未来。

Beancount.io 入门

Beancount.io 是一个基于云的现代财务管理平台,它将你的基于文本的交易记录转化为全面的财务报表,包括损益表、资产负债表和试算平衡表。通过将纯文本文件的可靠性与强大的可视化工具相结合,Beancount.io 帮助你在保持对财务生活的精确控制的同时,获得对投资表现的有价值的洞察。

在 Beancount.io 开启你的财务之旅 — 查看当前计划和定价了解每个层级包含的内容。

beancount.io 账本仪表板,显示净资产趋势图、账户余额和 AI 助手栏

探索实时账本 →

beancount.io 上 Apple 公共 Beancount 账本的损益表,包含净利润图表以及收入和支出明细

探索实时账本 →

beancount.io 上 Apple 公共 Beancount 账本的资产负债表,包含净资产图表以及资产和负债明细

探索实时账本 →

来源:https://beancount.io/zh/docs/introduction-to-beancount