import pandas as pd
import numpy as np
import pandas_datareader.data as web
from matplotlib import pyplot as plt
import cvxopt as opt
from cvxopt import blas, solvers
# Returns a list of 5000 portfolios with random weights given expected_returns on assets and a cov_matrix
def return_portfolios(expected_returns, cov_matrix):
port_returns = []
port_volatility = []
stock_weights = []
selected = (expected_returns.axes)[0]
num_assets = len(selected)
num_portfolios = 10000
for single_portfolio in range(num_portfolios):
weights = np.random.random(num_assets)
weights /= np.sum(weights)
returns = np.dot(weights, expected_returns)
volatility = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
port_returns.append(returns)
port_volatility.append(volatility)
stock_weights.append(weights)
portfolio = {'Returns': port_returns,
'Volatility': port_volatility}
for counter,symbol in enumerate(selected):
portfolio[symbol +' Weight'] = [Weight[counter] for Weight in stock_weights]
df = pd.DataFrame(portfolio)
column_order = ['Returns', 'Volatility'] + [stock+' Weight' for stock in selected]
df = df[column_order]
return df
# Finds the optimal portfolios (those that maximize \
# return at all risks and those that minimize risk at all returns) \
def optimal_portfolio(returns):
n = returns.shape[1]
returns = np.transpose(returns)
N = 100
mus = [10**(5.0 * t/N - 1.0) for t in range(N)]
# Convert to cvxopt matrices
S = opt.matrix(np.cov(returns))
pbar = opt.matrix(np.mean(returns, axis=1))
# Create constraint matrices
G = -opt.matrix(np.eye(n)) # negative n x n identity matrix
h = opt.matrix(0.0, (n ,1))
A = opt.matrix(1.0, (1, n))
b = opt.matrix(1.0)
# Calculate efficient frontier weights using quadratic programming
portfolios = [solvers.qp(mu*S, -pbar, G, h, A, b)['x']
for mu in mus]
## CALCULATE RISKS AND RETURNS FOR FRONTIER
returns = [blas.dot(pbar, x) for x in portfolios]
risks = [np.sqrt(blas.dot(x, S*x)) for x in portfolios]
## CALCULATE THE 2ND DEGREE POLYNOMIAL OF THE FRONTIER CURVE
m1 = np.polyfit(returns, risks, 2)
x1 = np.sqrt(m1[2] / m1[0])
# CALCULATE THE OPTIMAL PORTFOLIO
wt = solvers.qp(opt.matrix(x1 * S), -pbar, G, h, A, b)['x']
return np.asarray(wt), returns, risks
# Define the instruments to download. We would like to see Apple, Microsoft, Nio, Tesla, Nike, Snapchat, Palantir, Alibaba, Virgin Galactic, and Starbucks
tickers = ['AAPL', 'NIO', 'AMD', 'TSLA', 'NKE', 'SNAP', 'PLTR', 'BABA', 'SPCE', 'SBUX']
# We would like all available data from 01/01/2000 until 12/31/2016.
start_date = '2021-01-01'
end_date = '2021-05-28'
# User pandas_reader.data.DataReader to load the desired data. As simple as that.
d_panel_data = web.DataReader(tickers, 'yahoo', start_date, end_date)
m_panel_data = web.get_data_yahoo(tickers, start_date, end_date, interval='m')
d_adj_closings = d_panel_data['Adj Close']
m_adj_closings = m_panel_data['Adj Close']
selected = list(d_adj_closings.columns)
daily_returns = d_adj_closings[selected].pct_change()
selected = list(m_adj_closings.columns)
monthly_returns = m_adj_closings[selected].pct_change()
d_expected_returns = daily_returns.mean()
m_expected_returns = monthly_returns.mean()
print(d_expected_returns.round(4), m_expected_returns.round(4))
daily_returns_cov = daily_returns.cov()
monthly_returns_cov = monthly_returns.cov()
print(daily_returns_cov.round(4), ' ', monthly_returns_cov.round(4))
d_single_asset_std=np.sqrt(np.diagonal(daily_returns_cov))
m_single_asset_std=np.sqrt(np.diagonal(monthly_returns_cov))
d_random_portfolios = return_portfolios(d_expected_returns, daily_returns_cov)
dweights, dreturns, drisks = optimal_portfolio(daily_returns[1:])
m_random_portfolios = return_portfolios(m_expected_returns, monthly_returns_cov)
mweights, mreturns, mrisks = optimal_portfolio(monthly_returns[1:])
print(daily_returns.round(4))
d_random_portfolios.plot.scatter(x='Volatility', y='Returns', fontsize=12)
plt.scatter(d_single_asset_std,d_expected_returns,marker='X',color='red',s=200)
plt.plot(drisks, dreturns, 'g-x')
plt.figure(figsize=(12, 8))
m_random_portfolios.plot.scatter(x='Volatility', y='Returns', fontsize=12)
plt.plot(mrisks, mreturns, 'r-x')
plt.scatter(m_single_asset_std,m_expected_returns,marker='X',color='red',s=200)
Can anyone help me understand why the Efficient Frontier my code plots doesn’t line up on the edges of the scatter plot of ‘m_random_portfolios’ or ‘d_random_portfolios’?