12 KiB
This notebook demonstrates how to construct and optimize a portfolio using historical asset returns and various risk measures. It utilizes riskfolio to model the portfolio and yfinance to fetch historical stock data. The notebook calculates expected returns and covariance matrices, integrates benchmark indices, and applies tracking error constraints. It then optimizes the portfolio to maximize risk-adjusted returns, plotting the efficient frontier and optimal asset allocations. This is practical for portfolio managers and financial analysts to enhance investment strategies.
import riskfolio as rp import pandas as pd import yfinance as yf import warnings warnings.filterwarnings("ignore")
Define the list of assets for portfolio construction
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", "^GSPC", ]
Fetch historical stock data for the defined assets from Yahoo Finance
data = yf.download(assets, start="2016-01-01", end="2019-12-30")
Select adjusted close prices and rename columns to match asset tickers
data = data.loc[:, ("Adj Close", slice(None))] data.columns = assets
Calculate daily returns of the assets and isolate benchmark returns
returns = data.pct_change().dropna() bench_returns = returns.pop("^GSPC").to_frame()
Build the portfolio object and load the calculated returns into it
port = rp.Portfolio(returns=returns)
Estimate expected returns and covariance matrix using historical data
port.assets_stats(method_mu="hist", method_cov="hist", d=0.94)
Set to False to indicate no benchmark weights, using index instead
port.kindbench = False
Load benchmark returns into the portfolio object
port.benchindex = bench_returns
Enable the use of tracking error constraints in the optimization
port.allowTE = True
Define the maximum allowed tracking error relative to benchmark returns
port.TE = 0.008
Explain the goal of calculating optimal portfolios using different risk measures
Define the model type for optimization, here using historical data
model = "Classic"
Specify the risk measure to use, in this case, Conditional Value at Risk (CVaR)
rm = "CVaR"
Set the objective function to maximize Sharpe ratio
obj = "Sharpe"
Use historical scenarios for risk measures that depend on scenarios
hist = True
Define the risk-free rate for portfolio optimization calculations
rf = 0
Set the risk aversion factor, relevant only when the objective is 'Utility'
l = 0
Perform the portfolio optimization to maximize the Sharpe ratio using CVaR
w = port.optimization( model=model, rm=rm, obj=obj, rf=rf, l=l, hist=hist )
Plot the optimized portfolio allocation using a pie chart
ax = rp.plot_pie( w=w, title="Sharpe Mean CVaR", others=0.05, nrow=25, cmap="tab20", height=6, width=10, ax=None, )
Calculate the efficient frontier for the portfolio using the defined risk measure
frontier = port.efficient_frontier( model=model, rm=rm, points=50, rf=rf, hist=hist )
Plot the efficient frontier and the position of the optimized portfolio
ax = rp.plot_frontier( w_frontier=frontier, mu=port.mu, cov=port.cov, returns=port.returns, rm=rm, rf=rf, cmap="viridis", w=w, label="Max Risk Adjusted Return Portfolio", marker="*", )
Define the list of different risk measures to use for portfolio optimization
rms = [ "MV", "MAD", "MSV", "FLPM", "SLPM", "CVaR", "EVaR", "WR", "MDD", "ADD", "CDaR", "UCI", "EDaR", ]
Initialize an empty DataFrame to store the weights of optimized portfolios
w_s = pd.DataFrame([])
Loop through each risk measure, optimize the portfolio, and store the weights
for i in rms: w = port.optimization(model=model, rm=i, obj=obj, rf=rf, l=l, hist=hist) w_s = pd.concat([w_s, w], axis=1)
Assign the columns of the DataFrame to the respective risk measures and format the output
w_s.columns = rms w_s.style.format("{:.2%}").background_gradient(cmap="YlGn")
PyQuant News is where finance practitioners level up with Python for quant finance, algorithmic trading, and market data analysis. Looking to get started? Check out the fastest growing, top-selling course to get started with Python for quant finance. For educational purposes. Not investment advise. Use at your own risk.
