Portfolio

class Portfolio(assets=None, *, first_date=None, last_date=None, ccy='USD', inflation=True, weights=None, rebalancing_strategy=period           month abs_deviation      NaN rel_deviation      NaN dtype: str, symbol=None)

Bases: ListMaker

Investment portfolio.

An investment portfolio is a type of financial asset (same as stocks, ETFs, mutual funds, currencies, etc.). The arguments are similar to AssetList, but Portfolio additionally has:

  • weights

  • rebalancing_strategy

  • symbol

Portfolio is defined by the investment strategy, which includes:

  • asset allocation (financial assets and their proportions in the portfolio)

  • the rebalancing strategy (rebalancing_strategy parameter)

Rebalancing is the action of bringing the portfolio that has deviated away from the original target asset allocation back into line. After rebalancing, the portfolio assets have the original weights.

Parameters:
assetslist, default None

List of assets. Could include tickers or asset-like objects (Asset, Portfolio). If None, a single-asset list with a default ticker is used.

first_datestr, default None

First date of monthly return time series. If None, the first date is calculated automatically as the oldest available date for the listed assets.

last_datestr, default None

Last date of monthly return time series. If None, the last date is calculated automatically as the newest available date for the listed assets.

ccystr, default ‘USD’

Base currency for the list of assets. All risk metrics and returns are adjusted to the base currency.

inflationbool, default True

Defines whether to take inflation data into account in the calculations. Including inflation could limit available data (first_date, last_date) as the inflation data is usually published with a one-month delay. With inflation=False, some properties like real return are not available.

weightslist of float, default None

List of asset weights. The weight of an asset is the percent of an investment portfolio that corresponds to the asset. If None, an equally weighted portfolio is created (all weights are equal).

rebalancing_strategyRebalance, default Rebalance(period=”month”)

Rebalancing strategy for an investment portfolio. The strategy is defined by:

  • period (rebalancing frequency): predetermined time intervals when the investor rebalances the portfolio. If “none”, asset weights are not rebalanced.

  • abs_deviation: the absolute deviation allowed for the asset weights in the portfolio.

  • rel_deviation: the relative deviation allowed for the asset weights in the portfolio.

symbolstr, default None

Text symbol of portfolio. It is similar to tickers but have a namespace information. Portfolio symbol must end with .PF (all_weather_portfolio.PF). If None, a random symbol is generated (portfolio_7802.PF).

Methods & Attributes

annual_return_ts([return_type])

Calculate annual rate of return time series for portfolio.

assets_close_monthly

Show assets monthly close time series adjusted to the base currency.

assets_dividend_yield

Calculate last twelve months (LTM) dividend yield time series (monthly) for each asset.

assets_ror

Rate of return monthly time series for all assets.

close_monthly

Portfolio size monthly time series.

currency

Return the base currency.

describe([years])

Generate descriptive statistics for the portfolio.

diversification_ratio

Calculate Diversification Ratio for the portfolio.

dividend_yield

Calculate last twelve months (LTM) dividend yield time series for the portfolio.

dividend_yield_annual

Calculate last twelve months (LTM) dividend yield annual time series.

dividends

Calculate portfolio dividends monthly time series.

dividends_annual

Return calendar year dividends sum time series for each asset.

drawdowns

Calculate drawdowns time series for the portfolio.

get_cagr([period, real])

Calculate the expanding portfolio Compound Annual Growth Rate (CAGR) time series.

get_cumulative_return([period, real])

Calculate the expanding cumulative return time series for the portfolio.

get_cvar_historic([time_frame, level])

Calculate historic Conditional Value at Risk (CVAR, expected shortfall) for the portfolio.

get_monthly_geometric_mean_return()

Calculate monthly geometric mean return for the portfolio.

get_rolling_cagr([window, real])

Calculate rolling CAGR (Compound Annual Growth Rate) for the portfolio.

get_rolling_cumulative_return([window, real])

Calculate rolling cumulative return.

get_sharpe_ratio([rf_return])

Calculate Sharpe ratio.

get_sortino_ratio([t_return])

Calculate Sortino ratio for the portfolio with specified target return.

get_var_historic([time_frame, level])

Calculate historic Value at Risk (VaR) for the portfolio.

mean_return_annual

Calculate annualized mean return (arithmetic mean) for the portfolio rate of return time series.

mean_return_monthly

Calculate monthly mean return (arithmetic mean) for the portfolio rate of return time series.

name

Return text name of portfolio.

number_of_securities

Calculate the number of securities monthly time series for the portfolio assets.

okamaio_link

URL link to portfolio at okama.io.

percentile_cagr(years[, percentiles])

Calculate given percentiles for portfolio rolling CAGR distribution from the historical data.

percentile_inverse_cagr([years, score])

Compute the percentile rank of a score (CAGR value).

plot_assets([kind, tickers, pct_values, xy_text])

Plot asset points on the risk-return chart with annotations.

real_mean_return

Calculate annualized real mean return (arithmetic mean) for the rate of return time series.

rebalancing_events

