复式借贷记账法 Beancount (1) - 基础知识

本文介绍一些基本概念,推荐仔细阅读References. 然后就是 bean-example > example.beancoun 其实也非常具有参考价值。

基本概念

商品单位 Commodities

与其说是我们狭义理解的商品,应该说理解为广义的商品,即具有交换价值的东西。
这里定义的通常是账户的单位。它可以是货币单位,也可以是某一种资产的单位,比如汽车,房子等。

账户 Accounts

账户 详情
Asset 资产 有形或者无形的资产,比如 现金, 银行账户, 有价证券, 车子,房子 等等
Liabilities 负债 各种形式的负债,房贷,车贷,信用卡债,花呗
Income 收入 工资,奖金,彩票中奖,出租屋收入,股息,存款利息,借贷利息 等等
Expenses 支出 各种花费,手续费,购物,旅行,支付的贷款利息等等
Equity 权益 记录账本初始化之前的净收入(income - expenses)

前面四种账户的类型应该很好理解,可能就是权益类型的账户比较难以理解一些。

The account type “equity” is used for accounts that hold a summary of the net income implied by all the past activity.

所以权益账户的目的就是帮助 zero-out 你所有的账户,使得以下恒等式成立

$$
income + liabilities + assets + expenses + equity = 0
$$

权益账户的用处有

  • 初始化账本时已有的数据

其他情况下, 应该可以等价转换为Assets/Libabilities

基本语法

1
YYYY-MM-DD <操作> <参数...>

创建商品单位

1
2
1998-07-22 commodity AAPL
name: "Apple Computer Inc."

对商品定价

1
2
2015-04-30 price AAPL   125.15 USD
2015-05-30 price AAPL 130.28 USD

创建和关闭账户

账户需要显式的创建, 这里的关键字是open, 当现实中账户关闭的时候,也可以关闭 close 。账户命名是 colon-separated tags,一系列的标签,通过冒号连接起来。虽然没有特定的规范,但是在GUI上会以这样的树形结构来聚合账户上的余额,所以一般会利用标签来逐渐缩小范围。

比如

1
2
3
4
5
6
7
2002-01-17 open Assets:Cash USD
2002-01-17 open Equity:Open-Balances


2002-01-17 open Liabilities:CreditCard:US:Chase:Freedom

2020-01-17 close Liabilities:CreditCard:US:Chase:Freedom

交易

1
2
3
4
5
6
7
8
9
10
11
12
13
2014-05-05 txn "Cafe Mogador" "Lamb tagine with wine"
Liabilities:CreditCard:CapitalOne -37.45 USD
Expenses:Restaurant

2014-03-19 * "Acme Corp" "Bi-monthly salary payment"
Assets:MyBank:Checking 3062.68 USD ; Direct deposit
Income:AcmeCorp:Salary -4615.38 USD ; Gross salary
Expenses:Taxes:TY2014:Federal 920.53 USD ; Federal taxes
Expenses:Taxes:TY2014:SocSec 286.15 USD ; Social security
Expenses:Taxes:TY2014:Medicare 66.92 USD ; Medicare
Expenses:Taxes:TY2014:StateNY 277.90 USD ; New York taxes
Expenses:Taxes:TY2014:SDI 1.20 USD ; Disability insurance

通用格式

1
2
3
4
5
6
7
8
YYYY-MM-DD [txn|Flag] [[Payee] Narration]
[Key: Value] ; meta datas
...
...
[Flag] Account Amount [{Cost}] [@ Price] ; posting
...
...
...

通常交易的directives是txn 但是因为这个是beancount里最常见的记录,因此允许用户省略
通常 * 表示交易数据无误,而!表示交易数据可能有错。

* 后的两个string,第一个是payee,就是收款方, 可选的,也可以省略 第二个是narration 就是描述,

