Tracking asset allocation across different asset classes

124 views
Skip to first unread message

Nea Zăpadă

unread,
Jan 15, 2022, 11:52:42 AM1/15/22
to hledger
Hi,

I'm in the process of moving from ledger-cli and miss the asset allocation feature described at: https://www.ledger-cli.org/3.0/doc/ledger3.html#Asset-Allocation . I'd like to be able to see what percentage of e.g. Bonds I have across my different investment accounts and regardless of the actual fund that is invested in bonds.

Ideally I'd also be able to see when a fund has a specific percentage of Bonds. From ledger-cli's example:

= expr ( commodity == 'VTHRX' )
(Allocation:Equities:Global) 0.240
(Allocation:Equities:Domestic) 0.563
(Allocation:Bonds/Cash) 0.197

Is this functionality supported or are there any workarounds to get something like that working with hledger?

Thanks,
Nea

Simon Michael

unread,
Jan 15, 2022, 11:59:40 AM1/15/22
to hle...@googlegroups.com
Welcome. The doc seems rather complicated.. is this something different from seeing the portfolio balance with a combination of subaccounts, -% and -B or -V ?

Nea Zăpadă

unread,
Jan 15, 2022, 1:11:17 PM1/15/22
to hledger
Hi,

Yes. It's different than having subaccounts. I think in effect it's seeing two views of the same accounts. The initial accounts still exist, but you can view them in a different way.

I'll try to explain the ledger-cli example in a different way.

Starting with this ledger file:

= expr ( commodity == 'VIFSX' )
    (Allocation:Equities:Domestic)             1.000


= expr ( commodity == 'VTHRX' )
    (Allocation:Equities:Global)               0.240
    (Allocation:Equities:Domestic)             0.563
    (Allocation:Bonds/Cash)                    0.197

= expr ( commodity == 'VBMFX')
    (Allocation:Bonds/Cash)                    1.000

2015-01-01 Buy VIFSX
    Assets:Broker:VIFSX                          100 VIFSX
    Assets:Cash                              $-10000

2015-01-01 Buy VTHRX
    Assets:Broker:VTHRX                           10 VTHRX
    Assets:Cash                              $-10000

2015-01-01 Buy VBMFX
    Assets:Broker:VBMFX                            1 VBMFX
    Assets:Cash                              $-10000

You can then get both the value in subaccounts:

$ ledger -f my.ledger bal -V Assets
                   0  Assets
              $30000    Broker
              $10000      VBMFX
              $10000      VIFSX
              $10000      VTHRX
             $-30000    Cash
--------------------
                   0

And the asset allocation (this is the important bit):

$ ledger -f my.ledger bal -V Allocation
              $30000  Allocation
              $11970    Bonds/Cash
              $18030    Equities
              $15630      Domestic
               $2400      Global
--------------------
              $30000

Once we have that second view above, we can then do some nice formatting:

ledger -f my.ledger bal Allocation --current --format "\
        %-17((depth_spacer)+(partial_account))\
        %10(percent(market(display_total), market(parent.total)))\
        %16(market(display_total))\n%/"
        Allocation                  100.00%                  $30000
          Bonds/Cash                 39.90%                  $11970
          Equities                   60.10%                  $18030
            Domestic                 86.69%                  $15630
            Global                   13.31%                   $2400


Hope that makes more sense.

I dug around a bit more since my first email. From what I can see, the closest functionality that hledger has is using `rewrite` with virtual postings, but this only works at the account level, not at the commodity level:

$ cat my.journal
2015-01-01 Buy VIFSX
    Assets:Broker:VIFSX                          100 VIFSX
    Assets:Cash                              $-10000

2015-01-01 Buy VTHRX
    Assets:Broker:VTHRX                           10 VTHRX
    Assets:Cash                              $-10000

2015-01-01 Buy VBMFX
    Assets:Broker:VBMFX                            1 VBMFX
    Assets:Cash                              $-10000