Time series with the dates of rebalancing events.

rebalancing_strategy

Return rebalancing strategy of the portfolio.

recovery_period

Get recovery period time series for the portfolio value.

risk_annual

Calculate annualized risk expanding time series for portfolio.

risk_monthly

Calculate monthly risk expanding time series for Portfolio.

ror

Calculate monthly rate of return time series for portfolio considering rebalancing strategy.

semideviation_annual

Return semideviation annualized value for portfolio rate of return time series.

semideviation_monthly

Calculate semi-deviation monthly value for portfolio rate of return time series.

symbol

Return a text symbol of portfolio.

symbols

Return a list of used financial symbols.

table

Return table with security name, ticker, weight for assets in the portfolio.

tickers

Return a list of used tickers (symbols without a namespace).

wealth_index

Calculate wealth index time series for the portfolio and accumulated inflation.

wealth_index_with_assets

Calculate wealth index time series for the portfolio, all assets and accumulated inflation.

weights

Assets weights in portfolio.

weights_ts

Calculate assets weights time series considering rebalancing strategy.

property weights

Assets weights in portfolio.

If not defined equal weights are used for each asset.

Weights must be a list (or tuple) of float values.

Returns:
list or tuple

Values for the weights of assets in portfolio.

Examples

>>> x = ok.Portfolio(["SPY.US", "BND.US"])
>>> x.weights
[0.5, 0.5]
property weights_ts

Calculate assets weights time series considering rebalancing strategy.

The weights of assets in Portfolio are not constant if rebalancing_period is different from ‘month’.

Returns:
DataFrame

Weights of assets time series.

Examples

>>> import matplotlib.pyplot as plt
>>> reb_period = ok.Rebalance(period="none")  # The Portfolio is not rebalanced.
>>> pf = ok.Portfolio(["SPY.US", "AGG.US"], weights=[0.5, 0.5], rebalancing_strategy=reb_period)
>>> pf.weights_ts.plot()
>>> plt.show()
../_images/okama-Portfolio-1_00_00.png

The weights of assets time series will differ significantly if the portfolio rebalancing_period is 1 year.

>>> pf.rebalancing_strategy = ok.Rebalance(period="year")  # set a new rebalancing period
>>> pf.weights_ts.plot()
>>> plt.show()
../_images/okama-Portfolio-1_01_00.png
property rebalancing_events

Time series with the dates of rebalancing events.

Each event has the type of rebalancing event: - calendar (calendar event) - abs (rebalancing by absolute deviation) - rel (rebalancing by relative deviation)

Returns:
DataFrame

Dates of rebalancing events time series.

Examples

>>> pf = ok.Portfolio(
...     assets=["SPY.US", "AGG.US"],
...     weights=[0.5, 0.5],
...     rebalancing_strategy=ok.Rebalance(period="year", abs_deviation=0.05),
... )
>>> pf.rebalancing_events
date
2004-05    calendar
2005-05    calendar
2006-05    calendar
2007-05    calendar
2008-05    calendar
             ...
2020-05    calendar
2020-11         abs
2021-05    calendar
2022-05    calendar
2023-05    calendar
Name: event, Length: 21, dtype: object
property rebalancing_strategy

Return rebalancing strategy of the portfolio.

Rebalancing is the process by which an investor restores their portfolio to its target allocation by selling and buying assets. After rebalancing all the assets have original weights.

Rebalancing period (rebalancing frequency) is predetermined time intervals when the investor rebalances the portfolio.

Returns:
Rebalance

Portfolio rebalancing strategy.

Examples

>>> pf = ok.Portfolio(
...     assets=["SPY.US", "AGG.US"],
...     weights=[0.5, 0.5],
...     rebalancing_strategy=ok.Rebalance(period="year", abs_deviation=0.05),
... )
>>> pf.rebalancing_strategy
Rebalance(period='year', abs_deviation=0.05, rel_deviation=None)
property symbol

Return a text symbol of portfolio.

Symbols are similar to tickers but have a namespace information:

  • SPY.US is a symbol

  • SPY is a ticker

Portfolios have ‘.PF’ as a namespace.

Returns:
str

Text symbol of the portfolio.

Examples

>>> p = ok.Portfolio()
>>> p.symbol  # a randomly generated symbol will be shown
'portfolio_5312.PF'
>>> p.symbol = "spy_portfolo.PF"  # The symbol can be customized after initialization

New Portfolio can have a custom symbol.

>>> p = ok.Portfolio(symbol="aggressive.PF")
>>> p.symbol
'aggressive.PF'
property name

Return text name of portfolio.

For Portfolio name is equal to symbol.

Returns:
str

Text name of the portfolio.

>>> p = ok.Portfolio()
    ..
>>> p.name
    ..
‘portfolio_5312.PF’
property ror

Calculate monthly rate of return time series for portfolio considering rebalancing strategy.

Returns:
Series

Rate of return monthly time series for the portfolio.

Examples

