2016-10-13 9 views
1

制約最適化の問題を解決するためにメタヒューリスティックを使用するために、私は、ラムダは、0と1の間の値をとるR.ローカル検索を使用したMarkowitzモデル/ポートフォリオの最適化R

Min 
    lambda * [sum{i=1 to N}sum{j = 1 to N}w_i*w_i*Sigma_ij] - (1-lambda) * [sum{i=1 to N}(w_i*mu_i)] 
subject to 
    sum{i=1 to N}{w_i} = 1 
    0 <= w_i <= 1; i = 1,...,N 

NMOFパッケージを使用して(下記の)基本的なマーコウィッツ平均分散最適化モデルを解決しようとしています、Nは、資産の数です。私は目的関数(OF)でラムダを含める方法を確認していない

library(NMOF) 

na <- dim(fundData)[2L] 
ns <- dim(fundData)[1L] 
Sigma <- cov(fundData) 
winf <- 0.0 
wsup <- 1.0 
m <- colMeans(fundData) 


resample <- function(x,...) x[sample.int(length(x),...)] 


data <- list(R = t(fundData), 
      m = m, 
      na = dim(fundData)[2L], 
      ns = dim(fundData)[1L], 
      Sigma = Sigma, 
      eps = 0.5/100, 
      winf = winf, 
      wsup = wsup, 
      nFP = 100) 

w0 <- runif(data$na); w0 <- w0/sum(w0) 

OF <- function(w,data){  
    wmu <- crossprod(w,m) 
    res <- crossprod(w, data$Sigma) 
    res <- tcrossprod(w,res) 
    result <- res - wmu 
    } 


neighbour <- function(w, data){ 
    toSell <- w > data$winf 
    toBuy <- w < data$wsup 
    i <- resample(which(toSell), size = 1L) 
    j <- resample(which(toBuy), size = 1L) 
    eps <- runif(1) * data$eps 
    eps <- min(w[i] - data$winf, data$wsup - w[j], eps) 
    w[i] <- w[i] - eps 
    w[j] <- w[j] + eps 
    w 
} 


algo <- list(x0 = w0, neighbour = neighbour, nS = 5000L) 
system.time(sol1 <- LSopt(OF, algo, data)) 

:(:金融における数値解法と最適化ブックに基づいて)後

は私のコードです。上記のコードには、OFのラムダは含まれていません。私はforループを使用してみましたが、それは、次のエラーが発生しました:

OF <- function(w,data){ 

    lambdaSeq <- seq(.001,0.999, length = data$nFP) 
    for(lambda in lambdaSeq){ 
    wmu <- crossprod(w,m) 
    res <- crossprod(w, data$Sigma) 
    res <- tcrossprod(w,res) 
    result <- lambda*res - (1-lambda)*wmu 
    } 
} 

エラー:誰かがこの点で私を助けることができれば

Local Search. 
    Initial solution: 
     |                       | 0% 
    Error in if (xnF <= xcF) { : argument is of length zero 
    Timing stopped at: 0.01 0 0.03 

それはいいだろう。

p.s:これは、2次計画法を使用して解決できることも認識しています。これは単なる他の制約を含む開始です。

+0

だから、どうやって内側の 'for'ループを使う予定ですか?今、シーケンスの最後のラムダに到達するまで繰り返します。エラーを起こさなかったとしても、最初のn-1回の繰り返しは実際には何もしないので、私はその点を見ません。あなたはすべての反復または何かの「最小」結果を見つけたいですか? –

+0

@ Hack-R:いいえ、すべての反復の「最小」結果ではありません。私はラムダの異なる値に対して目的関数の最小値を求めたい。 'lambda'の値は0から1の範囲です。 –

+0

' for'ループのすべての反復の 'min'結果とどのように違いますか? 'for'ループには目的関数のコードがすべて含まれています。したがって、OFの最小値をラムダ以上にするには、 'for'ループのすべての反復の' min'があなたが望むものです。とにかく、現在のところ、すべての反復が前の反復を上書きするので、最後の反復の値だけを返します。したがって、 'lambda'も1と同じです。さらに、' for'ループは ' LSopt機能を有する。 –

答えて

1

私が正しく理解していれば、平均的な分散効率的なフロンティアをローカル検索で複製したいですか?次に、フロンティアに含めるすべての値lambdaをローカル検索で実行する必要があります。

次の例は、手伝ってください。まず、パッケージを添付してリストdataを設定します。

require("NMOF") 
data <- list(m = colMeans(fundData), ## expected returns 
      Sigma = cov(fundData), ## expected var of returns 
      na = dim(fundData)[2L], ## number of assets 
      eps = 0.2/100,   ## stepsize for LS 
      winf = 0,    ## minimum weight 
      wsup = 1,    ## maximum weight 
      lambda = 1) 

次にI(すなわちlambdaが1に等しい)最小分散のケースのためのベンチマークを計算します。

## benchmark: the QP solution 
## ==> this will only work with a recent version of NMOF, 
## which you can get by saying: 
## install.packages('NMOF', type = 'source', 
##     repos = c('http://enricoschumann.net/R', 
##        getOption('repos'))) 
## 
require("quadprog") 
sol <- NMOF:::minvar(data$Sigma, 0, 1) 

目的関数と近傍関数。私はわずかに両方の機能を簡略化しています(明確にするために、目的関数でcrossprodを使用するほうが効率的です)。

OF <- function(w, data){ 
    data$lambda * (w %*% data$Sigma %*% w) - 
    (1 - data$lambda) * sum(w * data$m) 
} 

neighbour <- function(w, data){ 
    toSell <- which(w > data$winf) 
    toBuy <- which(w < data$wsup) 
    i <- toSell[sample.int(length(toSell), size = 1L)] 
    j <- toBuy[sample.int(length(toBuy), size = 1L)] 
    eps <- runif(1) * data$eps 
    eps <- min(w[i] - data$winf, data$wsup - w[j], eps) 
    w[i] <- w[i] - eps 
    w[j] <- w[j] + eps 
    w 
} 

ここでローカル検索を実行できます。 QPソリューションを再現するには、かなり大きなデータセット(資産数200)、 が必要です。

w0 <- runif(data$na) ## a random initial solution 
w0 <- w0/sum(w0) 
algo <- list(x0 = w0, neighbour = neighbour, nS = 50000L) 
sol1 <- LSopt(OF, algo, data) 

ローカル検索から取得した重みをQPソリューションと比較できます。あなたは全体のフロンティアを計算したい場合は

par(mfrow = c(3,1), mar = c(2,4,1,1), las = 1) 
barplot(sol, main = "QP solution") 
barplot(sol1$xbest, main = "LS solution") 
barplot(sol - sol1$xbest, 
     ylim = c(-0.001,0.001)) ## +/-0.1% 

は最後に、あなたはdata$lambdaの異なるレベルのために、このコードを再実行する必要があります。