Efficient Frontier on a Portfolio of 10 Stocks

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’?