>>> pf = ok.Portfolio(first_date="2020-01", last_date="2020-12")
>>> pf.ror
Date
2020-01   -0.0004
2020-02   -0.0792
2020-03   -0.1249
2020-04    0.1270
2020-05    0.0476
2020-06    0.0177
2020-07    0.0589
2020-08    0.0698
2020-09   -0.0374
2020-10   -0.0249
2020-11    0.1088
2020-12    0.0370
Freq: M, Name: portfolio_4669.PF, dtype: float64
>>> import matplotlib.pyplot as plt
>>> pf.ror.plot(kind="bar")
>>> plt.show()
../_images/okama-Portfolio-2.png
property wealth_index

Calculate wealth index time series for the portfolio and accumulated inflation.

Wealth index (Cumulative Wealth Index) is a time series that presents the value of portfolio over historical time period. Accumulated inflation time series is added if inflation=True in the Portfolio.

Wealth index is obtained from the accumulated return multiplied by the initial investments. That is: 1000 * (Acc_Return + 1) Initial investments are taken as 1000 units of the Portfolio base currency.

Returns:
DataFrame

Time series of wealth index values for portfolio and accumulated inflation.

Examples

>>> import matplotlib.pyplot as plt
>>> x = ok.Portfolio(["SPY.US", "BND.US"])
>>> x.wealth_index.plot()
>>> plt.show()
../_images/okama-Portfolio-3.png
property wealth_index_with_assets

Calculate wealth index time series for the portfolio, all assets and accumulated inflation.

Cash flows are not taken into account.

Wealth index (Cumulative Wealth Index) is a time series that presents the value of portfolio over historical time period. Accumulated inflation time series is added if inflation=True in the Portfolio.

Wealth index is obtained from the accumulated return multiplied by the initial investments. initial_amount_pv * (Acc_Return + 1)

Returns:
DataFrame

Time series of wealth index values for portfolio, each asset and accumulated inflation.

Examples

>>> import matplotlib.pyplot as plt
>>> pf = ok.Portfolio(["VOO.US", "GLD.US"], weights=[0.8, 0.2])
>>> pf.wealth_index_with_assets.plot()
>>> plt.show()
../_images/okama-Portfolio-4.png
property mean_return_monthly

Calculate monthly mean return (arithmetic mean) for the portfolio rate of return time series.

Mean return calculated for the full history period.

Returns:
float

Mean return value.

Examples

>>> pf = ok.Portfolio(["ISF.LSE", "XGLE.LSE"], weights=[0.6, 0.4], ccy="GBP")
>>> pf.mean_return_monthly
0.0001803312727272665
property mean_return_annual

Calculate annualized mean return (arithmetic mean) for the portfolio rate of return time series.

Mean return calculated for the full history period.

Returns:
float

Mean return value.

Examples

>>> pf = ok.Portfolio(["XCS6.XETR", "PHAU.LSE"], weights=[0.85, 0.15], ccy="USD")
>>> pf.names
{'XCS6.XETR': 'Xtrackers MSCI China UCITS ETF 1C', 'PHAU.LSE': 'WisdomTree Physical Gold'}
>>> pf.mean_return_annual
0.09005826844072184
annual_return_ts(return_type='cagr')

Calculate annual rate of return time series for portfolio.

Rate of return is calculated for each calendar year.

Parameters:
return_type{‘cagr’, ‘arithmetic_mean’}, default ‘cagr’

Method used to calculate annual returns.

Returns:
Series

Calendar annual rate of return time series.

Examples

>>> import matplotlib.pyplot as plt
>>> pf = ok.Portfolio(["VOO.US", "AGG.US"], weights=[0.4, 0.6])
>>> pf.annual_return_ts().plot(kind="bar")
>>> plt.show()
../_images/okama-Portfolio-5_00_00.png

Plot annual returns for portfolio with EUR as the base currency.

>>> pf = ok.Portfolio(["VOO.US", "AGG.US"], weights=[0.4, 0.6], ccy="EUR")
>>> pf.annual_return_ts().plot(kind="bar")
>>> plt.show()
../_images/okama-Portfolio-5_01_00.png
get_cagr(period=None, real=False)

Calculate the expanding portfolio Compound Annual Growth Rate (CAGR) time series.

The expanding CAGR at each month is the annualized rate of return required for the investment to grow from its initial value to its value at that month, assuming all incomes were reinvested. The last row contains the CAGR over the full selected period.

Inflation adjusted annualized returns (real CAGR) are shown with real=True option. Annualized inflation is calculated for the same period if inflation=True in the Portfolio.

Parameters:
periodint, default None

CAGR trailing period in years. If None, use the full available period.

realbool, default False

CAGR is adjusted for inflation (real CAGR) if True. Portfolio should be initiated with inflation=True for real CAGR.

Returns:
DataFrame

Time series of expanding portfolio CAGR and annualized inflation (if inflation=True in Portfolio and real=False).

Notes

CAGR is not defined for periods less than 1 year. The first 11 rows are filled with NaN values.

Examples

