This tutorial will walk you through creating and configuring a new Inverno portfolio from scratch.
Index:
- Installation
- Creating a new project
- Configuring transactions
- Configuring prices
- Configuring options
- Adding metadata
- Including configs
If you haven't yet installed Inverno, follow the steps here to install it.
After installing Inverno, you should get a new command named inverno, try typing it in your terminal of choice:
$ inverno --help
Usage: inverno [OPTIONS] COMMAND [ARGS]...
Options:
--help Show this message and exit.
Commands:
gen-report Generate an html report from a config
new-project Generate a template for a new projectAt the time being Inverno offers two commands gen-report and new-project.
Let's use the latter to create a new blank portfolio:
$ mkdir myproject && inverno new-project myprojectThis should have created a new blank project inside the folder myproject:
$ ls myproject
project.yml transactions.csvYou should now see two files in there:
project.yml: a project configuration templatetransactions.csv: an example list of transactions
At the moment the project configuration consists only of a list of transactions (all the rest is commented out):
transactions:
- format: standard # Transactions format
file: transactions.csv # Transactions fileThis tells Inverno to load the transactions in the transactions.csv file which contains some example of transactions.
You can open and edit .csv files using any spreedsheet software such as Excel, Google Sheets, LibreOffice Calc, etc.
As you can see there are a couple of cash deposits and some purchases of Facebook, Google and Apple stock.
This is enough to generate our first report:
$ inverno gen-report myproject/project.yml myproject/report$ ls myproject/report
css index.html js media node_modules package.json package-lock.json vendorTo view it, simply open the index.html file using your browser of choice.
You should see something like this:
As we saw in the previous section, the project configuration needs a list of transactions. Transactions are listed in a separate .csv file, which is specified in the config as follows:
transactions:
- format: standard # Transactions format
file: transactions.csv # Transactions fileCSV files can be edited using any spreadsheet software (e.g. Excel). You can provide as many transactions files as you want:
transactions:
- format: standard
file: transactions1.csv
- format: schwab
file: transactions2.csvThe format field specifies which format the transaction file is using.
At the moment the available formats are standard and schwab.
The schwab format is compatible with the list of transactions exportable from Charles Schwab brokerage platform.
If you are manually filling in your transactions you should use the standard format.
In this format, each row corresponds to a transaction.
Your transactions file will have the following columns:
- date: day the transaction happened (e.g. 10/02/21)
- action: type of transaction, available types are:
- buy: for purchases of new holdings (e.g. buying stock)
- sell: for selling holdings (e.g. selling stock)
- cash_in: for cash flowing in (e.g. cash deposit, salary, etc.)
- cash_out: for cash flowing out (e.g. withdrowal)
- tax: for any sort of tax payment associated to the investment account
- vest: for vesting events (e.g. from RSU)
- dividends: for dividends payed by an holding
- split: for stock split events
- name: (optional) name of the holding, can be anything (e.g. Google, Facebook, MyFund, etc.)
- ticker: (optional) ticker of the holding, if applicable (e.g. GOOGL, FB, etc.)
- isin: (optional) ISIN of the holding, if applicable (e.g. US38259P7069)
- quantity: (needed for buy/sell/vest transactions) number of holdings purchased/sold/vested (e.g. 3.5)
- price: (either price or amount are needed for buy/sell transactions) holding price at the moment of the purchase/sale, corresponds to the price multiplied by the quantity (e.g. $102.2)
- amount: (either price or amount are needed for buy/sell transactions) total cash amount of the transaction price at the moment of the purchase/sale, corresponds to the price multiplied by the quantity (e.g. $424.2)
- fees: (optional) transaction costs (e.g. $2.4)
Once again, here is an example of transactions:
Inverno will try to fetch prices from Yahoo Finance. If prices of an holding are not available on Yahoo Finance, Inverno will try to estimate them based on the transactions (by interpolating the prices you have provided in the transactions). This last method isn't very precise (and might not be possible if there are too few transactions). In such cases you might want to provide the prices on your own.
You can specify a prices file for one or more holdings as follows:
prices:
- match:
name: My Fund
file: my_fund_prices.csv
- match:
ticker: FB
file: fb_prices.csvThe match section lets you specify the holding by name, ticker or ISIN.
Prices must be provided as CSV files with date and price columns, where each row represents the price for that day:
You can add an options section to your project to specify extra config parameter:
options:
title: My Portfolio # Name of the project
days: 90 # Show last N days (default is 90, relative to end_date)
end_date: 25/04/21 # Do not show after this date (defaults to today)
currency: USD # Convert everything to this currency (default USD)Peraphs one of the coolest features of Inverno is the ability to associate metadata to any holding.
This is done via the meta section.
Each metadata entry consists of a match section (similar to the one used for prices) which can match an holding by its name, ticker or ISIN,
and an apply section containing a list of attributes and values. Let's look at an example:
meta:
- match:
ticker: FB # Match holding by its ticker
apply:
sector: Communication Services # Set attribute "sector" to "Communication Services"Here we are saying that the sector of our holding with ticker FB is "Communication Services". Notice that instead of sector we could have put anything!
Let's add another holding:
meta:
- match:
ticker: FB
apply:
sector: Communication Services
- match:
ticker: JNJ
apply:
sector: Health CareAs a result we will get a new sector section in our report, showing how our holdings are distrubuted with respect to the sectors and how each sector is performing:
Notice that holdings for which we haven't specified any sector are left as "unkown". Using the same technique we could specify attributes for anything of interest: company cap, ratings, location, etc.
Sometime an holding may extend over multiple sectors, this is common for mutual funds, ETFs, etc. Inverno let's you specify multiple values for an attribute:
meta:
- match:
name: My Fund
apply:
sector:
Information Technology: 50%
Communication Services: 30%Here we are saying that the sector of My Fund is 50% Information Technology, 30% Communication Services and 20% unknown.
Some holdings are simply the composition of other holdings. Let's take an actual example: Vanguard's Lifestrategy funds are nothing but a composition of multiple other Vanguard funds.
This relation can be specified using the composition meta section:
- match:
name: LifeStrategy® 80% Equity Fund - Accumulation
apply:
type:
equity: 80%
bonds: 20%
composition:
name:
U.S. Equity Index Fund GBP Acc: 19.37%
FTSE U.K. All Share Index Unit Trust GBP Acc: 19.27%
FTSE Developed World ex-U.K. Equity Index Fund GBP Acc: 19.26%
Global Bond Index Fund GBP Hedged Acc: 14.01%
Emerging Markets Stock Index Fund - Accumulation: 6.96%
FTSE Developed Europe ex-U.K. Equity Index Fund GBP Acc: 5.42%
S&P 500 UCITS ETF (USD) Accumulating: 4.61%
Japan Stock Index Fund GBP Acc: 2.80%
U.K. Government Bond Index Fund GBP Acc: 2.49%
U.K. Inflation-Linked Gilt Index Fund GBP Acc: 1.89%
U.K. Investment Grade Bond Index Fund GBP Acc: 1.60%
Pacific ex-Japan Stock Index Fund GBP Acc: 1.46%
FTSE 100 UCITS ETF (GBP) Distributing: 0.79%
FTSE 250 UCITS ETF (GBP) Distributing: 0.07%
U.K. Gilt UCITS ETF (GBP) Distributing: 0.01%Here we are saying that the fund named LifeStrategy® 80% Equity Fund - Accumulation is composed of all those funds in the measure specified by the percentages. In this case composing holding are specified by name, it is also possible to specify them by ticker or ISIN:
- match:
name: My Fund
apply:
type: equity
composition:
ticker:
FB: 10%If you specify an attribute in the apply section, this will have priority over the composition. This means that, in the example above, the type of My Fund will be always 100% equity regardless of the type of its sub-holdings.
Instead of having all of your project in a single config file, you can split it over multiple files and include them from your main config.
This is, for example, very handy for populating your meta entries:
include:
- inverno/meta/equity.yaml
- inverno/meta/vanguard.yml


