roi: cmdline help simplified

This commit is contained in:
Dmitry Astapov 2021-02-23 22:55:18 +00:00 committed by Simon Michael
parent 150cf3f862
commit 582a1651b3

View File

@ -4,23 +4,22 @@ on your investments.
_FLAGS _FLAGS
This command assumes that you have account(s) that hold nothing but
your investments and whenever you record current appraisal/valuation
of these investments you offset unrealized profit and loss into
account(s) that, again, hold nothing but unrealized profit and loss.
Any transactions affecting balance of investment account(s) and not
originating from unrealized profit and loss account(s) are assumed to
be your investments or withdrawals.
At a minimum, you need to supply a query (which could be just an At a minimum, you need to supply a query (which could be just an
account name) to select your investments with `--inv`, and another account name) to select your investment(s) with `--inv`, and another
query to identify your profit and loss transactions with `--pnl`. query to identify your profit and loss transactions with `--pnl`.
This command will compute and display the internalized rate of return (IRR) and If you do not record changes in the value of your investment manually,
time-weighted rate of return (TWR) for your investments for the time or do not require computation of time-weighted return (TWR), `--pnl`
period requested. Both rates of return are annualized before display, could be an empty query (`--pnl ""` or `--pnl STR` where `STR` does
regardless of the length of reporting interval. not match any of your accounts).
This command will compute and display the internalized rate of return
(IRR) and time-weighted rate of return (TWR) for your investments for
the time period requested. Both rates of return are annualized before
display, regardless of the length of reporting interval.
Price directives will be taken into account if you supply appropriate
`--cost` or `--value` flags (see [VALUATION](https://hledger.org/hledger.html#valuation)).
Note, in some cases this report can fail, for these reasons: Note, in some cases this report can fail, for these reasons:
@ -31,10 +30,71 @@ Note, in some cases this report can fail, for these reasons:
Examples: Examples:
- Using roi to report unrealised gains: - Using roi to compute total return of investment in stocks:
https://github.com/simonmichael/hledger/blob/master/examples/roi-unrealised.ledger https://github.com/simonmichael/hledger/blob/master/examples/roi-unrealised.ledger
More background: - Cookbook -> [Return on Investment](return-on-investment.html)
### Semantics of `--inv` and `--pnl`
Query supplied to `--inv` has to match all transactions that are
related to your investment. Transactions not matching `--inv` will be
ignored.
In these transactions, ROI will conside postings that match `--inv` to
be "investment postings" and other postings (not matching `--inv`)
will be sorted into two categories: "cash flow" and "profit and loss",
as ROI needs to know which part of the investment value is your
contributions and which is due to the return on investment.
- "Cash flow" is depositing or withdrawing money, buying or selling
assets, or otherwise converting between your investment commodity and
any other commodity. Example:
```
2019-01-01 Investing in Snake Oil
assets:cash -$100
investment:snake oil
2020-01-01 Selling my Snake Oil
assets:cash $10
investment:snake oil = 0
```
- "Profit and loss" is change in the value of your investment:
```
2019-06-01 Snake Oil falls in value
investment:snake oil = $57
equity:unrealized profit or loss
```
All non-investment postings are assumed to be "cash flow", unless they
match `--pnl` query. Changes in value of your investment due to
"profit and loss" postings will be considered as part of your
investment return.
Example: if you use `--inv snake --pnl equity:unrealized`, then
postings in the example below would be classifed as:
```
2019-01-01 Snake Oil #1
assets:cash -$100 ; cash flow posting
investment:snake oil ; investment posting
2019-03-01 Snake Oil #2
equity:unrealized pnl -$100 ; profit and loss posting
snake oil ; investment posting
2019-07-01 Snake Oil #3
equity:unrealized pnl ; profit and loss posting
cash -$100 ; cash flow posting
snake oil $50 ; investment posting
```
### IRR and TWR explained
"ROI" stands for "return on investment". Traditionally this was "ROI" stands for "return on investment". Traditionally this was
computed as a difference between current value of investment and its computed as a difference between current value of investment and its
@ -54,36 +114,35 @@ percentage of your initial investment, and if you are adding to your
investment, you will receive bigger absolute gains (but probably at investment, you will receive bigger absolute gains (but probably at
the same rate of return). IRR is a way to compute rate of return for the same rate of return). IRR is a way to compute rate of return for
each period between in-flow or out-flow of money, and then combine each period between in-flow or out-flow of money, and then combine
them in a way that gives you an annual rate of return that investment them in a way that gives you a compound annual rate of return that investment
is expected to generate. is expected to generate.
As mentioned before, in-flows and out-flows would be any cash that you As mentioned before, in-flows and out-flows would be any cash that you
personally put in or withdraw, and for the "roi" command, these are personally put in or withdraw, and for the "roi" command, these are
transactions that involve account(s) matching `--inv` argument and NOT the postings that match the query in the`--inv` argument and NOT
involve account(s) matching `--pnl` argument. match the query in the`--pnl` argument.
Presumably, you will also record changes in the value of your If you manually record changes in the value of your investment as
investment, and balance them against "profit and loss" (or "unrealized transactions that balance them against "profit and loss" (or
gains") account. Note that in order for IRR to compute the precise "unrealized gains") account or use price directives, then in order for
effect of your in-flows and out-flows on the rate of return, you will IRR to compute the precise effect of your in-flows and out-flows on
need to record the value of your investement on or close to the days the rate of return, you will need to record the value of your
when in- or out-flows occur. investement on or close to the days when in- or out-flows occur.
Implementation of IRR in hledger should match the `XIRR` formula in
Excel.
Second way to compute rate of return that `roi` command implements is
called "time-weighted rate of return" or "TWR". Like IRR, it will also
break the history of your investment into periods between in-flows and
out-flows to compute rate of return per each period and then a
compound rate of return. However, internal workings of TWR are quite
different.
In technical terms, IRR uses the same approach as computation of net In technical terms, IRR uses the same approach as computation of net
present value, and tries to find a discount rate that makes net present value, and tries to find a discount rate that makes net
present value of all the cash flows of your investment to add up to present value of all the cash flows of your investment to add up to
zero. This could be hard to wrap your head around, especially if you haven't zero. This could be hard to wrap your head around, especially if you
done discounted cash flow analysis before. haven't done discounted cash flow analysis before. Implementation of
IRR in hledger should produce results that match the `XIRR` formula in
Excel.
Second way to compute rate of return that `roi` command implements is
called "time-weighted rate of return" or "TWR". Like IRR, it will also
break the history of your investment into periods between in-flows,
out-flows and value changes, to compute rate of return per each period
and then a compound rate of return. However, internal workings of TWR
are quite different.
TWR represents your investment as an imaginary "unit fund" where in-flows/ TWR represents your investment as an imaginary "unit fund" where in-flows/
out-flows lead to buying or selling "units" of your investment and changes in out-flows lead to buying or selling "units" of your investment and changes in
@ -96,162 +155,3 @@ References:
* [Explanation of TWR](https://www.investopedia.com/terms/t/time-weightedror.asp) * [Explanation of TWR](https://www.investopedia.com/terms/t/time-weightedror.asp)
* [Examples of computing IRR and TWR and discussion of the limitations of both metrics](https://blog.commonwealth.com/measuring-portfolio-performance-twr-vs.-irr) * [Examples of computing IRR and TWR and discussion of the limitations of both metrics](https://blog.commonwealth.com/measuring-portfolio-performance-twr-vs.-irr)
More examples:
Lets say that we found an investment in Snake Oil that is proising to give us 10% annually:
```hledger
2019-01-01 Investing in Snake Oil
assets:cash -$100
investment:snake oil
2019-12-24 Recording the growth of Snake Oil
investment:snake oil = $110
equity:unrealized gains
```
For now, basic computation of the rate of return, as well as IRR and TWR, gives us the expected 10%:
```
$ hledger roi -Y --inv investment --pnl "unrealized"
+---++------------+------------++---------------+----------+-------------+-----++--------+--------+
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
+===++============+============++===============+==========+=============+=====++========+========+
| 1 || 2019-01-01 | 2019-12-31 || 0 | 100 | 110 | 10 || 10.00% | 10.00% |
+---++------------+------------++---------------+----------+-------------+-----++--------+--------+
```
However, lets say that shorty after investing in the Snake Oil we started to have second thoughs, so we prompty withdrew $90, leaving only $10 in.
Before Christmas, though, we started to get the "fear of mission out", so we put the $90 back in. So for most of the year, our investment was just $10 dollars,
and it gave us just $1 in growth:
```hledger
2019-01-01 Investing in Snake Oil
assets:cash -$100
investment:snake oil
2019-01-02 Buyers remorse
assets:cash $90
investment:snake oil
2019-12-30 Fear of missing out
assets:cash -$90
investment:snake oil
2019-12-31 Recording the growth of Snake Oil
investment:snake oil = $101
equity:unrealized gains
```
Now IRR and TWR are drastically different:
```
$ hledger roi -Y --inv investment --pnl "unrealized"
+---++------------+------------++---------------+----------+-------------+-----++-------+-------+
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
+===++============+============++===============+==========+=============+=====++=======+=======+
| 1 || 2019-01-01 | 2019-12-31 || 0 | 100 | 101 | 1 || 9.32% | 1.00% |
+---++------------+------------++---------------+----------+-------------+-----++-------+-------+
```
Here, IRR tells us that we made close to 10% on the $10 dollars that
we had in the account most of the time. And TWR is ... just 1%? Why?
Based on the transactions in our journal, TWR "think" that we are buying back $90 worst of Snake Oil
at the same price that it had at the beginning of they year, and then after that our $100 investment
gets $1 increase in value, or 1% of $100. Let's take a closer look at what is happening here by
asking for quarterly reports instead of annual:
```
$ hledger roi -Q --inv investment --pnl "unrealized"
+---++------------+------------++---------------+----------+-------------+-----++--------+-------+
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
+===++============+============++===============+==========+=============+=====++========+=======+
| 1 || 2019-01-01 | 2019-03-31 || 0 | 10 | 10 | 0 || 0.00% | 0.00% |
| 2 || 2019-04-01 | 2019-06-30 || 10 | 0 | 10 | 0 || 0.00% | 0.00% |
| 3 || 2019-07-01 | 2019-09-30 || 10 | 0 | 10 | 0 || 0.00% | 0.00% |
| 4 || 2019-10-01 | 2019-12-31 || 10 | 90 | 101 | 1 || 37.80% | 4.03% |
+---++------------+------------++---------------+----------+-------------+-----++--------+-------+
```
Now both IRR and TWR are thrown off by the fact that all of the growth for our investment happens in
Q4 2019. This happes because IRR computation is still yielding 9.32% and TWR is still 1%, but
this time these are rates for three month period instead of twelve, so in order to get an annual rate
they should be multiplied by four!
Let's try to keep a better record of how Snake Oil grew in value:
```hledger
2019-01-01 Investing in Snake Oil
assets:cash -$100
investment:snake oil
2019-01-02 Buyers remorse
assets:cash $90
investment:snake oil
2019-02-28 Recording the growth of Snake Oil
investment:snake oil
equity:unrealized gains -$0.25
2019-06-30 Recording the growth of Snake Oil
investment:snake oil
equity:unrealized gains -$0.25
2019-09-30 Recording the growth of Snake Oil
investment:snake oil
equity:unrealized gains -$0.25
2019-12-30 Fear of missing out
assets:cash -$90
investment:snake oil
2019-12-31 Recording the growth of Snake Oil
investment:snake oil
equity:unrealized gains -$0.25
```
Would our quartery report look better now? Almost:
```
$ hledger roi -Q --inv investment --pnl "unrealized"
+---++------------+------------++---------------+----------+-------------+------++--------+--------+
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
+===++============+============++===============+==========+=============+======++========+========+
| 1 || 2019-01-01 | 2019-03-31 || 0 | 10 | 10.25 | 0.25 || 9.53% | 10.53% |
| 2 || 2019-04-01 | 2019-06-30 || 10.25 | 0 | 10.50 | 0.25 || 10.15% | 10.15% |
| 3 || 2019-07-01 | 2019-09-30 || 10.50 | 0 | 10.75 | 0.25 || 9.79% | 9.78% |
| 4 || 2019-10-01 | 2019-12-31 || 10.75 | 90 | 101.00 | 0.25 || 8.05% | 1.00% |
+---++------------+------------++---------------+----------+-------------+------++--------+--------+
```
Something is still wrong with TWR computation for Q4, and if you have been paying attention you know
what it is already: big $90 buy-back is recorded prior to the only transaction that captures the
change of value of Snake Oil that happened in this time period. Lets combine transactions from 30th
and 31st of Dec into one:
```hledger
2019-12-30 Fear of missing out and growth of Snake Oil
assets:cash -$90
investment:snake oil
equity:unrealized gains -$0.25
```
Now growth of investment properly affects its price at the time of buy-back:
```
$ hledger roi -Q --inv investment --pnl "unrealized"
+---++------------+------------++---------------+----------+-------------+------++--------+--------+
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
+===++============+============++===============+==========+=============+======++========+========+
| 1 || 2019-01-01 | 2019-03-31 || 0 | 10 | 10.25 | 0.25 || 9.53% | 10.53% |
| 2 || 2019-04-01 | 2019-06-30 || 10.25 | 0 | 10.50 | 0.25 || 10.15% | 10.15% |
| 3 || 2019-07-01 | 2019-09-30 || 10.50 | 0 | 10.75 | 0.25 || 9.79% | 9.78% |
| 4 || 2019-10-01 | 2019-12-31 || 10.75 | 90 | 101.00 | 0.25 || 8.05% | 9.57% |
+---++------------+------------++---------------+----------+-------------+------++--------+--------+
```
And for annual report, TWR now reports the exact profitability of our investment:
```
$ hledger roi -Y --inv investment --pnl "unrealized"
+---++------------+------------++---------------+----------+-------------+------++-------+--------+
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
+===++============+============++===============+==========+=============+======++=======+========+
| 1 || 2019-01-01 | 2019-12-31 || 0 | 100 | 101.00 | 1.00 || 9.32% | 10.00% |
+---++------------+------------++---------------+----------+-------------+------++-------+--------+
```