我从去年7月开始使用beancount记账,并写了一篇《记账神器beancount教程》。除了日常账(下文日常账均指日常收支账,即上一篇教程所讲内容),我的股票交易也用beancount记录,今天便来讲讲相关实践。

一、交易记录举例

直接贴几笔我的港股交易记录,记录如下:

2019-12-02 * "港股交易" "30.1元买入600股阅文集团"
    Assets:Broker:FutuHK:Cash              -18060.00 HKD
    Assets:Broker:FutuHK:Positions            600.00 HK_00772 {30.10 HKD}
    Expenses:Broker:FutuHK                     75.89 HKD ;手续费
    Assets:Broker:FutuHK:Cash                 -75.89 HKD ;手续费

2020-01-14 * "港股交易" "加仓阅文集团1000股"
    Assets:Broker:FutuHK:Positions           1000.00 HK_00772 {38.00 HKD}
    Assets:Broker:FutuHK:Cash              -38000.00 HKD
    Expenses:Broker:FutuHK                     96.43 HKD ;手续费
    Assets:Broker:FutuHK:Cash                 -96.43 HKD ;手续费

2020-01-31 price HK_00772 32.55 HKD ;一月底阅文集团收盘价

2020-02-28 * "港股交易" "减仓阅文集团1000股,筹集资金做恒指期货"
    Assets:Broker:FutuHK:Positions          -1000.00 HK_00772 {} @ 36.40 HKD
    Assets:Broker:FutuHK:Cash               36400.00 HKD
    Assets:Broker:FutuHK:Cash                 -95.30 HKD ;手续费
    Expenses:Broker:FutuHK                     95.30 HKD ;手续费
    Income:Broker:FutuHK                                 ;利润(负为盈利,正为亏损)
    
2020-03-09 * "货币兑换" "5000港币兑换美元"
    Assets:Broker:FutuHK:Cash               -5000.00 HKD
    Assets:Broker:FutuUS:Cash                 641.96 USD @@ 5000 HKD

接下来基于案例介绍。

二、股票账户

和日常账一样,记录股票交易也需要先准备账户。账户定义如下:

;我的港股账户
2019-06-30 open Assets:Broker:FutuHK:Cash HKD ;富途港股账户现金
2019-06-30 open Assets:Broker:FutuHK:Positions "FIFO"  ;富途港股账户持仓

股票账户一般包括现金和持仓,建两个账户。其中现金账户需要指定币种(Assets:Broker:FutuHK:Cash),而持仓账户(Assets:Broker:FutuHK:Positions)有类型之分,我习惯使用FIFO类型,另外也可以用LIFO类型。类型含义如下:

  • FIFO:「first in, first out」的缩写,表示先进先出,卖出股票时,先卖出「先买入」的。
  • LIFO:「last in, first out」的缩写,表示后进先出,卖出股票时,先卖出「后买入」的。

卖出股票时,beancount会基于卖出价和当初的买入价(有可能多笔买入,价格不同)计算利润,两种类型本质上是回溯买入价的方式不同,所以涉及多次加减仓时,账户类型会影响每一笔的利润计算,但全部清仓时,累计利润不受影响。

三、买入记录与Commodity

再讲个概念,Commodity,翻译为「商品」,即交易过程中的标的物。beancount系统中,货币和股票都是Commodity

下面是一条买入记录:

2019-12-02 * "港股交易" "30.1元买入600股阅文集团"
    Assets:Broker:FutuHK:Cash              -18060.00 HKD
    Assets:Broker:FutuHK:Positions            600.00 HK_00772 {30.10 HKD} 
    Expenses:Broker:FutuHK                     75.89 HKD ;手续费
    Assets:Broker:FutuHK:Cash                 -75.89 HKD ;手续费

直观上也能看到HKDHK_00772属同一位置,前者是港币,后者是阅文集团股票,都属于Commodity。

持仓账户记录买入股票数,大括号{}中则是Commodity的成本价,即买入阅文股票成本为30.10港币。

