Giter VIP home page Giter VIP logo

fava_investor's Introduction

Fava Investor

Fava Investor aims to be a comprehensive set of reports, analyses, and tools for investments, for Beancount and Fava (software for plain text, double entry bookkeeping). It is developed as a collection of modules, with each module offering a Fava plugin, a Beancount library, and a shell command.

Current modules:

Demo

Play with the live demo at pythonanywhere.

Screenshots (dated):

Screenshot: TLH Screenshot: Asset Allocation

Utilities

Fava Investor ships with ticker-util, which is a collection of utilities for:

  • downloading information from Yahoo for commodities (tickers), and annotating your commodity declarations with metadata
  • discovering relationships between tickers in your Beancount file, such as equivalent and substantially identical tickers, and tax loss harvesting partner groups, from a minimal and incomplete specification
  • providing ISIN an other ticker identifying information to your importers

For more, install fava_investor via pip, and then see:

ticker-util --help
ticker-util relate --help

Installation

pip3 install fava-investor

Or to install the bleeding edge version from git:

pip3 install git+https://github.com/redstreet/fava_investor

See #55 for MacOS installation.

Running Fava Investor

Running in Fava:

Add this to your beancount source, and start up fava as usual:

2000-01-01 custom "fava-extension" "fava_investor" "{}"

You should now see an 'Investor' link in the sidebar in fava. For more on how to configure the extension, see the included huge-example.beancount.

Running on the Command-Line:

The command line interface (CLI) is accessed using the investor command, which has subcommands for each module. Eg:

investor assetalloc-class
investor tlh
investor --help

Both the CLI and the utility (ticker-util) use click. See here to enable shell completion in zsh, bash, or fish, which is highly recommended.

Problems?

  • Monitor the terminal you are running fava from to look for error output from fava_investor
  • Include the error messages you see above when opening bug reports or asking for help

Contributing

Features, fixes, and improvements welcome. Remember:

  • Feel free to send send pull requests. Please include unit tests
  • For larger changes or changes that might need discussion, please reach out and discuss first to save time (open an issue)
  • Please squash your commits (reasonably)
  • Use conventional commits for commit messages

Thank you for contributing!

Related Projects

fava_investor's People

Contributors

aclindsa avatar adamgibbins avatar aldur avatar chouxi avatar dependabot[bot] avatar korrat avatar redstreet avatar tbm avatar tschicke avatar yagebu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fava_investor's Issues

[Feature] Use implicit prices

Fava currently doesn't use the price information provided in postings:

plugin "beancount.plugins.implicit_prices"
2000-01-01 * "" "Buy new Asset"
  Assets:Investments:MyNewAsset                                  1 NEWASSET {1000 USD} @ 1000 USD
  Assets:Cash

Will lead to fava exiting, as there is no explicit price directive.

You need to explicitly add a price directive for NEWASSET:

plugin "beancount.plugins.implicit_prices"
2000-01-01 * "" "Buy new Asset"
  Assets:Investments:MyNewAsset                                  1 NEWASSET {1000 USD} @ 1000 USD
  Assets:Cash

2000-01-01 price NEWASSET 1000 USD

I update some assets more or less only via the „implicit“ price directive syntax that beancount provides. It would be nice, if fava_investor would make use of the data.

fava_investor not loading