$ cat rewrite.journal
= Assets:Broker:VIFSX
    (allocation:equities:domestic)  *1

= Assets:Broker:VTHRX
    (allocation:equities:global)  *0.240
    (allocation:equities:domestic)  *0.563
    (allocation:bonds/cash)         *0.197

= Assets:Broker:VBMFX
    (allocation:bonds/cash)  *1

$ hledger rewrite -f my.journal -f rewrite.journal > ~/allocation.journal
$ hledger -f ~/allocation.journal bal
             1 VBMFX  Assets:Broker:VBMFX
           100 VIFSX  Assets:Broker:VIFSX
         10.00 VTHRX  Assets:Broker:VTHRX
             $-30000  Assets:Cash
             1 VBMFX
          1.97 VTHRX  allocation:bonds/cash
           100 VIFSX
          5.63 VTHRX  allocation:equities:domestic
          2.40 VTHRX  allocation:equities:global
--------------------
             $-30000
             2 VBMFX
           200 VIFSX
         20.00 VTHRX 

$ hledger -f ~/allocation.journal bal allocation --cost -%
              39.9 %  allocation:bonds/cash
              52.1 %  allocation:equities:domestic
               8.0 %  allocation:equities:global
--------------------
             100.0 % 


So I guess the question I have now is: how can I apply the rewrite rule to a commodity instead of an account?

Thanks,
Nea

Simon Michael

unread,
Jan 16, 2022, 12:58:21 PM1/16/22
to hledger
Ah I get you, thanks. Individual investment commodities have their own published allocation splits, and while you could model that with subaccounts, it would be a pain. So you use auto postings to generate a parallel set of virtual accounts showing the allocation. Neat.

You can do it the same way in hledger. Here's the translation:


= cur:VIFSX
    (Allocation:Equities:Domestic)             *1.000

= cur:VTHRX
    (Allocation:Equities:Global)               *0.240
    (Allocation:Equities:Domestic)             *0.563
    (Allocation:Bonds/Cash)                    *0.197

= cur:VBMFX
    (Allocation:Bonds/Cash)                    *1.000

2015-01-01 Buy VIFSX
    Assets:Broker:VIFSX                          100 VIFSX
    Assets:Cash                              $-10000

2015-01-01 Buy VTHRX
    Assets:Broker:VTHRX                           10 VTHRX
    Assets:Cash                              $-10000

2015-01-01 Buy VBMFX
    Assets:Broker:VBMFX                            1 VBMFX
    Assets:Cash                              $-10000


$ hledger bal -t -V --infer-market-prices Assets
                   0  Assets
              $30000    Broker
              $10000      VBMFX
              $10000      VIFSX
              $10000      VTHRX
             $-30000    Cash
--------------------
                   0  

$ hledger bal -t -V --infer-market-prices --auto Allocation
--
You received this message because you are subscribed to the Google Groups "hledger" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hledger+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/hledger/c43fdf8c-4bc5-46b8-8b62-382790fd1623n%40googlegroups.com.

Nea Zăpadă

unread,
Jan 18, 2022, 3:34:06 PM1/18/22
to hledger
That's brilliant! I didn't read much about the --auto postings because I was confused by the name, but that's exactly what I was after.

Thank!

Simon Michael

unread,
Jan 18, 2022, 4:18:14 PM1/18/22
to hledger
Nea that can be useful feedback - which name confused you ? "Auto postings" ?


Simon Michael

unread,
Jan 18, 2022, 4:43:29 PM1/18/22
to hledger
In that example, notice the extra flags needed to match the original Ledger example exactly. All of these are by design, but it's worth reviewing and asking if it's worth it ?

* -t : because our balance command defaults to list mode, because I have found it the more useful default for my own use, for explaining to new users, for sharing with non users, and for consistency across commands. I'm fine with this one.

* --infer-market-prices : because I felt Ledger's -V was a little too magical and doing too much - more to learn and understand all at once. And because it makes the default reports more fragile, and harder to troubleshoot: inferred market prices and calculated values depend on your transactions, not just P directives. Eg just changing the date of a transaction could have a big impact on your value reports. hledger reports aim to be intuitive, predictable, and stable (not disturbed by unimportant data changes).

