R语言调用tvm::xirr计算XIRR时出现uniroot报错问题
tvm::xirr默认调用报错的原因与解决办法
问题复现
使用tvm::xirr计算一组现金流的内部收益率时,默认参数调用触发报错:
v <- c(-400000.0,-200000.0, 660636.7) d <- c("2021-10-27","2022-12-23","2023-01-04") d1 <- as.Date(d, format="%Y-%m-%d") tvm::xirr(v, d1) # 触发错误
报错信息:
Error in uniroot(xnpv, interval = interval, cf = cf, d = d, tau = tau, : f.lower = f(lower) is NA
Excel计算该组现金流的XIRR结果为0.125,手动指定合理的上下界后,tvm::xirr能返回正确结果:
tvm::xirr(v, d1, lower = -0.99, upper=0.99) # [1] 0.1244512
原因分析
这是tvm::xirr的局限性,而非操作疏漏:
tvm::xirr内部依赖uniroot函数求解净现值(XNPV)为0的根,uniroot要求指定的区间两端点对应的XNPV值符号相反,且能正常计算出数值(非NA/Inf)。- 查看
tvm::xirr的默认参数,lower=-0.99,upper=1e6。对于该组现金流,极端的upper=1e6会导致计算XNPV时出现数值溢出((1+1e6)^tau是极大值,现金流项除以该值后变为0或触发NA);lower=-0.99也可能在部分场景下引发数值计算异常,导致uniroot无法获取有效的端点函数值,最终报错。 - 你之前尝试的
f.lower和f.upper是uniroot的参数(用于手动指定端点函数值),而非tvm::xirr的参数,这类调用属于参数误用,返回的10或-1并非正确的XIRR结果。
解决方案
针对这类情况,只需手动指定范围更小的合理上下界区间,避免极端值导致的数值计算问题:
- 参考Excel的计算结果,将区间缩小到接近真实值的范围(比如
lower=-0.5,upper=0.5),既保证uniroot能找到符号相反的端点值,又不会触发数值溢出。 - 示例调用:
tvm::xirr(v, d1, lower = -0.5, upper = 0.5) # [1] 0.1244512
内容的提问来源于stack exchange,提问作者ottodidakt
相关产品推荐
相关产品推荐

