CS代写 MIE1624 – Introduction to Data Science and Analytics¶

Tut_9_Portfolio_Optimization

MIE1624 – Introduction to Data Science and Analytics¶
Tutorial 9 – Optimization (Winter 2022)¶

Copyright By PowCoder代写 加微信 powcoder

Import the necessary libraries and data¶

import cvxpy as cp
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

#Load file and into dateframe
monthlyClosing_inSample = ‘monthly_closings_2018_to_2020.csv’
monthlyClosing_outSample = ‘monthly_closings_2021.csv’

df1 = pd.read_csv(monthlyClosing_inSample)
df2 = pd.read_csv(monthlyClosing_outSample)

#Remove date
price = df1.iloc[:,1:]

#Calculate monthly return as percent change of monthly closing values, reset indices
ret = price.pct_change().iloc[1:,:]
ret.reset_index(inplace = True, drop = True)

Compute the covariance matrix Q and means for each column¶

# Compute the covariance matrix of the percent change of prices
Q = ret.cov().to_numpy()

# Compute the mean for each column
mu = np.array(np.mean(ret, axis = 0))

# Store number of features
n = ret.shape[1]

Solve for the minimum variance portfolio¶
Using the covarinace matrix, solve for the minimum variance portfolio. The function should be constrained so that the sum of all weights is equal to 1. You may use a number other than 1 but it must be consistent for all calucations.

# Create optimization variable w1, 26 total variables
w1 = cp.Variable(n)

# Form the problem , minimize
constraints1 = [sum(w1) == 1 , w1 >= 0]
prob1 = cp.Problem(cp.Minimize(cp.quad_form(w1, Q)) , [sum(w1) == 1 , w1 >= 0])

#Solve Problem
prob1.solve(verbose=False)

0.0009278939303461067

# matrix of allocations which offers the minimum variance
w_minVar = w1.value #solution value: minimum variance

array([ 2.34709995e-19, 5.74335977e-20, 8.04914107e-21, 8.47497035e-20,
1.98804620e-20, 1.09436145e-20, 2.73062165e-20, 2.72297891e-19,
5.54485957e-02, 1.08374455e-19, 8.96585659e-20, 6.59194971e-01,
-6.72525493e-20, 2.57094819e-20, 1.76013193e-03, 8.87191244e-02,
5.48842212e-02, -5.82446152e-20, -4.53771914e-19, 3.42087441e-20,
-3.00374562e-20, 8.76638311e-20, 9.01180838e-02, -1.21208010e-21,
4.98748717e-02])

#Compute the variance of the portfolio
var_minVar = np.dot(w_minVar, np.dot(Q, w_minVar)) #variance
var_minVar

0.0009278939303461067

#Compute the return of the portfolio
ret_minVar = np.dot(mu, w_minVar) #expected return
ret_minVar

0.008653285914910979

Solve for the maximum return portfolio¶
Using the mean returns for each asset to compute the maximized return portfolio. The function should be constrained so that the sum of all weights is equal to 1. You may use a number other than 1 but it must be consistent for all calucations.

# Create optimization variable w2, 26 total variables
w2 = cp.Variable(n)

constraints2 = [sum(w2) == 1, w2 >= 0]
prob2 = constraints2)

# Solve the problem
prob2.solve(verbose=False)

0.10211634693131111

# matrix of allocations which offers th
w_maxRet = w2.value #solution value: maximum expected return

array([4.00446549e-11, 2.33109317e-11, 2.11897368e-11, 2.02514107e-11,
2.13526338e-11, 2.10766681e-11, 2.36702200e-11, 2.30281295e-11,
2.20156300e-11, 1.84127151e-11, 1.42266925e-11, 1.97676588e-11,
1.08469522e-09, 1.88147929e-11, 2.37055006e-11, 1.85314364e-11,
2.26815434e-11, 2.41212013e-11, 9.99999998e-01, 1.68558540e-11,
8.78989931e-12, 2.30303345e-11, 2.19747289e-11, 2.02437383e-11,
1.72961027e-11])

#Compute the variance of the portfolio
var_maxRet = np.dot(w_maxRet, np.dot(Q, w_maxRet)) #variance
var_maxRet

0.33974851965068

#Compute the return of the portfolio
ret_maxRet = np.dot(mu, w_maxRet) #expected return
ret_maxRet

0.10211634693131111