>>> pf = ok.Portfolio(["SPY.US", "BND.US"], weights=[0.6, 0.4], ccy="USD", inflation=True)
>>> pf.get_cagr(period=5).tail()

The last row contains the CAGR values over the full selected period.

To get inflation adjusted annualized return (real CAGR) add real=True option:

>>> pf.get_cagr(period=5, real=True).tail()
get_rolling_cagr(window=12, real=False)

Calculate rolling CAGR (Compound Annual Growth Rate) for the portfolio.

Parameters:
windowint, default 12

Size of the moving window in months. Window size should be at least 12 months for CAGR.

realbool, default False

CAGR is adjusted for inflation (real CAGR) if True. Portfolio should be initiated with Inflation=True for real CAGR.

Returns:
DataFrame

Time series of rolling CAGR and mean inflation (optionally).

Notes

CAGR is not defined for periods less than 1 year (NaN values are returned).

Examples

>>> x = ok.Portfolio(["SPY.US", "BND.US"], ccy="EUR", inflation=True)
>>> x.get_rolling_cagr(window=5 * 12, real=True)
         portfolio_...
date
...             ...
get_monthly_geometric_mean_return()

Calculate monthly geometric mean return for the portfolio.

The geometric mean return is the constant periodic return that would produce the same final value as a sequence of varying periodic returns when compounded over time.

Returns:
float

Monthly geometric mean return value.

Examples

>>> pf = ok.Portfolio(["SPY.US", "AGG.US"], weights=[0.6, 0.4])
>>> pf.get_monthly_geometric_mean_return()
0.005321
get_cumulative_return(period=None, real=False)

Calculate the expanding cumulative return time series for the portfolio.

The cumulative return is the total compounded change in the portfolio price from the start of the selected period up to and including each subsequent month. The last row contains the cumulative return over the full selected period.

Inflation adjusted cumulative returns (real cumulative returns) are shown with real=True option. Inflation data is taken from the same period if inflation=True in the Portfolio.

Parameters:
periodstr or int or None, default None

Trailing period in years. None - full time cumulative return. ‘YTD’ - (Year To Date) period of time beginning the first day of the calendar year up to the last month.

realbool, default False

Cumulative return is adjusted for inflation (real cumulative return) if True. Portfolio should be initiated with Inflation=True for real cumulative return.

Returns:
DataFrame

Time series of cumulative return for the portfolio and cumulative inflation (if inflation=True in Portfolio and real=False).

Examples

>>> pf = ok.Portfolio(["BTC-USD.CC", "LTC-USD.CC"], weights=[0.8, 0.2], last_date="2021-03")
>>> pf.get_cumulative_return(period=2, real=True).tail()
         portfolio_6232.PF
2020-11           3.624500
2020-12           5.125700
2021-01           7.328400
2021-02           8.612000
2021-03           9.393810

The last row contains the cumulative return over the full selected period.

get_rolling_cumulative_return(window=12, real=False)

Calculate rolling cumulative return.

The cumulative return is the total change in the portfolio price.

Parameters:
windowint, default 12

Size of the moving window in months.

realbool, default False

Cumulative return is adjusted for inflation (real cumulative return) if True. Portfolio should be initiated with Inflation=True for real cumulative return.

Returns:
DataFrame

Time series of rolling cumulative return and inflation (optional).

Examples

>>> pf = ok.Portfolio(
...     ["SPY.US", "AGG.US", "GLD.US"],
...     weights=[0.6, 0.35, 0.05],
...     rebalancing_strategy=ok.Rebalance(period="year"),
... )
>>> pf.get_rolling_cumulative_return(window=24, real=True)
         portfolio_9012.PF
2006-11           0.125728
2006-12           0.104348
2007-01           0.129601
2007-02           0.110680
2007-03           0.132610
                    ...
2021-03           0.263755
2021-04           0.275474
2021-05           0.322736
2021-06           0.264963
2021-07           0.273801
[177 rows x 1 columns]
property assets_close_monthly

Show assets monthly close time series adjusted to the base currency.

Returns:
DataFrame

Assets monthly close time series adjusted to the base currency.

Examples

>>> import matplotlib.pyplot as plt
>>> pf = ok.Portfolio(["SPY.US", "BND.US"], ccy="USD")
>>> pf.assets_close_monthly.plot()
>>> plt.show()
../_images/okama-Portfolio-6.png
property close_monthly

Portfolio size monthly time series.

Portfolio size is shown in base currency units. It is similar to the close value of an asset. Initial portfolio value is equal to 1000 units of base currency.

Returns:
pd.Series

Monthly portfolio size time series.

Notes

‘close_mothly’ shows the same output as the ‘wealth_index’. This property is required as Portfolio must have the same attributes as an Asset.

Examples

>>> import matplotlib.pyplot as plt
>>> pf = ok.Portfolio(["SPY.US", "BND.US"], ccy="USD")
>>> pf.close_monthly.plot()
>>> plt.show()
../_images/okama-Portfolio-7.png
property number_of_securities

Calculate the number of securities monthly time series for the portfolio assets.

