Beancount复式记账(三)

上一篇我介绍了Beancount的基本记账方法和一切常见的规范。这篇继续讲述Beancount的常用语法,主要内容是对账和资产折旧。

对账

Beancount的语法检查保证了每一笔交易的借记和贷记是平衡的,这已经可以避免许多会导致「账不平」的错误,但是对于数额本身的错误,或者某调账目漏记并没有办法。这就是为什么我们要定期对账。

资产负债表

所谓对账,就是看每个账户的结余(Balance)是否正确。每个账户的余额可以在资产负债表(Balance Sheet)页面中找到,可以查看样例资产负债表

资产负债表

fava资产负债表把资产列在左边,负债和权益列在右边。权益即净资产,是根据资产和负债计算出来的(除了Equity:Opening-Balances,之后会讲到)。

需要注意的是Beancount的债务和权益是负数,所以并不是资产 = 负债 + 权益,而是资产 + 负债 + 权益 = 0。我之前提过一次,这是Beancount使用正数来表示借记(Debit),负数表示贷记(Credit)的结果。在传统的复式记账中,数字的正负号并没有这样的意义,无论是借记还是贷记都是正数,所以绝对值资产 = abs(负债 + 权益)也许更好理解。

在资产负债表上点击任意账户,可以进入账户的明细界面。账户的明细界面列出了涉及该账户的每一笔交易,点开后可以看到具体的交易信息。每一行的最右侧是这一笔交易后的该账户结余,这个数字就是对账的关键。

账户明细

结余断言

假设已知账户的某日结余金额,只要在这个账户明细界面看一看对应的日期的最后一笔交易后结余是否正确就可以了。如果Beancount计算出的结余和已知的是一样的,那么基本上就可以确定账没有问题。

这个步骤看似容易,但是随着账目增多,对账的负担会很重,而且容易看错。更严重的问题是,如果因为某种原因要修改过去的账目,已经对好的账就不一定正确了。惟一保险的办法是每次修改了过去日期的交易后,把涉及到的账户未来的结余再全部重新对一遍。好在这个过程是可以自动化的,方法就是使用结余断言(Balance Assertion)。

结余断言就是在记账中加入已知事实,即某个日期开始的时候的某个账户结余。如果你对单元测试有了解,这个方法肯定不会陌生。结余断言的语法非常简单,如下例所示:

2017-08-20 balance Assets:US:BofA:Checking 2298.50 USD

惟一需要留意的地方是,结余断言是所声明日期开始的时候的余额,即当日的交易不算在内。

声明结余断言之后,Beancount会自动检查断言是否正确,如果不正确就会有错误出现。如果每个账户都有适当的结余断言,修改过去的交易就可以放心进行了。

文档链接

有了结余断言,接下来就是这个断言的事实从哪里来。最简单的方法当然是看看现在有多少结余,然后直接写上今天的日期。这种方法适合现金和其他一些不方便查询交易记录的账户。

除此之外,推荐使用银行月结单(Statement)上面的数字。许多国家的许多银行、信用卡都会定期发送交易明细,一般来说是每月。Beancount提供了管理这些文件的一个语法,例如:

2013-03-20 document Assets:US:BofA:Checking "path/to/statement.pdf"

在fava中这条记录也会被显示出来,并且提供可以点击的链接。这个路径是相对于这条记录所在的Beancount文件的目录,这对于多文件记账很重要(include语法,之后会讲到)。

根据个人经验还有一个重要的提醒,就是要看清楚月结单包含哪些交易,尤其是账单周期末的哪些。因为很多银行、信用卡的交易并不是即时结算的,特别是有跨国交易的时候。如果发现某些交易还没出账或者账单周期开始包含了上个周期的交易,一定要注意余额断言的数额。

结余调整

接下来说一说账对不上的情况。事实上,这是一种常态,人毕竟不是完美的,错记漏记实在是太正常了。一旦结余断言失败,当然是先看自己有没有记错什么,如果实在困难,或者金额差距不大自己没那么在乎,可以考虑用结余调整。

结余调整并不是非要用什么特别的语法不可,实际上只是一种规范。这个规范是使用Equity:Opening-Balances来表示初始结余。下面是一个例子:

2015-01-01 * "账户初始"
  Assets:US:BofA:Checking 3490.52 USD
  Equity:Opening-Balances -3490.52 USD

这个例子的意思是,在2015年1月1日给Assets:US:BofA:Checking增加3490.52美元结余。假设这个账户之前没有记录的话,那么它现在的结余就是3490.52美元,如果有就是在原来的基础上加上3490.52美元。这3490.52美元从哪里来呢?Beancount的规范是使用Equity:Opening-Balances

Equity:Opening-Balances是权益类别下面的账户,它是净资产的一部分。Beancount中权益是负数,所以数字减少代表了净资产的增加。这一部分资产的来源可以理解为表外资产,即来源不明确,在Beancount账本中没有更详细的记录。

