風險

投資組合優化:關於風險厭惡參數的有效邊界與 R

  • October 22, 2019

我目前正在嘗試在 R 中編寫一個小腳本,以確定給定固定風險厭惡參數的最佳權重。我遇到的問題是,通過增加風險厭惡參數,我認為拋物線應該變得更寬。但是,在我的情況下,它會產生相同的拋物線,但差異很小。我遇到的問題是我不確定我制定solve.qp的方式是否正確我的想法是最小化 -w^t mu+aversion/2 w^t Sigma*w; 其中 w = 權重,mu = 回報的平均值,Sigma = 回報的共變異數。我確實嘗試使用tseries 包中的portfolio.optim,但它不允許我修復風險規避參數,還是這樣?

您可以在下面找到我的程式碼。

   efficientPortfolio <- function(er,cov.mat,aversion=3,target.return){

   Dmat<- cov.mat*aversion
   dvec<- as.vector(er)
   ones<- rep(1,length(er))
   zeros <-rep(0,length(er))
   Identity <- matrix(0,length(er),length(er))
   diag(Identity)<-1
   Amat<- (cbind((ones),colMeans(data),Identity)) #no short sell

   bvec<- c(1,target.return,zeros) #no short sell

   sol<-solve.QP(Dmat,dvec,Amat,bvec=bvec,meq=1)
   weights<-sol$solution


   exp.ret <- crossprod(dvec,weights)
   std.dev <- sqrt(weights %*% cov.mat %*% weights)

   ret <- list("call" = call,
               "er" = as.vector(exp.ret),
               "sd" = as.vector(std.dev),
               "weights" = weights) 
   ret
   }



   efficientFrontier <- function(er,cov.mat, nport = 20,aversion=3) {
   ef <- matrix(0, nport, 2 + length(er))

   pm <- seq((min(er)), (max(er)), 
             length.out = nport)

   for (i in 1:nport) {

           port <-         efficientPortfolio(er,cov.mat,aversion=aversion,target.ret=pm[i])

           ef[i, 1] <- port$sd
               ef[i, 2] <- port$er
           ef[i, 3:ncol(ef)] <- port$weights

    }
   list(ef = ef[, 1:2], weights = ef[, -1:-2])
    }

我而言,er 和 cov.mat 是:

  er<-c(2.626568e-05, 6.542483e-06, 2.169358e-05, 1.510713e-04 ,7.113906e-05 )
  cov.mat<-matrix(c(4.408143e-04 ,   1.487359e-05, 1.680034e-05,   3.066478e-04,   2.069675e-04,
1.487359e-05,   7.270984e-03,   9.134981e-06,   -1.699836e-05,  7.956140e-06,
1.680034e-05,   9.134981e-06,   6.528898e-04,   5.397248e-06,   9.887768e-06,
3.066478e-04,   -1.699836e-05,  5.397248e-06,   1.473456e-03,   6.657914e-04,
2.069675e-04,   7.956140e-06,   9.887768e-06,   6.657914e-04,   5.090455e-04),5,5)

我使用的包是 quadprog 提前謝謝。Jc

編輯:在一些測試中,我注意到當我將 sove.qp 應用於不同的 Dmat=cov.mat*aversion(其中 aversion = 3 或 4)時,會產生相同的權重。這怎麼可能 ?

查看您的程式碼,您似乎將均值變異數問題的風險最小化公式與**風險厭惡公式混合在一起。兩種公式都包括“預算”約束,即權重之和等於 1,並且可以要求每個權重大於零,即“僅做多”不等式約束。在風險最小化問題中,在投資組合收益等於目標收益的約束下,找到最小化投資組合變異數的權重。

$$ \underset{w}{\arg \min} \quad w’ Q w \quad \text{s.t} \quad rw = r_p,\quad \sum_i w_i=1, \quad w_i \geq 0\quad $$ 在哪裡 $ Q $ 是共變異數矩陣和 $ r_p $ 是目標投資組合收益。在風險規避形式中,可以找到最大化回報的權重減去風險規避係數乘以您在文章中所述的投資組合變異數。

$$ \underset{w}{\arg \max} \quad w’r - \lambda w’ Q w \quad \text{s.t} \sum_i w_i=1, \quad w_i \geq 0\quad $$ 在哪裡 $ \lambda $ 是風險厭惡係數。請注意,風險厭惡公式中對投資組合收益沒有限制。

在您的程式碼中,第二個約束是收益的不等式約束,它要求投資組合收益為 $ \geq r_p $ . 有了這個約束,當回報低於目標回報時,您的解決方案就會從風險規避模型​​切換到風險最小化模型。這是一個可能的模型,但似乎不是您想要的。

儘管使用不同的方法來計算風險和回報的投資組合優化有很多變化,但一旦你選擇了一種方法,就只有一個有效的邊界。下面的程式碼是對您的程式碼的修改,它顯示了風險和回報如何隨著價值的降低而變化 $ \lambda $ 並且這只是在給定一組風險和回報的情況下繪製有效邊界的另一種方法。

