#!/usr/bin/env python # coding: utf-8 # # Riskfolio-Lib Tutorial: #
#
# #
#
# #
Buy Me a Coffee at ko-fi.com #
#
__[Financionerioncios](https://financioneroncios.wordpress.com)__ #
__[Orenji](https://www.linkedin.com/company/orenj-i)__ #
__[Riskfolio-Lib](https://riskfolio-lib.readthedocs.io/en/latest/)__ #
__[Dany Cajas](https://www.linkedin.com/in/dany-cajas/)__ # # ## Tutorial 10: Risk Parity Portfolio Optimization # # ## 1. Downloading the data: # In[ ]: import numpy as np import pandas as pd import yfinance as yf import warnings warnings.filterwarnings("ignore") pd.options.display.float_format = '{:.4%}'.format # Date range start = '2016-01-01' end = '2019-12-30' # Tickers of assets assets = ['JCI', 'TGT', 'CMCSA', 'CPB', 'MO', 'APA', 'MMC', 'JPM', 'ZION', 'PSA', 'BAX', 'BMY', 'LUV', 'PCAR', 'TXT', 'TMO', 'DE', 'MSFT', 'HPQ', 'SEE', 'VZ', 'CNP', 'NI', 'T', 'BA'] assets.sort() # Downloading data data = yf.download(assets, start = start, end = end, auto_adjust=False) data = data.loc[:,('Adj Close', slice(None))] data.columns = assets # In[3]: # Calculating returns Y = data[assets].pct_change().dropna() display(Y.head()) # ## 2. Estimating Mean Variance Portfolios # # ### 2.1 Calculating the portfolio that maximizes Sharpe ratio. # In[5]: import riskfolio as rp # Building the portfolio object port = rp.Portfolio(returns=Y) # Calculating optimal portfolio # Select method and estimate input parameters: method_mu='hist' # Method to estimate expected returns based on historical data. method_cov='hist' # Method to estimate covariance matrix based on historical data. port.assets_stats(method_mu=method_mu, method_cov=method_cov) # Estimate optimal portfolio: model='Classic' # Could be Classic (historical), BL (Black Litterman) or FM (Factor Model) rm = 'MV' # Risk measure used, this time will be variance obj = 'Sharpe' # Objective function, could be MinRisk, MaxRet, Utility or Sharpe hist = True # Use historical scenarios for risk measures that depend on scenarios rf = 0 # Risk free rate l = 0 # Risk aversion factor, only useful when obj is 'Utility' w = port.optimization(model=model, rm=rm, obj=obj, rf=rf, l=l, hist=hist) display(w.T) # ### 2.2 Plotting portfolio composition # In[7]: # Plotting the composition of the portfolio ax = rp.plot_pie(w=w, title='Sharpe Mean Variance', others=0.05, nrow=25, cmap = "tab20", height=6, width=10, ax=None) # ### 2.3 Plotting Risk Composition # In[9]: # Plotting the risk composition of the portfolio ax = rp.plot_risk_con(w, cov=port.cov, returns=port.returns, rm=rm, rf=0, alpha=0.01, color="tab:blue", height=6, width=10, ax=None) # ## 3. Estimating Risk Parity Portfolios for Other Risk Measures # # In this part I will calculate risk parity portfolios. First I'm going to calculate risk parity portfolio when we use variance as risk measure, then I'm going to calculate the risk parity portfolios for all available risk measures. # # ### 3.1 Calculating the risk parity portfolio for variance. # In[11]: b = None # Risk contribution constraints vector w_rp = port.rp_optimization(model=model, rm=rm, rf=rf, b=b, hist=hist) display(w.T) # ### 3.2 Plotting portfolio composition # In[13]: ax = rp.plot_pie(w=w_rp, title='Risk Parity Variance', others=0.05, nrow=25, cmap = "tab20", height=6, width=10, ax=None) # ### 3.3 Plotting Risk Composition # In[15]: ax = rp.plot_risk_con(w_rp, cov=port.cov, returns=port.returns, rm=rm, rf=0, alpha=0.01, color="tab:blue", height=6, width=10, ax=None) # ### 3.4 Calculate Optimal Portfolios for Several Risk Measures # In[17]: # Risk Measures available: # # 'MV': Standard Deviation. # 'MAD': Mean Absolute Deviation. # 'MSV': Semi Standard Deviation. # 'FLPM': First Lower Partial Moment (Omega Ratio). # 'SLPM': Second Lower Partial Moment (Sortino Ratio). # 'CVaR': Conditional Value at Risk. # 'EVaR': Entropic Value at Risk. # 'CDaR': Conditional Drawdown at Risk of uncompounded cumulative returns. # 'EDaR': Entropic Drawdown at Risk of uncompounded cumulative returns. # 'UCI': Ulcer Index of uncompounded cumulative returns. rms = ['MV', 'MAD', 'MSV', 'FLPM', 'SLPM', 'CVaR', 'EVaR', 'CDaR', 'UCI', 'EDaR'] w_s = pd.DataFrame([]) port.solvers = ['MOSEK'] for i in rms: w = port.rp_optimization(model=model, rm=i, rf=rf, b=b, hist=hist) w_s = pd.concat([w_s, w], axis=1) w_s.columns = rms # In[18]: w_s.style.format("{:.2%}").background_gradient(cmap='YlGn') # In[19]: import matplotlib.pyplot as plt # Plotting a comparison of assets weights for each portfolio fig = plt.gcf() fig.set_figwidth(16) fig.set_figheight(6) ax = fig.subplots(nrows=1, ncols=1) w_s.plot.bar(ax=ax)