Portfolio returns calculator

168 views
Skip to first unread message

Justus Pendleton

unread,
Jan 18, 2019, 11:22:49 PM1/18/19
to Beancount
Here's my take at a script that will calculate the money-weighted return for a portfolio (i.e. the XIRR function in spreadsheets).

https://github.com/hoostus/portfolio-returns

All it does it output a single number -- the rate of return. The only real work this script does is crawl through beancount files and figure out what cashflows in & out of the account there were over the specified time period. Then it feeds those cashflows into an IRR calculation.

Here's the return over the past 1 year.

> python irr.py --account Assets:US:Vanguard:Roth --1year /Volumes/my_docs/beancount/my.beancount --internal Income:TaxFree:Dividends
0.72%

(Apparently not a fantastic year for my Roth IRA!)
Here's the return year-to-date.

> python irr.py --account Assets:US:Vanguard:Roth --ytd /Volumes/my_docs/beancount/my.beancount --internal Income:TaxFree:Dividends
115.86%

(All numbers are annualised, so even a tiny increase after 19 days results in a huge annual rate of return.)

It seems to work the way I expect on my own beancount file and a few other small test cases I put together. Feel free to email me or post here if you have problems, suggestions, etc.

Patrick Ruckstuhl

unread,
Jan 20, 2019, 11:16:14 AM1/20/19
to bean...@googlegroups.com

Hi,


That looks very interesting. I'm doing something similar right now.

Two things that I found necessary/helpful:

* I have one interest account and I just tie it to the security by adding an empty posting.

e.g.

2015-01-22 * "Dividend"
  Assets:Investment:CHCORP                           0 CHCORP
  Assets:Liquidity:CHF                                  20.00 CHF
  Income:Patrick:Interest                           -20.00 CHF


That way I can tie all the flows together for CHCORP



* Another thing is to make sure to prevent transactions between different investments in the same transaction as this confuses my logic, so I'm preventing this by


import collections

from beancount.core import getters
from beancount.core import data

__plugins__ = ['check']

MixedInvestAssets = collections.namedtuple('MixedInvestAssets', 'source message entry')

def check(entries, options_map):
    errors = []

    commodity_map = getters.get_commodity_map(entries, create_missing=True)
    commodity_type_map = getters.get_values_meta(commodity_map, 'type')

    for entry in data.filter_txns(entries):
        ccys = set()
        for posting in entry.postings:
            ccy = posting.units.currency
            if commodity_type_map[ccy] == 'invest':
                ccys.add(ccy)

        if len(ccys) > 1:
            errors.append(MixedInvestAssets(
                entry.meta,
                "Transaction with two or more different investment postings",
                entry
            ))

    return entries, errors


Regards,

Patrick

--
You received this message because you are subscribed to the Google Groups "Beancount" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beancount+...@googlegroups.com.
To post to this group, send email to bean...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beancount/bba922da-b960-480e-9e0c-9aececcf39b1%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Justus Pendleton

unread,
Jan 20, 2019, 8:53:32 PM1/20/19
to Beancount
On Sunday, January 20, 2019 at 11:16:14 PM UTC+7, Patrick Ruckstuhl wrote:

Two things that I found necessary/helpful:


Yeah, as I worked on this and thought about I realised it is pretty hard to make something that is totally universal because of issues like the ones you point out.

A posting can -- at least in theory, though in practice I think it is probably uncommon -- refer to multiple securities, which then makes attributing performance impossible without some way to disambiguate.

Similarly, income like interest/dividends isn't explicitly attributed to a security -- unless you go out of your way to make separate income accounts for each security, which feels a bit over-the-top. In my personal beancount files I set the payee to the name of the fund but you can't really rely on other people following that convention. I suppose you could use metadata.

Martin Blais

unread,
Feb 18, 2019, 10:23:51 PM2/18/19
to Beancount
On Sun, Jan 20, 2019 at 8:53 PM Justus Pendleton <just...@gmail.com> wrote:
On Sunday, January 20, 2019 at 11:16:14 PM UTC+7, Patrick Ruckstuhl wrote:

Two things that I found necessary/helpful:


Yeah, as I worked on this and thought about I realised it is pretty hard to make something that is totally universal because of issues like the ones you point out.

I gave this a shot in the past. I agree, not super obvious.
There are some related ideas at the top of this file, this might be sufficient:
 

A posting can -- at least in theory, though in practice I think it is probably uncommon -- refer to multiple securities, which then makes attributing performance impossible without some way to disambiguate.

You mean "a transaction."

 

Similarly, income like interest/dividends isn't explicitly attributed to a security -- unless you go out of your way to make separate income accounts for each security, which feels a bit over-the-top. In my personal beancount files I set the payee to the name of the fund but you can't really rely on other people following that convention. I suppose you could use metadata.

--
You received this message because you are subscribed to the Google Groups "Beancount" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beancount+...@googlegroups.com.
To post to this group, send email to bean...@googlegroups.com.

Alen Šiljak

unread,
Apr 21, 2019, 12:54:11 PM4/21/19
to Beancount
Why do you think it is over the top? Wouldn't that be the cleanest way to categorize the income?
The accounts are free.
In any case, this is a recommendation from GnuCash docs which I've been following and found it quite easy to track income per each security, and also to compare to the same security held at another broker.

Patrick Ruckstuhl

unread,
Apr 21, 2019, 1:27:47 PM4/21/19
to bean...@googlegroups.com

Hi,


another way (that I'm doing) is to link the interest/dividens to the security by a 0 amount transaction on the security, that way I can easily query them.


e.g.


2014-07-15 * "Dividend"
  Assets:Broker:FooStock           0 FooStock

  Assets:Broker:Liquidity               100 CHF

  Income:Interest                          -100 CHF


and then I can fetch out the interest for FooStock by a query like


  1. select
  2. sum(number) as amount
  3. from
  4. has_account("Assets:Broker:FooStock")
  5. where
  6. account="Income:Interest"


Regards,

Patrick

--
You received this message because you are subscribed to the Google Groups "Beancount" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beancount+...@googlegroups.com.
To post to this group, send email to bean...@googlegroups.com.

Alen Šiljak

unread,
Apr 21, 2019, 2:30:51 PM4/21/19
to Beancount
It is very interesting to see all the things available with this.
Note that I'm currently in the toe-dip phase with plain text accounting but I'm using an exported GnuCash book (through piecash) with all my real data.

Red S

unread,
May 20, 2019, 4:55:06 AM5/20/19
to Beancount
Nicely done. It's simple, works for all my use cases, and compares correctly to what I see at my institutions. Thank you for sharing this!

These are some of the things I'd love to see, and will start coding them up soon. Are you open to PRs?

- accounts specifiable via a regex (I use top-level hierarchy for taxable vs. tax advantaged accounts) (PR sent)
  - also allow as a beancount option
- automatically fetch prices for the commodities needed on the start and end dates, before computing rate of return
- pretty summary: (start, contribs, end) values
  - even better: generate visualizations (graphs), perhaps as a plugin to fava
- option to start/end at beginning and end month (as some institutions do)

Justus Pendleton

unread,
May 20, 2019, 9:53:58 AM5/20/19
to Beancount

On Monday, May 20, 2019 at 3:55:06 PM UTC+7, Red S wrote:
These are some of the things I'd love to see, and will start coding them up soon. Are you open to PRs?

Sure. I'll take a look at your PRs and leave any feedback I have there.

- option to start/end at beginning and end month (as some institutions do)

I thought I already did that. Maybe I only thought about it but didn't actually do it :)

Cheers,
Justus
 
Reply all
Reply to author
Forward
0 new messages