将计算 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)
}
}
我正在使用 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)
}
}