r - Portfolio Optimisation under weight constraints -
with lot of contributors stackoverflow have managed put function derive weights of 2-asset portfolio maximises sharpe ratio. no short sales allowed , sum of weights add 1. constrain asset not being more or less 10% user defined weight. example constrain weight of asset no less 54% or more 66% (i.e 60% +/- 10%). on below example end weights of (0.54,0.66) instead of unsconstrained (0.243,0.7570) .i assume can done tweaking bvect not sure how go it. appreciated.
asset_a <- c(0.034320510,-0.001209628,0.031900161,0.023163947,-0.001872938,-0.010322489,0.006090395,-0.003270854,0.017778990,0.017204915) asset_b <- c(0.047103261,0.055175057,0.021019816,0.020602347,0.007281368,-0.006547404,0.019155238,0.005494798,0.025429958,0.014929124) require(quadprog) hr_solve <- function(asset_a,asset_b) { vol_a <- sd(asset_a) vol_b <- sd(asset_b) cor_ab <- cor(cbind(asset_a,asset_b),method="pearson") ret_a_b <- as.matrix(c(mean(asset_a),mean(asset_b))) vol_ab <- c(vol_a,vol_b) covmat <- diag(as.vector(vol_ab))%*%cor_ab%*%diag(as.vector(vol_ab)) amat <- cbind(rep(1,nrow(covmat)),diag(1,nrow(covmat))) bvec <- c(1,0,0) zeros <- array(0, dim = c(nrow(covmat),1)) minw <- solve.qp(covmat, zeros, amat, bvec, meq = 1 ,factorized = false)$solution rp <- as.numeric(t(minw) %*% ret_a_b) sp <- sqrt(t(minw) %*% covmat %*% minw) wp <- t(matrix(minw)) sret <- sort(seq(t(minw) %*% ret_a_b,max(ret_a_b),length.out=100)) amatt <- cbind(ret_a_b,amat) (ri in sret[-1]){ bvect <- c(ri,bvec) result <- trycatch({solve.qp(covmat, zeros, amatt, bvect, meq = 2,factorized = false)}, warning = function(w){ return(null) } , error = function(w){ return(null)}, = {} ) if (!is.null(result)){ wp <- rbind(wp,as.vector(result$solution)) rp <-c(rp,t(as.vector(result$solution) %*% ret_a_b)) sp <- c(sp,sqrt(t(as.vector(result$solution)) %*% covmat %*% as.vector(result$solution))) } } hr_weights <- wp[which.max(rp/sp),] as.matrix(hr_weights) } hr_solve(asset_a,asset_b) [,1] [1,] 0.2429662 [2,] 0.7570338
i think should take @ link below.
http://economistatlarge.com/portfolio-theory/r-optimized-portfolio/r-code-graph-efficient-frontier
i think you'll learn lot that. i'll post code here, in case link gets shut down sometime in future.
# economist @ large # modern portfolio theory # use solve.qp solve efficient frontier # last edited 5/3/13 # file uses solve.qp function in quadprog package solve # efficient frontier. # since efficient frontier parabolic function, can find solution # minimizes portfolio variance , vary risk premium find # points along efficient frontier. find portfolio # largest sharpe ratio (expected return / sd) identify # efficient portfolio library(stockportfolio) # base package retrieving returns library(ggplot2) # used graph efficient frontier library(reshape2) # used melt data library(quadprog) #needed solve.qp # create portfolio using etfs, incl. hypothetical non-efficient allocation stocks <- c( "vtsmx" = .0, "spy" = .20, "efa" = .10, "iwm" = .10, "vwo" = .30, "lqd" = .20, "hyg" = .10) # retrieve returns, earliest start date possible (where stocks have # data) through recent date returns <- getreturns(names(stocks[-1]), freq="week") #currently, drop index #### efficient frontier function #### eff.frontier <- function (returns, short="no", max.allocation=null, risk.premium.up=.5, risk.increment=.005){ # return argument should m x n matrix 1 column per security # short argument whether short-selling allowed; default no (short # selling prohibited)max.allocation maximum % allowed 1 # security (reduces concentration) risk.premium.up upper limit of # risk premium modeled (see loop below) , risk.increment # increment (by) value used in loop covariance <- cov(returns) print(covariance) n <- ncol(covariance) # create initial amat , bvec assuming equality constraint # (short-selling allowed, no allocation constraints) amat <- matrix (1, nrow=n) bvec <- 1 meq <- 1 # modify amat , bvec if short-selling prohibited if(short=="no"){ amat <- cbind(1, diag(n)) bvec <- c(bvec, rep(0, n)) } # , modify amat , bvec if max allocation (concentration) specified if(!is.null(max.allocation)){ if(max.allocation > 1 | max.allocation <0){ stop("max.allocation must greater 0 , less 1") } if(max.allocation * n < 1){ stop("need set max.allocation higher; not enough assets add 1") } amat <- cbind(amat, -diag(n)) bvec <- c(bvec, rep(-max.allocation, n)) } # calculate number of loops loops <- risk.premium.up / risk.increment + 1 loop <- 1 # initialize matrix contain allocation , statistics # not necessary, speeds processing , uses less memory eff <- matrix(nrow=loops, ncol=n+3) # need give matrix column names colnames(eff) <- c(colnames(returns), "std.dev", "exp.return", "sharpe") # loop through quadratic program solver (i in seq(from=0, to=risk.premium.up, by=risk.increment)){ dvec <- colmeans(returns) * # moves solution along ef sol <- solve.qp(covariance, dvec=dvec, amat=amat, bvec=bvec, meq=meq) eff[loop,"std.dev"] <- sqrt(sum(sol$solution*colsums((covariance*sol$solution)))) eff[loop,"exp.return"] <- as.numeric(sol$solution %*% colmeans(returns)) eff[loop,"sharpe"] <- eff[loop,"exp.return"] / eff[loop,"std.dev"] eff[loop,1:n] <- sol$solution loop <- loop+1 } return(as.data.frame(eff)) } # run eff.frontier function based on no short , 50% alloc. restrictions eff <- eff.frontier(returns=returns$r, short="no", max.allocation=.50, risk.premium.up=1, risk.increment=.001) # find optimal portfolio eff.optimal.point <- eff[eff$sharpe==max(eff$sharpe),] # graph efficient frontier # start color scheme ealred <- "#7d110c" ealtan <- "#cdc4b6" eallighttan <- "#f7f6f0" ealdark <- "#423c30" ggplot(eff, aes(x=std.dev, y=exp.return)) + geom_point(alpha=.1, color=ealdark) + geom_point(data=eff.optimal.point, aes(x=std.dev, y=exp.return, label=sharpe), color=ealred, size=5) + annotate(geom="text", x=eff.optimal.point$std.dev, y=eff.optimal.point$exp.return, label=paste("risk: ", round(eff.optimal.point$std.dev*100, digits=3),"\nreturn: ", round(eff.optimal.point$exp.return*100, digits=4),"%\nsharpe: ", round(eff.optimal.point$sharpe*100, digits=2), "%", sep=""), hjust=0, vjust=1.2) + ggtitle("efficient frontier\nand optimal portfolio") + labs(x="risk (standard deviation of portfolio)", y="return") + theme(panel.background=element_rect(fill=eallighttan), text=element_text(color=ealdark), plot.title=element_text(size=24, color=ealred)) ggsave("efficient frontier.png")
Comments
Post a Comment