The number of securities in the Portfolio is changing over time as the dividends are reinvested. Portfolio rebalancing also affects the number of securities.

Initial number of securities depends on the portfolio size in base currency (1000 units).

Returns:
DataFrame

Number of securities monthly time series for the portfolio assets.

Examples

>>> pf = ok.Portfolio(["SPY.US", "BND.US"], ccy="USD", last_date="07-2021")
>>> pf.number_of_securities
           SPY.US     BND.US
Date
2007-05  3.261153   6.687174
2007-06  3.337216   6.758447
2007-07  3.407015   6.643519
2007-08  3.410268   6.663862
2007-09  3.372630   6.798730
           ...        ...
2021-03  3.273521  15.313911
2021-04  3.204779  15.685601
2021-05  3.196768  15.749127
2021-06  3.186124  15.879056
2021-07  3.166335  16.003569
[171 rows x 2 columns]
property dividends

Calculate portfolio dividends monthly time series.

Portfolio dividends are obtained by summing asset dividends adjusted to the base currency. Dividends size depends on the portfolio value and number of securities.

Returns:
Series

Portfolio dividends monthly time series.

Examples

>>> pf = ok.Portfolio(["SPY.US", "BND.US"], ccy="USD", last_date="07-2021")
>>> pf.dividends
2007-05    0.849271
2007-06    3.928855
2007-07    1.551262
2007-08    2.023148
2007-09    4.423416
             ...
2021-03    6.155337
2021-04    3.019478
2021-05    2.056836
2021-06    6.519521
2021-07    2.114071
Freq: M, Name: portfolio_2951.PF, Length: 171, dtype: float64
property dividend_yield

Calculate last twelve months (LTM) dividend yield time series for the portfolio. Time series has monthly values.

Portfolio dividend yield is a weighted sum of the assets dividend yields (adjusted to the portfolio base currency).

For an asset LTM dividend yield is the sum trailing twelve months of common dividends per share divided by the current price per share.

Returns:
Series

Portfolio LTM dividend yield monthly time series.

Examples

>>> pf = ok.Portfolio(["T.US", "XOM.US"], weights=[0.8, 0.2], first_date="2010-01", last_date="2021-01", ccy="USD")
>>> pf.dividend_yield
2010-01    0.013249
2010-02    0.014835
2010-03    0.014257
             ...
2020-11    0.076132
2020-12    0.074743
2021-01    0.073643
Freq: M, Name: portfolio_8836.PF, Length: 133, dtype: float64
>>> import matplotlib.pyplot as plt
>>> pf.dividend_yield.plot()
>>> plt.show()
../_images/okama-Portfolio-8.png
property dividends_annual

Return calendar year dividends sum time series for each asset.

Returns:
DataFrame

Annual dividends time series for each asset.

Examples

>>> import matplotlib.pyplot as plt
>>> pf = ok.Portfolio(["SPY.US", "BND.US"], ccy="USD", last_date="07-2021")
>>> pf.dividends_annual.plot(kind="bar")
>>> plt.show()
../_images/okama-Portfolio-9.png
property dividend_yield_annual

Calculate last twelve months (LTM) dividend yield annual time series.

Time series is based on the dividend yield for the end of calendar year.

LTM dividend yield is the sum trailing twelve months of common dividends per share divided by the current price per share.

All yields are calculated in the asset list base currency after adjusting the dividends and price time series. Forecasted (future) dividends are removed.

Returns:
DataFrame

Time series of LTM dividend yield for each asset.

See also

dividend_yield

Dividend yield time series.

dividends_annual

Calendar year dividends time series.

dividend_paying_years

Number of years of consecutive dividend payments.

dividend_growing_years

Number of years when the annual dividend was growing.

get_dividend_mean_yield

Arithmetic mean for annual dividend yield.

get_dividend_mean_growth_rate

Geometric mean of annual dividends growth rate.

Examples

>>> import matplotlib.pyplot as plt
>>> pf = ok.Portfolio(["SPY.US", "BND.US"], ccy="USD", last_date="07-2021")
>>> pf.dividend_yield_annual.plot(kind="bar")
>>> plt.show()
../_images/okama-Portfolio-10.png
property assets_dividend_yield

Calculate last twelve months (LTM) dividend yield time series (monthly) for each asset.

LTM dividend yield is the sum trailing twelve months of common dividends per share divided by the current price per share.

All yields are calculated in the asset list base currency after adjusting the dividends and price time series. Forecasted (future) dividends are removed. Zero value time series are created for assets without dividends.

Returns:
DataFrame

Monthly time series of LTM dividend yield for each asset.

See also

dividend_yield_annual

Calendar year dividend yield time series.

dividends_annual

Calendar year dividends time series.

dividend_paying_years

Number of years of consecutive dividend payments.

dividend_growing_years

Number of years when the annual dividend was growing.

get_dividend_mean_yield

Arithmetic mean for annual dividend yield.

get_dividend_mean_growth_rate

Geometric mean of annual dividends growth rate.

Examples

