okama.EfficientFrontier
- class EfficientFrontier(assets=None, *, first_date=None, last_date=None, ccy='USD', bounds=None, inflation=False, full_frontier=True, n_points=20, ticker_names=True)
Bases:
AssetList
Efficient Frontier with classic Mean-Variance optimization.
Efficient Frontier is a set of portfolios which satisfy the condition that no other portfolio exists with a higher expected return but with the same risk (standard deviation of return).
The points on the Efficient Frontier are obtained through the constrained optimization process (optimization with bounds). Bounds are defined with ‘bounds’ property.
In classic Markowitz optimization portfolios are rebalanced monthly and has constant weights (single period optimization).
- 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.
- bounds: tuple of ((float, float),…)
Bounds for the assets weights. Each asset can have weights limitation from 0 to 1.0. If an asset has limitation for 10 to 20%, bounds are defined as (0.1, 0.2). bounds = ((0, .5), (0, 1)) shows that in Portfolio with two assets first one has weight limitations from 0 to 50%. The second asset has no limitations.
- inflationbool, default True
Defines whether to take inflation data into account in the calculations. Including inflation could limit available data (last_date, first_date) as the inflation data is usually published with a one-month delay. With inflation = False some properties like real return are not available.
- n_pointsint, default 20
Number of points in the Efficient Frontier.
- full_frontierbool, default True
Defines whether to show the full Efficient Frontier or only its upper part. If ‘False’ Efficient Frontier has only the points with the return above Global Minimum Volatility (GMV) point.
- ticker_namesbool, default True
Defines whether to include full names of assets in the optimization report or only tickers.
Methods & Attributes
Return bounds for the assets weights.
Generate single period Efficient Frontier.
get_monte_carlo
([n, kind])Generate N random portfolios with Monte Carlo simulation.
Calculate assets weights, risk, return and Diversification ratio for the most diversified portfolio given the target return within given bounds.
get_tangency_portfolio
([rf_return, ...])Calculate asset weights, risk and return values for tangency portfolio within given bounds.
Calculate the annualized risk and return of the Global Minimum Volatility (GMV) portfolio within given bounds.
Calculate the monthly risk and return of the Global Minimum Volatility (GMV) portfolio within given bounds.
Calculate asset weights of the Global Minimum Volatility (GMV) portfolio within given bounds.
Generate Most diversified portfolios frontier.
Calculate the range of mean monthly returns (from min to max).
minimize_risk
(target_return[, ...])Find minimal risk given the target return within given bounds.
optimize_return
([option])Find a portfolio with global max or min for the rate of return within given bounds.
plot_cml
([rf_return, y_axe, figsize])Plot Capital Market Line (CML).
plot_pair_ef
([tickers, figsize])Plot Efficient Frontier of every pair of assets.
plot_transition_map
([x_axe, figsize])Plot Transition Map for optimized portfolios on the single period Efficient Frontier.
- property bounds
Return bounds for the assets weights.
Bounds are used in Mean-Variance optimization. Each asset can have weights limitation from 0 to 1.0.
If an asset has limitation for 10 to 20% bounds are defined as (0.1, 0.2). bounds = ((0, .5), (0, 1)) shows that in Portfolio with two assets first one has weight limitations from 0 to 50%. The second asset has no limitations.
- Returns:
- tuple of ((float, float),…)
Weights bounds used for portfolio optimization.
Examples
>>> two_assets = ok.EfficientFrontier(['SPY.US', 'AGG.US']) >>> two_assets.bounds ((0.0, 1.0), (0.0, 1.0))
By default there are no limitations for assets weights. Bounds can be set for a Efficient Frontier object.
>>> two_assets.bounds = ((0.5, 0.9), (0, 1.0))
Now the optimization is bounded (SPY has weights limits from 50 to 90%).
- property gmv_weights
Calculate asset weights of the Global Minimum Volatility (GMV) portfolio within given bounds.
Global Minimum Volatility portfolio is a portfolio with the lowest risk of all possible. Along the Efficient Frontier, the left-most point is a portfolio with minimum risk when compared to all possible portfolios of risky assets.
In Mean-Variance optimization risk is defined as a standard deviation of return time series.
Bounds are defined with ‘bounds’ property.
- Returns:
- numpy.ndarray
GMV portfolio assets weights.
Examples
>>> two_assets = ok.EfficientFrontier(['SPY.US', 'AGG.US']) >>> two_assets.gmv_weights array([0.05474178, 0.94525822])
- property gmv_monthly
Calculate the monthly risk and return of the Global Minimum Volatility (GMV) portfolio within given bounds.
Global Minimum Volatility portfolio is a portfolio with the lowest risk of all possible. Along the Efficient Frontier, the left-most point is a portfolio with minimum risk when compared to all possible portfolios of risky assets.
In Mean-Variance optimization risk is defined as a standard deviation of return time series.
Bounds are defined with ‘bounds’ property.
- Returns:
- tuple
risk, return monthly values for GMV portfolio.
Examples
>>> ef = ok.EfficientFrontier(['SPY.US', 'AGG.US', 'GLD.US']) >>> ef.gmv_monthly (0.01024946425526032, 0.0036740056018316597)
- property gmv_annualized
Calculate the annualized risk and return of the Global Minimum Volatility (GMV) portfolio within given bounds.
Global Minimum Volatility portfolio is a portfolio with the lowest risk of all possible. Along the Efficient Frontier, the left-most point is a portfolio with minimum risk when compared to all possible portfolios of risky assets.
In Mean-Variance optimization risk is defined as a standard deviation of return time series.
Bounds are defined with ‘bounds’ property.
- Returns:
- tuple
risk, return annualized values for GMV portfolio.
Examples
>>> ef = ok.EfficientFrontier(['SPY.US', 'AGG.US', 'GLD.US']) >>> ef.gmv_annualized (0.03697734994430258, 0.0449899573148429)
- get_tangency_portfolio(rf_return=0, rate_of_return='cagr')
Calculate asset weights, risk and return values for tangency portfolio within given bounds.
Tangency portfolio or Maximum Sharpe Ratio (MSR) is the point on the Efficient Frontier where Sharpe Ratio reaches its maximum.
The Sharpe ratio is the average annual return in excess of the risk-free rate per unit of risk (annualized standard deviation).
Bounds are defined with ‘bounds’ property.
- Parameters:
- rate_of_return{cagr, mean_return}, default cagr
Use CAGR (Compound annual growth rate) or arithmetic mean of return to calculate Sharpe Ratio.
- rf_returnfloat, default 0
Risk-free rate of return.
- Returns:
- dict
Weights of assets, risk and return of the tangency portfolio.
Examples
>>> three_assets = ['MCFTR.INDX', 'RGBITR.INDX', 'GC.COMM'] >>> ef = ok.EfficientFrontier(assets=three_assets, ccy='USD', last_date='2022-06') >>> ef.get_tangency_portfolio(rf_return=0.03) # risk free rate of return is 3% {'Weights': array([0.30672901, 0. , 0.69327099]), 'Mean_return': 0.12265215404959617, 'Risk': 0.1882249366394522}
To calculate tangency portfolio parameters for CAGR (geometric mean) set cagr=True:
>>> ef.get_tangency_portfolio(rate_of_return="mean_return", rf_return=0.03) {'Weights': array([2.95364739e-01, 1.08420217e-17, 7.04635261e-01]), 'Mean_return': 0.10654206521088283, 'Risk': 0.048279725208422115}
- get_most_diversified_portfolio(target_return=None, monthly_return=False)
Calculate assets weights, risk, return and Diversification ratio for the most diversified portfolio given the target return within given bounds.
The most diversified portfolio has the largest Diversification Ratio.
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 .
- Parameters:
- target_returnfloat, optional
Rate of return value. The optimization process looks for a portfolio with the target_return and largest Diversification ratio. If not sepcifed global most diversified portfolio is obtained. Target return value can be in monthly or annual values depending on ‘monthly_return’ option.
- monthly_returnbool, default False
Defines whether to use rate of return monthly (True) or annual (False) values.
- Returns:
- dict
Weights of assets, risk and return of the most diversified portfolio.
Examples
>>> ls4 = ['SPY.US', 'AGG.US', 'VNQ.US', 'GLD.US'] >>> x = ok.EfficientFrontier(assets=ls4, ccy='USD', last_date='2021-12') >>> x.get_most_diversified_portfolio() # get a global most diversified portfolio {'SPY.US': 0.19612726258395477, 'AGG.US': 0.649730553241489, 'VNQ.US': 0.020096313783052246, 'GLD.US': 0.13404587039150392, 'Mean return': 0.0637820844415733, 'CAGR': 0.062355715886719176, 'Risk': 0.05510135025563423, 'Diversification ratio': 1.5665720501693001}
It is possible to get the most diversified portfolio for a given target rate of return. Set monthly_return=False to use annual values for the rate of return.
>>> x.get_most_diversified_portfolio(target_return=0.10, monthly_return=False) {'SPY.US': 0.3389762570274293, 'AGG.US': 0.12915657041748244, 'VNQ.US': 0.15083042115027034, 'GLD.US': 0.3810367514048179, 'Mean return': 0.10000000151051025, 'CAGR': 0.09370688842211439, 'Risk': 0.11725067815643951, 'Diversification ratio': 1.4419864802150442}
- optimize_return(option='max')
Find a portfolio with global max or min for the rate of return within given bounds.
The objective function is an arithmetic mean of monthly Rate of return.
Bounds are defined with ‘bounds’ property.
- Parameters:
- option{‘max’, ‘min’}, default ‘max’
Find objective function global maximun if ‘max’ or global minimum if ‘min’.
- Returns:
- dict
Weights of assets, risk and return of the portfolio.
Examples
>>> ef = ok.EfficientFrontier(['SPY.US', 'AGG.US', 'GLD.US']) >>> ef.optimize_return(option='max') {'Weights': array([1.00000000e+00, 1.94289029e-16, 1.11022302e-16]), 'Mean_return_monthly': 0.009144, 'Risk_monthly': 0.041956276163975015}
The global maximum can be found with constrained optimization using bounds.
>>> ef.bounds = ((0, 1.), (0, 1.), (0.20, 1.)) # The portfolio should have at least 20% of GLD >>> ef.optimize_return(option='max') {'Weights': array([8.00000000e-01, 5.48172618e-16, 2.00000000e-01]), 'Mean_return_monthly': 0.008894299999999997, 'Risk_monthly': 0.035570987973869726}
- minimize_risk(target_return, monthly_return=False, tolerance=1e-08)
Find minimal risk given the target return within given bounds.
In Mean-Variance optimization the objective function is risk (standard deviation of return time series).
Optimization returns a “point” on the Efficient Frontier with values:
weights of assets
annualized mean rate of return
Compound annual growth rate (CAGR)
annualized risk (annualized value of standard deviation)
Target return can have a monthly or annual value.
Bounds are defined with ‘bounds’ property.
- Parameters:
- target_returnfloat
Rate of return value. The optimization process looks for a portfolio with the target_return and minimum risk. Target return value can be in monthly or annual values depending on ‘monthly_return’ option.
- monthly_returnbool, default False
Defines whether to use rate of return monthly (True) or annual (False) values.
- tolerancefloat, default 1e-08
Sets the accuracy for the solver.
- Returns:
- dict
Point on the Efficient Frontier with assets weights, mean return, CAGR, risk.
Examples
>>> ef = ok.EfficientFrontier(['SPY.US', 'AGG.US', 'GLD.US'], last_date='2021-07') >>> ef.minimize_risk(target_return=0.044, monthly_return=False) {'SPY.US': 0.03817252986735185, 'AGG.US': 0.9618274701326482, 'GLD.US': 0.0, 'Mean return': 0.04400000000000004, 'CAGR': 0.04335075344214023, 'Risk': 0.037003608635098856}
- get_assets_tickers()
- property mean_return_range
Calculate the range of mean monthly returns (from min to max).
Number of values in the range is defined by ‘n_points’.
- Returns:
- numpy.ndarray
Monthly rate of return values from min to max.
Examples
>>> ef = ok.EfficientFrontier(['SPY.US', 'AGG.US', 'GLD.US'], last_date='2021-07') >>> ef.mean_return_range array([0.0033745 , 0.00367816, 0.00398182, 0.00428547, 0.00458913, 0.00489279, 0.00519645, 0.00550011, 0.00580376, 0.00610742, 0.00641108, 0.00671474, 0.00701839, 0.00732205, 0.00762571, 0.00792937, 0.00823303, 0.00853668, 0.00884034, 0.009144 ])
- property ef_points
Generate single period Efficient Frontier.
Each point on the Efficient Frontier is a portfolio with optimized risk for a given return.
The points are obtained through the constrained optimization process (optimization with bounds). Bounds are defined with ‘bounds’ property.
- Returns:
- DataFrame
Table of weights and risk/return values for the Efficient Frontier. The columns:
assets weights
CAGR (geometric mean)
Mean return (arithmetic mean)
Risk (standard deviation)
All the values are annualized.
Examples
>>> assets = ['SPY.US', 'AGG.US', 'GLD.US'] >>> last_date='2021-07' >>> y = ok.EfficientFrontier(assets, last_date=last_date) >>> y.ef_points Risk Mean return CAGR AGG.US GLD.US SPY.US 0 0.037707 0.041254 0.040579 1.000000e+00 9.278755e-09 2.220446e-16 1 0.036979 0.045042 0.044394 9.473684e-01 0.000000e+00 5.263158e-02 2 0.038027 0.048842 0.048157 8.947368e-01 0.000000e+00 1.052632e-01 3 0.040517 0.052655 0.051879 8.376442e-01 2.061543e-02 1.417404e-01 4 0.043944 0.056481 0.055569 7.801725e-01 4.298194e-02 1.768455e-01 5 0.048125 0.060320 0.059229 7.227015e-01 6.534570e-02 2.119528e-01 6 0.052902 0.064171 0.062856 6.652318e-01 8.770367e-02 2.470646e-01 7 0.058144 0.068035 0.066451 6.077632e-01 1.100558e-01 2.821809e-01 8 0.063753 0.071912 0.070014 5.502956e-01 1.324040e-01 3.173004e-01 9 0.069655 0.075802 0.073543 4.928283e-01 1.547504e-01 3.524213e-01 10 0.075796 0.079704 0.077039 4.353613e-01 1.770958e-01 3.875429e-01 11 0.082136 0.083620 0.080501 3.778987e-01 1.994207e-01 4.226806e-01 12 0.088645 0.087549 0.083928 3.204253e-01 2.217953e-01 4.577794e-01 13 0.095300 0.091491 0.087321 2.629559e-01 2.441514e-01 4.928926e-01 14 0.102084 0.095446 0.090678 2.054869e-01 2.665062e-01 5.280069e-01 15 0.108984 0.099414 0.093999 1.480175e-01 2.888623e-01 5.631202e-01 16 0.115991 0.103395 0.097284 9.054789e-02 3.112196e-01 5.982325e-01 17 0.123096 0.107389 0.100533 3.307805e-02 3.335779e-01 6.333441e-01 18 0.132674 0.111397 0.103452 0.000000e+00 2.432182e-01 7.567818e-01 19 0.161413 0.115418 0.103704 1.110223e-16 1.036379e-09 1.000000e+00
To plot the Efficient Frontier use the DataFrame with the points data. Additionaly ‘Plot.plot_assets()’ can be used to show the assets in the chart.
>>> import matplotlib.pyplot as plt >>> fig = plt.figure() >>> # Plot the assets points >>> y.plot_assets(kind='cagr') # kind should be set to "cagr" as we take "CAGR" column from the ef_points. >>> ax = plt.gca() >>> # Plot the Efficient Frontier >>> df = y.ef_points >>> ax.plot(df['Risk'], df['CAGR']) # we chose to plot CAGR which is geometric mean of return series >>> # Set the axis labels and the title >>> ax.set_title('Single period Efficient Frontier') >>> ax.set_xlabel('Risk (Standard Deviation)') >>> ax.set_ylabel('Return (CAGR)') >>> ax.legend() >>> plt.show()
- property mdp_points
Generate Most diversified portfolios frontier.
Each point on the Most diversified portfolios frontier is a portfolio with optimized Diversification ratio for a given return.
The points are obtained through the constrained optimization process (optimization with bounds). Bounds are defined with ‘bounds’ property.
- Returns:
- DataFrame
Table of weights and risk/return values for the Efficient Frontier. The columns:
assets weights
CAGR (geometric mean)
Mean return (arithmetic mean)
Risk (standard deviation)
Diversification ratio
All the values are annualized.
Examples
>>> ls4 = ['SP500TR.INDX', 'MCFTR.INDX', 'RGBITR.INDX', 'GC.COMM'] >>> y = ok.EfficientFrontier(assets=ls4, ccy='RUB', last_date='2021-12', n_points=100) >>> y.mdp_points # print mdp weights, risk, mean return, CAGR and Diversification ratio Risk Mean return CAGR ... MCFTR.INDX RGBITR.INDX SP500TR.INDX 0 0.066040 0.094216 0.092220 ... 2.081668e-16 1.000000e+00 0.000000e+00 1 0.064299 0.095342 0.093451 ... 0.000000e+00 9.844942e-01 5.828671e-16 2 0.062761 0.096468 0.094670 ... 0.000000e+00 9.689885e-01 1.110223e-16 3 0.061445 0.097595 0.095874 ... 5.828671e-16 9.534827e-01 0.000000e+00 4 0.060364 0.098724 0.097065 ... 3.191891e-16 9.379769e-01 0.000000e+00 .. ... ... ... ... ... ... ... 95 0.258857 0.205984 0.178346 ... 8.840844e-01 1.387779e-17 0.000000e+00 96 0.266583 0.207214 0.177941 ... 9.130633e-01 3.469447e-18 0.000000e+00 97 0.274594 0.208446 0.177432 ... 9.420422e-01 0.000000e+00 1.075529e-16 98 0.282873 0.209678 0.176820 ... 9.710211e-01 2.428613e-17 6.938894e-18 99 0.291402 0.210912 0.176103 ... 1.000000e+00 2.775558e-16 3.951094e-09 [100 rows x 8 columns]
To plot the Most diversification portfolios line use the DataFrame with the points data. Additionaly ‘Plot.plot_assets()’ can be used to show the assets in the chart.
>>> import matplotlib.pyplot as plt >>> fig = plt.figure() >>> # Plot the assets points >>> y.plot_assets(kind='cagr') # kind should be set to "cagr" as we take "CAGR" column from the ef_points. >>> ax = plt.gca() >>> # Plot the Most diversified portfolios line >>> df = y.mdp_points >>> ax.plot(df['Risk'], df['CAGR']) # we chose to plot CAGR which is geometric mean of return series >>> # Set the axis labels and the title >>> ax.set_title('Most diversified portfolios line') >>> ax.set_xlabel('Risk (Standard Deviation)') >>> ax.set_ylabel('Return (CAGR)') >>> plt.show()
- get_monte_carlo(n=100, kind='mean')
Generate N random portfolios with Monte Carlo simulation.
Risk (annualized standard deviation) and Return (CAGR) are calculated for a set of random weights.
- Parameters:
- nint, default 100
Number of random portfolios to generate with Monte Carlo simulation.
- kind{‘mean’,’cagr’}, default ‘mean’
Use CAGR for return if kind=’cagr’, or annualized arithmetic mean if kind=’mean’.
- Returns:
- DataFrame
Table with Return, Risk and weights values for random portfolios.
Examples
>>> assets = ['SPY.US', 'AGG.US', 'GLD.US'] >>> last_date='2021-07' >>> base_currency = 'EUR' >>> y = ok.EfficientFrontier(assets, ccy=base_currency, last_date=last_date) >>> y.get_monte_carlo(n=10) # generate 10 random portfolios Risk Return SPY.US AGG.US GLD.US 0 0.099168 0.101667 0.470953 0.205227 0.323819 1 0.099790 0.076282 0.070792 0.558928 0.370280 2 0.129312 0.106620 0.274261 0.050524 0.675215 3 0.102031 0.083311 0.129375 0.443444 0.427182 4 0.102956 0.105136 0.489213 0.146174 0.364614 5 0.095690 0.091834 0.297122 0.335066 0.367812 6 0.103747 0.090285 0.203408 0.334694 0.461898 7 0.148311 0.099617 0.082660 0.120871 0.796470 8 0.115780 0.082983 0.042871 0.422335 0.534794 9 0.093903 0.088553 0.266303 0.387332 0.346365
To plot Monte Carlo simulation result it’s useful to combine in with the Efficien Frontier chart. Additionaly assets points could be plotted with ‘Plot.plot_assets()’.
>>> import matplotlib.pyplot as plt >>> fig = plt.figure() >>> # Plot the assets points (optional). >>> # The same first and last dates, base currency and return type should be used. >>> y.plot_assets(kind='cagr') >>> ax = plt.gca() >>> # Plot random portfolios risk-return points. >>> mc = y.get_monte_carlo(n=1000, kind='cagr') >>> ax.scatter(mc.Risk, mc.CAGR, linewidth=0, color='green') >>> # Plot the Efficient (optional) >>> df = y.ef_points >>> ax.plot(df['Risk'], df['CAGR'], color='black', linestyle='dashed', linewidth=3) >>> # Set the title and axis labels >>> ax.set_title('Single period Efficient Frontier & Monte Carlo simulation') >>> ax.set_xlabel('Risk (Standard Deviation)') >>> ax.set_ylabel('CAGR') >>> ax.legend() >>> plt.show()
- plot_transition_map(x_axe='risk', figsize=None)
Plot Transition Map for optimized portfolios on the single period Efficient Frontier.
Transition Map shows the relation between asset weights and optimized portfolios properties:
CAGR (Compound annual growth rate)
Risk (annualized standard deviation of return)
Wights are displayed on the y-axis. CAGR or Risk - on the x-axis.
Constrained optimization with weights bounds is available.
- Parameters:
- boundstuple of ((float, float),…)
Bounds for the assets weights. Each asset can have weights limitation from 0 to 1.0. If an asset has limitation for 10 to 20%, bounds are defined as (0.1, 0.2). bounds = ((0, .5), (0, 1)) shows that in Portfolio with two assets first one has weight limitations from 0 to 50%. The second asset has no limitations.
- x_axe{‘risk’, ‘cagr’}, default ‘risk’
Show the relation between weights and CAGR (if ‘cagr’) or between weights and Risk (if ‘risk’). CAGR or Risk are displayed on the x-axis.
- figsize(float, float), optional
Figure size: width, height in inches. If None default matplotlib size is taken: [6.4, 4.8]
- Returns:
- Axes‘matplotlib.axes._subplots.AxesSubplot’
Examples
>>> import matplotlib.pyplot as plt >>> x = ok.EfficientFrontier(['SPY.US', 'AGG.US', 'GLD.US'], ccy='USD', inflation=False) >>> x.plot_transition_map() >>> plt.show()
Transition Map with default setting show the relation between Risk (stanrd deviation) and assets weights for optimized portfolios. The same relation for CAGR can be shown setting x_axe=’cagr’.
>>> x.plot_transition_map(x_axe='cagr') >>> plt.show()
- property annual_return_ts
Calculate annual rate of return time series for each asset.
Rate of return is calculated for each calendar year.
- Returns:
- DataFrame
Calendar annual rate of return time series.
Examples
>>> import matplotlib.pyplot as plt >>> al = ok.AssetList(['SPY.US', 'BND.US'], last_date='2021-08') >>> al.annual_return_ts.plot(kind='bar') >>> plt.show()
- property currency
Return the base currency of the Asset List.
Such properties as rate of return and risk are adjusted to the base currency.
- Returns:
- okama.Asset
Base currency of the Asset List in form of okama.Asset class.
- describe(years=(1, 5, 10), tickers=True)
Generate descriptive statistics for a list of assets.
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 period):
risk (standard deviation)
CVAR (timeframe is 1 year)
max drawdowns (and dates of the drawdowns)
Statistics also shows for each asset: - inception date - first date available for each asset - last asset date - available for each asset date - Common last data date - common for the asset list data (may be set by last_date manually)
- Parameters:
- yearstuple of (int,), default (1, 5, 10)
List of periods for CAGR.
- tickersbool, default True
Defines whether show tickers (True) or assets names in the header.
- Returns:
- DataFrame
Table of descriptive statistics for a list of assets.
See also
get_cumulative_return
Calculate cumulative return.
get_cagr
Calculate assets Compound Annual Growth Rate (CAGR).
dividend_yield
Calculate dividend yield (LTM).
risk_annual
Return annualized risks (standard deviation).
get_cvar
Calculate historic Conditional Value at Risk (CVAR, expected shortfall).
drawdowns
Calculate drawdowns.
Examples
>>> al = ok.AssetList(['SPY.US', 'AGG.US'], last_date='2021-08') >>> al.describe(years=[1, 10, 15]) property period AGG.US SPY.US inflation 0 Compound return YTD -0.005620 0.180519 0.048154 1 CAGR 1 years -0.007530 0.363021 0.053717 2 CAGR 10 years 0.032918 0.152310 0.019136 3 CAGR 15 years 0.043013 0.107598 0.019788 4 CAGR 17 years, 10 months 0.039793 0.107972 0.022002 5 Dividend yield LTM 0.018690 0.012709 NaN 6 Risk 17 years, 10 months 0.037796 0.158301 NaN 7 CVAR 17 years, 10 months 0.023107 0.399398 NaN
- property dividend_growing_years
Return the number of years when the annual dividend was growing for each asset.
- Returns:
- DataFrame
Dividend growth length periods time series for each asset.
See also
dividend_yield
Dividend yield time series.
dividend_yield_annual
Calendar year dividend yield time series.
dividends_annual
Calendar year dividends.
dividend_paying_years
Number of years of consecutive dividend payments.
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 >>> x = ok.AssetList(['T.US', 'XOM.US'], first_date='1984-01', last_date='1994-12') >>> x.dividend_growing_years.plot(kind='bar') >>> plt.show()
- property dividend_paying_years
Return the number of years of consecutive dividend payments for each asset.
- Returns:
- DataFrame
Dividend payment period length time series for each asset.
See also
dividend_yield
Dividend yield time series.
dividend_yield_annual
Calendar year dividend yield time series.
dividends_annual
Calendar year dividends.
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 >>> x = ok.AssetList(['T.US', 'XOM.US'], first_date='1984-01', last_date='1994-12') >>> x.dividend_paying_years.plot(kind='bar') >>> plt.show()
- property 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
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 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 >>> x = ok.AssetList(['T.US', 'XOM.US'], first_date='2010-01', last_date='2020-12') >>> x.dividend_yield_annual.plot(kind='bar') >>> plt.show()
- property dividends_annual
Return calendar year dividends sum time series for each asset.
- Returns:
- DataFrame
Annual dividends time series for each asset.
See also
dividend_yield
Dividend yield time series.
dividend_yield_annual
Calendar year dividend yield 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 >>> x = ok.AssetList(['T.US', 'XOM.US'], first_date='2010-01', last_date='2020-12') >>> x.dividends_annual.plot(kind='bar') >>> plt.show()
- property drawdowns
Calculate drawdowns time series for the assets.
The drawdown is the percent decline from a previous peak in wealth index.
- Returns:
- DataFrame
Time series of drawdowns.
See also
risk_monthly
Calculate montly risk for each asset.
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).
Examples
>>> import matplotlib.pyplot as plt >>> al = ok.AssetList(['SPY.US', 'BND.US'], last_date='2021-08') >>> al.drawdowns.plot() >>> plt.show()
- get_cagr(period=None, real=False)
Calculate assets Compound Annual Growth Rate (CAGR) for a given trailing period.
Compound annual growth rate (CAGR) is the rate of return that would be required for an investment to grow from its initial to its final value, assuming all incomes were reinvested.
Inflation adjusted annualized returns (real CAGR) are shown with real=True option.
Annual inflation value is calculated for the same period if inflation=True in the AssetList.
- Parameters:
- period: int, optional
CAGR trailing period in years. None for the full time CAGR.
- real: bool, default False
CAGR is adjusted for inflation (real CAGR) if True. AssetList should be initiated with Inflation=True for real CAGR.
- Returns:
- Series
CAGR values for each asset and annualized inflation (optional).
See also
get_rolling_cagr
Calculate rolling CAGR.
Notes
CAGR is not defined for periods less than 1 year (NaN values are returned).
Examples
>>> x = ok.AssetList() >>> x.get_cagr(period=5) SPY.US 0.1510 USD.INFL 0.0195 dtype: float64
To get inflation adjusted return (real annualized return) add real=True option:
>>> x = ok.AssetList(['EURUSD.FX', 'CNYUSD.FX'], inflation=True) >>> x.get_cagr(period=5, real=True) EURUSD.FX 0.000439 CNYUSD.FX -0.017922 dtype: float64
- get_cumulative_return(period=None, real=False)
Calculate cumulative return over a given trailing period for each asset.
The cumulative return is the total change in the asset price during the investment period.
Inflation adjusted cumulative returns (real cumulative returns) are shown with real=True option. Annual inflation data is calculated for the same period if inflation=True in the AssetList.
- Parameters:
- period: str, int or None, default None
Trailing period in years. Period should be more then 0. 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.
- real: bool, default False
Cumulative return is adjusted for inflation (real cumulative return) if True. AssetList should be initiated with Inflation=True for real cumulative return.
- Returns:
- Series
Cumulative return values for each asset and cumulative inflation (if inflation=True in AssetList).
See also
get_rolling_cagr
Calculate rolling CAGR.
get_cagr
Calculate CAGR.
get_rolling_cumulative_return
Calculate rolling cumulative return.
annual_return
Calculate annualized mean return (arithmetic mean).
Examples
>>> x = ok.AssetList(['MCFTR.INDX'], ccy='RUB') >>> x.get_cumulative_return(period='YTD') MCFTR.INDX 0.1483 RUB.INFL 0.0485 dtype: float64
- get_cvar_historic(time_frame=12, level=1)
Calculate historic Conditional Value at Risk (CVAR, expected shortfall) for the assets with a given timeframe.
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:
- Series
CVaR values for each asset in form of Series.
See also
risk_monthly
Calculate montly risk for each asset.
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).
drawdowns
Calculate drawdowns.
Examples
>>> x = ok.AssetList(['SPY.US', 'AGG.US']) >>> x.get_cvar_historic(time_frame=60, level=1) SPY.US 0.2574 AGG.US -0.0766 dtype: float64 Name: VaR, dtype: float64
- get_dividend_mean_growth_rate(period=5)
Calculate geometric mean of annual dividends growth rate time series for a given trailing period.
Growth rate is taken for full calendar annual dividends.
- Parameters:
- periodint, default 5
Growth rate trailing period in years. Period should be a positive integer and not exceed the available data period_length.
- Returns:
- Series
Dividend growth geometric mean value for each asset.
See also
dividend_yield
Dividend yield time series.
dividend_yield_annual
Calendar year dividend yield time series.
dividends_annual
Calendar year dividends.
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.
Examples
>>> x = ok.AssetList(['T.US', 'XOM.US'], first_date='1984-01', last_date='1994-12') >>> x.get_dividend_mean_growth_rate(period=3) T.US 0.020067 XOM.US 0.024281 dtype: float64
- get_dividend_mean_yield(period=5)
Calculate the arithmetic mean for annual dividend yield (LTM) over a specified period.
Dividend yield is taken for full calendar annual dividends.
- Parameters:
- periodint, default 5
Mean dividend yield trailing period in years. Period should be a positive integer and not exceed the available data period_length.
- Returns:
- Series
Mean dividend yield value for each asset.
See also
dividend_yield
Dividend yield time series.
dividend_yield_annual
Calendar year dividend yield time series.
dividends_annual
Calendar year dividends.
get_dividend_mean_growth_rate
Geometric mean of annual dividends growth rate.
dividend_paying_years
Number of years of consecutive dividend payments.
dividend_growing_years
Number of years when the annual dividend was growing.
Examples
>>> al = ok.AssetList(["SBERP.MOEX", "LKOH.MOEX"], ccy='RUB', first_date='2005-01', last_date='2023-12') >>> al.get_dividend_mean_yield(period=3) SBERP.MOEX 0.052987 LKOH.MOEX 0.156526 dtype: float64
- get_rolling_cagr(window=12, real=False)
Calculate rolling CAGR for each asset.
Compound annual growth rate (CAGR) is the rate of return that would be required for an investment to grow from its initial to its final value, assuming all incomes were reinvested.
Inflation adjusted annualized returns (real CAGR) are shown with real=True option.
- Parameters:
- windowint, default 12
Size of the moving window in months. Window size should be at least 12 months for CAGR.
- real: bool, default False
CAGR is adjusted for inflation (real CAGR) if True. AssetList should be initiated with Inflation=True for real CAGR.
- Returns:
- DataFrame
Time series of rolling CAGR and mean inflation (optionally).
See also
get_rolling_cagr
Calculate rolling CAGR.
get_cagr
Calculate CAGR.
get_rolling_cumulative_return
Calculate rolling cumulative return.
annual_return
Calculate annualized mean return (arithmetic mean).
Notes
CAGR is not defined for periods less than 1 year (NaN values are returned).
Examples
>>> import matplotlib.pyplot as plt >>> x = ok.AssetList(['SPY.US', 'AGG.US'], ccy='USD', inflation=True) >>> x.get_rolling_cagr(window=5*12).plot() >>> plt.show()
For inflation adjusted rolling CAGR add ‘real=True’ option:
>>> x.get_rolling_cagr(window=5*12, real=True).plot() >>> plt.show()
- get_rolling_cumulative_return(window=12, real=False)
Calculate rolling cumulative return for each asset.
The cumulative return is the total change in the asset price.
- Parameters:
- windowint, default 12
Size of the moving window in months.
- real: bool, default False
Cumulative return is adjusted for inflation (real cumulative return) if True. AssetList should be initiated with Inflation=True for real cumulative return.
- Returns:
- DataFrame
Time series of rolling cumulative return.
See also
get_rolling_cagr
Calculate rolling CAGR.
get_cagr
Calculate CAGR.
get_cumulative_return
Calculate cumulative return.
annual_return
Calculate annualized mean return (arithmetic mean).
Examples
>>> import matplotlib.pyplot as plt >>> x = ok.AssetList(['SPY.US', 'AGG.US'], ccy='USD', inflation=True) >>> x.get_rolling_cumulative_return(window=5*12).plot() >>> plt.show()
For inflation adjusted rolling cumulative return add ‘real=True’ option:
>>> x.get_rolling_cumulative_return(window=5*12, real=True).plot() >>> plt.show()
- get_rolling_risk_annual(window=12)
Calculate annualized risk rolling time series for each asset.
Risk is a standard deviation of the rate of return.
Annualized risk time series is calculated for the rate of return values limited by moving window.
- Parameters:
- windowint, default 12
Size of the moving window in months.
- Returns:
- DataFrame
Annualized risk (standard deviation) rolling time series for each asset.
See also
risk_monthly
Calculate montly risk expanding time series for each asset.
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 assets drawdowns.
Examples
>>> import matplotlib.pyplot as plt >>> x = ok.AssetList(['SPY.US', 'AGG.US'], ccy='USD', inflation=True) >>> x.get_rolling_risk_annual(window=5*12).plot() >>> plt.show()
- get_sharpe_ratio(rf_return=0)
Calculate Sharpe ratio for the assets.
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 AssetList base currency.
- Parameters:
- rf_returnfloat, default 0
Risk-free rate of return.
- Returns:
- pd.Series
Examples
>>> al = ok.AssetList(['VOO.US', 'BND.US']) >>> al.get_sharpe_ratio(rf_return=0.02) VOO.US 0.962619 BND.US 0.390814 dtype: float64
- get_sortino_ratio(t_return=0)
Calculate Sortino ratio for the assets with specified target return.
Sortion ratio measures the risk-adjusted return of each asset. 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:
- pd.Series
Examples
>>> al = ok.AssetList(['VOO.US', 'BND.US'], last_date='2021-12') >>> al.get_sortino_ratio(t_return=0.03) VOO.US 1.321951 BND.US 0.028969 dtype: float64
- get_var_historic(time_frame=12, level=1)
Calculate historic Value at Risk (VaR) for the assets with a given timeframe.
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 period size in months
- levelint, default 1
Confidence level in percents. Default value is 1%.
- Returns:
- Series
VaR values for each asset in form of Series.
See also
risk_monthly
Calculate montly risk for each asset.
risk_annual
Calculate annualized risks.
semideviation_monthly
Calculate semideviation monthly values.
semideviation_annual
Calculate semideviation annualized values.
get_cvar_historic
Calculate historic Conditional Value at Risk (CVaR).
drawdowns
Calculate drawdowns.
Examples
>>> x = ok.AssetList(['SPY.US', 'AGG.US']) >>> x.get_var_historic(time_frame=60, level=1) SPY.US 0.2101 AGG.US -0.0867 Name: VaR, dtype: float64
- index_beta(rolling_window=None)
Compute beta coefficient time series for the assets.
Beta coefficient is defined in Capital Asset Pricing Model (CAPM). It is a measure of how an individual asset moves (on average) when the benchmark increases or decreases. When beta is positive, the asset price tends to move in the same direction as the benchmark, and the magnitude of beta tells by how much.
Index (benchmark) should be in the first position of the symbols list in AssetList parameters. There should be at least 12 months of historical data.
- Parameters:
- rolling_windowint or None, default None
Size of the moving window in months. Must be at least 12 months. If None calculate expanding beta coefficient.
- Returns:
- DataFrame
rollinf or expanding beta coefficient time series for each asset.
See also
index_corr
Compute correlation with the index (or benchmark).
index_rolling_corr
Compute rolling correlation with the index (or benchmark).
index_beta
Compute beta coefficient.
Examples
>>> import matplotlib.pyplot as plt >>> sp = ok.AssetList(['SP500TR.INDX', 'VBMFX.US', 'GC.COMM', 'VNQ.US']) >>> sp.names {'SP500TR.INDX': 'S&P 500 (TR)', 'VBMFX.US': 'VANGUARD TOTAL BOND MARKET INDEX FUND INVESTOR SHARES', 'GC.COMM': 'Gold', 'VNQ.US': 'Vanguard Real Estate Index Fund ETF Shares'} >>> sp.index_beta().plot() >>> plt.show()
To calculate rolling beta set rolling_window to a number of months (moving window size):
>>> sp.index_beta(rolling_window = 12 * 5).plot() # 5 years moving window >>> plt.show()
- index_corr(rolling_window=None)
Compute correlation with the index (or benchmark) time series for the assets. Expanding or rolling correlation is available.
Index (benchmark) should be in the first position of the symbols list in AssetList parameters. There should be at least 12 months of historical data.
- Parameters:
- rolling_windowint or None, default None
Size of the moving window in months. Must be at least 12 months. If None calculate expanding correlation with index.
- Returns:
- DataFrame
Rolling or expanding correlation with the index (or benchmark) time series for each asset.
Examples
>>> import matplotlib.pyplot as plt >>> sp = ok.AssetList(['SP500TR.INDX', 'VBMFX.US', 'GC.COMM']) >>> sp.names {'SP500TR.INDX': 'S&P 500 (TR)', 'VBMFX.US': 'VANGUARD TOTAL BOND MARKET INDEX FUND INVESTOR SHARES', 'GC.COMM': 'Gold'} >>> sp.index_corr().plot() # expanding correlation with S&P 500 >>> plt.show()
To calculate rolling correlation with S&P 500 set rolling_window to a number of months (moving window size):
>>> sp.index_corr(rolling_window=24).plot() >>> plt.show()
- property jarque_bera
Perform Jarque-Bera test for normality of assets returns historical data.
Jarque-Bera test shows whether the returns have the skewness and kurtosis matching a normal distribution (null hypothesis or H0).
- Returns:
- DataFrame
Returns test statistic and the p-value for the hypothesis test. large Jarque-Bera statistics and tiny p-value indicate that null hypothesis (H0) is rejected and the time series are not normally distributed. Low statistic numbers correspond to normal distribution.
See also
skewness
Compute skewness.
skewness_rolling
Compute rolling skewness.
kurtosis
Calculate expanding Fisher (normalized) kurtosis.
kurtosis_rolling
Calculate rolling Fisher (normalized) kurtosis.
kstest
Perform Kolmogorov-Smirnov test for different types of distributions.
Examples
>>> al = ok.AssetList(['GC.COMM', 'FNER.INDX'], first_date='2000-01', last_date='2021-01') >>> al.names {'GC.COMM': 'Gold', 'FNER.INDX': 'FTSE NAREIT All Equity REITs'} >>> al.jarque_bera GC.COMM FNER.INDX statistic 4.507287 593.633047 p-value 0.105016 0.000000
Gold return time series (GC.COMM) distribution have small p-values (H0 is not rejected). Null hypothesis (H0) is rejected for FTSE NAREIT Index (FNER.INDX) as Jarque-Bera test shows very small p-value and large statistic.
- kstest(distr='norm')
Perform Kolmogorov-Smirnov test for goodness of fit the asset returns to a given distribution.
Kolmogorov-Smirnov is a test of the distribution of assets returns historical data against a given distribution. Under the null hypothesis (H0), the two distributions are identical.
- Parameters:
- distr{‘norm’, ‘lognorm’, ‘t’}, default ‘norm’
Distribution type for the rate of return of portfolio. ‘norm’ - for normal distribution. ‘lognorm’ - for lognormal distribution. ‘t’ - for Student’s T distribution.
- Returns:
- DataFrame
Returns test statistic and the p-value for the hypothesis test. Large test statistics and tiny p-value indicate that null hypothesis (H0) is rejected.
Examples
>>> al = ok.AssetList(['EDV.US'], last_date='2021-01') >>> al.kstest(distr='lognorm') EDV.US p-value 0.402179 statistic 0.070246
H0 is not rejected for EDV ETF and it seems to have lognormal distribution.
- property kurtosis
Calculate expanding Fisher (normalized) kurtosis of the return time series for each asset.
Kurtosis is the fourth central moment divided by the square of the variance. It is a measure of the “tailedness” of the probability distribution of a real-valued random variable.
Kurtosis should be close to zero for normal distribution.
- Returns:
- DataFrame
Expanding kurtosis time series for each asset.
See also
skewness
Compute skewness.
skewness_rolling
Compute rolling skewness.
kurtosis_rolling
Calculate rolling Fisher (normalized) kurtosis.
jarque_bera
Perform Jarque-Bera test for normality.
kstest
Perform Kolmogorov-Smirnov test for different types of distributions.
Examples
>>> import matplotlib.pyplot as plt >>> al = ok.AssetList(['GC.COMM', 'FNER.INDX'], first_date='2000-01', last_date='2021-01') >>> al.names {'GC.COMM': 'Gold', 'FNER.INDX': 'FTSE NAREIT All Equity REITs'} >>> al.kurtosis.plot() >>> plt.show()
- kurtosis_rolling(window=60)
Calculate rolling Fisher (normalized) kurtosis of the return time series for each asset.
Kurtosis is the fourth central moment divided by the square of the variance. It is a measure of the “tailedness” of the probability distribution of a real-valued random variable.
Kurtosis should be close to zero for normal distribution.
- Parameters:
- windowint, default 60
Rolling window size in months. This is the number of observations used for calculating the statistic. The window size should be at least 12 months.
- Returns:
- DataFrame
Rolling kurtosis time series for each asset.
See also
skewness
Compute skewness.
skewness_rolling
Compute rolling skewness.
kurtosis
Calculate expanding Fisher (normalized) kurtosis.
jarque_bera
Perform Jarque-Bera test for normality.
kstest
Perform Kolmogorov-Smirnov test for different types of distributions.
Examples
>>> import matplotlib.pyplot as plt >>> al = ok.AssetList(['GC.COMM', 'FNER.INDX'], first_date='2000-01', last_date='2021-01') >>> al.names {'GC.COMM': 'Gold', 'FNER.INDX': 'FTSE NAREIT All Equity REITs'} >>> al.kurtosis_rolling(window=12*5).plot() >>> plt.show()
- property mean_return
Calculate annualized mean return (arithmetic mean) for the rate of return time series (each asset).
Mean return calculated for the full history period. Arithmetic mean for the inflation is also shown if there is an inflation=True option in AssetList.
- Returns:
- Series
Mean return value for each asset.
Examples
>>> x = ok.AssetList(['MCFTR.INDX', 'RGBITR.INDX'], ccy='RUB', inflation=True) >>> x.mean_return MCFTR.INDX 0.209090 RGBITR.INDX 0.100133 dtype: float64
- plot_assets(kind='mean', tickers='tickers', pct_values=False, xy_text=(0, 10))
Plot the assets points on the risk-return chart with annotations.
Annualized values for risk and return are used. Risk is a 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’ - assets symbols are shown in form of ‘SPY.US’ ‘names’ - assets names are used like - ‘SPDR S&P 500 ETF Trust’ To show custom annotations for each asset pass the list of names.
- pct_valuesbool, default False
Risk and return values in the axes: Algebraic annotation (False) Percents (True)
- xy_texttuple, default (0, 10)
The shift of the annotation text (x, y) from the point.
- Returns:
- Axes‘matplotlib.axes._subplots.AxesSubplot’
Examples
>>> import matplotlib.pyplot as plt >>> al = ok.AssetList(['SPY.US', 'AGG.US'], ccy='USD', inflation=False) >>> al.plot_assets() >>> plt.show()
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()
- plot_pair_ef(tickers='tickers', figsize=None)
Plot Efficient Frontier of every pair of assets.
Efficient Frontier is a set of portfolios which satisfy the condition that no other portfolio exists with a higher expected return but with the same risk (standard deviation of return).
Arithmetic mean (expected return) is used for optimized portfolios.
- Parameters:
- tickers{‘tickers’, ‘names’} or list of str, default ‘tickers’
Annotation type for assets. ‘tickers’ - assets symbols are shown in form of ‘SPY.US’ ‘names’ - assets names are used like - ‘SPDR S&P 500 ETF Trust’ To show custom annotations for each asset pass the list of names.
- figsize: (float, float), optional
Figure size: width, height in inches. If None default matplotlib size is taken: [6.4, 4.8]
- Returns:
- Axes‘matplotlib.axes._subplots.AxesSubplot’
Notes
It should be at least 3 assets.
Examples
>>> import matplotlib.pyplot as plt >>> ls4 = ['SPY.US', 'BND.US', 'GLD.US', 'VNQ.US'] >>> curr = 'USD' >>> last_date = '07-2021' >>> ef = ok.EfficientFrontier(ls4, ccy=curr, last_date=last_date) >>> ef.plot_pair_ef() >>> plt.show()
It can be useful to plot the full Efficent Frontier (EF) with optimized 4 assets portfolios together with the EFs for each pair of assets.
>>> ef4 = ok.EfficientFrontier(assets=ls4, ccy=curr, n_points=100) >>> df4 = ef4.ef_points >>> fig = plt.figure() >>> # Plot Efficient Frontier of every pair of assets. Optimized portfolios will have 2 assets. >>> ef4.plot_pair_ef() # mean return is used for optimized portfolios. >>> ax = plt.gca() >>> # Plot the full Efficient Frontier for 4 asset portfolios. >>> ax.plot(df4['Risk'], df4['Mean return'], color = 'black', linestyle='--') >>> plt.show()
- property real_mean_return
Calculate annualized real mean return (arithmetic mean) for the rate of return time series (each assets).
Real rate of return is adjusted for inflation. Real return is defined if there is an inflation=True option in AssetList.
- Returns:
- Series
Mean real return value for each asset.
Examples
>>> x = ok.AssetList(['MCFTR.INDX', 'RGBITR.INDX'], ccy='RUB', inflation=True) >>> x.real_mean_return MCFTR.INDX 0.118116 RGBITR.INDX 0.017357 dtype: float64
- property recovery_periods
Calculate the longest recovery periods for the assets.
The recovery period (drawdown duration) is the number of months to reach the value of the last maximum.
- Returns:
- Series
Max recovery period for each asset (in months).
See also
drawdowns
Calculate drawdowns time series.
Notes
If the last asset maximum value is not recovered NaN is returned. The largest recovery period does not necessary correspond to the max drawdown.
Examples
>>> x = ok.AssetList(['SPY.US', 'AGG.US']) >>> x.recovery_periods SPY.US 52 AGG.US 15 dtype: int32
- property risk_annual
Calculate annualized risk expanding time series for each asset.
Risk is a standard deviation of the rate of return.
Annualized risk time series is calculated for the rate of return from ‘first_date’ to ‘last_date’ (expanding).
- Returns:
- DataFrame
Annualized risk (standard deviation) expanding time series for each asset.
See also
risk_monthly
Calculate montly risk expanding time series for each asset.
get_rolling_risk_annual
Calculate annualized risk rolling time series.
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 assets drawdowns.
Notes
CFA recomendations are used to annualize risk values [1].
[1]What’s Wrong with Multiplying by the Square Root of Twelve. Paul D. Kaplan, CFA Institute Journal Review, 2013
Examples
>>> al = ok.AssetList(['GC.COMM', 'SHV.US'], ccy='USD', last_date='2021-01') >>> al.risk_annual GC.COMM 0.195236 SHV.US 0.004960 dtype: float64
- property risk_monthly
Calculate monthly risk expanding time series for each asset.
Monthly risk of the asset is a standard deviation of the rate of return time series. Standard deviation (sigma σ) is normalized by N-1.
Monthly risk is calculated for the rate of retirun time series for the sample from ‘first_date’ to ‘last_date’.
- Returns:
- DataFrame
Monthly risk (standard deviation) expanding time series for each asset in form of Series.
See also
risk_annual
Calculate annualized risks expanding time series.
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
>>> al = ok.AssetList(['GC.COMM', 'SHV.US'], ccy='USD', last_date='2021-01') >>> al.risk_monthly Symbols GC.COMM SHV.US date 2007-03 0.025668 0.000141 2007-04 0.020872 0.000153 2007-05 0.027513 0.000451 2007-06 0.025988 0.000406 ... ... 2020-09 0.051006 0.001380 2020-10 0.050861 0.001377
- property semideviation_annual
Return semideviation annualized values for each asset.
Semi-deviation (Downside risk) is the risk of the return being below the expected return.
Semi-deviation is calculated for rate of retirun time series for the sample from ‘first_date’ to ‘last_date’.
- Returns:
- Series
Annualized semideviation values for each asset in form of Series.
See also
risk_monthly
Calculate montly risk for each asset.
risk_annual
Calculate annualized risks.
semideviation_monthly
Calculate semideviation monthly values.
get_var_historic
Calculate historic Value at Risk (VaR).
get_cvar_historic
Calculate historic Conditional Value at Risk (CVaR).
drawdowns
Calculate drawdowns.
Examples
>>> al = ok.AssetList(['GC.COMM', 'SHV.US'], ccy='USD', last_date='2021-01') >>> al.semideviation_annual GC.COMM 0.115302 SHV.US 0.000560 dtype: float64
- property semideviation_monthly
Calculate semi-deviation monthly values for each asset.
Semi-deviation (Downside risk) is the risk of the return being below the expected return.
Semi-deviation is calculated for rate of retirun time series for the sample from ‘first_date’ to ‘last_date’.
- Returns:
- Series
Monthly semideviation values for each asset in form of Series.
See also
risk_monthly
Calculate montly risk for each asset.
risk_annual
Calculate annualized risks.
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
>>> al = ok.AssetList(['GC.COMM', 'SHV.US'], ccy='USD', last_date='2021-01') >>> al.semideviation_monthly GC.COMM 0.039358 SHV.US 0.000384 dtype: float64
- property skewness
Compute expanding skewness of the return time series for each asset returns.
Skewness is a measure of the asymmetry of the probability distribution of a real-valued random variable about its mean. The skewness value can be positive, zero, negative, or undefined.
For normally distributed returns, the skewness should be about zero. A skewness value greater than zero means that there is more weight in the right tail of the distribution.
- Returns:
- Dataframe
Expanding skewness time series for each asset.
See also
skewness_rolling
Compute rolling skewness.
kurtosis
Calculate expanding Fisher (normalized) kurtosis.
kurtosis_rolling
Calculate rolling Fisher (normalized) kurtosis.
jarque_bera
Perform Jarque-Bera test for normality.
kstest
Perform Kolmogorov-Smirnov test for different types of distributions.
Examples
>>> import matplotlib.pyplot as plt >>> al = ok.AssetList(['VFINX.US', 'GC.COMM'], last_date='2021-01') >>> al.names {'VFINX.US': 'VANGUARD 500 INDEX FUND INVESTOR SHARES', 'GC.COMM': 'Gold'} >>> al.skewness.plot() >>> plt.show()
- skewness_rolling(window=60)
Compute rolling skewness of the return time series for each asset.
Skewness is a measure of the asymmetry of the probability distribution of a real-valued random variable about its mean. The skewness value can be positive, zero, negative, or undefined.
For normally distributed returns, the skewness should be about zero. A skewness value greater than zero means that there is more weight in the right tail of the distribution.
- Parameters:
- windowint, default 60
Rolling window size in months. This is the number of observations used for calculating the statistic. The window size should be at least 12 months.
- Returns:
- DataFrame
Rolling skewness time series for each asset.
See also
skewness
Compute skewness.
kurtosis
Calculate expanding Fisher (normalized) kurtosis.
kurtosis_rolling
Calculate rolling Fisher (normalized) kurtosis.
jarque_bera
Perform Jarque-Bera test for normality.
kstest
Perform Kolmogorov-Smirnov test for different types of distributions.
Examples
>>> import matplotlib.pyplot as plt >>> al = ok.AssetList(['VFINX.US', 'GC.COMM'], last_date='2021-01') >>> al.names {'VFINX.US': 'VANGUARD 500 INDEX FUND INVESTOR SHARES', 'GC.COMM': 'Gold'} >>> al.skewness_rolling(window=12*5).plot() >>> plt.show()
- property symbols
Return a list of financial symbols used to set the AssetList.
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 symbols included in the Asset List.
- property tickers
Return a list of tickers (symbols without a namespace) used to set the AssetList.
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 tickers included in the Asset List.
- tracking_difference(rolling_window=None)
Return tracking difference for the rate of return of assets.
Tracking difference is calculated by measuring the accumulated difference between the returns of a benchmark and those of the ETF replicating it (could be mutual funds, or other types of assets). Tracking difference is measured in percents.
Benchmark should be in the first position of the symbols list in AssetList parameters.
- Parameters:
- rolling_windowint or None, default None
Size of the moving window in months. If None calculate expanding tracking difference.
- Returns:
- DataFrame
Tracking diffirence time series for each asset.
Examples
>>> import matplotlib.pyplot as plt >>> x = ok.AssetList(['SP500TR.INDX', 'SPY.US', 'VOO.US'], last_date='2021-01') >>> x.tracking_difference().plot() >>> plt.show()
To calculate rolling Tracking difference set rolling_window to a number of months (moving window size):
>>> x.tracking_difference(rolling_window = 24).plot() >>> plt.show()
- property tracking_difference_annual
Calculate tracking difference for each calendar year.
Tracking difference is calculated by measuring the accumulated difference between the returns of a benchmark and ETFs replicating it (could be mutual funds, or other types of assets). Tracking difference is measured in percents.
Benchmark should be in the first position of the symbols list in AssetList parameters.
- Returns:
- DataFrame
Time series with tracking difference for each calendar year period.
Examples
>>> import matplotlib.pyplot as plt >>> al = ok.AssetList(['SP500TR.INDX', 'VOO.US', 'SPXS.LSE'], inflation=False) >>> al.tracking_difference_annual.plot(kind='bar')
- tracking_difference_annualized(rolling_window=None)
Calculate annualized tracking difference time series for the rate of return of assets.
Tracking difference is calculated by measuring the accumulated difference between the returns of a benchmark and ETFs replicating it (could be mutual funds, or other types of assets). Tracking difference is measured in percents.
Benchmark should be in the first position of the symbols list in AssetList parameters.
Annual values are available for history periods of more than 12 months. Returns for less than 12 months can’t be annualized According to the CFA Institute’s Global Investment Performance Standards (GIPS).
- Parameters:
- rolling_windowint or None, default None
Size of the moving window in months. Must be at least 12 months. If None calculate expanding annualized tracking difference.
- Returns:
- DataFrame
Annualized tracking diffirence time series for each asset.
Examples
>>> import matplotlib.pyplot as plt >>> x = ok.AssetList(['SP500TR.INDX', 'SPY.US', 'VOO.US'], last_date='2021-01') >>> x.tracking_difference_annualized().plot()
To calculate rolling annualized tracking difference set rolling_window to a number of months (moving window size):
>>> x.tracking_difference_annualized(rolling_window = 12*5).plot() >>> plt.show()
- tracking_error(rolling_window=None)
Calculate tracking error time series for the rate of return of assets.
Tracking error is defined as the standard deviation of the difference between the returns of the asset and the returns of the benchmark. Tracking error is measured in percents.
Benchmark should be in the first position of the symbols list in AssetList parameters.
- Parameters:
- rolling_windowint or None, default None
Size of the moving window in months. Must be at least 12 months. If None calculate expanding tracking error.
- Returns:
- DataFrame
rolling or expanding tracking error time series for each asset.
Examples
>>> import matplotlib.pyplot as plt >>> x = ok.AssetList(['SP500TR.INDX', 'SPY.US', 'VOO.US'], last_date='2021-01') >>> x.tracking_error().plot() >>> plt.show()
To calculate rolling tracking error set rolling_window to a number of months (moving window size):
>>> x.tracking_error(rolling_window = 12*5).plot() >>> plt.show()
- property wealth_indexes
Calculate wealth index time series for the assets and accumulated inflation.
Wealth index (Cumulative Wealth Index) is a time series that presents the value of each asset over historical time period. Accumulated inflation time series is added if inflation=True in the AssetList.
Wealth index is obtained from the accumulated return multiplicated by the initial investments. That is: 1000 * (Acc_Return + 1) Initial investments are taken as 1000 units of the AssetList base currency.
- Returns:
- DataFrame
Time series of wealth index values for each asset and accumulated inflation.
Examples
>>> import matplotlib.pyplot as plt >>> x = ok.AssetList(['SPY.US', 'BND.US']) >>> x.wealth_indexes.plot() >>> plt.show()
- plot_cml(rf_return=0, y_axe='cagr', figsize=None)
Plot Capital Market Line (CML).
The Capital Market Line (CML) is the tangent line drawn from the point of the risk-free asset (volatility is zero) to the point of tangency portfolio or Maximum Sharpe Ratio (MSR) point.
The slope of the CML is the Sharpe ratio of the tangency portfolio.
- Parameters:
- rf_returnfloat, default 0
Risk-free rate of return.
- y_axe{‘cagr’, ‘mean_return’}, default ‘cagr’
Show the relation between Risk and CAGR (if ‘cagr’) or between Risk and Mean rate of return (if ‘mean_return’). CAGR or Mean Rate of Return are displayed on the y-axis.
- figsize(float, float), optional
Figure size: width, height in inches. If None default matplotlib size is taken: [6.4, 4.8]
- Returns:
- Axes‘matplotlib.axes._subplots.AxesSubplot’
Examples
>>> import matplotlib.pyplot as plt >>> three_assets = ['MCFTR.INDX', 'RGBITR.INDX', 'GC.COMM'] >>> ef = ok.EfficientFrontier(assets=three_assets, ccy='USD', full_frontier=True) >>> ef.plot_cml(rf_return=0.05, y_axe="cagr") # Risk-Free return is 5% >>> plt.show