gpt4 book ai didi

r - 在 R 中计算 XIRR 时出现 uniroot 错误

转载 作者:行者123 更新时间:2023-12-02 17:58:33 25 4
gpt4 key购买 nike

可重现的示例:

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) # gives the error below
Error in uniroot(xnpv, interval = interval, cf = cf, d = d, tau = tau,  : 
f.lower = f(lower) is NA

Excel XIRR 返回 0.125,这似乎是正确的。

uniroot documentation说“必须指定间隔或下限和上限”,我不确定 tvm::xirr 是否这样做。我想确实如此,因为它适用于许多其他数据集。

无论如何,在这种情况下,我可以通过提供下限和上限(现在我通过 Excel 知道答案)并进行一些试验和错误,使其正常工作,如下所示。但我不确定我的界限是否永远有效。

> tvm::xirr(v, d1, f.lower = -0.2, f.upper=0.5)
[1] 10
> tvm::xirr(v, d1, f.lower = -0.2, f.upper=5)
[1] -1
> tvm::xirr(v, d1, lower = -0.99, upper=0.99)
[1] 0.1244512

这是 tvm::xirr 的错误或限制还是我遗漏了什么?

最佳答案

让我们进入兔子洞吧。首先,让我们阅读tvm::xirr的源代码:

xirr = function (cf, d, tau = NULL, comp_freq = 1, interval = c(-1, 10), ...) 
{
uniroot(xnpv, interval = interval, cf = cf, d = d, tau = tau,
comp_freq = comp_freq, extendInt = "yes", ...)$root
}

Xirr 调用 uniroot 来识别函数 xnpv 在区间 c(-1, 10) 中等于 0 的位置。默认参数值为 tau = NULL 和 comp_freq = 1。 其次,让我们看一下 xnpv 的源代码:

xnpv = function (i, cf, d, tau = NULL, comp_freq = 1) 
{
if (is.null(tau))
tau <- as.integer(d - d[1])/365
delta <- if (comp_freq == 0) {
1/(1 + i * tau)
}
else if (comp_freq == Inf) {
exp(-tau * i)
}
else {
1/((1 + i/comp_freq)^(tau * comp_freq))
}
sum(cf * delta)
}

我们可以将 xnpv 及其根可视化如下:

library(tvm)
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")
x = seq(-0.8, 10, 0.01)
y = sapply(x, function(x) xnpv(i = x, cf = v, d = d1, tau = as.integer(d1 - d1[1])/365))
plot(x, y, type = 'l', ylab = "xnpv", xlab = "cf"); abline(h = 0, lty = 2); abline(v = 0.1244512, lty = 2)

如您所见,对于 comp_freq = 1,因子 1/(1 + i/comp_freq)(在 delta 的定义中)对于指数不同于 0 的情况在 i = -1 处有一个垂直渐近线 (0^0 = R 中的 1)。此外,对于 i < -1,该表达式在 R 中未定义(负数的十进制幂等于 R 中的 NaN)。

要解决此问题,假设 comp_freq 不同于 0 或 +Inf,您可以按如下方式调用 xirr:

offset = 0.001; comp_freq = 1
tvm::xirr(v, d1, lower = -comp_freq+offset, upper = 10, comp_freq = comp_freq, tol = 1e-7) # I also changed the numerical tolerance for increased accuracy.

这假设 cf <= 10。最后,鉴于 comp_freq = 1 是默认值,xirr 在默认设置下总是失败(因此:该函数尚未经过其开发人员的彻底测试)。

关于r - 在 R 中计算 XIRR 时出现 uniroot 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75024100/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com