Eric Zivot
August 6, 2015
options(digits=3, width=70)
# install IntroCompFinR package from R-forge
# use install.packages("IntroCompFinR", repos="http://R-Forge.R-project.org")
library(IntroCompFinR)
## Loading required package: xts
## Loading required package: zoo
##
## Attaching package: 'zoo'
##
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
library(PerformanceAnalytics)
##
## Attaching package: 'PerformanceAnalytics'
##
## The following object is masked from 'package:graphics':
##
## legend
library(zoo)
Sys.setenv(TZ="UTC")
cex.val = 2
Estimates of CER model for Microsoft, Nordstrom and Starbucks stock from monthly returns over the period January 1995 to January 2000.
asset.names <- c("MSFT", "NORD", "SBUX")
mu.vec = c(0.0427, 0.0015, 0.0285)
names(mu.vec) = asset.names
sigma.mat = matrix(c(0.0100, 0.0018, 0.0011,
0.0018, 0.0109, 0.0026,
0.0011, 0.0026, 0.0199),
nrow=3, ncol=3)
dimnames(sigma.mat) = list(asset.names, asset.names)
r.f = 0.005
mu.vec
## MSFT NORD SBUX
## 0.0427 0.0015 0.0285
cov2cor(sigma.mat)
## MSFT NORD SBUX
## MSFT 1.000 0.172 0.078
## NORD 0.172 1.000 0.177
## SBUX 0.078 0.177 1.000
# create vector of portfolio weights
x.vec = rep(1,3)/3
names(x.vec) = asset.names
# compute mean, variance and volatility
mu.p.x = crossprod(x.vec,mu.vec)
sig2.p.x = t(x.vec)%*%sigma.mat%*%x.vec
sig.p.x = sqrt(sig2.p.x)
# show mean and volatility
mu.p.x
## [,1]
## [1,] 0.0242
sig.p.x
## [,1]
## [1,] 0.0759
# create vector of portfolio weights
y.vec = c(0.8, 0.4, -0.2)
names(y.vec) = asset.names
# compute mean, variance and volatility
mu.p.y = crossprod(y.vec,mu.vec)
sig2.p.y = t(y.vec)%*%sigma.mat%*%y.vec
sig.p.y = sqrt(sig2.p.y)
# show mean and volatility
mu.p.y
## [,1]
## [1,] 0.0291
sig.p.y
## [,1]
## [1,] 0.0966
# covariance
sig.xy = t(x.vec)%*%sigma.mat%*%y.vec
sig.xy
## [,1]
## [1,] 0.00391
# correlation
rho.xy = sig.xy/(sig.p.x*sig.p.y)
rho.xy
## [,1]
## [1,] 0.533
Create 100 random portfolio vectors with weights that sum to one.
set.seed(123)
x.msft = runif(100, min=-1.5, max=1.5)
x.nord = runif(100, min=-1.5, max=1.5)
x.sbux = 1 - x.msft - x.nord
head(cbind(x.msft, x.nord, x.sbux))
## x.msft x.nord x.sbux
## [1,] -0.637 0.3000 1.337
## [2,] 0.865 -0.5015 0.637
## [3,] -0.273 -0.0342 1.307
## [4,] 1.149 1.3634 -1.512
## [5,] 1.321 -0.0513 -0.270
## [6,] -1.363 1.1711 1.192
# plot portfolio weights
chart.StackedBar(cbind(x.msft, x.nord, x.sbux),
main="100 Random portfolio weight vectors",
xlab = "portfolio", ylab = "weights",
xaxis.labels=as.character(1:100))
Use \(z_m = A^{-1}_m b\).
top.mat = cbind(2*sigma.mat, rep(1, 3))
bot.vec = c(rep(1, 3), 0)
Am.mat = rbind(top.mat, bot.vec)
b.vec = c(rep(0, 3), 1)
z.m.mat = solve(Am.mat)%*%b.vec
m.vec = z.m.mat[1:3,1]
# minimum variance portfolio weights
m.vec
## MSFT NORD SBUX
## 0.441 0.366 0.193
Mean and volatility of minimum variance portfolio
mu.gmin = as.numeric(crossprod(m.vec, mu.vec))
sig2.gmin = as.numeric(t(m.vec)%*%sigma.mat%*%m.vec)
sig.gmin = sqrt(sig2.gmin)
mu.gmin
## [1] 0.0249
sig.gmin
## [1] 0.0727
Use analytic formula for minimum variance portfolio
one.vec = rep(1, 3)
sigma.inv.mat = solve(sigma.mat)
top.mat = sigma.inv.mat%*%one.vec
bot.val = as.numeric((t(one.vec)%*%sigma.inv.mat%*%one.vec))
m.mat = top.mat/bot.val
m.mat[, 1]
## MSFT NORD SBUX
## 0.441 0.366 0.193
Use matrix algebra formula to compute efficient portfolio.
top.mat = cbind(2*sigma.mat, mu.vec, rep(1, 3))
mid.vec = c(mu.vec, 0, 0)
bot.vec = c(rep(1, 3), 0, 0)
Ax.mat = rbind(top.mat, mid.vec, bot.vec)
bmsft.vec = c(rep(0, 3), mu.vec["MSFT"], 1)
z.mat = solve(Ax.mat)%*%bmsft.vec
x.vec = z.mat[1:3,]
x.vec
## MSFT NORD SBUX
## 0.8275 -0.0907 0.2633
Compute mean and volatility of efficient portfolio.
mu.px = as.numeric(crossprod(x.vec, mu.vec))
sig2.px = as.numeric(t(x.vec)%*%sigma.mat%*%x.vec)
sig.px = sqrt(sig2.px)
mu.px
## [1] 0.0427
sig.px
## [1] 0.0917
Compare with mean and volatility of Microsoft.
mu.vec["MSFT"]
## MSFT
## 0.0427
sd.vec["MSFT"]
## MSFT
## 0.1
# solve for portfolio weights
bsbux.vec = c(rep(0, 3), mu.vec["SBUX"], 1)
z.mat = solve(Ax.mat)%*%bsbux.vec
y.vec = z.mat[1:3,]
y.vec
## MSFT NORD SBUX
## 0.519 0.273 0.207
# compute mean, variance and std deviation
mu.py = as.numeric(crossprod(y.vec, mu.vec))
sig2.py = as.numeric(t(y.vec)%*%sigma.mat%*%y.vec)
sig.py = sqrt(sig2.py)
mu.py
## [1] 0.0285
sig.py
## [1] 0.0736
# compare with Starbucks
mu.vec["SBUX"]
## SBUX
## 0.0285
sd.vec["SBUX"]
## SBUX
## 0.141
Later on, we will use the covariance between the two efficient portfolios.
sigma.xy = as.numeric(t(x.vec)%*%sigma.mat%*%y.vec)
rho.xy = sigma.xy/(sig.px*sig.py)
sigma.xy
## [1] 0.00591
rho.xy
## [1] 0.877
Here we use the fact that any efficient portfolio is a convex combination of any two efficient portfolios:
\[z = \alpha \times x + (1 - \alpha) \times y\]
Set \(\alpha = 0.5\).
a = 0.5
z.vec = a*x.vec + (1-a)*y.vec
z.vec
## MSFT NORD SBUX
## 0.6734 0.0912 0.2354
Compute the mean and volatility.
sigma.xy = as.numeric(t(x.vec)%*%sigma.mat%*%y.vec)
mu.pz = as.numeric(crossprod(z.vec, mu.vec))
sig2.pz = as.numeric(t(z.vec)%*%sigma.mat%*%z.vec)
sig.pz = sqrt(sig2.pz)
mu.pz
## [1] 0.0356
sig.pz
## [1] 0.0801
Here the mean is half-way between the mean of Microsoft and the mean of Starbucks.
Given a target mean value, \(\mu_0 = 0.05\), you can solve for \(\alpha\).
a.05 = (0.05 - mu.py)/(mu.px - mu.py)
a.05
## [1] 1.51
Given \(\alpha=\) 1.514 solve for \(z\).
z.05 = a.05*x.vec + (1 - a.05)*y.vec
z.05
## MSFT NORD SBUX
## 0.986 -0.278 0.292
Finally, compute the mean and volatility.
mu.pz.05 = a.05*mu.px + (1-a.05)*mu.py
sig2.pz.05 = a.05^2 * sig2.px + (1-a.05)^2 * sig2.py + 2*a.05*(1-a.05)*sigma.xy
sig.pz.05 = sqrt(sig2.pz.05)
mu.pz.05
## [1] 0.05
sig.pz.05
## [1] 0.107
Here we compute efficient portfolios as convex combinations of the the global minimum variance portfolio and the efficient portfolio with the same mean as Microsoft.
a = seq(from=1, to=-1, by=-0.1)
n.a = length(a)
z.mat = matrix(0, n.a, 3)
colnames(z.mat) = names(mu.vec)
mu.z = rep(0, n.a)
sig2.z = rep(0, n.a)
sig.mx = t(m.vec)%*%sigma.mat%*%x.vec
for (i in 1:n.a) {
z.mat[i, ] = a[i]*m.vec + (1-a[i])*x.vec
mu.z[i] = a[i]*mu.gmin + (1-a[i])*mu.px
sig2.z[i] = a[i]^2 * sig2.gmin + (1-a[i])^2 * sig2.px + 2*a[i]*(1-a[i])*sig.mx
}
chart.StackedBar(z.mat, xaxis.labels=round(sqrt(sig2.z),digits=3),
xlab="Portfolio SD", ylab="Weights")
Here we use the analytic matrix albegra formula for the tangency portfolio.
rf = 0.005
sigma.inv.mat = solve(sigma.mat)
one.vec = rep(1, 3)
mu.minus.rf = mu.vec - rf*one.vec
top.mat = sigma.inv.mat%*%mu.minus.rf
bot.val = as.numeric(t(one.vec)%*%top.mat)
t.vec = top.mat[,1]/bot.val
t.vec
## MSFT NORD SBUX
## 1.027 -0.326 0.299
Compute mean and volatility of tangency portfolio
mu.t = as.numeric(crossprod(t.vec, mu.vec))
sig2.t = as.numeric(t(t.vec)%*%sigma.mat%*%t.vec)
sig.t = sqrt(sig2.t)
mu.t
## [1] 0.0519
sig.t
## [1] 0.112
Efficient portfolios are combinations of T-Bills and the tangency portfolio.
Every efficient portfolio is a combination of T-bills and the tangency portfolio. The volatility of such an efficient portfolio is:
\[ \sigma_e = x_{tan} \times \sigma_{tan} \]
Given a target volatility, \(\sigma_0 = 0.02\), you can solve for \(x_{tan}\) and \(x_f = 1 - x_{tan}\):
x.t.02 = 0.02/sig.t
x.t.02
## [1] 0.179
1-x.t.02
## [1] 0.821
The efficient portfolio weights in MSFT, NORD, SBUX are:
x.t.02*t.vec
## MSFT NORD SBUX
## 0.1840 -0.0585 0.0537
The mean and volatility of this efficient portfolio are:
mu.t.02 = x.t.02*mu.t + (1-x.t.02)*rf
sig.t.02 = x.t.02*sig.t
mu.t.02
## [1] 0.0134
sig.t.02
## [1] 0.02
Every efficient portfolio is a combination of T-bills and the tangency portfolio. The mean of such an efficient portfolio is:
\[ \mu_e = r_f + x_{tan} \times (\mu_{tan} - r_f) \]
Given a target mean, \(\mu_0 = 0.07\), you can solve for \(x_{tan}\) and \(x_f = 1 - x_{tan}\):
x.t.07 = (0.07 - rf)/(mu.t - rf)
x.t.07
## [1] 1.39
1-x.t.07
## [1] -0.386
The efficient portfolio weights in MSFT, NORD, SBUX are:
x.t.07*t.vec
## MSFT NORD SBUX
## 1.423 -0.452 0.415
The mean and volatility of this efficient portfolio are:
mu.t.07 = x.t.07*mu.t + (1-x.t.07)*rf
sig.t.07 = x.t.07*sig.t
mu.t.07
## [1] 0.07
sig.t.07
## [1] 0.155