when i try to use it even with your beancount example, i have "loading http://localhost:5000/huge-example-file/extension/investor failed"
and in the console of fava i have

  File "c:\program files\python38\lib\site-packages\jinja2\lexer.py", line 381, in expect
    raise TemplateSyntaxError("expected token %r, got %r" %
jinja2.exceptions.TemplateSyntaxError: expected token 'end of print statement', got '_'

so basically noting work :(

Per-module list of options / help

Does a list of arguments for each of the modules exist someplace? Trying to understand a bit more about options are possible and what changes I need to make to my BC file.

Fava QueryShell Change

Upstream Fava changed the arguments to QueryShell.execute_query() in beancount/fava@6f4bcd5#diff-7ae3e08b8e89a98b64814a30622d443c8b09336df4f7b866c941476f14090bc5 such that it takes an additional positional argument, 'entries', prior to the pre-existing 'query' argument.

This leads to failures like:

Exception on /my-finances/extension/Investor/ [GET]
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/flask/app.py", line 2077, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python3.10/dist-packages/flask/app.py", line 1525, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python3.10/dist-packages/flask/app.py", line 1523, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python3.10/dist-packages/flask/app.py", line 1509, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
  File "/usr/local/lib/python3.10/dist-packages/fava/application.py", line 345, in extension_report
    content = render_template_string(template, extension=extension)
  File "/usr/local/lib/python3.10/dist-packages/flask/templating.py", line 166, in render_template_string
    return _render(ctx.app.jinja_env.from_string(source), context, ctx.app)
  File "/usr/local/lib/python3.10/dist-packages/flask/templating.py", line 128, in _render
    rv = template.render(context)
  File "/usr/local/lib/python3.10/dist-packages/jinja2/environment.py", line 1301, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.10/dist-packages/jinja2/environment.py", line 936, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 46, in top-level template code
  File "/usr/local/lib/python3.10/dist-packages/fava_investor/__init__.py", line 44, in build_tlh_tables
    return libtlh.get_tables(accapi, self.config.get('tlh', {}))
  File "/usr/local/lib/python3.10/dist-packages/fava_investor/modules/tlh/libtlh.py", line 16, in get_tables
    retrow_types, to_sell, recent_purchases = find_harvestable_lots(accapi, options)
  File "/usr/local/lib/python3.10/dist-packages/fava_investor/modules/tlh/libtlh.py", line 107, in find_harvestable_lots
    rtypes, rrows = accapi.query_func(sql)
  File "/usr/local/lib/python3.10/dist-packages/fava_investor/common/favainvestorapi.py", line 28, in query_func
    contents, rtypes, rrows = self.ledger.query_shell.execute_query(sql)
TypeError: QueryShell.execute_query() missing 1 required positional argument: 'query'

Setup releases via PyPI

I'd like to start releasing alpha versions via PyPI, so users can start using this, and we can get feedback. Help appreciated, particularly if you've done this via github before.

twine
howto

Asset Allocation by Class does not convert prices transitively

With the following minimal example:

plugin "beancount.plugins.auto"

option "operating_currency" "EUR"

1980-01-01 custom "fava-extension" "fava_investor" "{
  'asset_alloc_by_class' : {
      'accounts_patterns': ['Assets:Investment'],
  },
}"

2023-01-01 price USD 2 EUR

2023-01-01 *
    Assets:Investment:SOME-TICKER              10.000 STCK {1 USD}
    Assets:Checking                           - 5.00  EUR @ 2 USD

When running fava-investor, I get an error:

$ investor assetalloc-class .\main.bean
Error: unable to convert 10.000 STCK to base currency EUR (Missing price directive?)

Running the following beancount query works:

$ bean-query.exe .\main.bean 'SELECT account, convert(sum(position), "EUR")'
           account            convert_s
----------------------------- ---------
Assets:Investment:SOME-TICKER  5.00 EUR
Assets:Checking               -5.00 EUR

This suggests, to me, that fava-investor cannot make use of transitive pricing relations. Could this be added?

Error: Importing module failed

Hi,
I have been following the instructions in the readme on how to use this extension directly in the beancount ledger folder, or installed via pip. All I get is an error "Importing module "fava_investor" failed.".

Is there anything I am missing?

Incorrect allocation percentage computation in "Asset Allocation Accounts"

The allocation percentage is computed incorrectly when positive and negative balances are mixed in one table, see the following patch for a fix.

diff --git a/fava_investor/modules/assetalloc_account/libaaacc.py b/fava_investor/modules/assetalloc_account/libaaacc.py
index 6dea472..4607e7d 100644
--- a/fava_investor/modules/assetalloc_account/libaaacc.py
+++ b/fava_investor/modules/assetalloc_account/libaaacc.py
@@ -73,9 +73,9 @@ def asset_allocation(nodes, accapi, include_children):
             row["balance"] = balance[operating_currency]
             rows.append(row)
 
-    portfolio_total = sum(row['balance'] for row in rows)
+    portfolio_total = sum(abs(row['balance']) for row in rows)
     for row in rows:
         if "balance" in row:
-            row["allocation %"] = round((row["balance"] / portfolio_total) * 100, 1)
+            row["allocation %"] = round(abs(row["balance"] / portfolio_total) * 100, 1)
 
     return types, rows

Fava Investor Won't Load (Windows-only issue?)

When I click the Investor link (using the included huge-example) in Fava I get a loading failed error, similar to issue #47 . I get a slew of flask and jinja errors, but the trigger is:

File "<unknown>", line 45, in template jinja2.exceptions.TemplateSyntaxError: expected token 'end of print statement', got '_'

account_open_metadata bug

I'm trying the AA pattern "account_open_metadata" but it's failing. Using the example.bc I edited the arguments in the second config of AA by account, and set a tax: metadata equal to 1 on an account open directive.

2010-01-01 custom "fava-extension" "fava_investor" "{
 'tlh' : {
    'account_field': 'account',
    'accounts_pattern': 'Assets:Investments:Taxable',
    'loss_threshold': 50,
    'wash_pattern': 'Assets:Investments',
 },

 'asset_alloc_by_account': [{
     'title':            'Allocation by Account',
     'pattern_type':     'account_name',
     'pattern':          'Assets:Investments:.*',
 },
 {
     'title':            'Allocation by Tax Meta',
     'pattern_type':     'account_open_metadata',
     'pattern':          'tax',
     'metadata_key':     '1',
 }],

 'asset_alloc_by_class' : {
     'accounts_patterns': ['Assets:.*'],
 },
}"

Error message:

 File "/home/pi/beancount/fava_investor/fava_investor/modules/assetalloc_account/libaaacc.py", line 47, in by_account_open_metadata
    for entry in accapi.all_entries_by_type[Open]:
AttributeError: 'FavaInvestorAPI' object has no attribute 'all_entries_by_type'

Missing dependency on tabular

setup.py is missing a dependency on tabular:

  File "/home/tbm/.local/lib/python3.7/site-packages/fava_investor/common/clicommon.py", line 4, in <module>
    import tabulate
ModuleNotFoundError: No module named 'tabulate'

Fava investor tab fails to load

When I click on Fava Investor tab it fails to load. I reproduced using the example from:

https://github.com/redstreet/fava_investor/blob/main/fava_investor/pythonanywhere/

When I run investor assetalloc-class <beancount_file> it runs without issue.

I'm running on MacOS Ventura (arm) with the following:

beancount                2.3.5
beancount-reds-importers 0.5.1
click                    8.1.3
click-aliases            1.0.1
fava                     1.21
fava-investor            0.3.0
Flask                    2.2.2
Flask-Babel              2.0.0

Here's what I see in terminal:

Exception on /example-beancount-file/extension/Investor/ [GET]
Traceback (most recent call last):
  File "/Users/redacted/projects/test3-beans/venv-beans/lib/python3.9/site-packages/flask/app.py", line 2525, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/redacted/projects/test3-beans/venv-beans/lib/python3.9/site-packages/flask/app.py", line 1822, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/redacted/projects/test3-beans/venv-beans/lib/python3.9/site-packages/flask/app.py", line 1820, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/redacted/projects/test3-beans/venv-beans/lib/python3.9/site-packages/flask/app.py", line 1796, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
  File "/Users/redacted/projects/test3-beans/venv-beans/lib/python3.9/site-packages/fava/application.py", line 341, in extension_report
    content = render_template_string(template, extension=extension)
  File "/Users/redacted/projects/test3-beans/venv-beans/lib/python3.9/site-packages/flask/templating.py", line 159, in render_template_string
    return _render(app, template, context)
  File "/Users/redacted/projects/test3-beans/venv-beans/lib/python3.9/site-packages/flask/templating.py", line 130, in _render
    rv = template.render(context)
  File "/Users/redacted/projects/test3-beans/venv-beans/lib/python3.9/site-packages/jinja2/environment.py", line 1301, in render
    self.environment.handle_exception()
  File "/Users/redacted/projects/test3-beans/venv-beans/lib/python3.9/site-packages/jinja2/environment.py", line 936, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 220, in top-level template code
  File "/Users/redacted/projects/test3-beans/venv-beans/lib/python3.9/site-packages/fava_investor/__init__.py", line 21, in build_assetalloc_by_class
    return libassetalloc.assetalloc(accapi, self.config.get('asset_alloc_by_class', {}))
  File "/Users/redacted/projects/test3-beans/venv-beans/lib/python3.9/site-packages/fava_investor/modules/assetalloc_class/libassetalloc.py", line 192, in assetalloc
    realacc = build_interesting_realacc(accapi, config.get('accounts_patterns', ['.*']))
  File "/Users/redacted/projects/test3-beans/venv-beans/lib/python3.9/site-packages/fava_investor/modules/assetalloc_class/libassetalloc.py", line 156, in build_interesting_realacc
    realroot = accapi.realize()
  File "/Users/redacted/projects/test3-beans/venv-beans/lib/python3.9/site-packages/fava_investor/common/favainvestorapi.py", line 23, in realize
    return g.filtered.root_account
  File "/Users/redacted/projects/test3-beans/venv-beans/lib/python3.9/site-packages/flask/ctx.py", line 52, in __getattr__
    raise AttributeError(name) from None
AttributeError: filtered

Design: Investment Performance

Continuing the conversation from the net worth work. Here are some thoughts. Perhaps, more than net worth with Fava already displays on the main page (which is by definition across one's entire accounts, and not restricted to investments), what we are interested in here is investment performance analysis. Refining our goals further:

Investment Performance Analysis: Design Goals

What do we seek to understand?

Let's understand what we may want out of the investment performance analysis component
by asking typical questions around this topic:

  • What's the balance in my investment accounts? How much has it gone up/down by in the
    past?
  • How much of my balance has been my original contributions, vs. returns from the
    investment, and appreciation
  • How much have I contributed over time?
  • How much have I withdrawn over time?
  • How is a specific account (or set of accounts) doing with respect to all the questions
    above?

What does a mock up look like?

We want to show graphs for the following:
A. show balances across time

B. balance breakdown across time: show split of 1) contributions, 2) income (dividends,
gains, interest, etc.), and 3) appreciation

C. Contributions and withdrawals (cumulative) across time

All these should be:

  • filterable by accounts (using standard fava interface)
  • across arbitrary time periods (using standard fava interface)

Eventually, we should have this module also calculate IRR (internal rate of return). I'll flesh this out later.

Can't view "Asset Allocation Classes": I get the error "Message Corrupt"

I'm trying to get Fava Investor working but am having some trouble.

I'll say first of all that it works fine if I open the included example file. However when I use my own ledger file, clicking "Asset Allocation Classes" gives me the following error message:

Loading http://127.0.0.1:35335/my-ledger/extension/Investor/?module=aa_class failed: Message Corrupt

I can view the "Asset Allocation Accounts", "Cash Drag" and "Tax Loss Harvestor" pages just fine. The problem only occurs on the "Asset Allocation Classes" page, which is the most important one to me and the entire reason why I wanted to use the extension.

Since it works with the example file, I'm not sure whether this is a bug in the extension or something I'm doing wrong with my ledger. Obviously I don't want to post my real ledger files for privacy reasons. As far as I can tell, I'm doing the same thing as in the example though.

I have this at the top of my file:

2000-01-01 custom "fava-extension" "fava_investor" "{
	'tlh' : {
		'account_field': 'account',
		'accounts_pattern': 'Assets:',
		'loss_threshold': 10,
		'wash_pattern': 'Assets:',
	},
	'asset_alloc_by_account': [{
		'title':            'Allocation by Account',
		'pattern_type':     'account_name',
		'pattern':          'Assets:.*',
	},
	{
		'title':            'Allocation by Taxability',
		'pattern_type':     'account_name',
		'pattern':          'Assets:[^:]*$',
		'include_children': True,
	}],
	'asset_alloc_by_class' : {
		'accounts_patterns': ['Assets:.*'],
	},
}"

And I also define all the commodities I'm using. Here are some examples:

2021-02-12 commodity GBP
	name: "Pound sterling"
	asset-class: "Cash"
	asset_allocation_Cash: 100

2021-02-12 commodity USD
	name: "US dollar"
	asset-class: "Cash"
	asset_allocation_Cash: 100

2021-02-16 commodity XAU
	name: "Gold (troy ounce)"
	asset-class: "Commodity"
	asset-subclass: "Gold"
	asset_allocation_PreciousMetals_Gold: 100

2021-02-16 commodity XAG
	name: "Silver (troy ounce)"
	asset-class: "Commodity"
	asset-subclass: "Silver"
	asset_allocation_PreciousMetals_Silver: 100

2021-02-16 commodity ETH
	name: "Ethereum"
	asset-class: "Cryptocurrency"
	asset_allocation_Cryptocurrencies_Ethereum: 100

2021-02-16 commodity AMD
	name: "Advanced Micro Devices, Inc."
	asset-class: "Stock"
	asset_allocation_Stocks_Tech: 100

Any idea why this isn't working or what I can do to troubleshoot it?

Exception on Load: jinja2.exceptions.UndefinedError: 'url_for_current' is undefined

Run
cd fava_investor
fava example.beancount

Exception
Exception on /baker/extension/Investor/ [GET]
Traceback (most recent call last):
File "/home/patrick/.local/pyenv/versions/Venti/lib/python3.9/site-packages/flask/app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "/home/patrick/.local/pyenv/versions/Venti/lib/python3.9/site-packages/flask/app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/patrick/.local/pyenv/versions/Venti/lib/python3.9/site-packages/flask/app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/patrick/.local/pyenv/versions/Venti/lib/python3.9/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/home/patrick/.local/pyenv/versions/Venti/lib/python3.9/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/home/patrick/.local/pyenv/versions/Venti/lib/python3.9/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functionsrule.endpoint
File "/home/patrick/Sources/Venti/modules/fava/src/fava/application.py", line 352, in extension_report
content = render_template_string(template, extension=extension)
File "/home/patrick/.local/pyenv/versions/Venti/lib/python3.9/site-packages/flask/templating.py", line 155, in render_template_string
return _render(ctx.app.jinja_env.from_string(source), context, ctx.app)
File "/home/patrick/.local/pyenv/versions/Venti/lib/python3.9/site-packages/flask/templating.py", line 120, in _render
rv = template.render(context)
File "/home/patrick/.local/pyenv/versions/Venti/lib/python3.9/site-packages/jinja2/environment.py", line 1090, in render
self.environment.handle_exception()
File "/home/patrick/.local/pyenv/versions/Venti/lib/python3.9/site-packages/jinja2/environment.py", line 832, in handle_exception
reraise(*rewrite_traceback_stack(source=source))
File "/home/patrick/.local/pyenv/versions/Venti/lib/python3.9/site-packages/jinja2/_compat.py", line 28, in reraise
raise value.with_traceback(tb)
File "", line 10, in top-level template code
jinja2.exceptions.UndefinedError: 'url_for_current' is undefined

Requirements (Python 3.9.5)
argcomplete==1.12.3
argh==0.26.2
atomicwrites==1.4.0
attrs==21.2.0
Babel==2.9.1
beancount==2.3.4
beancount-import==1.3.3.post1.dev159
beancount-plugins-metadata-spray==0.0.1
beautifulsoup4==4.9.3
bottle==0.12.19
cachetools==4.2.2
certifi==2021.5.30
cffi==1.14.5
chardet==4.0.0
cheroot==8.5.2
click==7.1.2
cryptography==3.4.7
fava==1.20.dev17+ge987bb99
fava-investor==0.2.2.dev19+g0b9da55
Flask==1.1.4
Flask-Babel==1.0.0
google-api-core==1.30.0
google-api-python-client==2.8.0
google-auth==1.31.0
google-auth-httplib2==0.1.0
googleapis-common-protos==1.53.0
httplib2==0.19.1
idna==2.10
importlib-metadata==4.5.0
iniconfig==1.1.1
itsdangerous==1.1.0
jaraco.functools==3.3.0
jeepney==0.6.0
Jinja2==2.11.3
joblib==1.0.1
jsonschema==3.2.0
keyring==23.0.1
lxml==4.6.3
markdown2==2.4.0
MarkupSafe==2.0.1
more-itertools==8.8.0
nltk==3.6.2
numpy==1.20.3
ofxclient==2.0.4
ofxhome==0.3.3
ofxparse==0.21
packaging==20.9
pip==21.1.2
pluggy==0.13.1
ply==3.11
protobuf==3.17.3
py==1.10.0
pyasn1==0.4.8
pyasn1-modules==0.2.8
pycparser==2.20
pyparsing==2.4.7
pyrsistent==0.17.3
pytest==6.2.4
python-dateutil==2.8.1
python-magic==0.4.24
pytz==2021.1
regex==2021.4.4
requests==2.25.1
rsa==4.7.2
scikit-learn==0.24.2
scipy==1.6.3
SecretStorage==3.3.1
setuptools==56.0.0
simplejson==3.17.2
six==1.16.0
soupsieve==2.2.1
tabulate==0.8.9
threadpoolctl==2.1.0
toml==0.10.2
tornado==6.1
tqdm==4.61.0
uritemplate==3.0.1
urllib3==1.26.5
venti==0.0
watchdog==2.1.2
Werkzeug==1.0.1
zipp==3.4.1

[Feature] Asset allocation tools

Nice to have additions to asset allocation by class module:

  • compute how to allocate a given fixed amount to move one's AA close to their target (contribution)
  • compute, for a given amount, what assets to sell to maintain or move one's AA close to their target (drawdown)
  • compute recommendations to sell/purchase assets to rebalance so one can move to one's target AA (while minimizing capital gains)

TLH: Detect non-wash sales when *all* positions are sold

If one sells *all * their positions of a ticker across their portfolio, a wash sale does not occur since there is no replacement of sold shares (assuming no repurchase in the future for 30 days). Detect this (when the advise is to sell all owned positions of a ticker) and advise.

huge-example.beancount included twice

Is there a reason this file is shipped twice:

ll huge-example.beancount fava_investor/huge-example.beancount
-rw-r--r-- 1 tbm tbm 913210 May  6 19:36 fava_investor/huge-example.beancount
-rw-r--r-- 1 tbm tbm 913210 May  6 19:36 huge-example.beancount

Some tables don't load with 'master' fava

If I use fava 1.18, fava_investor loads as expected. However, if I use the latest git version of fava from 'master' (I'm testing SHA 367c86ccdb73ad21a01afe8d2279f7c454adc7a8 as of this writing), some of the tables do not load. I get this instead:

2021-04-05-073714_1334x698_scrot

Interestingly, both the chart and 'Portfolio: Asset Allocation by Class' on the Asset Allocation Classes view load fine, but most of the tables on the Asset Allocation Accounts, Cash Drag, and Tax Loss Harvestor views do not. There is one table in the Tax Loss Harvestor view that does show up - the Summary one at the top:

2021-04-05-074024_1316x1106_scrot

Importing module "fava_investor.fava_investor" failed.

The readme says to include the line 2000-01-01 custom "fava-extension" "fava_investor.fava_investor" "{}" in order to load the plugin.

However, when doing so I get an error: Importing module "fava_investor.fava_investor" failed.

The fix seems to be to include 2000-01-01 custom "fava-extension" "fava_investor" "{}". At least that worked for me. Maybe I missed something, but if the fix is correct the readme should be updated.

Thx for the plugin, its great!

Demo example

This project now can show asset allocation percentages by class and by accounts, and has a refined tax loss harvester. A demo example that has the complexity required to show these features would help users understand it, and will help developers figure out where and how to provide help.

[Feature] Sum up allocation sub classes

Currently fava_investor shows the percentage for each asset class in relation to the total:
image

It would be nice if fava_investor showed the sum of a class in regards to the total and to its parent(s):
image
(Something like this)

This might get confusing if there are more than three sublevels. Therefore, It might be best to include an addition column:

  • Ratio in parent which holds the ratio in regards to the total of the parent.

Investor Link shows in Fava, but individual modules fail

Thank you for this project! Investor tools will be very useful in Fava. I successfully installed the extension and added the fava-extension to my beancount file, which appears to work (Investor link shows in Fava and the new screen loads). But when I click on any of the tabs -- Asset Allocation, Cash Drag, TLH, etc, I get a module failed error within Fava.

"Loading http://localhost:5000/ledger/extension/Investor/?module=aa_class failed."

Probably something simple I am missing :) Any suggestions?

Fava Investor won't load

When I click the Investor link in Fava on my beancount file I get a loading failed error.
The relevant console output is "jinja2.exceptions.UndefinedError: 'url_for_current' is undefined"

beancount - 2.3.4
fava investor - 0.2.1
jinja2 - 3.0.3
MacOS BigSur 11.6

dividend calculation in networth report

There is no clear indication which stock is generating dividends. Probably they are usualy coming from one income account like Income:Dividends or maybe with child accounts per stock.

Seems like this query does the job:

select sum(cost(position)) 
    where account ~ 'investments' 
    and joinstr(other_accounts) ~ 'dividends'

Is there some better way of calculating dividends?

Also joinstr(other_accounts) seems slightly hacky but i couldnt find anything better to match string in a Set. Is there something else to do it?

does the module fetch prices from the web?

I was under the impression that this module fetches commodity prices from Google, I guess.

However, when running the module without explicit price directives in the *.beancount file it fails and I get:

'''Error: unable to convert XXX LHA to base currency EUR (Missing price directive?)
SystemExit raised: shutting down
'''

A related issue, which might be more of a question for core beancount, is the capabity of conversion across several units. Personally I denote in EUR but some stocks, fonds, etc. are denoted in USD on the web. So I would need a conversion of commodity -> USD -> EUR.

PS: I love the module. Still not sure how to configure it all but I am getting there.

Setup.py

Can we get a setup.py so I can import this repo into my beancount virtual environment?

List TLH sales within 30 days ("do not buy" list)

A wash sale can also be created by selling a lot and then, within 30 days, buying a "substantially similar" security. The "Purchases within the past 30 days creating wash sales" could be extended to also list sales that have occurred within 30 days, so users can easily see what things they should not repurchase.

New fava version breaks fava-investor

Hi! Apparently, v1.2.5 breaks fava_dashboards. For example, I've seen that FavaAPIException is not FavaAPIError in helpers.py.

I get this error:

werkzeug.routing.exceptions.BuildError: Could not build url for endpoint 'extension_report' with values ['bfile', 'module', 'report_name']. Did you forget to specify values ['extension_name']?

Reference:

Incorrect proceeds because sale price not used

Consider the following ledger

2021-01-02 * "Buy 1 HOOL"
  Assets:Cash
  Assets:HOOL   1 HOOL {10 USD}

2021-01-10 price HOOL  15 USD

2021-01-13 * "Sell HOOL"
 Assets:Cash
 Assets:HOOL -1 HOOL {} @ 20 USD 
 Income:Gains  -10 USD 

The correct proceeds from the sale are clearly 20 USD.
The SQL query in the recently_sold_at_loss method uses the CONVERT method to compute the proceeds from the 01-13 sale.
However by inspection CONVERT, while lives at line 153 of core/convert.py, looks up the most recent price available rather than the sale price (which it does not have access to anyway). In the absence of a price entry that exactly agrees with the sale price, the proceeds are incorrect.

Furthermore, if no price entry exists for that commodity up until the sale date, an exception is raised because CONVERT gives up on the conversion and reports the proceeds in terms of the commodity sold, rather than USD. This leads to the Inventory object having multiple positions.

MacOS Install Problem? `Importing module "fava_investor" failed.`

I'm trying to use beancount, fava and fava-investor.

I am using MacOS BigSur with all upgrades, and Safari.

I have installed brew, have done brew install fava which installs beancount and fava. I then did pip3 install fava-investor.

My beancount file is one known to be working with someone else, and it has the line:

2000-01-01 custom "fava-extension" "fava_investor" "{}"

However, when I fava my.beancount and open http://localhost:5000 I get in the Fava web interface under errors:
Importing module "fava_investor" failed.

I'm not sure what I'm doing wrong, or how to diagnose the problem.

Postive amounts of non-monetary commodities crash aa_class

I have an issue with my vacation hours VACHR commodity and fava_investor: Whenever I have a positive balance of vacation hours, aa_class stops working with the message

Error: unable to convert 15 VACHR to base currency USD (Missing price directive?)

Steps to reproduce:

  1. Remove lines 3742-3744 from huge-example.beancount to produce a positive balance
  2. Open aa_class module

I would expect fava_investor to completely ignore this commodity, as it holds no monetary value.

[Feature] Write errors to GUI callout instead of exiting

TLDR
If fava_investor hits some errors it writes to stderr, which leads fava to crash/exit with error code 1.

It would be nicer to display a warning callout instead—just like the

This page adds charts using a deprecated method which will be removed soon.

notification.


Two examples:

No asset allocation account found

2000-01-01 custom "fava-extension" "fava_investor" "{
  'asset_alloc_by_class' : {
    'accounts_patterns'    : [
			'Assets:Investing',
			'Assets:DoesNotExist'],
  },
}"

This will print error specificed in

sys.stderr.write("No included accounts found. (Your --accounts <regex> failed to match any account)\n")

Related: #76
One could argue that it doesn't make sense to include a non-existing account. But:

  • One use case could be a common fava/fava_investor config that gets included by multiple ledgers that have different accounts.
  • Another quite more common use case: You can't exclude accounts in fava to customize a view. An example:
2000-01-01 custom "fava-extension" "fava_investor" "{
  'asset_alloc_by_class' : {
    'accounts_patterns'    : [
			'Assets:Investing',
			'Assets:Cash'],
  },
}"

With this config I can compare my investments and the amount of cash I'm holding. If I wanted to know the ratios of my investments I need to exclude the cash accounts. I'd do it in fava via the GUI, but it "breaks" fava:

image

Nov 10 15:44:27: No included accounts found. (Your --accounts <regex> failed to match any account)
Nov 10 15:44:27: fava.service: Main process exited, code=exited, status=1/FAILURE
Nov 10 15:44:27: fava.service: Failed with result 'exit-code'.