现金账户记录花了多少钱。不难猜到,现金账户的成本价被省略了,如果完整记录,应该如下:

Assets:Broker:FutuHK:Cash              -18060.00 HKD {1.00 HKD}

四、卖出记录与利润计算

下面是案例中的卖出记录。

2020-02-28 * "港股交易" "减仓阅文集团1000股,筹集资金做恒指期货"
    Assets:Broker:FutuHK:Positions           -600.00 HK_00772 {} @ 36.40 HKD
    Assets:Broker:FutuHK:Cash               36400.00 HKD
    Assets:Broker:FutuHK:Cash                 -95.30 HKD ;手续费
    Expenses:Broker:FutuHK                     95.30 HKD ;手续费
    Income:Broker:FutuHK                                 ;利润(负为盈利,正为亏损)

首先,看看持仓账户:

Assets:Broker:FutuHK:Positions          -1000.00 HK_00772 {} @ 36.40 HKD

1、@后表示卖出价。
2、{}中应该给出卖出股票对应的成本价,但因为我们已经约定按FIFO规则计算成本,所以可以省略。

现金账户Assets:Broker:FutuHK:Cash实际入账多少,记录多少。
利润账户Income:Broker:FutuHK直接空着,beancount会自动计算利润。

看到这里,beancount记录股票的基本方法讲完了。

不过,为了更好的理解beancount的工作原理及FIFO规则,我们把{}内容补全看看。如下:

2020-02-28 * "港股交易" "减仓阅文集团1000股,筹集资金做恒指期货"
    Assets:Broker:FutuHK:Positions           -600.00 HK_00772 {30.10 HKD} @ 36.40 HKD
    Assets:Broker:FutuHK:Positions           -400.00 HK_00772 {38.00 HKD} @ 36.40 HKD
    Assets:Broker:FutuHK:Cash               36400.00 HKD
    Assets:Broker:FutuHK:Cash                 -95.30 HKD ;手续费
    Expenses:Broker:FutuHK                     95.30 HKD ;手续费
    Income:Broker:FutuHK                                 ;利润(负为盈利,正为亏损)

补全后,因为成本不同,减持变为两条记录,这很好的体现了FIFO规则。

1、我分两笔共买入1600股,先是30.10买入的600股,后以38买入1000股。
2、那么卖出1000股时,按FIFO规则,卖出的1000股构成如下:
(1)600股30.10的成本(先买入的,先卖出)
(2)400股38.00的成本

beancount自动计算的利润就是:

; 总收入减去两笔总成本
利润 = 36400 - 600 * 30.10 - 400 * 38.00 = 3140

五、股票最新价

持仓时股价大幅上涨或下跌,但又没卖掉,如何统计最新市值及浮动盈亏呢。

beancount提供了price关键字记录股票价格,格式如下:

2020-01-31 price HK_00772 32.55 HKD ;一月底阅文集团收盘价

fava查看「资产负债表」时,右上角有统计口径选项,其中两个如下:

  • At Cost:按成本价统计资产,也就是最初买入的成本
  • At Market Value:按市价统计资产,beancount会使用最新一条price指定的价格

相信读者注意到了,beancount所有记录时间都只精确到天,意味着beancount无法记录日内交易

六、汇率换算

我有时会在美股和港股账户间换汇,平时消费也有美元消费人民币入账的情况,涉及到汇率时,也可以使用@@进行转化,如下:

2020-03-09 * "货币兑换" "5000港币兑换美元"
    Assets:Broker:FutuHK:Cash               -5000.00 HKD
    Assets:Broker:FutuUS:Cash                 641.96 USD @@ 5000 HKD

七、beancount数据结构总结

讲到这,可以对beancount数据结构做个总结,便于理解beancount的原理。

beancount一条完整数据格式如下:

账户名                           数量      商品      成本价          最新价/总价
account
Assets:Broker:FutuHK:Positions  -1000.00 HK_00772 {30.10 HKD} @ 36.40 HKD
Assets:Broker:FutuHK:Positions  -1000.00 HK_00772 {30.10 HKD} @@ 36400 HKD