从第二行起,可以加入metadata
meta data完了之后是 交易的数据(postings)
可以是很多条,这也是复式记账的好处,可以完整的描述钱的去向,比如上面的例子中,工资的发放就涉及到了很多账户。

在Posting中可以记录价格,和货币转换

1
2
3
2012-11-03 * "Transfer to account in Canada"
Assets:MyBank:Checking -400.00 USD @ 1.09 CAD
Assets:FR:SocGen:Checking 436.01 CAD

这里一个 @ 表示的是单价,如果用 @@则表示的是总成本

1
2
3
2012-11-03 * "Transfer to account in Canada"
Assets:MyBank:Checking -400.00 USD @@ 436.01 CAD
Assets:FR:SocGen:Checking 436.01 CAD

断言 Balance Assertion

编程的同学应该很容易理解. 这个概念和测试中的断言是一个意思。

当你对某一个账户在某个时间点上做断言的时候,

1
2015-06-01 balance Liabilities:CreditCard  -634.30 USD

Beancount会根据这个来验证其账目的正确性,如果不匹配,则会报错。这个时候就需要对账找出并且修复错误。显然,时不时的对账户做断言是保持账户正确性的必要条件。而且如果出错,你只需要对比上一次正确断言和当前出错断言之间的记录即可。

填充 Padding

填充是和断言一起使用的,当balance assertion出现在pad之后(二者时间之内不能有其他交易),beancount会自动根据pad的参数,将余额调整至断言中的数据。

1
2
2019-12-31 pad Liabilities:CreditCard:US:Chase:SapphirePreferred  Equity:Opening-Balances
2020-01-01 balance Liabilities:CreditCard:US:Chase:SapphirePreferred -95.0 USD

这个在初始化账本的时候,需要设定账户初始值的时候会频繁使用。

项目结构

Beancount的项目其实就是一堆beancount文件。
由于有include 关键字的存在,其项目结构是可以很松散的。

我的建议是合理的利用文件夹和include来管理beancount项目。

folder structure

以我个人的经验,首先有一个main.beancount 作为入口文件。
里面并没有任何交易记录,只做一些全局变量的定义,比如Assets,Equity,货币单位。
然后利用 include 去索引其他文件夹

1
2
3
4
5
include "income/_index.beancount"
include "expense/_index.beancount"
include "property/_index.beancount"
include "vehicle/_index.beancount"
include "investment/_index.beancount"

这里我利用_index.beancount来做文件的索引,每一个文件夹相当于一个scope 就会有一个index文件。这个index位于每一个文件夹下,确保每一个数据文件都被include进来,同时我也在index文件中定义在这个scope里需要的账户。

至于如何分文件夹,则是一个千人千面的问题了。
由于我大部分的账目都是信用卡,然后银行卡多数是付信用卡账单。这些都可以自动化导入,所以我利用年份命名的文件来记录这些流水。
这里面的大部分去想都是expense。但是因为比较杂所以不好归纳到单个文件。
至于expense文件夹下,我只放置一些周期性的支出,比如手机账单,水电气账单,车险房险等。
车贷房贷都是单独track,所以各放入了一个文件夹。
收入里面则按照公司,每一个公司一个beancount文件。

参考文献

系列介绍

准备用一个系列的文章来介绍这个工具和一些技巧。
这些技巧有一些是我从已有的模版中找出来,也有一些是在Google Group里看到大家的推荐,自己又尝试出来的方法。

  1. 先导 复式借贷记账法 Beancount (0) - 先导
  2. 基础知识 复式借贷记账法 Beancount (1) - 基础知识
  3. 环境设置 复式借贷记账法 Beancount (2) - 环境设置
  4. 如何对房产建模 复式借贷记账法 Beancount (3) - 房产
  5. 如何对RSU建模 复式借贷记账法 Beancount (4) - RSU
  6. 如何对ESPP建模
  7. 自动化导入
  8. 安全

希望快速得到新文章的通知?请关注作者的微信公众号

wechat-qrcode