Compute classical Markowitz efficent frontier¶
For each expected return, ranging from the return of the minimum variance portfolio to return of the maximum return portfolio, compute the optimal portfolio. The set of these optimal portfolios equals the efficient fronteir for the given dataset.

#Create tareget ranges for portfolio returns
targetLen = 50
#targetRet = np.linspace(ret_minVar,ret_maxRet,50)
targetRet = np.linspace(ret_minVar,ret_maxRet,targetLen)

# Define optimization problem and compute one portfolio on efficient frontier
w = cp.Variable(n)
eps = cp.Parameter()

constraints3 = >= eps,sum(w) == 1,w >= 0]
prob3 = cp.Problem(cp.Minimize(cp.quad_form(w, Q)), constraints3)

# Compute efficient frontier
w_front_clas = []
var_front_clas = []
ret_front_clas = []
for epsilon in targetRet:
eps.value = epsilon
prob3.solve()
w_front_clas.append(w.value)
var_front_clas.append(np.dot(w.value, np.dot(Q, w.value)))
ret_front_clas.append(np.dot(mu, w.value))

Compute the resampled efficient frontier¶
To compute the resampled frontier, from the origional dateset compute simulated (resampled) data. Form each resampled dataset, compute the new efficient frontier. The efficient frontier for the resampled data is found as the average weight of each asset at each return level along each resampled frontier.

#incomplete – do not run

sample_size = ret.shape[0]
repetition = ??

#set variables for storing resuts

#Usa a random seed so that results will be consistent
np.random.seed(10)

#Resample by taking n (sample size) draws from the original input
for i in range(repetition):

#resample by drawing from the multivariate normal distribution with mu and Q
x_resample = ??

#Calculate the new mean vector (mu_resample) and new variance-covariance matrix (Q _resample)
#resampled mu and Q
mu_resample = ??
Q_resample = ??

#Compute minimum variance

w_minVar = w1.value #solution value: minimum variance
var_minVar = np.dot(w_minVar, np.dot(Q_resample, w_minVar)) #variance
ret_minVar = np.dot(mu_resample, w_minVar) #expected return

#compute maximum expected return

w_maxRet = w2.value #solution value: maximum expected return
var_maxRet = np.dot(w_maxRet, np.dot(Q_resample, w_maxRet)) #variance
ret_maxRet = np.dot(mu_resample, w_maxRet) #expected return

#target return
targetRet = np.linspace(ret_minVar,ret_maxRet,50)

# Define optimization problem and compute one portfolio on efficient frontier
w_re = cp.Variable(n)
eps_re = cp.Parameter()

constraints4 = ??
prob4 = ??

# Compute efficient frontier
w_front_re = []
var_front_re = []
ret_front_re = []
for epsilon in targetRet:

#Store results for each resampling

#compute the average weights at each return leve

#compute the resampled efficient frontier based on the average weights and orignial mu & Q

For the classical frontier, determine and store the portfolio weights for the minimum variance, maximum return, and Sharpe ratio optimized portfolio’s¶
The Sharpe ratio of each portfolio is calculatd as the (portfolio return – the risk free rate) / portfolio standard deviation
Use a risk free rate of 0.2% (0.002) monthly.

riskFreeRate = 0.002

#Determine weights of minimum variance and maximum return along the efficient frontier

#Min variance
orig_weights_minVar = w_front_clas[0]
print(orig_weights_minVar)

#Max return
orig_weights_maxRet = w_front_clas[targetLen – 1]
print(orig_weights_maxRet)

[ 3.27230514e-19 -1.14168501e-20 -8.31476257e-22 1.11997349e-19
1.90859691e-20 1.70010969e-20 -2.67206636e-20 8.07691367e-20
5.54485957e-02 8.99769245e-20 9.08772714e-20 6.59194971e-01
9.71734393e-20 3.48208987e-20 1.76013193e-03 8.87191244e-02
5.48842212e-02 -8.25235299e-20 -1.26901397e-20 4.97870966e-20
4.42499270e-20 2.33153316e-20 9.01180838e-02 8.74735709e-21
4.98748717e-02]
[-1.31075269e-15 -6.16528539e-15 -5.19951772e-15 -4.94667076e-15
-5.26860930e-15 -5.16434209e-15 -6.33874698e-15 -5.85370259e-15
-5.49013629e-15 -4.51579498e-15 -3.84817773e-15 -4.82621158e-15
5.15958422e-09 -4.59747759e-15 -6.38732563e-15 -4.54605481e-15
-5.74461164e-15 -6.86109638e-15 9.99999995e-01 -4.24601328e-15
-3.09630928e-15 -5.91825243e-15 -5.46379763e-15 -4.93574474e-15
-4.31381808e-15]

