Skip to main content

Portfolio

The Portfolio menu, from the OpenBB Terminal, is wrapped into a Python SDK layer, enabling users to programmatically work with the data in a flexible environment, fully customizable for the needs of any user. This guide will introduce the functions within the main Portfolio module, and walk through examples demonstrating how to work with a portfolio file and object.

How to Use

Below is a brief description of each function within the Portfolio module:

PathTypeDescription
openbb.portfolio.allocSub-ModuleAllocation Metrics Compared to the Benchmark
openbb.portfolio.benchFunctionSelect a Benchmark for the Portfolio
openbb.portfolio.distrFunctionDistribution of Daily Returns
openbb.portfolio.dretFunctionDaily Returns
openbb.portfolio.esFunctionExpected Shortfall
openbb.portfolio.holdpFunctionHoldings of Assets as a %
openbb.portfolio.holdvFunctionHoldings of Assets as an Absolute Value
openbb.portfolio.loadFunctionLoad a Portfolio File
openbb.portfolio.maxddFunctionMaximum Drawdown
openbb.portfolio.metricSub-ModuleRisk and Portfolio Metrics
openbb.portfolio.mretFunctionMonthly Returns
openbb.portfolio.omFunctionOmega Ratio
openbb.portfolio.perfFunctionPortfolio Performance vs Benchmark
openbb.portfolio.poSub-ModulePortfolio Optimization Sub Menu
openbb.portfolio.rbetaFunctionRolling Beta of Portfolio and Benchmark Returns
openbb.portfolio.rsharpeFunctionRolling Sharpe Ratio
openbb.portfolio.rsortFunctionRolling Sortino Ratio
openbb.portfolio.rvolFunctionRolling Volatility
openbb.portfolio.showFunctionPortfolio Transactions
openbb.portfolio.summaryFunctionSummary of Portfolio and Benchmark Returns
openbb.portfolio.varFunctionPortfolio VaR
openbb.portfolio.yretFunctionYearly Returns

Alternatively, the contents of the Porfolio module is printed with:

help(openbb.portfolio)

Many of the functions in this module will also have a companion command, _chart.

Portfolio Files

Portfolio files are spreadsheets (xlsx or csv files) containing historical trades which add up to represent a net balance in the Portfolio Engine. Users should keep their collection of holdings files in the OpenBBUserData folder, ~/OpenBBUserData/portfolio/holdings.

If you wish to load in your own Excel holdings file, please follow the following steps:
  1. Download the Excel file that can be used as a template here.
  2. Move the file inside the portfolio/holdings folder within the OpenBBUserData folder and, optionally, adjust the name to your liking.
  3. Open the Excel file and remove, edit or add to the values as you desire (e.g. your own orders). This is the default template that is also loaded in with load --example.
  4. Open up the OpenBB Terminal, go to portfolio and type load --file. Your Excel file should then be one of the options.

Note that the Excel sheet requires the following columns:

  • Date - The date the trade occurred
  • Name - The name of the security
  • Type - The type of the security. Use Cash/Stock/Crypto/ETF as appropriate
  • Price - The price the security was added or removed at, on a per-unit basis
  • Quantity - How much of the security in question was added or removed
  • Side - Whether you bought or sold. Use Buy/Deposit/1 to add to the portfolio or Sell/Withdrawal/0 to remove from the portfolio a search criteria, country, sector or industry.

The table below illustrates the required column titles:

DateTypeTickerSidePriceQuantityFeesInvestmentCurrencySectorIndustryCountryRegion
2021-10-29STOCKK.TOBuy7.93190201526.7CADBasic MaterialsGoldCanadaNorth America
2015-01-02ETFSPYBuy178.285.60998.368USD----
2015-01-01CRYPTOBTC-USDBuy1000202000USDCryptoCryptoCryptoCrypto
2011-01-03STOCKAMZNBuy9.221000922USDConsumer CyclicalInternet RetailUnited StatesNorth America
2011-01-03STOCKAAPLBuy11.7410001174USDTechnologyConsumer ElectronicsUnited StatesNorth America
2011-01-03STOCKMSFTBuy28.0410002804USDTechnologySoftware-InfrastructureUnited StatesNorth America
2011-01-03STOCKTSLABuy1.761000176USDConsumer CyclicalAuto ManufacturersUnited StatesNorth America
2011-01-03STOCKGOOGBuy15.0110001501USDCommunication ServicesInternet Content & InformationUnited StatesNorth America

The template Excel file also has additional columns but these are optional. The OpenBB SDK can figure out by itself what industry, sector, country and region belongs to the loaded in Equity. So the field can be left blank if your holdings do not include this information.

Examples

The examples in this guide will assume that the import statements below are included at the top of the Python script or Jupyter Notebook.

Import Statements

from openbb_terminal.sdk import openbb
import pandas as pd
# %matplotlib inline (uncomment if using a Jupyter Notebook or an Interactive Window)

Load

Taking the downloaded holdings_example.xlsx file from the previous section, let's load it into the Portfolio Engine. There are a few parameters available for this function, and an object is returned.

help(openbb.portfolio.load)
    Get PortfolioEngine object

Parameters
----------
transactions_file_path : str
Path to transactions file
benchmark_symbol : str
Benchmark ticker to download data
full_shares : bool
Whether to mimic the portfolio trades exactly (partial shares) or round down the
quantity to the nearest number
risk_free_rate : float
Risk free rate in float format

Returns
-------
PortfolioEngine
PortfolioEngine class instance, this will hold transactions and perform calculations