library(quadprog)
efficientPortfolio <- function(er,cov.mat,aversion=3, target_return=NULL, method= c("risk_min","risk_aver","mixed","min_var") ){
 n_asset <- length(er)
# quad problem
 if(method %in%  c("risk_min", "min_var")){
   aversion  = 1
   Dmat <- cov.mat
   dvec <- rep(0, n_asset)
   meq <- ifelse(method == "min_var", 1, 2)}  
 else {
   Dmat <- aversion*cov.mat
   dvec <- er
   meq <-  1}
# constraint eqns
 if(method %in% c("risk_aver","min_var")) {
   bvec <- c(1, rep(0,n_asset))
   Amat <- matrix( c(rep(1,n_asset), diag(nrow=n_asset)), nrow=n_asset)  }
 else {
   bvec <- c(1, target_return, rep(0,n_asset))
   Amat <- matrix( c(rep(1,n_asset), er, diag(nrow=n_asset)), nrow=n_asset)  }
 sol<-solve.QP(Dmat, dvec,Amat, bvec=bvec, meq=meq)
 weights<-sol$solution
     exp.ret <- t(er)%*%weights
     std.dev <- sqrt(weights %*% cov.mat %*% weights)
     ret <- list(er = as.vector(exp.ret),
                 sd = as.vector(std.dev),
                 weights = weights,
                 lagrange_mults=sol$Lagrangian )  
}

efficientFrontier <- function(er,cov.mat, nport=20, lambda_min = .1, lambda_max=2, lambda = 1,
                             target_return = NULL,  method = c("risk_min","risk_aver","mixed") ) {
# if method = risk_min, input sequence of target_returns or use defaults; input target_returns < min_var return are not used
#           = risk_aver, input upper and lower bounds of risk aversion coefficients lambda or use defaults
#           = mixed, input single value of risk aversion coefficient lambda and seq of target_returns or use default
 n_asset <- length(er)
 method <- method[1]
 lambda <- if(method == "risk_min"){
                nport <- ifelse(is.null(target_return), nport, length(target_return)) 
                rep(NA_real_,nport) }
           else if(method == "mixed") rep(lambda, nport)
                 else seq(lambda_max, lambda_min, (lambda_min-lambda_max)/(nport-1)) 
 ef <- list(Efficient_Frontier_method = method, sol=matrix(0, nrow=nport, ncol=3, dimnames=list(NULL, c("lambda", "sd", "return")) ),
            weights= matrix(0, nrow=nport, ncol=n_asset),
            lagrange_mults=matrix(0, nrow=nport, ncol=ifelse(method=="risk_aver", 1, 2) +n_asset) )
 colnames(ef$lagrange_mults) <- if(method == "risk_aver") c("budget",rep("",n_asset)) else c("budget","target_return",rep("", n_asset))
   # calculate minimum variance portfolio
     port_min_var <- efficientPortfolio(er,cov.mat,target_return=NULL, aversion=NULL, method="min_var")
     cat("Mininum Variance Portfolio\n      sd          return\n")
     cat(sd=port_min_var$sd, return=port_min_var$er,"\n\n")
     target_return <- if(is.null(target_return)) seq(port_min_var$er, max(er), length.out=nport)
                  else {
                    target_return[target_return < port_min_var$er] <- port_min_var$er
                    target_return
                  }
 for (i in 1:nport) {
   port <- efficientPortfolio(er,cov.mat,aversion=lambda[i], target_return=target_return[i], method=method)
   ef$sol[i,"lambda"] <- lambda[i]
       ef$sol[i,"sd"] <- port$sd
       ef$sol[i,"return"] <- port$er
       ef$weights[i,] <- port$weights
       ef$lagrange_mults[i,] <- port$lagrange_mults
 }
 return(ef)
}

編輯

評論中對您的問題的簡短回答是肯定的。由於可能對不同風險公式之間的關係感興趣,我更新了上面的程式碼,以使用風險最小化(method = “risk_min”)和風險規避(method=“risk_aver”)方法計算有效邊界。它還將處理兩種情況混合的情況(method=“mixed”)。該程式碼現在還報告了有效邊界上點的拉格朗日乘數。

特別是,對於對投資組合收益使用不平等約束的混合案例,您可以看到從風險不利解決方案到風險最小化解決方案的轉換。對於較小的目標回報值,其中回報不平等約束不活躍,投資組合解決方案對於不同的目標回報值是相同的,因為沒有任何變化並且回報不平等的拉格朗日乘數為零。隨著目標回報的增加,投資組合回報約束變得活躍並確定解決方案,並且相關的拉格朗日乘數採用非零值。解決方案已切換到風險最小化案例。可以證明,當投資組合收益拉格朗日乘數不為零時,它的倒數等於風險厭惡係數。 風險規避對優化的影響, 特別是在他們的 B.6 節中,其中拉格朗日乘數之間的關係(它們的對偶變數 $ \pi_3 $ 和 $ \pi_4 $ ) 並證明了風險厭惡係數。

引用自:https://quant.stackexchange.com/questions/17149