Arguments against this one: --infer-market-prices is a long flag to type, seems to be used quite often, and seems to be relatively harmless most of the time. You can still ensure robust stable value reports by having a daily P directive, since P always takes precedence. Or we could provide a --no-infer-market-prices for when that's wanted. Having it on by default means -V/-X require a bit more learning, but they do require some docs study in any case. And it would be one less small hurdle for Ledger users.

* --auto: again because I felt always-on auto posting generation was too much magic, and I'm a fan of recording real concrete journal entries and not relying overmuch on fragile tool-dependent less-visible generated data. And --auto is easy to type. And, not all auto posting rules are desirable to be active all the time (no example handy, but I have experienced this in practice).

Arguments against: having it on by default does no harm if you have no auto posting rules. Auto posting rules you don't want active all the time can be conditionally included from separate files. One less hurdle for [Ledger] users.

Thoughts welcome!

Nea Zăpadă

unread,
Jan 18, 2022, 5:19:19 PM1/18/22
to hledger
Yes, when skimming the docs, I thought "Auto postings" would be recurring transactions, basically the feature called "periodic transactions" in the docs.

Simon Michael

unread,
Jan 18, 2022, 6:50:31 PM1/18/22
to hle...@googlegroups.com
I see.  I kept "auto" for similarity with Ledger's "Automated/Automatic Transactions" (but changed "transactions" to "postings" since that's what they generate, and to differentiate them from "Periodic Transactions".

If one abandoned familiarity and tradition, is there a clearer name I wonder ? Generated Postings ? Dynamic Postings ?



On Jan 18, 2022, at 12:19, Nea Zăpadă <prinz...@gmail.com> wrote:

Yes, when skimming the docs, I thought "Auto postings" would be recurring transactions, basically the feature called "periodic transactions" in the docs.

Patrik keller

unread,
Jan 19, 2022, 5:24:19 AM1/19/22
to hle...@googlegroups.com

Hello,

I really appreciate the "low magic" approach. Some additional thoughts:

* --infer-market-prices: seems to rely on another magical feature itself. It is not intuitive to me, that

2015-01-01 Buy VTHRX
    Assets:Broker:VTHRX         10 VTHRX
    Assets:Cash            $-10000
automatically becomes
2015-01-01 Buy VTHRX 
    Assets:Broker:VTHRX    10 VTHRX @@ $10000 
    Assets:Cash                       $-10000
Inferring a price from 10 VTHRX @@ $10000 seems to be the smaller step here. I wish for a flag to turn this off. A setting in the journal file would be even better. --strict does too much for me, I have many accounts and symbols.

* --auto: Having this optional is good. I also like how you put additional safeguards, such as  "balance assignments cannot be used with accounts which are posted to by transaction modifier rules (auto postings)." Without that, generated postings could influence amounts of later transactions, right? Maybe put the reasoning into the error message?

> Simon: I'm a fan of recording real concrete journal entries

Agreed. What do you think about an --auto-inline flag, that writes the generated postings back into the journal file? That might be a nice trade-off between automation and persistent recording. Considering the original example where VTHRX is spread across the allocation accounts, what if this allocation changes over time?

A mode that writes all implicit behavior back into the journal file might be helpful as well.

Best,
Patrik

On 18.01.22 22:43, Simon Michael wrote:.

Simon Michael

unread,
Jan 21, 2022, 8:18:19 PM1/21/22
to hledger
On Jan 19, 2022, at 12:24 AM, Patrik keller <pat...@pkel.dev> wrote:

I really appreciate the "low magic" approach. Some additional thoughts:

* --infer-market-prices: seems to rely on another magical feature itself. It is not intuitive to me, that

automatically becomes
2015-01-01 Buy VTHRX 
    Assets:Broker:VTHRX    10 VTHRX @@ $10000 
    Assets:Cash                       $-10000
