beancount股票实践教程
我从去年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 ;手续费
直观上也能看到HKD
与HK_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,日常账不涉及。
您好:请教 如果现在 beancount 开始记.之前的持仓怎么操作?好像股票名称不支持中文.
1、对股票账户进行初始化设置即可,初始化方法见另一篇文章 https://www.skyue.com/19101819.html
2、没试过中文,我用的股票代码。代码更稳定,A股和港股公司可能改股票名,但代码不会变。
【二、账户设置】
;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再一笔写交易记录 如上面。望指教!
比如持仓万科1000股,代码是SZ000002。这样写:
Assets:Trade:Stock 1000 SZ000002
equity:OpenBalance -1000 SZ000002
其实,就是把SZ000002当CNY看待。货币是一种资产,股票本质也是一种资产。
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提示有错误?意思没有持仓。如果是这样,就没有录入之前持仓的必要了?是不是我写错了?
初始化也需要有日期,并且初始化的日期必须在卖出日期之前,同一天貌似也不行。
谢谢啊!目前没有问题。我把现金,仓位,收入,支出都按您说的分类。再次谢谢您耐心回答。有问题再打扰您🙏
这个option好像不影响账户,是一些统计逻辑和前端展示逻辑,账户的币种要单独设置。
option "title" "证券投资" ;账本名称
option "operating_currency" "CNY" ;账本主货币
option "operating_currency" "HKD" ;
如报错,你在定义账户的时候,这些账户是不是指定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
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
哥又出错😓
不用,写在一起可以的。
像下面这样呢,初始化时在后面以 {} 格式追加成本价(用持仓成本),这样才能计算利润,否则你的 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}
;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
有的。日期没贴出来。不会每一项初始化都写日期吧
非常感谢!👍 新年快乐!
请问下有了每个交易日的price,能在fava看到收益曲线吗
可以,曲线右上角有个价格选项,不要用成本,用实际价格。
调整后,曲线就是根据每天价格计算出来的资产曲线(换算收益率暂时应该没办法)
请问是资产那一列吗,我点进去资产是一条直线
对,左侧选资产负责表(也可以点击具体某个投资账户),图表的右上方有个菜单,默认是「按成本」,改为「按市价」。
应该是分段带梯度的直线吧,感觉这个是fava的bug,不过,还是能看趋势。
只能看持仓资产的成本折线图(按成本)和持仓总额折线图(按市价)。
持仓浮动收益应该是这两者的差值,这个没有。😭
感觉可以去github上提个feature request,看项目迭代,还挺频繁的。
github项目地址:https://github.com/beancount/fava
请问下基金该怎么记录
和股票一样,基金有净值和成交份额,相当于股价和买卖数量。