#Data
asset.names = c("MSFT", "NORD", "SBUX")
er = c(0.0427, 0.0015, 0.0285)
names(er) = asset.names
covmat = matrix(c(0.0100, 0.0018, 0.0011,0.0018, 0.0109, 0.0026,0.0011, 0.0026, 0.0199),nrow=3, ncol=3)
r.free = 0.005
dimnames(covmat) = list(asset.names, asset.names)
 
#Define function globalMin.portfolio 
globalMin.portfolio <-
     function(er, cov.mat, shorts=TRUE)
     {
         call <- match.call()
asset.names <- names(er)
er <- as.vector(er)
cov.mat <- as.matrix(cov.mat)
N <- length(er)
if(N != nrow(cov.mat))
    stop("invalid inputs")
if(any(diag(chol(cov.mat)) <= 0))
    stop("Covariance matrix not positive definite")
if(shorts==TRUE){
    cov.mat.inv <- solve(cov.mat)
    one.vec <- rep(1,N)
    w.gmin <- rowSums(cov.mat.inv) / sum(cov.mat.inv)
    w.gmin <- as.vector(w.gmin)
} else if(shorts==FALSE){
    Dmat <- 2*cov.mat
    dvec <- rep.int(0, N)
    Amat <- cbind(rep(1,N), diag(1,N))
    bvec <- c(1, rep(0,N))
    result <- quadprog::solve.QP(Dmat=Dmat,dvec=dvec,Amat=Amat,bvec=bvec,meq=1)
    w.gmin <- round(result$solution, 6)
} else {
    stop("shorts needs to be logical. For no-shorts, shorts=FALSE.")
}
names(w.gmin) <- asset.names
er.gmin <- crossprod(w.gmin,er)
sd.gmin <- sqrt(t(w.gmin) %*% cov.mat %*% w.gmin)
gmin.port <- list("call" = call,
                   "er" = as.vector(er.gmin),
                   "sd" = as.vector(sd.gmin),
                   "weights" = w.gmin)
class(gmin.port) <- "portfolio"
gmin.port
}
 
#compute global minimum variance portfolio
gmin.port = globalMin.portfolio(er, covmat)
attributes(gmin.port)
## $names
## [1] "call"    "er"      "sd"      "weights"
## 
## $class
## [1] "portfolio"
print(gmin.port)
## $call
## globalMin.portfolio(er = er, cov.mat = covmat)
## 
## $er
## [1] 0.02489184
## 
## $sd
## [1] 0.07267607
## 
## $weights
##      MSFT      NORD      SBUX 
## 0.4411093 0.3656263 0.1932644 
## 
## attr(,"class")
## [1] "portfolio"
summary(gmin.port, risk.free=r.free)
##         Length Class  Mode   
## call    3      -none- call   
## er      1      -none- numeric
## sd      1      -none- numeric
## weights 3      -none- numeric
plot(gmin.port$weights, col="red")

#compute global minimum variance portfolio with no short sales
gmin.port.ns = globalMin.portfolio(er, covmat, shorts=FALSE)
attributes(gmin.port.ns)
## $names
## [1] "call"    "er"      "sd"      "weights"
## 
## $class
## [1] "portfolio"
print(gmin.port.ns)
## $call
## globalMin.portfolio(er = er, cov.mat = covmat, shorts = FALSE)
## 
## $er
## [1] 0.02489182
## 
## $sd
## [1] 0.072676
## 
## $weights
##     MSFT     NORD     SBUX 
## 0.441109 0.365626 0.193264 
## 
## attr(,"class")
## [1] "portfolio"
summary(gmin.port.ns, risk.free=r.free)
##         Length Class  Mode   
## call    4      -none- call   
## er      1      -none- numeric
## sd      1      -none- numeric
## weights 3      -none- numeric
plot(gmin.port.ns$weights, col="red")