Lab 4
#environment
#!pip install yfinance --upgrade --no-cache-dir
#!pip install PyPortfolioOpt==1.2.1
# Import modules
import requests
import io
import pandas as pd
import requests
import json
from datetime import datetime
import numpy as np
import yfinance as yf
import seaborn as sns
import plotly.express as px
import plotly.graph_objs as go
import matplotlib.pyplot as plt
import scipy.stats as st
from pypfopt.efficient_frontier import EfficientFrontier
from pypfopt import risk_models
from pypfopt import expected_returns
from pypfopt import cla
from pypfopt.plotting import Plotting
from pypfopt.discrete_allocation import DiscreteAllocation, get_latest_prices
from matplotlib.ticker import FuncFormatter
## JHU Vaccination Rates (Taken From: https://github.com/owid/covid-19-data/tree/master/public/data)
url = 'https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/owid-covid-data.csv'
download = requests.get(url).content
covid = pd.read_csv(io.StringIO(download.decode('utf-8')), parse_dates=['date'])
covid.tail()
sns.scatterplot('date', 'new_cases', data=covid, hue='continent')
us = covid[covid['location']=='United States']
us_covid = us.set_index('date')
us_covid.info()
us_covid.head()
df1 = pd.DataFrame()
df1['new cases'] = us_covid['new_cases_smoothed']
df1['new deaths'] = us_covid['new_deaths_smoothed']
df1.dropna()
df1.plot(secondary_y = ["new deaths"], title = 'New Cases and Deaths')
df2 = pd.DataFrame()
df2['positive rate'] = us_covid['positive_rate']
df2['fatality rate'] = us_covid['total_deaths']/us_covid['total_cases']
df2.dropna()
df2.plot(secondary_y = ["fatality rate"], title = 'Positive Rate and Fatality Rate')
df3 = pd.DataFrame()
df3['icu rate'] = us_covid['icu_patients']/us_covid['total_cases']
df3['hosp rate'] = us_covid['hosp_patients']/us_covid['total_cases']
df3['fatality rate'] = df2['fatality rate']
df3.dropna()
df3.plot(secondary_y = ["fatality rate"], title = 'Hospital Rate and Fatality Rate')
df4 = pd.DataFrame()
df4['vaccination rate'] = us_covid['people_fully_vaccinated']/us_covid['population']
df4['fatality rate'] = df2['fatality rate']
df4.dropna()
df4.plot(secondary_y = ["fatality rate"], title = 'Vaccination Rate and Fatality Rate')
Lab 5
assets_list = ['VV','VB', 'GOVT', 'LQD','HYG','USRT','GLD', 'BTC-USD']
start = datetime(2020,1,23)
end = datetime(2021,9,15)
assets_df = yf.download(assets_list, start=start, end=end)
assets = assets_df['Adj Close']
assets.ffill()
benchmark_df = yf.download(['SPY'], start=start, end=end)
benchmark = benchmark_df['Adj Close']
benchmark.ffill()
assets.tail()
# Check NaN values in the data
nullin_df = pd.DataFrame(assets,columns=assets_list)
print(nullin_df.isnull().sum())
# Calculate portfolio mean return
mu = expected_returns.mean_historical_return(assets)
print(mu)
# Calculate portfolio return variance
sigma = risk_models.sample_cov(assets)
print(sigma)
Maximum Sharp Ratio Portfolio
# weight bounds in negative allows shorting of stocks
ef = EfficientFrontier(mu, sigma, weight_bounds=(-1,1))
# optional constraints possible, read pypfopt documentation.
sharpe_portfolio=ef.max_sharpe(risk_free_rate=0.005)
sharpe_portfolio_wt=ef.clean_weights()
print(sharpe_portfolio_wt)
Plotting.plot_weights(sharpe_portfolio_wt)
latest_prices = get_latest_prices(assets)
# Allocate Portfolio Value in $ as required to show number of shares/stocks to buy,
# also bounds for shorting will affect allocation
# Maximum Sharpe Portfolio Allocation $1000000
da = DiscreteAllocation(sharpe_portfolio_wt, latest_prices, total_portfolio_value=1000000)
allocation, leftover = da.greedy_portfolio()
print(allocation)
print("Leftover Fund value for the maximum Sharpe portfolio is ${:.2f}".format(leftover))
max_sharpe_cla = cla.CLA(mu, sigma)
max_sharpe_cla.max_sharpe()
Plotting.plot_efficient_frontier(max_sharpe_cla, show_assets="True")
sharpe_portfolio_wt_list = list(sharpe_portfolio_wt.values())
ret_data1 = assets.pct_change()[1:]
weighted_returns1 = (sharpe_portfolio_wt_list * ret_data1)
portfolio_ret1 = pd.DataFrame(weighted_returns1.sum(axis=1))
ret_data1 = ret_data1.merge(portfolio_ret1, on="Date", how="left")
ret_data1 = ret_data1.rename(columns={0: "portfolio_ret"})
ret_data1.head()
ret_benchmark = benchmark.pct_change()[1:]
ret_data1['cumulative_portfolio_ret'] = (ret_data1['portfolio_ret'] + 1).cumprod()
ret_benchmark['cumulative_spy_ret'] = (ret_benchmark + 1).cumprod()
ret_data1.tail()
sns.scatterplot('Date', 'cumulative_portfolio_ret', data=ret_data1)
sns.scatterplot('Date', 'cumulative_spy_ret', data=ret_benchmark)
plt.hist(ret_data1['portfolio_ret'], bins=10)
st.norm.interval(alpha=0.95, loc=np.mean(ret_data1['portfolio_ret']), scale=st.sem(ret_data1['portfolio_ret']))
Minimum Volatility Portfolio
ef = EfficientFrontier(mu, sigma, weight_bounds=(-1,1))
min_vol_portfolio=ef.min_volatility()
min_vol_portfolio_wt=ef.clean_weights()
print(min_vol_portfolio_wt)
Plotting.plot_weights(min_vol_portfolio_wt)
da = DiscreteAllocation(min_vol_portfolio_wt, latest_prices, total_portfolio_value=1000000)
allocation, leftover = da.greedy_portfolio()
print(allocation)
print("Leftover Fund value for the maximum Sharpe portfolio is ${:.2f}".format(leftover))
min_vol_cla = cla.CLA(mu, sigma)
min_vol_cla.min_volatility()
Plotting.plot_efficient_frontier(min_vol_cla, show_assets="True")
min_vol_portfolio_wt_list = list(min_vol_portfolio_wt.values())
ret_data2 = assets.pct_change()[1:]
weighted_returns2 = (min_vol_portfolio_wt_list * ret_data2)
portfolio_ret2 = pd.DataFrame(weighted_returns2.sum(axis=1))
ret_data2 = ret_data2.merge(portfolio_ret2, on="Date", how="left")
ret_data2 = ret_data2.rename(columns={0: "portfolio_ret"})
ret_data2.head()
ret_data2['cumulative_portfolio_ret'] = (ret_data2['portfolio_ret'] + 1).cumprod()
ret_data2.tail()
sns.scatterplot('Date', 'cumulative_portfolio_ret', data=ret_data2)
sns.scatterplot('Date', 'cumulative_spy_ret', data=ret_benchmark)
plt.hist(ret_data2['portfolio_ret'], bins=10)
st.norm.interval(alpha=0.95, loc=np.mean(ret_data2['portfolio_ret']), scale=st.sem(ret_data2['portfolio_ret']))