(一个@记录单价,两个@@记录总价)

fava界面左侧有个「资产」项目,如下图所示,能看到所有字段。

资产界面
资产界面

各列数据:

  • account:账户名
  • units:商品及数量
  • cost:成本价
  • price:最新价
  • book_value:成本*数量,即投入总成本
  • market_value:最新价*数量,即最新总市值
  • acquisition_date:成本对应的日期。一般是买入的日期。

记账时,股票交易会用到cost和price,日常账不涉及。

🔔 Email 或 RSS 订阅本博客

已有 22 条评论

  1. 阿华 阿华

    您好:请教 如果现在 beancount 开始记.之前的持仓怎么操作?好像股票名称不支持中文.

    1. 1、对股票账户进行初始化设置即可,初始化方法见另一篇文章 https://www.skyue.com/19101819.html
      2、没试过中文,我用的股票代码。代码更稳定,A股和港股公司可能改股票名,但代码不会变。

      1. 阿华 阿华

        【二、账户设置】
        ;1、开设账户
        2022-12-31 open Assets:Trade:Cash CNY ;
        2022-12-31 open Assets:Trade:Positions "FIFO" ;
        2022-12-31 open Assets:Trade:PnL CNY ;
        2022-12-31 open Income:Trade:Dividend ;
        2022-12-31 open Expenses:Trade:Commissions CNY ;
        2022-12-31 open Equity:OpenBalance ;

        ;2、账户初始化
        2023-01-01 * "初始账户20万元"
        Assets:Trade:Cash 200000.00 CNY
        Equity:OpenBalance -200000.00 CNY

        ;【三、交易记录】
        2023-01-03 * "买入陕西煤业"
        Assets:Trade:Cash
        Assets:Trade:Positions 1000 SH_601225 {18.58 CNY}
        Expenses:Trade:Commissions 20 CNY
        Assets:Trade:Cash -20 CNY

        谢谢回复.看了另外一篇.还是有疑问。比如股票账户现在只有几百元520. 但是之前持有陕西煤业,兴业银行等市值20万。现在是Assets:Trade:Cash 520.00 CNY
        Equity:OpenBalance -520.00 CNY ?这样股票持仓初始化不会写了。还是根据持仓市值20万+520,初始化20万+520再一笔写交易记录 如上面。望指教!

        1. 比如持仓万科1000股,代码是SZ000002。这样写:

          Assets:Trade:Stock 1000 SZ000002
          equity:OpenBalance -1000 SZ000002

          其实,就是把SZ000002当CNY看待。货币是一种资产,股票本质也是一种资产。

          1. 阿华 阿华

            Assets:Trade:Positions 100 HK_00700
            Equity:OpenBalances -100 HK_00700

            2023-01-30 * "卖出腾讯控股"
            Assets:Trade:Positions -100 HK_00700 {} @ 406.00 HKD
            Assets:Trade:Cash 40600.00 HKD
            Expenses:Trade:Commissions 100.00 HKD
            Assets:Trade:Cash -100.00 HKD
            Income:Trade:PnL

            No position matches "Posting(account='Assets:Trade:Positions', units=-100 HK_00700, cost=CostSpec(number_per=, number_total=None, currency='HKD', date=None, label=None, merge=False), price=406.00 HKD, flag=None, meta={'filename: '/bean/main.bean', 'lineno: 81})" against balance (100 HK_00700, 2000 HK_03933,

            您好!麻烦问下,今天我记录一条卖出之前初始化持仓,fava提示有错误?意思没有持仓。如果是这样,就没有录入之前持仓的必要了?是不是我写错了?

            1. 初始化也需要有日期,并且初始化的日期必须在卖出日期之前,同一天貌似也不行。

              1. 阿华 阿华

                谢谢啊!目前没有问题。我把现金,仓位,收入,支出都按您说的分类。再次谢谢您耐心回答。有问题再打扰您🙏

              2. 这个option好像不影响账户,是一些统计逻辑和前端展示逻辑,账户的币种要单独设置。

              3. 阿华 阿华

                option "title" "证券投资" ;账本名称
                option "operating_currency" "CNY" ;账本主货币
                option "operating_currency" "HKD" ;

              4. 如报错,你在定义账户的时候,这些账户是不是指定CNY币种了,不支持HKD。如下设置多个币种就可以了。

                2019-06-30 open Assets:Liquid:Bank:CMBHK8707 HKD,USD,CNY

                个人建议把美股、港股、A股的CASH账户分开,分别对应一个币种,币种可以约束记账不出错。比如我是这样的:
                2019-06-30 open Assets:Broker:FutuUS:Cash USD
                2019-06-30 open Assets:Broker:FutuHK:Cash HKD
                2019-06-30 open Assets:Broker:Pingan:Cash CNY

              5. 阿华 阿华

                69 Invalid currency HKD for account 'Assets:Trade:Cash'
                69 Invalid currency HKD for account 'Expenses:Trade:Commissions'
                69 Invalid currency HKD for account 'Assets:Trade:Cash'
                69 Invalid currency HKD for account 'Income:Trade:PnL'

                69 2023-01-30 * "卖出腾讯控股"
                70 Assets:Trade:Positions -100 HK_00700 {} @
                406.00 HKD
                71 Assets:Trade:Cash 40600.00 HKD
                72 Expenses:Trade:Commissions 100.00 HKD
                73 Assets:Trade:Cash -100.00 HKD
                74 Income:Trade:PnL

                哥又出错😓

              6. 不用,写在一起可以的。
                像下面这样呢,初始化时在后面以 {} 格式追加成本价(用持仓成本),这样才能计算利润,否则你的 Income:Trade:PnL 这个账户是算不出来的。

                2019-06-30 * "初始化" "富途证券账户持仓"
                Equity:OpenBalance
                Assets:Broker:FutuHK:Positions 1.00 HK_00772 {36.80 HKD}
                Assets:Broker:FutuUS:Positions 1.00 US_BABA {169.45 USD}
                Assets:Broker:FutuUS:Positions 1.00 US_PDD {20.63 USD}

              7. 阿华 阿华

                ;2、账户初始化
                2023-01-01 * "初始账户"
                Assets:Trade:Cash 0.00 CNY
                Equity:OpenBalances 0.00 CNY
                Assets:Trade:Positions 1000 SH_601225
                Equity:OpenBalances -1000 SH_601225
                Assets:Trade:Positions 6900 SZ_002233
                Equity:OpenBalances -6900 SZ_002233
                Assets:Trade:Positions 8100 SH_600123
                Equity:OpenBalances -8100 SH_600123

                有的。日期没贴出来。不会每一项初始化都写日期吧

          2. 阿华 阿华

            非常感谢!👍 新年快乐!

  2. GreenHat HG GreenHat HG

    请问下有了每个交易日的price,能在fava看到收益曲线吗

    1. 可以,曲线右上角有个价格选项,不要用成本,用实际价格。
      调整后,曲线就是根据每天价格计算出来的资产曲线(换算收益率暂时应该没办法)

      1. GreenHat HG GreenHat HG

        请问是资产那一列吗,我点进去资产是一条直线

        1. 对,左侧选资产负责表(也可以点击具体某个投资账户),图表的右上方有个菜单,默认是「按成本」,改为「按市价」。
          应该是分段带梯度的直线吧,感觉这个是fava的bug,不过,还是能看趋势。

          1. Simon Simon

            只能看持仓资产的成本折线图(按成本)和持仓总额折线图(按市价)。
            持仓浮动收益应该是这两者的差值,这个没有。😭

            1. 感觉可以去github上提个feature request,看项目迭代,还挺频繁的。
              github项目地址:https://github.com/beancount/fava

  3. 小王 小王

    请问下基金该怎么记录

    1. 和股票一样,基金有净值和成交份额,相当于股价和买卖数量。

添加新评论