>>> x = ok.AssetList(["T.US", "XOM.US"], first_date="1984-01", last_date="1994-12")
>>> x.dividend_yield
           T.US    XOM.US
1984-01  0.000000  0.000000
1984-02  0.000000  0.002597
1984-03  0.002038  0.002589
1984-04  0.001961  0.002346
           ...       ...
1994-09  0.018165  0.012522
1994-10  0.018651  0.011451
1994-11  0.018876  0.012050
1994-12  0.019344  0.011975
[132 rows x 2 columns]
property real_mean_return

Calculate annualized real mean return (arithmetic mean) for the rate of return time series.

Real rate of return is adjusted for inflation. Real return is defined if there is an inflation=True option in Portfolio.

Returns:
float

Annualized value of the mean for the real rate of return time series.

Examples

>>> pf = ok.Portfolio(["MSFT.US", "AAPL.US"])
>>> pf.real_mean_return
0.3088967455111862
property risk_monthly

Calculate monthly risk expanding time series for Portfolio.

Monthly risk of portfolio is a standard deviation of the rate of return time series. Standard deviation (sigma) is normalized by N-1.

Returns:
Series

Standard deviation of the monthly return expanding time series.

See also

risk_annual

Calculate annualized risks.

semideviation_monthly

Calculate semideviation monthly values.

semideviation_annual

Calculate semideviation annualized values.

get_var_historic

Calculate historic Value at Risk (VaR).

get_cvar_historic

Calculate historic Conditional Value at Risk (CVaR).

drawdowns

Calculate drawdowns.

Examples

>>> pf = ok.Portfolio(["MSFT.US", "AAPL.US"])
>>> pf.risk_monthly
date
1986-05    0.020117
1986-06    0.122032
1986-07    0.130113
1986-08    0.116642
             ...
2023-08    0.092875
2023-09    0.092861
2023-10    0.092759
2023-11    0.092763
2023-12    0.092665
Freq: M, Name: portfolio_1094.PF, Length: 453, dtype: float64
property risk_annual

Calculate annualized risk expanding time series for portfolio.

Risk is a standard deviation of the rate of return.

Annualized risk is calculated for rate of retirun time series for the sample from ‘first_date’ to ‘last_date’.

Returns:
Series

Annualized standard deviation of the monthly return expanding time series.

Examples

>>> pf = ok.Portfolio(["MSFT.US", "AAPL.US"])
>>> pf.risk_annual
date
1986-05    0.285175
1986-06    0.890909
1986-07    0.616876
1986-08    0.632270
1986-09    0.509642
             ...
2023-08    0.428297
2023-09    0.427350
2023-10    0.426961
2023-11    0.427930
property semideviation_monthly

Calculate semi-deviation monthly value for portfolio rate of return time series.

Semi-deviation (Downside risk) is the risk of the return being below the expected return.

Returns:
float

Semi-deviation monthly value for portfolio rate of return time series.

Examples

>>> pf = ok.Portfolio(["MSFT.US", "AAPL.US"], last_date="2024-12")
>>> pf.semideviation_monthly
0.057319735856567695
property semideviation_annual

Return semideviation annualized value for portfolio rate of return time series.

Semi-deviation (Downside risk) is the risk of the return being below the expected return.

Returns:
float

Annualized semi-deviation monthly value for portfolio rate of return time series.

Examples

>>> pf = ok.Portfolio(["MSFT.US", "AAPL.US"], last_date="2024-12")
>>> pf.semideviation_annual
0.1985613895600056
get_var_historic(time_frame=12, level=1)

Calculate historic Value at Risk (VaR) for the portfolio.

The VaR calculates the potential loss of an investment with a given time frame and confidence level. Loss is a positive number (expressed in cumulative return). If VaR is negative there are expected gains at this confidence level.

Parameters:
time_frameint, default 12

Time frame for VAR. Default is 12 months.

levelint, default 1

Confidence level in percents. Default value is 1%.

Returns:
float

Historic Value at Risk (VaR) value for the portfolio.

Examples

>>> x = ok.Portfolio(["SP500TR.INDX", "SP500BDT.INDX"], last_date="2021-01")
>>> x.get_var_historic(time_frame=12, level=1)
0.24030006476701732
get_cvar_historic(time_frame=12, level=1)

Calculate historic Conditional Value at Risk (CVAR, expected shortfall) for the portfolio.

CVaR is the average loss over a specified time period of unlikely scenarios beyond the confidence level. Loss is a positive number (expressed in cumulative return). If CVaR is negative there are expected gains at this confidence level.

Parameters:
time_frameint, default 12

Time period size in months.

levelint, default 1

Confidence level in percents to calculate the VaR. Default value is 1% (1% quantile).

Returns:
float

Historic Conditional Value at Risk (CVAR, expected shortfall) value for the portfolio.

Examples

>>> x = ok.Portfolio(["USDEUR.FX", "BTC-USD.CC"], last_date="2021-01")
>>> x.get_cvar_historic(time_frame=2, level=1)
0.3566909250442616
property drawdowns

