--
You received this message because you are subscribed to the Google Groups "Beancount" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beancount+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beancount/CAK21%2BhNLfJcaD7RFcFsJ%2B-xbk90F3Gr40A8dC0ZQENfHg_QakA%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beancount/e04c3eff-5f00-42b0-a86d-de145e69bad6%40Spark.
To view this discussion on the web visit https://groups.google.com/d/msgid/beancount/CAK21%2BhN6ndWJoyqPtuNKG77TJMmvwqgQfqb8iQL%2B_jmhxSge8A%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beancount/d3084ba9-9272-4281-b377-e9c07c9b5423n%40googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beancount/41d4e5c1-de3a-41c5-aae2-2c7a39ab99b5n%40googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beancount/2a6bf01f-ca97-4bd3-9d61-9c0ef75e4678n%40googlegroups.com.
Overview
Extracting cashflows needed to compute IRR is challenging because of the flexibility that bookkeeping systems like Beancount need to offer in order to be useful.
This is a review of beancount/experiments/returns that Martin posted recently, including what you need to get up and running, and pitfalls to watch out for.
First, a review:
Per-commodity accounting: not a hard requirement
The documentation may seem to suggest that per-commodity accounts are a requirement or are assumed by the code, but this is not actually true. The code works at the account level, and if you don’t have or use per-commodity accounting, you can still compute returns at an account level. Below are some pitfalls, solutions, and some drawbacks to not using per-commodity accounting.
2020-01-02 * "Buy"
Assets:Brokerage 1000 HOOL {1 USD}
Assets:Bank
2020-08-01 * "Dividends"
Assets:Brokerage 500 USD
Income:Dividends:Brokerage ; ← not a cash account; not counted
2020-08-01 * "Reinvest dividends"
Assets:Brokerage 500 HOOL {1 USD}
Assets:Brokerage -500 USD ; ← not an external account; not counted
However, this is only a problem if you want your total performance broken down into dividends vs. appreciation. If not, the total performance numbers you get will still be correct. Simply ignore the ex-dividends and dividends numbers.
@@ -141,7 +144,10 @@ def truncate_cash_flows(
balance = compute_balance_at(account_data.transactions, date_start)
if not balance.is_empty():
cost_balance = balance.reduce(pricer.get_value, date_start)
+ cost_balance = cost_balance.reduce(convert.convert_position, "USD", pricer.price_map)
cost_position = cost_balance.get_only_position()
@@ -154,7 +160,13 @@ def truncate_cash_flows(
balance = compute_balance_at(account_data.transactions, date_end)
if not balance.is_empty():
cost_balance = balance.reduce(pricer.get_value, date_end)
- cost_position = cost_balance.get_only_position()
+ cost_balance = cost_balance.reduce(convert.convert_position, "USD", pricer.price_map)
+ try:
+ cost_position = cost_balance.get_only_position()
Verification of results can be challenging:
After building a basic config file and perhaps making a few simple changes to your ledger, compute_returns.py spits out numbers. How can the correctness of these numbers be verified?
One way to identify problems is to construct groupings that reflect IRRs provided by brokerages. However, the details and terminology of how IRR calculations are made can vary widely by brokerage. For example, there seems to be no agreement on what the start/end dates should be when computing “3-year performance”. It can thus be a lot of effort to figure these out even if one has just a handful of brokerages.
Verifying the output of compute_returns.py may involve some effort. The challenge fundamentally seems to stem from the (fantastic) flexibility Beancount provides in constructing one's ledger, which means that the configuration for compute_returns.py needs to be correct. Short of bugs, all incorrect results are generally because of errors in configuration.
So how can one verify that their configuration is correct? Thankfully, this is a place where compute_returns.py shines, with its clear, relevant output. Below, I share a few tips and personal stumbling blocks to help others figure their own:
cat returns.output/investments/*.org | grep "^.'" | grep None
Also consider whether each of them has been categorized correctly:
cat returns.output/investments/*.org | grep "^.'"
Modifications I had to make to my ledger:
There were some gotchas that I had to work through that I’ve shared below to give a sense of what one might need to look out for:
Configuration maintenance
As one’s ledger evolves, the reports config needs to be kept up to date. One downside of per-commodity accounts is they are likely to be opened and closed more frequently than physical accounts.
Omissions of all types in the returns configuration (asset, dividend, and cash accounts) can be hard to detect. Solutions are likely to be highly specific to the conventions one uses in their ledger. For my ledger for example, I plan to ensure all accounts under “(Assets|Income):Investments:*” appear at least once in the reports config file.
In-kind transfers and returns
One case that is not covered seems to be in-kind transfers. For example:
option "operating_currency" "USD"
plugin "beancount.plugins.implicit_prices"
2005-01-01 commodity USD
2005-01-01 commodity HOOL
2000-01-01 open Assets:Bank
2000-01-01 open Assets:Brokerage:HOOL "STRICT"
2000-01-01 open Assets:Zero-Sum-Accounts:Transfers "STRICT"
2010-01-01 * "Buy"
Assets:Zero-Sum-Accounts:Transfers 1000 HOOL {0.5 USD}
Assets:Bank
2020-01-01 price HOOL 1 USD
2020-01-02 * "Transfer"
Assets:Brokerage:HOOL 1000 HOOL {0.5 USD}
Assets:Zero-Sum-Accounts:Transfers -1000 HOOL {0.5 USD}
2020-12-23 price HOOL 1.1 USD
Using the market value on the transfer date for the cashflow value should solve this case.
This appears in several cases in me ledger: moving from one brokerage to another, and options exercise. It could be argued that the former could be handled by bundling together the old and new accounts, but that assumes all accounts in question deal with only a single commodity each, which means (for me), redoing a whole bunch of historical transactions.
The latter is an interesting case. For context, assume an option to buy stock ABC at 1 USD was exercised when the fair market value of ABC was 5 USD. It was then held for a year, and sold for 10 USD. It is helpful to compute the returns of holding on to the exercised stock (which is an investing decision) separately from the “compensation” portion, which is the 5-1 = 4 USD. To do this, I track them in separate accounts like so:
2015-01-01 * "Exercised"
Assets:Vested -100 ABC_OPTIONS
Expenses:Stock-Options 100 ABC_OPTIONS
Assets:XTrade:Exercised 100 ABC {1 USD} ; FMV was 4 USD
Assets:Bank 100 USD ; 100 * 1 USD
2015-01-01 price ABC 4 USD ; FMV
2015-01-01 * “Transferred to brokerage”
Assets:XTrade:Exercised -100 ABC {1 USD}
Assets:XTrade:Invested 100 ABC {1 USD}
If stock transfers in-kind were computed in the way above, one could simply compute returns separately on Assets:XTrade:Exercised and Assets:XTrade:Invested, and distinguish between the “compensation” and the “investment” portions.
Minor feedback
# Run on 2020-12-23
>>> from reports import *
>>> from tabulate import tabulate
>>> print(tabulate(get_calendar_intervals(TODAY)))
---- ---------- ----------
2005 2005-01-01 2006-01-01
2006 2006-01-01 2007-01-01
2007 2007-01-01 2008-01-01
2008 2008-01-01 2009-01-01
2009 2009-01-01 2010-01-01
2010 2010-01-01 2011-01-01
2011 2011-01-01 2012-01-01
2012 2012-01-01 2013-01-01
2013 2013-01-01 2014-01-01
2014 2014-01-01 2015-01-01
2015 2015-01-01 2016-01-01
2016 2016-01-01 2017-01-01
2017 2017-01-01 2018-01-01
2018 2018-01-01 2019-01-01
2019 2019-01-01 2020-01-01
2020 2020-01-01 2020-12-23
---- ---------- ----------
>>> print(tabulate(get_cumulative_intervals(TODAY)))
-------------------- ---------- ----------
15_years_ago 2005-01-01 2020-12-23
10_years_ago 2010-01-01 2020-12-23
5_years_ago 2015-01-01 2020-12-23
4_years_ago 2016-01-01 2020-12-23
3_years_ago 2017-01-01 2020-12-23
2_years_ago 2018-01-01 2020-12-23
1_year_ago 2019-01-01 2020-12-23
ytd 2020-01-01 2020-12-23
rolling_6_months_ago 2020-06-25 2020-12-23
rolling_3_months_ago 2020-09-25 2020-12-23
-------------------- ---------- ----------
--
You received this message because you are subscribed to the Google Groups "Beancount" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beancount+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beancount/ebba4de0-c401-4290-a119-2cab59d5b432n%40googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "Beancount" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beancount+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beancount/fdb4dad4-1d92-4f7b-92e0-26e3732e7603n%40googlegroups.com.
You received this message because you are subscribed to a topic in the Google Groups "Beancount" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/beancount/OJBIGFvbBC8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to beancount+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beancount/50e30e64-b537-4fc3-8654-75a2fa3945c2n%40googlegroups.com.
Guys hiFirst of all i want to thank Martin for superb work! I have been using beancount for 2 years and flexibility / functionality beancount provides are simply amazing. I always recommend beancount on plain text accounting sub and now have 1 extra reason to suggest it :)
Secondly i have several questions / issues with installation and will appreciate your help:1. should i use "v2 master + beangrow repo" OR "beancount 2.3.3" ?
2. when i run configure.py, it generates empty file, what can be the reason for this?
3. Do i understand it right that the only change we need to do in main beancount file is add signature handlers?
(using beancount 2.3.2)R:\b\b-office>python returns/compute_returns.py b.beancount conf-returns out
Traceback (most recent call last):
File "returns/compute_returns.py", line 97, in <module>
main()
File "returns/compute_returns.py", line 73, in main
config = configlib.read_config(args.config, args.filter_reports, accounts)
File "R:\b\b-office\returns\config.py", line 44, in read_config
text_format.Merge(infile.read(), config)
File "C:\Users\Btycoon\AppData\Local\Programs\Python\Python38\lib\site-packages\google\protobuf\text_format.py", line 696, in Merge
return MergeLines(
File "C:\Users\Btycoon\AppData\Local\Programs\Python\Python38\lib\site-packages\google\protobuf\text_format.py", line 770, in MergeLines
return parser.MergeLines(lines, message)
File "C:\Users\Btycoon\AppData\Local\Programs\Python\Python38\lib\site-packages\google\protobuf\text_format.py", line 795, in MergeLines
self._ParseOrMerge(lines, message)
File "C:\Users\Btycoon\AppData\Local\Programs\Python\Python38\lib\site-packages\google\protobuf\text_format.py", line 817, in _ParseOrMerge
self._MergeField(tokenizer, message)
File "C:\Users\Btycoon\AppData\Local\Programs\Python\Python38\lib\site-packages\google\protobuf\text_format.py", line 907, in _MergeField
raise tokenizer.ParseErrorPreviousToken(
google.protobuf.text_format.ParseError: 15:1 : Message type "beancount.returns.Config" has no field named "groups".
5. Could someone please share sample beancount and returns config files?
To view this discussion on the web visit https://groups.google.com/d/msgid/beancount/50e30e64-b537-4fc3-8654-75a2fa3945c2n%40googlegroups.com.
thank you for your reply,i understand that beangrow is experimental, and i really appreciate what it can do even in this form, hopefully we (i see some users on github) will contribute to work too. Your work is really helpful to lots of people, one more time thank you.I managed to make bean grow work, i needed to add "commodity" declarations. (surprisingly beancount / fava worked without them just fine) Plus couple windows related bugs for which i opened issues on beangrow's github providing temp fixes.
I have couple of additional questions on bean grow set-up:1. configure.py seems to ignore closed accounts, is it how it supposed to work?(usually for strictness i was closing accounts after i exited/sold position, example: "2020-10-06 close Assets:Investing:CSchwab:RDFN")
2. "Including Uninvested Cash"Do i understand it right that the easiest way to account for uninvested cash is to create-commodity "IDDLEUSD"-account Assets:Investing:IDDLEUSDbuy IDDLEUSD for all cash (USD) that i can invest at rate 1:1,and then at each interval i do reports "price IDDLEUSD 1 USD",and when i want to buy smng sell IDDLEUSD for USD, and buy what i want.?OR is there a way to make my investment cash accounts "Assets:Investing:CSchwab:Cash", etc to be counted as investment (with 0 return) ?
3. Is there recommended time frame for "price" quotes?Usually i open positions for 3-5 years, so not interested in daily or even monthly fluctuations.Do i understand it right that if i use-"plugin "beancount.plugins.implicit_prices"" (to get price from buy/sell transactions)-price my investments on 1st of each Quarter-run compute_returns.py with -e DATE = 1st of each Quarter (basically same cut off as date of last price quote)then i will be fine and won't need any more price quotes?
To view this discussion on the web visit https://groups.google.com/d/msgid/beancount/702f73e7-70b1-4dfe-b119-706ab320243bn%40googlegroups.com.
I have couple of additional questions on bean grow set-up:1. configure.py seems to ignore closed accounts, is it how it supposed to work?(usually for strictness i was closing accounts after i exited/sold position, example: "2020-10-06 close Assets:Investing:CSchwab:RDFN")
2. "Including Uninvested Cash"Do i understand it right that the easiest way to account for uninvested cash is to create-commodity "IDDLEUSD"-account Assets:Investing:IDDLEUSDbuy IDDLEUSD for all cash (USD) that i can invest at rate 1:1,and then at each interval i do reports "price IDDLEUSD 1 USD",and when i want to buy smng sell IDDLEUSD for USD, and buy what i want.?OR is there a way to make my investment cash accounts "Assets:Investing:CSchwab:Cash", etc to be counted as investment (with 0 return) ?
3. Is there recommended time frame for "price" quotes?Usually i open positions for 3-5 years, so not interested in daily or even monthly fluctuations.Do i understand it right that if i use-"plugin "beancount.plugins.implicit_prices"" (to get price from buy/sell transactions)-price my investments on 1st of each Quarter-run compute_returns.py with -e DATE = 1st of each Quarter (basically same cut off as date of last price quote)then i will be fine and won't need any more price quotes?
and include the resulting price database in your source, and re-reun beangrow. Without that, beangrow uses the price values on the closest dates it can find, which in your case could be weeks or months off, which means your returns numbers will be off.
The file generated above provides the only dates on which the prices matter to beangrow for your configuration. These are the start and end dates of your cashflow. Meaning, period opening and closing dates, and dates on which you bought/sold, IIRC. More detail here.
Enjoy!
thank you for reply,"If you're seeing a problem case, would you mind opening a bug in the repo with a demo example?"- opened the issue https://github.com/beancount/beangrow/issues/12
"The latter is exactly what I do for now: simply include "Assets:Investing:CSchwab:Cash" as a commodity, and it'll show up with very low returns."- could you please share your config file for this cash account?I can't seem to make it work with currency same as my main currency (USD). Or do you use separate currency/commodity just for that account?

--
You received this message because you are subscribed to the Google Groups "Beancount" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beancount+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beancount/87548033-01bd-463c-b096-aceafc15fc7fn%40googlegroups.com.