使用Beancount记账

前前后后开始记账已经一年多了,最开始使用FireflyIII,今年以来开始用Beancount,总而言之,两个软件都是不错的记账工具,Beancount是纯粹的复式记账,FireflyIII基本上也是复式记账,但也有一些单式记账的残余。

本人并非专业的会计,也从未系统学习过会计相关知识,仅以普通人身份表达对于使用Beancount进行复式记账的一点感受

为什么要用复式记账

在会计学中,复式簿记(又称为复式记账法)是商业及其他组织上记录金融交易的标准系统。

该系统之所以称为复式簿记,是因为每笔交易都至少记录在两个不同的账户当中。每笔交易的结果至少被记录在一个借方和一个贷方的账户,且该笔交易的借贷双方总额相等,即“有借必有贷,借贷必相等”。

例如,如果A企业向B企业销售商品,B企业用即期支票向A企业支付货款,那么A企业的会计就应该在贷方记为“销售收入”,在借方记为“现金”。相反地,B企业的会计应该在借方记为“进货”,并在贷方记为“银行存款”。

借方项目通常记在左边,贷方则记在右边,空白账簿看起来像个T字,故账户也被称为T字帐。

—- 维基百科-《复式簿记》

有复式记账,那么一定有单式记账,所谓单式记账就是常说的“流水账”,主要用于记录一个账户上的账面流水。比如支付宝里的账单就是典型的单式记账。

为何要才用复式记账,我常听到个人用不上复式记账的说法,然而事实显然并非如此,这一原因在于,每一笔账面数字的减少都是不一样的,每一笔资产都不会是从天上掉下来的(虽然我的账户里的确有“Windfall”这一账户),同时还有的资产可能会通过某种交易后变换一种形式回到自己的资产中(如购买股票),在这种情况下单式记账只能记为如下的两笔:

2020-08-29 支出 1600 USD ; 购入 1 GOOG
2020-08-29 收入 1 GOOG

你真的支出了1600 USD么?没有,你只是将这1600 USD兑换成了1股GOOG的股票,而复式记账则会记为如下的一笔

2020-08-29
   A银行现金账户 -1600 USD
   B券商股票账户 +1 GOOG

复式记账将支出与收入连起来了,我们也可以看出,这一次交易没有净资产的变化,变化的只是净资产的类别。单式记账的表达能力较复式记账低了许多。如果说这个例子不够明显的话,不如举另一个例子,即假设你购入了一件商品。

购买操作是完完全全的支出行为,几乎所有人都会记为:

2020-08-29 支出 100 CNY ; 购买日用品

由于你是网购,5天后,你发现这个东西收到之后就堆在角落,甚至没有开箱,你决定用“七天无理由”退货,这时候,你会记作:

2020-09-04 收入 100 CNY ; 退货

当你统计这一年的总开支的时候,就会凭空多了100元的支出与100元的收入,但实际上你并没有真正花掉这笔钱,你只是将这笔钱暂存在售货方,并在退货时取回了它,对于复式记账,则会记作这么两笔交易:

2020-08-29
    A银行现金账户 -100 CNY ; 日用品
    消费账户      +100 CNY

2020-08-29
    A银行现金账户 +100 CNY ; 日用品退货
    消费账户      -100 CNY

当你年末统计自己的消费的时候,你看了一眼消费账户,会发现有一笔增量与一笔减量,但这不要紧,你总是将“消费账户”的值视作自己的自己的消费。

买了又退货,显然算不上消费。

与退货交易类似的,那就是借贷交易了。在借款的过程当中,你的净资产并没有增加,因为随着你的资产增加的,还有你的债务,最常见的就是信用卡了。如果使用单式记账,那么直到信用卡账单到来之前,你都会对着你的银行存款开心,并不知不觉超额消费。而如果你使用复式记账,并追踪自己的“净资产”,则会快速发觉这一点。

但至少……即使你用单式记账,你看到了账单。

  • 讲道理单式记账也可以看总和啊。

  • 但是哪家单式记账软件给你看综总和的?我的银行App都不告诉我净资产的。

复式记账拥有极强的表达能力,因此即使是个人使用,也能从中获益。

使用Beancount进行复式记账

Beancount是一个基于文本的复式记账软件,当然,于其说是一个复式记账软件,不如说是一个复式账软件,毕竟,它没有提供任何对于记账相关的功能,它提供的是对于某种特定格式的账本的解析功能,实际上的记账人只是你自己,甚至你的账本Beancount不会做任何操作。

众所周知,这个是著名的会计恒等式:

资产(Assets) = 负债(Liabilities) + 股东权益(Shareholders’ / Owners’ Equity)

这就引入了Beancount的五个基本账户中的三个:Assets / Liabilities / Equity,此外Beancount还有两个账户:Income / Expense,分别表示收入和支出的“账户”。

相比于大多数记账软件,Beancount推广了“货币”这一概念,一般翻译成“通货”,在实际对于个人而言,不如说是“有价证券”或者“等价物”,其实还是回到了“通货”的含义上。在Beancount看来,人民币(CNY)和美元(USD)和一股谷歌C类股票(GOOG)和一辆车都是没有区别的,都是一类等价物,但你可以在交易的时候,标记每个等价物之间的价值,也可以时不时地在账本中写下等价物之间地价值关系。