#Compute sharp ratio
ret_array_clas = np.array(ret_front_clas)
var_array_clas = np.array(var_front_clas)

sharpe_array_clas = (ret_array_clas – riskFreeRate)/np.sqrt(var_array_clas)

weights_sharpe_clas = w_front_clas[sharpe_array_clas.argmax()]
print(sharpe_array_clas)
print(sharpe_array_clas.argmax())
print(weights_sharpe_clas)

[0.21841729 0.27800793 0.32774795 0.36827174 0.4008275 0.42613411
0.44630936 0.46246746 0.47543186 0.48587106 0.49430315 0.50103627
0.5064046 0.51069581 0.51411326 0.51665943 0.51848227 0.5197395
0.52055446 0.52102369 0.52122284 0.52121134 0.52103597 0.52073366
0.52033363 0.51985904 0.5193283 0.51875604 0.51815393 0.51753126
0.51689544 0.51625237 0.51560673 0.51496224 0.51432183 0.51368778
0.5130289 0.51215006 0.50586457 0.49160956 0.47226911 0.45041653
0.42794104 0.40604084 0.38566114 0.3420309 0.28395628 0.23536734
0.19889106 0.17176165]
[ 3.03160097e-01 -2.51104684e-22 -2.18834623e-22 -9.98195762e-22
2.80063553e-22 1.40269759e-22 1.05222599e-22 1.36537702e-21
8.22330413e-22 1.19218622e-22 -1.36878928e-22 4.07725910e-01
1.68209250e-01 -4.02460862e-22 1.73977686e-21 -1.13658312e-21
-6.17327472e-22 6.85033555e-22 2.27436297e-02 1.41718742e-22
9.81611134e-02 -2.17487770e-22 -1.21027064e-21 1.21213741e-22
-1.79537982e-22]

For each of the 6 portfolios, calculate the expected return on the 2021 (out-of-sample) data¶

#drop date
price2021 = df2.iloc[:,1:]

#We want return for the whole year so only use first and last month
price2021_ = price2021.drop(price2021.index[1:11])
price2021_.reset_index(inplace = True, drop = True)

#Compute percent change
ret_2021 = price2021_.pct_change().iloc[1:,:]

AMD OXY XLF BABA F BAC CCL AMC DAL FB … UNH MMM AAL MULN QQQ AAPL XLE FXI JPM V
1 0.68029 0.446726 0.366112 -0.53201 0.982391 0.522067 0.077665 1.051282 0.029505 0.302017 … 0.521509 0.043312 0.04601 -0.584591 0.269255 0.353931 0.458557 -0.256478 0.261573 0.128286

1 rows × 25 columns

#From classical frontier find
#Minimum variance portfolio
#orig_weights_minVar
orig_minVar_ret2021 = np.dot(ret_2021, orig_weights_minVar)
print(orig_minVar_ret2021)

#Maximum return portfolio
#orig_weights_maxRet
orig_maxRet_ret2021 = np.dot(ret_2021, orig_weights_maxRet)
print(orig_maxRet_ret2021)

#Sharpe ratio portfolio
#orig_weights_sharpe
orig_sharpe_ret2021 = np.dot(ret_2021, weights_sharpe_clas)
print(orig_sharpe_ret2021)

[0.02822425]
[-0.58459094]
[0.27958832]

#Compute returns on $1000

#Compute returns on $1000

print(‘Out-of-sample returns on $1000 investment: \n’)
print(‘On the Classical Efficient Frontier, the minimum variance portfolio returns $’ , orig_minVar_ret2021*1000)
print(‘On the Classical Efficient Frontier, the maximum return portfolio returns $’ , orig_maxRet_ret2021*1000)
print(‘On the Classical Efficient Frontier, the optimal Sharpe ratio portfolio returns $’ , orig_sharpe_ret2021*1000 , ‘\n’)
# print(‘On the Resampled Efficient Frontier, the minimum variance portfolio returns $’ , re_minVar_ret2021*1000)
# print(‘On the Resampled Efficient Frontier, the maximum return portfolio returns $’ , re_maxRet_ret2021*1000)
# print(‘On the Resampled Efficient Frontier, the optimal Sharpe ratio portfolio returns $’ , re_sharpe_ret2021*1000)

