On comparing rates of return

All timestamps are based on your local time of:

Posted by: stak
Posted on: 2020-08-30 21:28:22

Something that has bugged me for a while is how brokerages never seem to provide an annualized rate of return for stocks/portfolios. They tell you things like the book value, market value, and closed profit/loss, but computing a rate of return from that totally discounts the time factor and incremental/partial investments, and gives you a rate of return that is not meaningfully comparable across different stocks or portfolios.

I've written my own financial tracking software (this should come as a surprise to no-one who knows me) and I figured I should build this in. It turned out to be a somewhat interesting problem to come up with something reasonable, so I thought it would be worth describing.

First we have to figure out what kind of rate of return can be meaningfully compared across different investment portfolios. Consider an easy scenario:

t=0: Buy $100 of stock A
t=1 year: Sell stock A for $110

What should be the rate of return here? The obvious answer is 10% because we sold for 10% more than we bought. But compare against this:

t=0: Buy $100 of stock B
t=1 year: Sell half of stock B for $55
t=2 years: Sell remaining stock B for $60

We can think of this as two sub-stocks, B1 and B2:

t=0: Buy $50 of B1, $50 of B2
t=1 year: Sell B1 for $55
t=2 years: Sell B2 for $60

If we want to be consistent with our calculation for stock A, then B1 got a rate of return of 10%, and B2 got 20% but over 2 years. You could treat that as equivalent to 10% per year, but... if B1 was worth $55 at t=1 year, then so was B2. Which means B2 went up from $55 to $60 over the second year, which is less than 10% per year. So that seems like a contradiction.

With a bit of thought it seemed to me that what we really want here is a "continuous compounding" rate of return rather than a "yearly compounding" (or "no compounding") rate of return. The continuous compounding formula is:

Pt = P0 * er * t, where P0 is the initial investment, r is the rate of return and t is the time.

So let's look at B1 and B2 again:

Formula for B1: 55 = 50 * er * 1 which produces r as 9.53%.
Formula for B2: 60 = 50 * er * 2 which produces r as 9.12%.

This makes sense since we know B did worse in the second year than it did in the first year, so B2's rate over 2 years should be lower than B1's rate over the first year. (Note that with this formula we also get 9.53% for stock A above, which seems consistent.)

What about combining B1 and B2 back into a single rate of return for B? They're over different time periods so just taking the arithmetic mean doesn't seem right. I realized instead that we can think of the investments as putting money into and taking money out of an imaginary savings account with continuous compounding. That's similar to the stock market (or other investment vehicles) with the difference that the stock market fluctuates a lot and the instantaneous value at any given time is pretty meaningless, so we want to avoid using that anywhere in our calculations. We want to get away with just using the cash flows in and out of the investment.

So to compute the return for B, we could do something like this:

(((100 * er * 1) - 55) * er * 1) - 60 = 0

This says the $100 grew at continuously-compounded rate r for one year, at which point we removed $55 and let the rest grow for another year at the same r, and then removed $60 and ended up with $0 left. And here solving for r gives us 9.25% which seems like a reasonable number given our values for B1 and B2 above.

This solution can be extended for all sorts of complex scenarios spanning different time periods and with many cash flows in and out. I don't know if there's a closed-form solution to this but I ended up writing some code that did a binary search to converge on r.

Another interesting factor to consider is related transactions that don't actually affect the "stored value" in the investment. This includes things like dividend payouts (excluding reinvested dividends) or transaction commissions taken by the broker. I wasn't quite sure how to fit these in, but eventually decided that they should just be treated as non-compounding. So, for example, if we have this scenario:

t=0: Buy $100 of stock C
t=1 year: Receive $10 dividend from C
t=2 years: Sell all of C for $130

We'd use this formula:

(100 * er * 2) - 130 = 10

The left side is what we'd normally put in for the buy/sell transactions, but the right side is the net result of all the related transactions (in this case, a $10 dividend payout). In this case, it gives us a 16.82% rate of return, versus a 13.12% return without the dividend. So again, seems reasonable since the net value at the end is $40, versus $30 without the dividend.

Accounting for dividends this way makes it so that the time at which we receive the dividend doesn't make a difference to the overall rate of return - we could receive the dividend right at the beginning, or even after we sell the stock, and our rate of return will be the same. I considered the argument that dividends that arrive sooner are better, because we have access to the money earlier. Upon further reflection, I think that's only true if we actually invest that money in something. If that something is part of the portfolio we're evaluating, that dividend is effectively a reinvested dividend and shouldn't get counted as a dividend at all. And if that something is outside the portfolio we're evaluating, then it should get counted towards that other portfolio. I'm not totally sold on this bit yet but even with this caveat the overall approach seems to work well enough.

Posted by botond at 2021-03-28 17:48:10
Thanks, this is pretty useful!

One question: why not treat receiving a $10 dividend at t=1 year the same as selling $10 worth of stock at t=1 year?
[ Reply to this ]
Posted by stak at 2021-04-10 05:49:22
If I did that then then the dividend value would be assumed to get compounded over time, which I don't think is desirable because the $10 remains $10.
Allowed expansions in comments/replies: [i]italic[/i], [u]underline[/u], [b]bold[/b], [code]code[/code], [sub]subscript[/sub], [sup]superscript[/sup], [url=http://some.url]linked text[/url]
Human verification: Sum of twenty-three and thirty-one =

[ Add a new comment ]

(c) Kartikaya Gupta, 2004-2024. User comments owned by their respective posters. All rights reserved.
You are accessing this website via IPv4. Consider upgrading to IPv6!