繁体   English   中英

投资组合优化SOLVE.QP不等式约束

[英]Portfolio Optimization SOLVE.QP inequality constraints

我的名字叫格雷戈里(Grégory),我正在尝试计算具有以下约束的最小方差投资组合:

  1. 权重之和小于或等于1(投资组合可以完全投资,但这不是义务)
  2. 权重总和等于或大于0(投资组合可以全额现金支付,但这不是义务)
  3. 0 <=资产权重<= 5%(不允许卖空,最大资产权重为5%)

    MV<-function (Returns, percentage = TRUE, ...) { if (is.null(dim(Returns))) { stop("Argument for 'Returns' must be rectangular.\\n") } call <- match.call() V <- cov(Returns, ...) V <- make.positive.definite(V) N <- ncol(Returns) a1 <- rep(-1, N) b1 <- -1 a2 <- diag(N) b2 <- rep(0, N) c1<- -diag(N) ## This has been added to the model (to say: min 5%) c2<-rep(-0.05,N) ## This has been added to the model (to say: min 5%) c3<- rep(1,N) c4<- 0 Amat <- cbind(a1,c3,a2,c1) ### Corresponds to the matrix defining the different constraints Bvec <- c(b1,c4,b2,c2) ### Corresponds to the vector of constraints Dvec <- rep(0, N) ### Set to 0 because the first term of the routine must be equal to 0 #meq<- c(1,1,rep(1,N), rep(1,N)) opt <- solve.QP(Dmat = 2 * V, dvec = Dvec, Amat = Amat, bvec = Bvec, meq =0) w_mv <- opt$solution names(w_mv) <- colnames(Returns) if (percentage) w_mv <- w_mv * 100 return(w_mv) }

当我查看MV组合权重时,所有资产权重都等于0,所以我不知道错误的来源。

如果你能帮助我,我将非常感激。

提前谢谢了,

亲切的问候,

了Grégory

看一下这个脚本。

library(stockPortfolio) # Base package for retrieving returns
library(ggplot2) # Used to graph efficient frontier
library(reshape2) # Used to melt the data
library(quadprog) #Needed for solve.QP

# Create the 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, from earliest start date possible (where all stocks have
# data) through most 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 be a m x n matrix with one column per security
 # short argument is whether short-selling is allowed; default is no (short
 # selling prohibited)max.allocation is the maximum % allowed for any one
 # security (reduces concentration) risk.premium.up is the upper limit of the
 # risk premium modeled (see for loop below) and risk.increment is the
 # increment (by) value used in the for loop

 covariance <- cov(returns)
 print(covariance)
 n <- ncol(covariance)

 # Create initial Amat and bvec assuming only equality constraint
 # (short-selling is allowed, no allocation constraints)
 Amat <- matrix (1, nrow=n)
 bvec <- 1
 meq <- 1

 # Then modify the Amat and bvec if short-selling is prohibited
 if(short=="no"){
 Amat <- cbind(1, diag(n))
 bvec <- c(bvec, rep(0, n))
 }

 # And modify Amat and bvec if a max allocation (concentration) is specified
 if(!is.null(max.allocation)){
 if(max.allocation > 1 | max.allocation <0){
 stop("max.allocation must be greater than 0 and less than 1")
 }
 if(max.allocation * n < 1){
 stop("Need to set max.allocation higher; not enough assets to add to 1")
 }
 Amat <- cbind(Amat, -diag(n))
 bvec <- c(bvec, rep(-max.allocation, n))
 }

 # Calculate the number of loops
 loops <- risk.premium.up / risk.increment + 1
 loop <- 1

 # Initialize a matrix to contain allocation and statistics
 # This is not necessary, but speeds up processing and uses less memory
 eff <- matrix(nrow=loops, ncol=n+3)
 # Now I need to give the matrix column names
 colnames(eff) <- c(colnames(returns), "Std.Dev", "Exp.Return", "sharpe")

 # Loop through the quadratic program solver
 for (i in seq(from=0, to=risk.premium.up, by=risk.increment)){
 dvec <- colMeans(returns) * i # This moves the solution along the 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 the eff.frontier function based on no short and 50% alloc. restrictions
eff <- eff.frontier(returns=returns$R, short="no", max.allocation=.50,
 risk.premium.up=1, risk.increment=.001)

# Find the optimal portfolio
eff.optimal.point <- eff[eff$sharpe==max(eff$sharpe),]

# graph efficient frontier
# Start with 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")

在下面的链接中有一个很好的解释。

http://economistatlarge.com/portfolio-theory/r-optimized-portfolio

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM