Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TWR aggregation looks wrong #2298

Open
TPolzer opened this issue Dec 10, 2024 · 14 comments · May be fixed by #2300
Open

TWR aggregation looks wrong #2298

TPolzer opened this issue Dec 10, 2024 · 14 comments · May be fixed by #2300
Labels
A-BUG Something wrong, confusing or sub-standard in the software, docs, or user experience. roi valuation

Comments

@TPolzer
Copy link

TPolzer commented Dec 10, 2024

I was trying to plot cumulative TWR values from hledger over time (side note: is there a machine readable version of roi?), but couldn't make sense of the numbers. In the end I've come to the conclusion that something isn't right.

Here's an example ledger that demonstrates the problem:

D 1,000.00 EUR 

2018-07-01 investment
        assets:bank
        investments:iShares Core MSCI World     1 "IE00B4L5Y983"

P 2018-12-28 "IE00B4L5Y983" 43.11000000 "EUR"
P 2019-06-28 "IE00B4L5Y983" 50.93000000 "EUR"

2019-07-01 investment
        assets:bank    
        investments:iShares Core MSCI World     10 "IE00B4L5Y983"

P 2019-12-30 "IE00B4L5Y983" 56.59000000 "EUR"

Following https://hledger.org/roi.html#using-commodities-and-prices I get this report:

$ hledger roi --value then --begin 2019 --end 2020 --inv investmen --pnl '"profit and loss"' -p 'every 2 quarters'
+-------++------------+------------++---------------+------------+-------------+-----------++--------++------------+----------+
|       ||      Begin |        End || Value (begin) |   Cashflow | Value (end) |       PnL ||    IRR || TWR/period | TWR/year |
+=======++============+============++===============+============+=============+===========++========++============+==========+
|     1 || 2019-01-01 | 2019-06-30 ||     43.11 EUR |          0 |   50.93 EUR |  7.82 EUR || 39.96% ||     18.14% |   39.96% |
|     2 || 2019-07-01 | 2019-12-31 ||     50.93 EUR | 509.30 EUR |  622.49 EUR | 62.26 EUR || 23.25% ||     11.11% |   23.24% |
+-------++------------+------------++---------------+------------+-------------+-----------++--------++------------+----------+
| Total || 2019-01-01 | 2019-12-31 ||     43.11 EUR | 509.30 EUR |  622.49 EUR | 70.08 EUR || 24.51% ||     12.69% |   12.69% |
+-------++------------+------------++---------------+------------+-------------+-----------++--------++------------+----------+

My hand calculations for TWR would be:

  • 2019-01-01 to 2019-06-30: no cashflow, price moved from 43.11 to 50.93 => 18.14% TWR/period
  • 2019-07-01 to 2019-12-31: cashflow immediately at the begin, afterwards appreciation from 50.93 to 56.59 => 11.11% TWR/period
  • Total TWR over the year should simply be the appreciation of IE00B4L5Y983 over the period (since the portfolio composition didn't change, only the size did): 56.59/43.11 => 31.27%. That doesn't match what the Total row of the report says.
  • Using hledger roi -Y is consistent with the Total above, not with the expected TWR.
@adept
Copy link
Collaborator

adept commented Dec 11, 2024

To give you a quick feedback: thank you for your report, this is a bug, I see where it is, expect a fix soon.
(TWR incorrectly updates internal unit price)

@adept
Copy link
Collaborator

adept commented Dec 11, 2024

Should be fixed by #2300

adept added a commit to adept/hledger that referenced this issue Dec 11, 2024
@TPolzer
Copy link
Author

TPolzer commented Dec 11, 2024

Thank you for the quick reaction and fix! I can confirm that the numbers with #2300 look much better.

Unfortunately the proposed fix also makes my yearly ROI report 7-8x slower. That's better than wrong data, but somewhat painful.

@simonmichael simonmichael added A-BUG Something wrong, confusing or sub-standard in the software, docs, or user experience. roi valuation labels Dec 12, 2024
@adept
Copy link
Collaborator

adept commented Dec 12, 2024

Unfortunately the proposed fix also makes my yearly ROI report 7-8x slower

I do see slowdown, but not as drastic as you.

Trying my dataset:

v1.32.99 :  13.5-14s
v1.40 : 14-14.5s
v1.41.99 (current HEAD) : 15s
v1.41.99+#2300 : 25s

This is ... weird. I'll try and see why it is so slow, change certainly does not look like something that should have a pronounced effect

@adept
Copy link
Collaborator

adept commented Dec 12, 2024

@TPolzer i've pushed something into #2300 that should hopefully lead to more sharing of intermediate results and recover some of the lost performance. Can you please see how this behaves for you?

For me this brings runtimes back to v1.40 levels

@TPolzer
Copy link
Author

TPolzer commented Dec 12, 2024

Tried it just now, I don't see a significant change in performance, it's still pretty slow.

Trying with a subset of my roi query and some debug output:
old:

$ time hledger roi [...] --value then,CHF --begin 2018 --end tomorrow -Y --debug=2 |& grep seeking | sort | uniq -c
     15 seeking EUR to CHF price using forward prices
      9 seeking IE00B4L5Y983 to CHF price using forward prices
[...]

real	0m0.760s
user	0m0.731s
sys	0m0.035s

vs. new:

$ time hledger roi [...] --value then,CHF --begin 2018 --end tomorrow -Y --debug=2 |& grep seeking | sort | uniq -c
     15 seeking EUR to CHF price using forward prices
   2154 seeking IE00B4L5Y983 to CHF price using forward prices
[...]

real	0m15.982s
user	0m15.246s
sys	0m0.863s

The 15 EUR lookups are cashflow (in EUR) transactions I think, and they're the same. It should need the "IE00B4L5Y983 to CHF" chain only at period boundaries and cashflow events, too?

@adept
Copy link
Collaborator

adept commented Dec 12, 2024

and ond dates you have P directives too (which was not happening earlier)

@TPolzer
Copy link
Author

TPolzer commented Dec 12, 2024

Yeah... that explains the dramatic difference in runtime, since I have a large automatically created list of prices.

But that's not actually necessary, is it? To compute TWR it's sufficient to compute prices at period boundaries and cashflow events. E.g. in the initial example on this bug, inserting a lot of fine grained P directives would not change the result at all.

@adept
Copy link
Collaborator

adept commented Dec 12, 2024

Just to double-check, in the example above is "old" a v1.40, or v1.41.99 without #2300?

@TPolzer
Copy link
Author

TPolzer commented Dec 12, 2024

"old" is actually 1.32.3 from Debian.

@simonmichael
Copy link
Owner

How many P directives have you @TPolzer ? I'm thinking we might need to mention that in general docs.

@TPolzer
Copy link
Author

TPolzer commented Dec 12, 2024

I'm storing daily FX rates for three currencies and weekly rates for a handful of investments. I should probably reduce the latter to monthly rates. My current auto generated price list has ~21k entries.

I understand that general parsing etc scales linearly, but I was under the impression (so far I think correctly) that most analysis cost should be unaffected by the number of P statements.

@simonmichael
Copy link
Owner

It's good to know the number. If you're seeing no slowdowns in most features, with 20k prices, that's good - perhaps it's something suboptimal in roi then.

@adept
Copy link
Collaborator

adept commented Dec 13, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-BUG Something wrong, confusing or sub-standard in the software, docs, or user experience. roi valuation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants