Investment portfolio management with Python

2022-05-07

See all posts

If you are searching for a simple way to keep track of your personal investment portfolio and you are savvy on the command line you can check out the portfolio management tool that I have written in Python: finance

Example output, plotted with matplotlib:

A piechart diagram plotted with matplotlib

For installation and usage instructions please refer to the README of the project.

Why did I code this?

Let's start at the beginning: I am very passionate about personal finance and investing. However, as much as I like researching the markets, I absolutely do not want to spend more time than necessary micro-managing my portfolio or keeping track of every little change.

If you search for existing portfolio managers on the internet, you find a good amount of high-quality apps and projects that help you keep track of almost everything you want in a personal finance tool, e.g., Portfolio Performace (Website) (Github).

While Portfolio Performance is great and powerful (it really is!), it simply does not work for me. Setting everything up and creating entries for assets, asset classes and transactions can take multiple hours. Personally, I find this too much of a hassle. While it may work really well for some people, it really does not work for me.

Online tools such as a simple Google Sheet offer almost everything I want (e.g. Google Finance live quotes). However, they leave me somewhat uncomfortable from a privacy standpoint, since my personal portfolio balance is stored online in the cloud. I prefer my financial data balance to remain offline if possible.

Also: FUN! Why not take the time to learn something new and build my own tool from scratch?

Here are my requirements for a personal investment portfolio management tool that suits my needs best:

The data file

I settled for this structure for the portfolio file:

Name Ticker Asset Class Amount
Stock A AAA.AA Stocks 1
Bond B BBB.BB Bonds 2
Crypto C CRYPTO-CURR Crypto 0.5

With this structure as a data model, users only need to add a single line for each asset and only ever update the last column (amount) if the balance of the portfolio changes.

Tickers are important for querying market quotas and are pretty easy to look up online. I decided to use pandas and get_quote_yahoo from pandas_datareader to get live market prices from yahoo finance.

Maintaining a healthy asset allocation and diversification across asset classes is a must for me, so the data model should also include the type of asset class for each asset in the file.

The data itself can be stored in a simple .csv file, looking something like this:

Name,Ticker,AC,Amount
S&P 500,SPY,S,2
US Treasury 20+yr,TLT,B,4
Commodities,GSG,C,3
Gold,GLD,G,1
Bitcoin,BTC-USD,CRYPTO,0.01
Cash,-,CASH,200

Getting current market quote

Getting the current price of an asset via yahoo finance is fairly simple using pandas_datareader.get_quote_yahoo():

from pandas_datareader.data import get_quote_yahoo
ticker = "AAPL" # ticker for Apple Inc.
currPrice = get_quote_yahoo(ticker)["price"][0]

Showing balances and allocations

The pandas python library makes it really easy to print out the overall balances of the portfolio in a well-formed and pleasing format. After getting quotes for each asset, we only need to update the balance for that asset by multiplying it with the amount stored in the data file.

def getQuotes(data):
    tickers = data["Ticker"]

    print("Getting current prices from Yahoo Finance...")
    balances = []

    for i in range(0, len(tickers)):
        ac = data["AC"][i]
        # If Asset Class is cash, then get amount only
        if ac == "CASH":
            balances.append(data["Amount"][i])
        else:
            try:
                currPrice = get_quote_yahoo(tickers[i])["price"][0]
                amount = data["Amount"][i]
                balances.append(round(currPrice*amount, 2))
            except Exception:
                print("No quote for this ticker")
    data["Balance"] = balances
    return data

The overall result looks like this:

================================================================
                Name   Ticker      AC   Amount    Balance
0         NASDAQ 100      QQQ       S     50.0   15462.50
1            S&P 500      SPY       S    350.0  143969.00
2  US Treasury 20+yr      TLT       B    750.0   85252.50
3        Commodities      GSG       C   1000.0   24370.00
4               Gold      GLD       G    150.0   26313.00
5            Bitcoin  BTC-USD  CRYPTO      0.5   17987.15
6              Ether  ETH-USD  CRYPTO      2.5    6384.83
7               Cash        -    CASH  15000.0   15000.00
Your total balance is: $334738.98
================================================================

Note: This is example data and does not reflect my actual balance and/or allocation.

Security

Users can use the third-party encryption utility gpg to encrypt their data file. In that case, the data stays encrypted at rest and users are prompted for their gpg passphrase (if they have one) for their default gpg identity. This allows for secure sync between platforms via, e.g., git. Decrypted values are never written to disk.

In order to transparently edit encrypted data files, I recommend vim-gnupg for editing your data file.

Outlook

I might consider adding performance tracking in the future, but this will require some form of persistant datastore of balances and transactions (buy/sell/etc.). Since this will likely add significant complexity, you should be better off using something like Portfolio Performance.