Calculate drawdowns time series for the portfolio.

The drawdown is the percent decline from a previous peak in wealth index.

Returns:
Series

Drawdowns time series for the portfolio

property recovery_period

Get recovery period time series for the portfolio value.

The recovery period (drawdown duration) is the number of months to reach the value of the last maximum.

Returns:
pd.Series

Recovery period time series for the portfolio value

See also

drawdowns

Calculate drawdowns time series.

Notes

The largest recovery period does not necessary correspond to the max drawdown.

Examples

>>> pf = ok.Portfolio(["SPY.US", "AGG.US"], weights=[0.5, 0.5])
>>> pf.recovery_period.nlargest()
date
2010-10    35
2004-10     7
2012-01     7
2019-03     6
2018-07     5
Freq: M, Name: portfolio_5724.PF, dtype: int32
describe(years=(1, 5, 10))

Generate descriptive statistics for the portfolio.

Statistics includes:

  • YTD (Year To date) compound return

  • CAGR for a given list of periods and full available period

  • Annualized mean rate of return (full available period)

  • LTM Dividend yield - last twelve months dividend yield

Risk metrics (full available period):

  • risk (standard deviation)

  • CVAR (timeframe is 1 year)

  • max drawdowns (and dates)

Parameters:
yearstuple of int, default (1, 5, 10)

List of periods for CAGR statistics.

Returns:
DataFrame

Table of descriptive statistics for the portfolio.

See also

get_cumulative_return

Calculate cumulative return.

get_cagr

Calculate portfolio Compound Annual Growth Rate (CAGR).

dividend_yield

Calculate dividend yield (LTM).

risk_annual

Return annualized risks (standard deviation).

get_cvar_historic

Calculate historic Conditional Value at Risk (CVAR, expected shortfall).

drawdowns

Calculate drawdowns.

Examples

>>> pf = ok.Portfolio(["SPY.US", "BND.US"], ccy="USD", last_date="07-2021")
>>> pf.describe(years=[2, 5, 7])  # 'years' customizes the timeframe for the CAGR
            property              period portfolio_2951.PF  inflation
0    compound return                 YTD          0.084098   0.048154
1               CAGR             2 years          0.141465   0.031566
2               CAGR             5 years          0.102494   0.025582
3               CAGR             7 years          0.091694   0.019656
4               CAGR  14 years, 3 months          0.074305   0.019724
5     Dividend yield                 LTM          0.016504        NaN
6               Risk  14 years, 3 months          0.086103        NaN
7               CVAR  14 years, 3 months          0.214207        NaN
8       Max drawdown  14 years, 3 months         -0.266915        NaN
9  Max drawdown date  14 years, 3 months           2009-02        NaN
property table

Return table with security name, ticker, weight for assets in the portfolio.

Returns:
DataFrame

Security name - ticker - weight table.

Examples

>>> pf = ok.Portfolio(["MSFT.US", "AAPL.US"])
>>> pf.table
                asset name   ticker  weights
0  Microsoft Corporation  MSFT.US      0.5
1              Apple Inc  AAPL.US      0.5
property assets_ror

Rate of return monthly time series for all assets.

Returns:
DataFrame

Rate of return monthly data.

property currency

Return the base currency.

Such properties as rate of return and risk are adjusted to the base currency.

Returns:
str

Base currency.

percentile_inverse_cagr(years=1, score=0)

Compute the percentile rank of a score (CAGR value).

Percentile rank can be calculated for a historical distribution of CAGR.

If percentile_inverse of, for example, 0% (CAGR value) is equal to 8% for 1 year time frame it means that 8% of the CAGR values in the distribution are negative in 1 year periods. Or in other words the probability of getting negative result after 1 year of investments is 8%.

Parameters:
yearsint, default 1

Period length (time frame) in years when CAGR is calculated.

scorefloat, default 0

Score that is compared to the elements in CAGR array.

Returns:
float

Percentile-position of score (0-100) relative to distribution.

Examples

>>> pf = ok.Portfolio(
...     ["SPY.US", "AGG.US", "GLD.US"],
...     weights=[0.60, 0.35, 0.05],
...     rebalancing_strategy=ok.Rebalance(period="year"),
... )
>>> pf.percentile_inverse_cagr(score=0, years=1)
18.08
The probability of getting negative result (score=0) in 1 year period for historical distribution.
plot_assets(kind='mean', tickers='tickers', pct_values=False, xy_text=(0, 10), **kwargs)

Plot asset points on the risk-return chart with annotations.

Annualized values for risk and return are used. Risk is the standard deviation of monthly rate of return time series. Return can be an annualized mean return (expected return) or CAGR (compound annual growth rate).

Parameters:
kind{‘mean’, ‘cagr’}, default ‘mean’

Type of return: annualized mean return (expected return) or CAGR (compound annual growth rate).

tickers{‘tickers’, ‘names’} or list of str, default ‘tickers’

Annotation type for assets.

  • ‘tickers’: asset symbols are shown in the form ‘SPY.US’.

  • ‘names’: asset names are shown (for example, ‘SPDR S&P 500 ETF Trust’).

  • list of str: custom annotations for each asset.

