2015-04-21 93 views
1

我想使用optim函數找到內部收益率(IRR),基本上是使得我的NPV函數爲零的'利率'。使用優化計算內部收益率

我目前的NPV函數(工作)的代碼是:

npv <- function(rate, cf){ 
    r_v <- rep (rate,length (cf)) 
    t_v <- as.numeric (seq(1:length (cf))) 
    pv <- cf * exp (-t_v*r_v) 
    sum (pv) 
} 

我用下面optim功能的嘗試:

InternalRateReturn <- optim(c(0,1), npv, cf = testcf2, gr = NULL, method = "L-BFGS-B", lower = -Inf, upper = Inf,control=list(), hessian = FALSE)

但它不具有正確回來回答爲InternalRateReturn$par,而不是使用下面的uniroot方法。

請問如何修改此代碼(重申,我只想優化npv函數中的速率,使npv函數等於零)?

使用uniroot IRR函數是按如下:

irr1 <- function(cf) { 
    uniroot(npv, c(0, 1), cf=cf)$root 
} 
+0

嗯,我可以看到一個問題,它可能不是唯一的問題:'optim'優化你的函數的第一個參數(例如,'rate',它是函數'npv'中的一個標量)。你提供的初始值是兩個元素的向量,所以'optim'會拋出一個錯誤。你可以使你的初始值成爲一個標量來解決這個問題,或者在'npv'中將'rate'和'values'打包成一個向量。然而,當我試圖複製這個問題時,我得到了一個不同於你的錯誤,所以也許嘗試修復和更新。 – tkmckenzie

+0

@ tkmckenzie我明白你在做什麼。但是,我對這個網站(或者一般的編程)非常陌生,並且不確定如何將速率和值打包到npv中的矢量中。是否可以詳細闡述一下,或指引我參考相關鏈接?非常感謝你的幫助。 – dhhs91

+0

對不起,它並沒有幫助我也遇到了字符限制(對不起,我想把它作爲答案,但我不確定這實際上是否解決了問題)。你想要做的是'npv < - function(x)',那麼函數的第一對行應該是'rate < - x [1]'和'values < - x [2]'。之後,你可以讓你的功能做它以前做的任何事情。希望這可以幫助,讓我知道,如果我可以進一步澄清。 – tkmckenzie

回答

0

如果您只是需要計算IRR或NPV(或MIRR),由於目前尚不清楚爲什麼你會絕對需要使用optim,你可以簡單地考慮包financialFinCal而不是黑客自己的功能。就像這樣:

> require(financial) 
> cf(c(-123400, 36200, 54800, 48100), i = 2.5) 

Cash Flow Model 

Flows: 
     1  2  3  4 
-123400 36200 54800 48100 

IRR%: 5.96 
NPV Extremes at I%: 

    I%  NPV  NFV  NUS 
1 2.5 8742.13 9414.32 3060.95 

> require(FinCal) 
> npv(c(-123400, 36200, 54800, 48100), r = 0.025) 
[1] 8742.134 
> irr(c(-123400, 36200, 54800, 48100)) 
[1] 0.05959787 
1

有由Matt Brigida

使用 optim計算IRR的很酷的例子
### IRR Function: Takes a vector of payments and returns a list which includes the internal rate of return ($IRR) and possible word of warning ($beware) ---- 

irr <- function(x, period = 1, starting.value = .1){ 

### This should detect the number of sign changes. Should correctly not warn if there are many negative cash flows (so long as there is only 1 change in sign). 

    irr.func <- function(r){ (sum(x/(1 + r)^{0:(length(x)-1)}))^2 } 
    result <- optim(par = starting.value, fn = irr.func, method = "Brent", lower = -1000000, upper = 1000000) 

    ## detecting number of sign changes 
    x.ge.0 <- 1 * (x >= 0) 
    changes <- diff(x.ge.0) 
    changes <- changes * changes 
    num.changes <- sum(changes) 

    if(num.changes > 1) { 

     statement <- "Your cash flows change more than once -- so you may have multiple IRRs. This function will only return the first IRR it finds. To find the others, you can try different starting values. However, note the IRR does not make sense if the signs change more than once (try Modified IRR or NPV)." 
     value <- period * result$par 
     return(list(beware = statement, IRR = value)) 

    } else { 

     return(list(IRR = period * result$par)) 

    } 
} 

馬特也有一個更現實的修改IRR一個非常有用的功能(不做出不合理的假設再投資率)

### Modified IRR (MIRR) Function: Takes a vector of payments and returns the MIRR by ---- 

mirr <- function(x, period = 1, starting.value = .1, discount.rate = 0.1, investment.rate = 0.05){ 

    ## move cash flows 
    ## negative 
    cf.neg <- (x < 0) * x 
    ## discounted 
    pv.cf.neg <- cf.neg/(1 + discount.rate)^{0:(length(x)-1)} 
    pv <- sum(pv.cf.neg) 

    ## positive 
    cf.pos <- (x > 0) * x 
    fv.cf.pos <- cf.pos * (1 + investment.rate)^{0:(length(x)-1)} 
    fv <- sum(fv.cf.pos) 

    mirr.per.period <- (fv/abs(pv))^{1/(length(x))} - 1 

    return(period * mirr.per.period) 
}