Beancount还提供了一个更加简易的语法pad,结合了结余断言,功能是把结余调整到使得下个余额断言满足。用法如下所示:

2015-01-01 pad Assets:US:BofA:Checking Equity:Opening-Balances
2015-01-02 balance Assets:US:BofA:Checking 3490.52 USD

以上的效果是,无论Assets:US:BofA:Checking之前余额多少,在2015年1月2日开始之前都调整到3490.52 USD,差额从Equity:Opening-Balances来。

一般来说除非是调试错误或者导入数据过程中,否则我不建议使用pad这个语法,因为它会让结余断言丧失一定的准确性。使用pad的风险是,如果自动调整的数额过大,当修改了过去其他的账目导致需要调整的数额发生改变的时候,Beancount并不会出现任何警告和错误。我更倾向于把需要调整的金额明确写出来,这样一旦变化就会有错误提醒,避免更大的错误。

资产购入与折旧

生活中有一些交易我们需要考虑到底要记为花费,还是资产的购入。在光谱的两端一般没什么争议,譬如吃饭肯定是消费,买房无疑是购入资产。中间许多类别就不一定了,这取决于个人的偏好和目的。

拿买汽车作为例子,无论是新车还是旧车,许多人在开一段时间以后会选择卖掉。如果我们把买车记为消费,卖车记为收入,这本身并没有任何错误。问题是,对很多人来说汽车还是一笔不可忽略的资产,如果直接记为消费,没有对应的资产入账,那就意味着净资产突然大幅减值。几年后卖出,净资产又突然增加。

要解决这个问题,我们就要把汽车记为一项资产,下面是例子:

2015-01-01 * "丰田汽车" "买入Corolla"
  Assets:Car:ToyotaCorolla 20000 USD
  Assets:US:BofA:Checking -5000 USD
  Liabilities:Loan:Car -15000 USD

2019-01-01 * "二手车商" "卖出Corolla"
  Assets:Car:ToyotaCorolla -20000 USD
  Assets:US:BofA:Checking 10000 USD
  Expenses:CarUsage 10000 USD

上面这个例子是2015年1月1日贷款买入了价格为$20000的汽车,并计入资产Assets:Car:ToyotaCorolla。中间省略还贷款的过程,四年后2019年1月1日,把车卖给了二手商,获得$10000,剩下的$10000就是三年来用车的消费了。

这个方法对买卖交易之间的这段时间内净资产计算仍然不够准确,并没有完全解决净资产跳变。因为汽车的使用是三年来平均花费出去的,而不是最后卖的时候一下子花了$10000。要解决这个问题就要引入定期进行折旧(Depreciation)计算。一般的会计方法中把因为资产使用或者随着时间自然减值称为折旧,我记为Expenses:Depreciation:CarUsage

接下来需要决定的是折旧的周期,即把车的使用费按照多大的粒度来记录。这个完全因人而异,也因金额的大小而异。对于车我可以选择按年折旧,因为在许多国家(譬如美国),工作原因的资产折旧是可以按年抵税的。如果希望每个月的花销更加细致,那么按月折旧也是一个方案,只是需要多记录几笔而异。

2015-12-31 * "Corolla折旧"
  Assets:Car:ToyotaCorolla -2500 USD
  Expenses:Depreciation:CarUsage

2016-12-31 * "Corolla折旧"
  Assets:Car:ToyotaCorolla -2500 USD
  Expenses:Depreciation:CarUsage

2017-12-31 * "Corolla折旧"
  Assets:Car:ToyotaCorolla -2500 USD
  Expenses:Depreciation:CarUsage

2018-12-31 * "Corolla折旧"
  Assets:Car:ToyotaCorolla -2500 USD
  Expenses:Depreciation:CarUsage

下一个问题是,每次折旧减值多少。这个问题就是会计上可以操作的空间了,因为实际的价格只有在出售的时候才知道。一般会计准则是预估一个折旧年限,然后以此为根据来折旧。譬如说,我们预期汽车的寿命是10年,即10年后该车的价值清零,这样我们可以按照每年10%的折旧率每年减记。最终当实际卖出的时候,我们再根据卖出价格做调整,或者差额记为其他类别。如果有特别的事件发生,还可以另外单独折旧。例如发生了车祸,车的估值大幅下降,可以在此时额外减值。

Beancount并没有自动折旧的功能,每一笔都是要自己写的。如果怕忘了,其实可以把未来日期的折旧也写上。另外还有第三方的插件beancount-interpolate可以尝试使用。

在以后的文章中,我还会介绍更多实际的记账方法,包括更细致的资产记账,价格追踪。欢迎加入Beancount中文讨论:t.me/beancount_zh

以下链接是其他介绍:

相关日志