かなり一般的な (そして単純な) 最適化問題を解決したいと思いますが、これに関する投稿はないようです: ロング/ショート マーケット ニュートラル 最小分散最適化. 「R 疑似コード」での最適化の形式:
min (t(h) %*% D %*% h ) s.t. # minimize portfolio variance, h weights, D covar matrix
sum(h) == 0 # market neutral; weights sum to 0
sum(abs(h)) == 1 # book-size/fully-invested; abs(weights) sum to 1
h %*% e >= threshold # the portfolio expected return is > some threshold
h <= maxPos # each long position is less than some maxPos
h >= -maxPos # each short position is greater than -maxPos
他の質問に欠けているこの質問の鍵は、「本のサイズ」の制約です。ロング/ショート最適化では、この制約が必要です。そうしないと、ナンセンスな結果が得られます。これは二次最適化問題ですが、制約の「abs」のために、非線形制約があります。「abs」制約を非線形制約から線形制約に変換するためのよく知られた(私が推測する特定のサークルでは)トリックがあります。方程式に補助変数を導入することでこれを行います ( lp_solve リファレンス ガイド: 絶対値でこの説明を参照してください)。
多因子リスクモデルの入力が与えられた場合に、最小のポートフォリオ分散の重みを計算するために、この関数を作成しました。
portSolveMinVol <- function(er,targetR,factorVols,factorCorrel,idioVol) {
require(quadprog)
# min ( -d'b + 1/2 b'Db)
# A'b >= b_0
# b = weights --> what we are solving for
# D = covariance matrix
# d = we can set this to zero as we have no linear term in the objective function
# set up the A matrix with all the constraints
# weights sum to 0
# abs weights sum to 1
# max pos < x, greater than -x
# return > some thresh
numStocks <- length(er) # er is the expected return vector
numAbs <- numStocks # this is redundant but I do this to make the code easier to read
VCV <- factorVols %*% t(factorVols) * factorCorrel # factor covariance matrix
S <- matrix(0,ncol=numStocks,nrow=numStocks)
diag(S) <- idioVol * idioVol # stock specific covariance (i.e., 0's except for diagonal)
common <- factorBetas %*% VCV %*% t(factorBetas) # stock common risk covar matrix
# need to fill in the Dmat b/c of the abs constraint
Dmat <- matrix(0,ncol=numStocks+numAbs,nrow=numStocks+numAbs)
Dmat[1:numStocks,1:numStocks] <- (common + S) # full covariance matrix
dvec <- rep(0,numStocks + numAbs) # ignored but solve.QP wants it
# A'b >= b_0
Amat <- matrix(0,nrow= 3,ncol=numStocks + numAbs)
Amat[1,] <- c(rep(1,numStocks),rep(0,numAbs)) # sum weights equal zero
Amat[2,] <- c(rep(0,numStocks),rep(1,numAbs)) # sum abs weights equal 1
Amat[3,] <- c(er,rep(0,numAbs)) # expected return >= threshold
# add contraints on min and max pos size
maxpos <- matrix(0,nrow=numStocks,ncol=numStocks + numAbs)
minpos <- matrix(0,nrow=numStocks,ncol=numStocks + numAbs)
for(i in 1:numStocks) {
maxpos[i,i] = -1 # neg and neg b/c of >= format of contraints
minpos[i,i] = 1 # pos and neg b/c of >= format of contraints
}
absmaxpos <- matrix(0,nrow=numStocks,ncol=numStocks + numAbs)
absminpos <- matrix(0,nrow=numStocks,ncol=numStocks + numAbs)
# add contraints on the sum(abs(wi)) = 1 and each
for(i in 1:numStocks) {
absmaxpos[i,i] = 1
absmaxpos[i,i+numAbs] = -1
absminpos[i,i] = 1
absminpos[i,i+numAbs] = 1
}
# Set up the Amat
Amat <- rbind(Amat,maxpos,minpos,absmaxpos,absminpos)
# set up the rhs
bvec <- c(0, # sum of weights
1, # sum of abs weights
0.005, # min expected return
rep(-0.025,numStocks), # max pos
rep(-0.025,numStocks), # min pos
rep(0,numAbs), # abs long dummy var
rep(0,numAbs)) # abs short dummy var
# meq is the number of first constraints that are equality
res <- solve.QP(Dmat, dvec, t(Amat), bvec, meq=2)
res
}
次の単体テストで呼び出します(多要素モデル入力のスプーフィング):
set.seed(1)
nStocks <- 100
nBetas <- 5
er <-rnorm(nStocks,mean=0.0012,0.0075)
factorVols <- 0.08 + runif(nBetas,0,0.15)
factorCorrel <- matrix(rep(0,nBetas*nBetas),nrow=nBetas,ncol=nBetas)
for(i in 1:(nBetas)) {
for(j in 1:(nBetas)) {
factorCorrel[i,j] = rnorm(1,mean=0.2,sd=0.05)
factorCorrel[j,i] = factorCorel[i,j]
}
}
diag(factorCorrel) <- 1
idioVol <- abs(rnorm(nStocks,mean=0.01,sd=0.05))
res <- portSolveMinVol(er,0.005,factorVols,factorCorrel,idioVol)
これにより、次のエラーがスローされます。
Error in solve.QP(Dmat, dvec, t(Amat), bvec, meq = 2) : matrix D in
quadratic function is not positive definite!
そのため、私の質問は、Rのsolve.QPでロング/ショート最適化にabs制約をどのように実装するのですか?
さらなる注意として、Paper Portfolio Optimization with Transaction Costsは、Matlab でこれを行う方法を示していますが、R の solve.QP では機能しないようです。