(I'm running fava as a linux service unit)

The only way to exclude accounts is by changing the config and restarting fava. It would be way nicer to leverage the powerful webUI for excluding specific accounts temporarily.
Why is this useful? Well, besides the cash example, if there's real estate in your assets it normally makes 70-90% of your asset allocation. This makes it hard to see if you're overexposed to another investment.


Error: unable to convert PRICE to base currency XY
If you didn't explicitly add a price directive for an exit, fava_investor prints this error message

Error: unable to convert NEWASSET to base currency USD.
(Missing price directive?)

sys.stderr.write("Error: unable to convert {} to base currency {}"

So, a bean containing this:

plugin "beancount.plugins.implicit_prices"
2000-01-01 * "" "Buy new Asset"
  Assets:Investments:MyNewAsset                                  1 NEWASSET {1000 USD} @ 1000 USD
  Assets:Cash

Would "break" fava because of the stderr message. You need to explicitly add a price directive for NEWASSET:

plugin "beancount.plugins.implicit_prices"
2000-01-01 * "" "Buy new Asset"
  Assets:Investments:MyNewAsset                                  1 NEWASSET {1000 USD} @ 1000 USD
  Assets:Cash

2000-01-01 price NEWASSET 1000 USD

(Actually, this is also a feature request: #77 import/use the implicit prices that are added to postings)

Asset Allocation Classes-- TypeError: unsupported operand type(s) for /: 'str' and 'int'

I received the below error when trying to access "Asset Allocation Classes" in Fava Investor.

I was able to get around it by casting meta_value to a Decimal on line 122 and 123.

Exception on /generic-users-finances/extension/Investor/ [GET]
Traceback (most recent call last):
  File "/Users/generic-user/.virtualenvs/beans/lib/python3.9/site-packages/flask/app.py", line 2525, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/generic-user/.virtualenvs/beans/lib/python3.9/site-packages/flask/app.py", line 1822, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/generic-user/.virtualenvs/beans/lib/python3.9/site-packages/flask/app.py", line 1820, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/generic-user/.virtualenvs/beans/lib/python3.9/site-packages/flask/app.py", line 1796, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
  File "/Users/generic-user/.virtualenvs/beans/lib/python3.9/site-packages/fava/application.py", line 360, in extension_report
    content = Markup(render_template_string(template, extension=extension))
  File "/Users/generic-user/.virtualenvs/beans/lib/python3.9/site-packages/flask/templating.py", line 159, in render_template_string
    return _render(app, template, context)
  File "/Users/generic-user/.virtualenvs/beans/lib/python3.9/site-packages/flask/templating.py", line 130, in _render
    rv = template.render(context)
  File "/Users/generic-user/.virtualenvs/beans/lib/python3.9/site-packages/jinja2/environment.py", line 1301, in render
    self.environment.handle_exception()
  File "/Users/generic-user/.virtualenvs/beans/lib/python3.9/site-packages/jinja2/environment.py", line 936, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 239, in top-level template code
  File "/Users/generic-user/.virtualenvs/beans/lib/python3.9/site-packages/fava_investor/__init__.py", line 22, in build_assetalloc_by_class
    return libassetalloc.assetalloc(accapi, self.config.get('asset_alloc_by_class', {}))
  File "/Users/generic-user/.virtualenvs/beans/lib/python3.9/site-packages/fava_investor/modules/assetalloc_class/libassetalloc.py", line 203, in assetalloc
    asset_buckets = bucketize(vbalance, accapi)
  File "/Users/genric-user/.virtualenvs/beans/lib/python3.9/site-packages/fava_investor/modules/assetalloc_class/libassetalloc.py", line 122, in bucketize
    asset_buckets[bucket] += amount.number * (meta_value / 100)
TypeError: unsupported operand type(s) for /: 'str' and 'int'

I recently moved to using OFX and the corresponding reds importer for OFX files and it introduced some Assets:Zero-Sum-Accounts:Transfers that I believe created some "unknown" asset_alloc_by_class. I added this to my fava_config to get unknown to zero but even after doing that it looks like I need to cast meta_value to decimal to get Asset Allocation Classes to load

Function get_account_open in favainvestorapi.py returns an empty list

With fava 1.20.1, using option 'pattern_type' = 'account_open_metadata' in 'asset_alloc_by_account' renders an empty table in the "Asset Allocation by Accounts" tab. I've tracked the issue to the function get_account_open in favainvestorapi.py which returns an empty list. I believe the correct way is to return self.ledger.all_entries_by_type.Open in the function, which corrects the behaviour.

diff --git a/fava_investor/common/favainvestorapi.py b/fava_investor/common/favainvestorapi.py
index 28caee5..cd591d8 100644
--- a/fava_investor/common/favainvestorapi.py
+++ b/fava_investor/common/favainvestorapi.py
@@ -38,9 +38,7 @@ class FavaInvestorAPI:
         return getters.get_account_open_close(self.ledger.entries)
 
     def get_account_open(self):
-        oc = getters.get_account_open_close(self.entries)
-        opens = [e for e in oc if isinstance(e, Open)]
-        return opens
+        return self.ledger.all_entries_by_type.Open
 
     def cost_or_value(self, node, date, include_children):
         if include_children:

Tree table won't collapse

Tree table in Asset Allocation by Class won't collapse when the triangles are clicked. This happened after upgrading fava from 1.13 to 1.15. The macro used is in Investor.html:
{% macro asset_tree(account_node) %}

Contribution guideline on separation from fava/bc code

Hi. Regarding following note from CONTRIBUTING.md:

### Contribution Guidelines

Each module must include a Fava plugin, a Beancount library, and a Beancount based CLI
(command line interface). APIs in `fava_investor/common/{favainvestorapi.py,
beancountinvestorapi.py}` allow for easily developing these three interfaces to the
library. The goal is to keep fava or beancount specific code neatly separated.

These interfaces are not really decoupling things as their methods are returning data stuctures and classes directly from beancount and fava. If things are going to change there, all code using these interfaces will break anyway.

Looks like we're going to rely on beancount's features a lot and I don't really see a way to avoid coupling. Whats the plan here with these APIs?

Display of numbers with zero decimal places

We need to be able to display a value of type Decimal in a table, without displaying the decimal point or digits after it. Eg: Decimal(23.92) should display simply as '24' in the table. This helps with several investing reports, since decimal places don't matter, and the display is cleaner without them.

Tabbed webpage display in fava extension

We will likely need to display a page with "tabs," with tabs for asset allocation, TLH, rebalancing, etc. See the holdings page in fava for an example.

The holdings page uses def holdings_by() in fava/applications.py. Static pages suffices for us, unlike the holdings page which is parameterized. Can we do this in an extension?

[Feature] Allow filtering for accounts

TLDR
Allow filtering accounts to exclude specific assets from fava investor modules


Say you have the following asset_alloc config

2000-01-01 custom "fava-extension" "fava_investor" "{
  'asset_alloc_by_class' : {
    'accounts_patterns'    : [
			'Assets:Stocks',
			'Assets:Bonds',
			'Assets:Cash',
			'Assets:RealEstate'],
  },
}"

RealEstate will make probably 70-95% of your asset allocation. While this is good to know and good to track, it would be nice to exlucde the real estate account from the view via the fava webUI. (Filter: -Asset:RealEstate). This would allow to easily check the allocation of your more liquid assets and track the asset allocations on "every level", without the need to adjust the config and restart fava.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.