同时,Beancount使用纯文本记账,相比于数据库而言,就是不需要任何的API知识,自己写一个简单而糙的程序,就可以实现各种导入、导出操作,再也不用配置各种数据库,也不会因为软件的导入导出功能而烦恼。同时你甚至可以将其存储在Git上做各种维护。

当然,账本属于个人隐私,请使用私人Git仓库,并在必要时加密。

Beancount的一条记录大致长这样:

2020-08-29 * "一笔消费"
    Assets:Bank:CMB       -199.00 CNY
    Expenses:Daily:Misc    199.00 CNY

作为复式记账的基本原则“有借必有贷,借贷必相等”,Beancount要求每一条记录中的所有数值相加,(由于通货转换过程中的四舍五入,不可避免地会引入舍入误差,那么在可以接受的误差内)相等。

既然提到了通货之间的转换问题,那么,对于前文购入谷歌股票的记录,则长这样:

2020-08-29 * "购入1股谷歌-C"
    Assets:Bank:MatsuBank -1600.00 USD
    Assets:Stock              1.00 GOOG { 1600.00 USD }

看!我们的资产(Assets)并没有减少,只是从一个账户转移到了另一个账户(同时变换了一下形式)。但这里就会说,-1600 USD + 1.00 GOOG 显然不等于0啊。

这就是Beancount对于资产的“标签”功能,在这笔交易中,这一股GOOG被打上了值1600美金的标签,那么实际计算的时候,就是:-1600 USD + 1.00 GOOG ( = 1600 USD ) = 0,这就平了。

Beancount还支持一些别的记录,比如Balance记录,表示一条断言,即某一天某个账户上的某个通货的资产应当等于某个数值。比如:

2020-08-30 balance Assets:Stock 1.00 GOOG

非常简单的一句话,当Beancount发现资产不能对上的时候,就会报出错误,我常常在信用卡的账单日,和一个月结束的时候,通过这一条语句来完成对账操作。

那么,在卖出的时候要怎么记账呢?

2020-08-30 * "卖出1股谷歌-C"
    Assets:Bank:MatsuBank 1650.00 USD
    Assets:Stock 1.00 GOOG { 1650.00 USD }

这样看起来是正确的,但实际上Beancount会报错,因为你没有购入价格是1650美金的谷歌C股票,实际上,这笔交易可以记成这样:

2020-08-30 * "卖出1股谷歌-C"
    Assets:Bank:MatsuBank  1650.00 USD
    Assets:Stock             -1.00 GOOG { 1600.00 USD } @@ 1650.00 USD
    Income:Invesrment       -50.00 USD

表示你以1650.00美金卖出了1股以1600.00买入的谷歌C股票,并获得了50美金的收益。在实际操作中,常常会在不同价格零散买入股票、基金,并在某个时间点一口气卖出一定数量的资产。Beancount支持自动选择一个通货的标签,一般情况下,我用的是“先进先出”的策略,这需要在定义账户的时候写明:

1970-01-01 open Assets:Stock "FIFO"

即表示此账户上的交易遵循“先进先出”的策略,当没有指明标签的时候,从最早的标签开始。

现实中,仅仅维护5个账户(收入、支出、资产、债务、权益)是不够的,Beancount支持许多个账户,并将其划分到这五类账户当中。

对于我本人而言,我有这么些账户:

; 银行存款
1970-01-01 open Assets:Bank
; 各类基金及股票
1970-01-01 open Assets:Investment:Fund:R5 "FIFO"
1970-01-01 open Assets:Investment:Fund:R4 "FIFO"
1970-01-01 open Assets:Investment:Fund:R3 "FIFO"
1970-01-01 open Assets:Investment:Fund:R2 "FIFO"
1970-01-01 open Assets:Investment:Stock "FIFO"

; 信用卡
1970-01-01 open Liabilities:CreditCards
; 个人借款
1970-01-01 open Liabilities:Personal

; 工资
1970-01-01 open Income:Salary
; 股权激励
1970-01-01 open Income:RSU
; 奇怪的收入
1970-01-01 open Income:Windfall

; 分红和切割
1970-01-01 open Income:Investment:Fund:R5:Dividend
; 盈亏
1970-01-01 open Income:Investment:Fund:R5:PnL
1970-01-01 open Income:Investment:Fund:R3:Dividend
1970-01-01 open Income:Investment:Fund:R3:PnL

此外,还有针对各类消费类别的各个消费账户。通过这些账户,可以较为轻松地统计资产配置、统计各个时间段内的收入、支出情况。

使用 Fava 查看账本 及 其它

Fava是一个Beancount的前端工具,用以直观地查看Beancount账本里的各个统计数据。

Fava的界面截图,可以看到其各种图表的选项(图片来自Fava项目主页)

除此之外,我还启用了Beancount的计算浮盈的插件,将下面这行放到文件的开头即可:

plugin "beancount.plugins.unrealized" "Unrealized"

同时,我还用脚本每天从“天天基金”上抓取基金净值,并通过Beancount里的price记录来自动更新账本里的数值,以此获得浮盈和收益率等数据。

在记账过程中,发现由于日常零用开支过于分散,难以对账,因而将这些零用开支专卡进出,不再单独记录,考虑到零用花销大多集中在日常零食、饮料等极小额支出方向,故不会对统计有太大影响。同时每日保证其余额在100元以方便使用。

记账一年多以来,由于本来就不好消费,所以对消费结构也没有多大影响,倒是对自己的资产配置影响不小,能较为方便地了解和控制自己当前的风险水平。