Examples
--------
>>> from openbb_terminal.sdk import openbb
>>> p = openbb.portfolio.load("openbb_terminal/miscellaneous/portfolio_examples/holdings/example.csv")

The syntax should resemble something like the sample below; don't forget to modify the path to match the local path.

P = openbb.portfolio.load(
transactions_file_path = '/Users/path_to/OpenBBUserData/portfolio/holdings/holdings_example.xlsx',
benchmark_symbol = 'VTI',
full_shares = False,
risk_free_rate = 3.0
)
Preprocessing transactions: 100%|██████████| 14/14 [00:01<00:00,  8.82it/s]
Loading price data: 100%|██████████| 3/3 [00:01<00:00, 2.64it/s]
Calculating returns: 100%|██████████| 1/1 [00:00<00:00, 14.52it/s]
Loading benchmark: 100%|██████████| 4/4 [00:04<00:00, 1.21s/it]

The Portfolio Object

A Portfolio Object is assigned to the variable, P. The created object, or parts of it, are used as inputs to the other functions in this module. It can also be interacted with directly, for example, to change the benchmark ticker. SPY is a holding in the example portfolio, so let's stick with VTI as the performance benchmark.

P.set_benchmark(symbol = 'SPY')

Loading benchmark: 50%|█████ | 2/4 [00:00<00:00, 5.69it/s]

print(P.benchmark_ticker)

SPY

Populating a list of tickers from the Portfolio Object is accomplished by assigning a variable to it:

tickers = P.tickers_list
print(tickers)

['SPY', 'TSLA', 'K.TO', 'AAPL', 'AMZN', 'MSFT', 'BTC-USD', 'GOOG']

Show

openbb.portfolio.show is for displaying the transactions from the loaded portfolio file. Scroll back up to view the output of this function again.

openbb.portfolio.show(P)

Perf

Performance against the benchmark is summarized in a table with, openbb.portfolio.perf.

print(openbb.portfolio.perf(P))
PortfolioBenchmarkDifference
Total Investment11102.0711102.07-
Total Value114027.3836203.9677823.43
Total % Return927.08%226.10%700.98%
Total Abs Return102925.3125101.8977823.43

Summary

openbb.portfolio.summary prints a table of risk metrics, comparing the portfolio against the benchmark.

print(openbb.portfolio.summary(P))
PortfolioBenchmarkDifference
Volatility1.65%0.99%0.66%
Skew-0.32-0.610.29
Kurtosis8.8016.87-8.079
Maximum Drawdown-59.05%-35.00%-24.05%
Sharpe ratio0.050.0390.011
Sortino ratio0.060.040.021
R2 Score41.36%41.36%0.00%

MaxDD

openbb.portfolio.maxdd calculates the maximum drawdown as price and % value; it returns a Tuple.

holdings,dd = openbb.portfolio.maxdd(P)
dd = pd.DataFrame(dd)
dd.rename(columns = {'Total': 'Portfolio % Drawdown'}, inplace = True)
holdings = pd.DataFrame(holdings)
holdings.rename(columns = {'Total': 'Portfolio Value'}, inplace = True)
dd = dd.join(holdings)
dd.index = dd.index.strftime(date_format='%Y-%m-%d')
print(dd.tail(5))
DatePortfolio % DrawdownPortfolio Value
2022-11-21-0.58109442
2022-11-22-0.57111257
2022-11-23-0.56114017
2022-11-24-0.56114027
2022-11-25-0.56113302

MaxDD also has a _chart command, and is called with:

openbb.portfolio.maxdd_chart(P)

openbb.portfolio.maxdd_chart

RSharpe

Calculate a rolling sharpe ratio over a specified window.

rs = openbb.portfolio.rsharpe(P, window = '3m')
rs.rename(columns = {'portfolio': 'Portfolio Sharpe', 'benchmark': 'Benchmark Sharpe'}, inplace = True)
rs.index = rs.index.strftime(date_format='%Y-%m-%d')
print(rs.tail(5))
DatePortfolio SharpeBenchmark Sharpe
2022-11-21-0.150.02
2022-11-22-0.130.05
2022-11-23-0.090.07
2022-11-24-0.090.08
2022-11-25-0.090.11

RVol

openbb.portfolio.rvol has the same input parameters as rsharpe.

rv = openbb.portfolio.rvol(P, window = '3m')
rv.rename(columns={'portfolio': 'Portfolio Volatility', 'benchmark': 'Benchmark Volatility'}, inplace = True)
rv.index = rv.index.strftime(date_format='%Y-%m-%d')

print(rv.tail(5))
DatePortfolio VolatilityBenchmark Volatility
2022-11-230.0217270.014490
2022-11-240.0217150.014439
2022-11-250.0215960.014256
2022-11-260.0215910.014256
2022-11-270.0215920.014256

DRet

openbb.portfolio.dret returns a DataFrame with daily returns of the portfolio and benchmark.

returns = openbb.portfolio.dret(P)
returns.rename(columns = {'portfolio': 'Portfolio % Returns', 'benchmark': 'Benchmark % Returns'}, inplace = True)
returns.index = returns.index.rename('Date')

print(returns.tail(5))
DatePortfolio % ReturnsBenchmark % Returns
2022-11-21-0.03-0.00
2022-11-220.020.01
2022-11-230.020.01
2022-11-240.000.00
2022-11-25-0.010.00

Read the Portfolio Optimization Intro to learn about the optimization features, and the parameters preset template.