6.3.1 Asset Allocation
----------------------
A very popular method of managing retirement portfolios is to
control the percent allocation of assets by certain categories. The
mix of categories and the weights applied to them vary by investing
philosophy, but most follow a similar pattern. Tracking asset
allocation in ledger is not difficult but does require some additional
effort to describe how the various assets you own contribute to the
asset classes you want to track.
In our simple example we assume you want to apportion you assets into
the general categories of domestic and international equities (stocks)
and a combined category of bonds and cash. For illustrative purposes we
will use several publicly available mutual funds from Vanguard. the
three funds we will track are the Vanguard 500 IDX FD Signal (VIFSX),
the Vanguard Target Retirement 2030 (VTHRX), and the Vanguard Short Term
Federal Fund (VSGBX). Each of these funds allocates assets to different
categories of the investment universe and in different proportions.
When you buy a share of VTHRX, that share is partially invested in
equities, and partially invested in bonds and cash. Below is the asset
allocation for each of the instruments listed above:
Domestic Global
Symbol Equity Equity bonds/cash
VIFSX 100%
VTHRX 24.0% 56.3% 19.7%
VSGBX 100%
These numbers are available from the prospectus of any publicly
available mutual fund. Of course a single stock issue is 100% equity
and a single bond issue is 100% bonds.
We track purchases of specific investments using the symbol of that
investment as its commodity. How do we tell Ledger that a share of
VTHRX is 24% Global equity etc.? Enter automatic transactions and
virtual accounts.
At the top of our ledger we enter automatic transactions that
describe these proportions to Ledger. In the same entries we set up
virtual accounts that let us separate these abstract calculations from
our actual balances.
For the three instruments listed above, those automatic transactions
would look like:
;
; automatic calculations for asset allocation tracking
;
= 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
How do these work? First the `=' sign at the beginning of the line
tells ledger this is an automatic transaction to be applied when the
condition following the `=' is true. After the `=' sign is a value
expression (*note Value Expressions::) that returns true any time a
posting contains the commodity of interest.
The following line gives the proportions (not percentages) of each
unit of commodity that belongs to each asset class. Whenever Ledger
sees a buy or sell of a particular commodity it will credit or debit
these virtual accounts with that proportion of the number of shares
moved.
Now that Ledger understands how to distribute the commodities amongst
the various asset classes how do we get a report that tells us our
current allocation? Using the balance command and some tricky
formatting!
ledger bal Allocation --current --format "\
%-17((depth_spacer)+(partial_account))\
%10(percent(market(display_total), market(parent.total)))\
%16(market(display_total))\n"
Which yields:
Allocation 100.00% $100000.00
Bonds/Cash 38.94% $38940.00
Equities 61.06% $61060.00
Domestic 95.31% $58196.29
Global 4.69% $2863.71
Let's look at the Ledger invocation a bit closer. The command above
is split into lines for clarity. The first line is very vanilla Ledger
asking for the current balances of the account in the "Allocation"
tree, using a special formatter.
The magic is in the formatter. The second line simply tells Ledger to
print the partial account name indented by its depth in the tree. The
third line is where we calculate and display the percentages. The
`display_total' command give the values of the total calculated for the
account in this line. The `parent.total' command gives the total for
the next level up in the tree. `percent' format their ratio as a
percentage. The fourth line tells ledger to display the current market
value of the the line.
--
Craig, Corona De Tucson, AZ
enderw88.wordpress.com
On Sat, 19 Nov 2011, Craig Earls wrote:
> I have written a new section for the manual that goes into something
> that I have spent a bit of time working on. Just in case there is a
> far easier way to do it I thought I would broadcast the section to get
> any comments. It may be a while before it shows up in the *next*
> branch. This is best read in fixed width font. It is taken from the
> info version of the manual.
This looks promising, but I can't make it work. I tried it with a simple
test file, using your example allocations below, but the ledger report
query generates this error message:
While parsing file "ledgerfile/test", line 3:
While parsing automated transaction:
> = expr ( commodity == 'VIFSX' )
Error: Missing ')'
While parsing file "ledgerfile/test", line 6:
While parsing automated transaction:
> = expr ( commodity == 'VTHRX' )
Error: Missing ')'
While parsing file "ledgerfile/test", line 11:
While parsing automated transaction:
> = expr ( commodity == 'VBMFX')
Error: Missing ')'
(The automatic entries are a straight copy/paste from your email.)
Thanks.
--
John Rakestraw
Indeed, thanks.
--John
--
John Rakestraw
--percent only works with balance reports. The error reporting should be
clearer about this. Do you have a balance report where it's failing?
John
>>>>> Jim Robinson writes:
> This is awesome, thanks for writing it up. I tried it out and found that
> ledger 3.0.0-20120217 complaints about not understanding the format string
...
> While I did find that this appeared to work:
> ledger balance -X '$' Allocation --current -%
--percent only works with balance reports. The error reporting should be
clearer about this. Do you have a balance report where it's failing?
> But the format example doesn't like parent.total:
> $ ledger -f test.txt balance Allocation --current --format "\
> %-17((depth_spacer)+(partial_account))\
> %10(percent(market(display_total),
> %market(parent.total)))\ 16(market(display_total))\n"
> While calculating format expression:
> percent(market(display_total), market((parent.total)))
> While evaluating value expression:
> percent(market(display_total), market((parent.total)))
> ^^^^^^^^^^^^^^
Ah, you need to do something closer to what -% is doing, to be more defensive:
%((is_account&parent&parent.total) ? percent(scrub(market(display.total)), %scrub(market(parent.total))) : 0)
Parent is null when it gets to "root" account (which contain the final total
at the bottom).
> Apologies if I'm missing something obvious!
I must admit, the solution is far from obvious. :(
John
Parent is null when it gets to "root" account (which contain the final total
at the bottom).
This doesn't explain why it IS working for me without the protection you mention. "Allocation" is a top level account so I would think the paretn.total would puke on it, but it doesn't.
Ooh, now I see it. I DO suppress the total at the end since I print out a bounding box rather than letting ledger finish up on its own. I tried taking out the final line and it fails as you saw. I will update the documentation.
philosophy, but most follow a similar pattern. Tracking asset
allocation in ledger is not difficult but does require some additional
effort to describe how the various assets you own contribute to the
These numbers are available from the prospectus of any publicly available mutual fund.
> This doesn't explain why it IS working for me without the protection you
> mention. "Allocation" is a top level account so I would think the
> paretn.total would puke on it, but it doesn't.
When I say top-level, I mean the invisible account which is the parent of
*all* accounts, not the visibly top-level accounts, which are actually at
--depth=1.
John