pct_valuesbool, default False

If True, show risk and return values in percent. If False, show values as decimals.

xy_texttuple, default (0, 10)

The shift of the annotation text (x, y) from the point.

**kwargs

Arbitrary keyword arguments passed to matplotlib.pyplot.scatter.

Returns:
Axes

Matplotlib axes object.

Examples

>>> import matplotlib.pyplot as plt
>>> al = ok.AssetList(["SPY.US", "AGG.US"], ccy="USD", inflation=False)
>>> al.plot_assets()
>>> plt.show()
../_images/okama-Portfolio-11_00_00.png

Plotting with default parameters values shows expected return, ticker annotations and algebraic values for risk and return. To use CAGR instead of expected return use kind=’cagr’.

>>> al.plot_assets(
...     kind="cagr",
...     tickers=["US Stocks", "US Bonds"],  # use custom annotations for the assets
...     pct_values=True,  # risk and return values are in percents
... )
>>> plt.show()
../_images/okama-Portfolio-11_01_00.png
property symbols

Return a list of used financial symbols.

Symbols are similar to tickers but have a namespace information:

  • SPY.US is a symbol

  • SPY is a ticker

Returns:
list of str

List of used symbols.

property tickers

Return a list of used tickers (symbols without a namespace).

Tickers are similar to symbols but do not have namespace information:

  • SPY is a ticker

  • SPY.US is a symbol

Returns:
list of str

List of used tickers.

percentile_cagr(years, percentiles=[10, 50, 90])

Calculate given percentiles for portfolio rolling CAGR distribution from the historical data.

CAGR - Compound Annual Growth Rate. Each percentile is calculated for a period range from 1 year to ‘years’.

Parameters:
yearsint

Max window size for rolling CAGR in the distribution in years. It should not exceed 1/2 of the portfolio history period length ‘period_length’.

percentileslist of int, default [10, 50, 90]

List of percentiles to be calculated.

Returns:
DataFrame

Table with percentiles values for each period from 1 to ‘years’.

Examples

>>> pf = ok.Portfolio(
...     ["SPY.US", "AGG.US", "GLD.US"],
...     weights=[0.60, 0.35, 0.05],
...     rebalancing_strategy=ok.Rebalance(period="none"),
... )
>>> pf.percentile_cagr(years=5, percentiles=[1, 50, 99])
             1         50        99
years
1     -0.231327  0.098693  0.295343
2     -0.101689  0.091824  0.206471
3     -0.036771  0.085428  0.157833
4     -0.007674  0.085178  0.142195
5      0.030933  0.082865  0.134496
get_sharpe_ratio(rf_return=0)

Calculate Sharpe ratio.

The Sharpe ratio is the average annual return in excess of the risk-free rate per unit of risk (annualized standard deviation).

Risk-free rate should be taken according to the Portfolio base currency.

Parameters:
rf_returnfloat, default 0

Risk-free rate of return.

Returns:
float

Examples

>>> pf = ok.Portfolio(["VOO.US", "BND.US"], weights=[0.40, 0.60])
>>> pf.get_sharpe_ratio(rf_return=0.04)
0.7412193684695373
get_sortino_ratio(t_return=0)

Calculate Sortino ratio for the portfolio with specified target return.

Sortion ratio measures the risk-adjusted return of portfolio. It is a modification of the Sharpe ratio but penalizes only those returns falling below a specified target rate of return, while the Sharpe ratio penalizes both upside and downside volatility equally.

Parameters:
t_returnfloat, default 0

Traget rate of return.

Returns:
float

Examples

>>> pf = ok.Portfolio(["VOO.US", "BND.US"], last_date="2021-12")
>>> pf.get_sortino_ratio(t_return=0.02)
1.4377728903230174
property diversification_ratio

Calculate Diversification Ratio for the portfolio.

The Diversification Ratio is the ratio of the weighted average of assets risks divided by the portfolio risk. In this case risk is the annuilized standatd deviation for the rate of return .

Returns:
float

Examples

>>> pf = ok.Portfolio(["VOO.US", "BND.US"], weights=[0.7, 0.3], last_date="2021-12")
>>> pf.diversification_ratio
1.1264305597257505

URL link to portfolio at okama.io.

Portfolio with the same tickers, weights and other properties at okama.io financial widgets.

Returns:
str

URL link to portfolio at okama.io.

Examples

>>> pf = ok.Portfolio(
...     ["SPY.US", "AGG.US"],
...     weights=[0.60, 0.40],
...     rebalancing_strategy=ok.Rebalance(period="year", abs_deviation=0.05),
... )
>>> pf.okamaio_link
'https://okama.io/portfolio?tickers=SPY.US,AGG.US&weights=60.0,40.0&ccy=USD&first_date=2003-10-01&last_date=2024-08-01&rebal=year&rebalancing_period=year&rebalancing_abs_deviation=0.05&symbol=portfolio_6323.PF'