将计算 XIRR 的函数更改为 return NA 而不是在 R 中停止

Changing a function that calculates XIRR to return NA instead of stopping in R

我正在使用 XIRR 函数来计算几个不同数据帧的 XIRR。所有数据框都有 2 列,日期和现金流量。对于某些数据帧,XIRR 函数 returns 一个值,对于其他数据帧,函数只是停止并抛出错误。这是函数的 link:

https://github.com/SunilVeeravalli/XIRR_in_R/blob/master/Xirr%20Code.R

函数为:

library(tidyverse)

xirr <- function(dataset) {
  
  # creating a function to calculate npv value
  npv <- function(range, dataset){
    for(test.rate in range) {
      
      max.date <- max(dataset$dates)
      
      temp <- dataset %>%
        mutate(npv = amount * ((1 + test.rate/100)^(as.numeric(max.date - dates)/365))) %>%
        select(npv) %>%
        .[1]
      if(sum(dataset$amount) > 0) {
        if(sum(temp) > 0) {
          min.rate <- test.rate
          next
        } else {
          max.rate <- test.rate
          break
        }
      } else {
        if(sum(temp) < 0) {
          min.rate <- test.rate
          next
        } else {
          max.rate <- test.rate
          break
        }
      }
    }
    return(list(min.rate = min.rate, max.rate = max.rate))
  }
  
  
  names(dataset) <- c("dates", "amount")
  
  max.rate <- c()
  min.rate <- c()
  
  if(sum(dataset$amount) > 0) {
    
    range <- seq(from = 0, to = 10000, by = 100)    
    hundreds <- npv(range, dataset)
    
    range <- seq(from = hundreds$min.rate, to = hundreds$max.rate, by = 10)
    tens <- npv(range, dataset)
    
    range <- seq(from = tens$min.rate, to = tens$max.rate, by = 1)
    ones <- npv(range, dataset)
    
    range <- seq(from = ones$min.rate, to = ones$max.rate, by = 0.01)
    decimals <- npv(range, dataset)
    
    return(paste("XIRR is ", mean(unlist(decimals)), "%", sep = ""))   
    
  } else {
    
    range <- seq(from = 0, to = -10000, by = -100)
    hundreds <- npv(range, dataset)
    
    range <- seq(from = hundreds$min.rate, to = hundreds$max.rate, by = -10)
    tens <- npv(range, dataset)
    
    range <- seq(from = tens$min.rate, to = tens$max.rate, by = -1)
    ones <- npv(range, dataset)
    
    range <- seq(from = ones$min.rate, to = ones$max.rate, by = -0.01)
    decimals <- npv(range, dataset)
    
    return(paste("XIRR is ", mean(unlist(decimals)), "%", sep = "")) 
  }
}

两个测试数据框是:

mydate <- seq.Date(from = as.Date("2015-01-01"), to = as.Date("2015-12-01"),
                   by = "month")
cashflow1 <- c(-50000, 0, 100, 200, 300, 400, 100, 200, 300, 400, 440, 0)
testdf1 <- cbind.data.frame(mydate, cashflow1)

cashflow2 <- c(451266, rep(0, times = 11))
testdf2 <- cbind.data.frame(mydate, cashflow2)
xirr(testdf1)
xirr(testdf2)

如您所见,运行 testdf2 的 xirr 导致错误“Error in seq.default(from = hundreds$min.rate, to = hundreds$max.rate, : 'from' 的长度必须为 1 "

我不想让这个函数抛出错误,而是想以 returns NA 而不是给出错误的方式修改它。

只有当至少 1 个值低于零且至少 1 个值高于零时才能计算 XIRR(根据 Excel 定义:“XIRR 预计至少有一个正现金流和一个负现金流; 否则,XIRR return 是 #NUM! 个错误值。" https://support.microsoft.com/en-us/office/xirr-function-de1242ec-6477-445b-b11b-a303ad9adc9d

所以我们可以做的是先检查您的数据,然后立即 return NA 或进行计算。您可以自己编写代码,也可以使用 tvm 包中的 xirr 函数。

xirr <- function(dataset) {
  if(min(dataset$cashflow) < 0 & max(dataset$cashflow) > 0) {
    # do your stuff (your function OR tvm::xirr)
  } else {
    return(NA)
  }
}