Out-of-sample returns on $1000 investment:

On the Classical Efficient Frontier, the minimum variance portfolio returns $ [28.22424688]
On the Classical Efficient Frontier, the maximum return portfolio returns $ [-584.59094047]
On the Classical Efficient Frontier, the optimal Sharpe ratio portfolio returns $ [279.5883226]

3. Plot the classical and resampled efficient frontiers [10pts]¶

#Missing varianble – do not run

axC = plt.gca()
plt.rcParams[‘figure.figsize’] = [9, 8]

for i in range(repetition):
# Plot volatility versus expected return for individual stocks
axC.scatter(x=np.sqrt(np.diag(Q_resample_list[i])), y=mu_resample_list[i], color=’darkgray’, label=’Individual Stocks’ if i == 0 else “”)

# Plot volatility versus expected return for mimimum variance portfolio
axC.scatter(x=np.sqrt(var_minVar_list[i]), y=ret_minVar_list[i], marker=’D’, s=30, color=’limegreen’, label=’Minimum Variance Portfolio’ if i == 0 else “”)

# Plot volatility versus expected return for maximum return portfolio
axC.scatter(x=np.sqrt(var_maxRet_list[i]), y=ret_maxRet_list[i], marker=’D’, s=30, color=’darkviolet’, label=’Maximum Return Portfolio’ if i == 0 else “”)

# Plot efficient frontier
axC.plot(np.sqrt(var_frontC_list[i]), ret_frontC_list[i], ‘–‘, color=’peachpuff’, label=’Efficient Frontier’ if i == 0 else “”)

#Plot the classical mean-variance efficient frontier
axC.plot(np.sqrt(var_front_clas), ret_front_clas, color=’blue’, linewidth=3, label=’Classical Efficient Frontier’)

#Plot the resampled efficient frontier
axC.plot(np.sqrt(var_frontC_resample), ret_frontC_resample, color=’red’, linewidth=3, label=’Resampled Efficient Frontier’)

axC.set_xlabel(‘Volatility (Standard Deviation)’)
axC.set_ylabel(‘Expected Return’)
plt.title(‘Efficient Frontier’)
axC.legend(loc=”lower right”)
axC.grid()
plt.show()

4. Plot the portfolio compositions for classical and resampled frontiers. [15pts]¶

x_tick = np.arange(len(targetRet))+1
color_list = [‘fuchsia’,’green’,’pink’,’orange’,’purple’,’royalblue’,’grey’,’firebrick’,’olive’,’black’,’yellow’,’lime’,’indigo’,’red’,’blue’,’teal’,’skyblue’,’tan’,’cyan’,’navy’]
plt.figure(figsize=(8, 6))
plt.stackplot(x_tick, np.array(w_front_clas).T, colors=color_list)
plt.legend(df1.columns[1:], bbox_to_anchor=(1.2, 1))
plt.xlim((1,len(targetRet)))
plt.ylim((0,1))
plt.xticks(np.arange(1,len(targetRet)+1,5))
plt.xlabel(“Portfolio No. (with increasing target return)”)
plt.ylabel(“Portfolio Weights”)
plt.title(“Portfolio Allocations: Classical Mean-Variance Optimization”)
plt.show()

#Missing variables – do not run

x_tick = np.arange(len(targetRet))+1
color_list = [‘fuchsia’,’green’,’pink’,’orange’,’purple’,’royalblue’,’grey’,’firebrick’,’olive’,’black’,’yellow’,’lime’,’indigo’,’red’,’blue’,’teal’,’skyblue’,’tan’,’cyan’,’navy’]
plt.figure(figsize=(8, 6))
plt.stackplot(x_tick, np.array(average_weight_list).T, colors=color_list)
plt.legend(df1.columns[1:], bbox_to_anchor=(1.2, 1))
plt.xlim((1,len(targetRet)))
plt.ylim((0,1))
plt.xticks(np.arange(1,len(targetRet)+1,5))
plt.xlabel(“Portfolio No. (with increasing target return)”)
plt.ylabel(“Portfolio Weights”)
plt.title(“Portfolio Allocations: Resampled”)
plt.show()

程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com