Inferring a price from 10 VTHRX @@ $10000 seems to be the smaller step here. I wish for a flag to turn this off. A setting in the journal file would be even better. --strict does too much for me, I have many accounts and symbols.

Thanks.. FYI, the above is standard transaction balancing behaviour which we inherited from Ledger; --infer-market-prices does something else. 

It has been discussed a lot eg at https://github.com/simonmichael/hledger/issues/1177. You can disallow it:

$ hledger -f a.j print | hledger -f- check balancednoautoconversion
hledger: "-" (lines 1-3)
could not balance this transaction:
real postings' sum should be 0 but is:  $-10000
10 VTHRX
2015-01-01 Buy VTHRX
    Assets:Broker:VTHRX        10 VTHRX
    Assets:Cash                 $-10000

Or in the latest prerelease you can convert it to a more explicit entry with --infer-equity:

$ hledger -f a.j print --infer-equity
2015-01-01 Buy VTHRX
    Assets:Broker:VTHRX                    10 VTHRX
    equity:conversion:$-VTHRX:VTHRX       -10 VTHRX  ; generated-posting:
    equity:conversion:$-VTHRX:$              $10000  ; generated-posting:
    Assets:Cash                             $-10000


* --auto: Having this optional is good. I also like how you put additional safeguards, such as  "balance assignments cannot be used with accounts which are posted to by transaction modifier rules (auto postings)." Without that, generated postings could influence amounts of later transactions, right? Maybe put the reasoning into the error message?

Right, and balancing the journal becomes undecidable. Saying this more clearly in the error message is an excellent idea.

> Simon: I'm a fan of recording real concrete journal entries

Agreed. What do you think about an --auto-inline flag, that writes the generated postings back into the journal file? That might be a nice trade-off between automation and persistent recording. Considering the original example where VTHRX is spread across the allocation accounts, what if this allocation changes over time?

A mode that writes all implicit behavior back into the journal file might be helpful as well.

It sounds nice alright. For now, the way is to overwrite the journal with `hledger print` (must be done with care, as print does not preserve everything). I quite often rewrite individual transactions this way using C-u M-| in Emacs. Enhancements that will help this: 1. a more data-preserving print mode or 2. support for surgically replacing parts of data files.


Simon Michael

unread,
Jan 21, 2022, 10:43:36 PM1/21/22
to hledger


On Jan 21, 2022, at 3:18 PM, Simon Michael <si...@joyful.com> wrote:
* --auto: Having this optional is good. I also like how you put additional safeguards, such as  "balance assignments cannot be used with accounts which are posted to by transaction modifier rules (auto postings)." Without that, generated postings could influence amounts of later transactions, right? Maybe put the reasoning into the error message?

Right, and balancing the journal becomes undecidable. Saying this more clearly in the error message is an excellent idea.

Now slightly clearer and tidier:

Old

$ hledger -f a.j print
hledger: balance assignments cannot be used with accounts which are
posted to by transaction modifier rules (auto postings).
Please write the posting amount explicitly, or remove the rule.

account: a

transaction:

2022-01-01
    (a)                 = 1



$ hledger -f b.j print
hledger: postings which are balance assignments may not have a custom date.
Please write the posting amount explicitly, or remove the posting date:

2022-01-01
    (a)                 = 1  ; [1/2]



New

$ hledger -f a.j print
hledger: can't use balance assignment with auto postings

2022-01-01
    (a)                 = 1

Balance assignments may not be used on accounts affected by auto posting rules
(it makes balancing the journal impossible).
Please write the posting amount explicitly (or remove the auto posting rule).
$ hledger -f b.j print
hledger: can't use balance assignment with custom posting date

2022-01-01
    (a)                 = 1  ; [1/2]

Balance assignments may not be used on postings with a custom posting date
(it makes balancing the journal impossible).
Please write the posting amount explicitly (or remove the posting date).


Reply all
Reply to author
Forward
0 new messages