投資組合管理

solve.QP R 函式中的 Dmat 參數:Cov 還是 2*Cov?

  • April 19, 2017

背景

我的最終目標是從股票指數(例如 S&P500)的 100 隻股票中找到位於有效前沿的投資組合。

這種有效的投資組合將使其變異數與股票指數變異數相同。總結一下,最大化給定目標風險的回報

問題

我首先學習瞭如何使用 PortfolioAnalytics 包,但是每當我將參數type=“mean-StdDev " 傳遞給函式時,函式 create.efficientFrontier 都會出錯。

在沒有解決上述問題的情況下,我決定使用 fPortfolio 包。我有一個有效的邊界,但我無法得到一個包含權重、收益和變異數的矩陣,所以我可以對變異數列進行二進制搜尋,然後選擇相應的權重(也許有一種方法,但我是新手R)。

如果沒有解決上述問題,我決定直接使用solve.QP 解決方案。我終於能夠做我想做的事情。

一旦我得到一個有效的邊界,我決定將它與我從 fPortfolio 得到的進行比較。令我驚訝的是,當收益相同時,變異數結果顯著不同。一旦我排除故障,我發現差異是由於 Dmat 參數,即共變異數矩陣。

我將Dmat <- Cov * 2傳遞給solve.QP 函式,但如果我改為使用Dmat <- Cov,那麼我會從 fPortfolio 獲得相同的結果。沒有任何改變,相同的數據集,相同的約束。顯然,solve.QP 的投資組合變異數是 fPortfolio 的變異數的兩倍。

我在 fPortfolio 中使用最基本的預設配置,即只將返回數據集傳遞給它。

MV Portfolio Frontier 
Estimator:         covEstimator 
Solver:            solveRquadprog 
Optimize:          minRisk 
Constraints:       LongOnly

問題

我在網路上遇到了一些程式碼,將共變異數矩陣乘以 2並將其作為Dmat傳遞。然而,其他一些程式碼只是將共變異數矩陣作為 Dmat 傳遞給 solve.QP 函式(即,不將其乘以 2)。

  • 哪種方法是正確的?

根據我對二次規劃和 solve.QP 函式的研究,我相信共變異數矩陣必須乘以 2

solve.QP 常式實現了 Goldfarb 和 Idnani (1982, 1983) 的對偶方法,用於求解形式為 min(-d^T b + 1/2 b^TD b) 且約束為 A^T b > 的二次規劃問題= b_0。

均值變異數優化(有效邊界)是形式為 min(w^TD w - q R^T w) 的二次規劃問題,約束條件為 A^T w >= w_0。

因此,在將 MV 目標函式轉換為 solve.QP 使用的等效形式時,共變異數矩陣必須乘以 2

但是,這意味著fPortfolio 中的程式碼不正確

  • 以前有人注意到 fPortfolio 的這種行為嗎?

我想我在這裡遺漏了一些非常基本的東西!


程式碼

eff.frontier &lt;- function (ret, max.allocation=NULL, rf=0, risk.limit=.5, risk.increment=.005)
{          
 Dmat &lt;- 2 * cov(ret)      
 n &lt;- ncol(Dmat)      
 Amat &lt;- cbind(1, diag(n))
 bvec &lt;- c(1, rep(0, n))
 meq &lt;- 1

 if(!is.null(max.allocation)){
   Amat &lt;- cbind(Amat, -diag(n))
   bvec &lt;- c(bvec, rep(-max.allocation, n))
 }

 nLoops &lt;- risk.limit / risk.increment + 1
 iLoop &lt;- 1

 eff &lt;- matrix(.0, nrow=nLoops, ncol=n+3)
 colnames(eff) &lt;- c(colnames(returns), "Return", "StdDev", "SharpeRatio")

 for (i in seq(from=0, to=risk.limit, by=risk.increment))
   {
   dvec &lt;- colMeans(ret) * i
   sol &lt;- solve.QP(Dmat=Dmat, dvec=dvec, Amat=Amat, bvec=bvec, meq=meq)
   eff[iLoop,"StdDev"] &lt;- sqrt(sum(sol$solution %*% colSums((Dmat * sol$solution))))
   eff[iLoop,"Return"] &lt;- as.numeric(sol$solution %*% colMeans(ret))
  eff[iLoop,"SharpeRatio"] &lt;- (eff[iLoop,"Return"]-rf) / eff[iLoop,"StdDev"]
  eff[iLoop,1:n] &lt;- sol$solution
   iLoop &lt;- iLoop+1
   }
   return(as.data.frame(eff))
}

您從fPortfolio包中獲得的結果是正確的。如果您不將共變異數矩陣乘以 2,您將從quadprog包中得到相同的結果。所以,要麼使用fPortfolio要麼使用quadprog而不使用 2。

您找到的那個公式中的“1/2”可能指的是一些特定的問題。但是,我在投資組合優化研究中也看到了這種乘以 2 的方法。例如,Eric Zivot 在他的材料中使用了這種方法。我不認為這是正確的。可以肯定的是,我建議您使用 Excel 完成一個簡單的範例,手動完成所需的所有步驟。

編輯:

進一步研究了這個問題並嘗試了以下程式碼:

library(fPortfolio)
library(quadprog)
ret = 100 * LPP2005.RET[,1:6]
Dmat1 &lt;- cov(ret)     
Dmat2 = 2 * cov(ret)
Dmat3 = 10 * cov(ret)
n &lt;- ncol(Dmat)      
dvec = rep(0, n)
Amat &lt;- cbind(rep(1, n), diag(n))
bvec &lt;- c(1, rep(0, n))
meq &lt;- 1
## Dmat
## n
## dvec
## Amat
## bvec
qp.out1 = solve.QP(Dmat, dvec, Amat, bvec, meq, FALSE)
qp.out2 = solve.QP(Dmat, dvec, Amat, bvec, meq, FALSE)
qp.out3 = solve.QP(Dmat, dvec, Amat, bvec, meq, FALSE)
qp.out1$solution
qp.out2$solution
qp.out3$solution

我得到了相同的重量Dmats。因此,看起來將共變異數矩陣乘以常數的權重不會改變優化結果。但是,當您建構您的時,eff.frontier您仍然通過那些 n 倍的共變異數矩陣來獲得您的標準偏差:

eff[iLoop,"StdDev"] &lt;- sqrt(sum(sol$solution %*% colSums((Dmat * sol$solution))))

我認為解決方案是:

eff[iLoop,"StdDev"] &lt;- sqrt(sum(sol$solution %*% colSums((cov(ret) * sol$solution)))) 

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