R中的滚动计算

Rolling calculations in R

我正在尝试使用数据 table 在 R 中为分期偿还贷款帐户建模。每行代表一个月。每个月都有一笔还款或预支资金,并根据上个月的余额收取利息。

例如:

> loan <- data.table(loan.age = seq(0:9), payment = c(5000, -rep(100,9)))

我找不到添加利息和余额列的简单方法。对于每月1%的利率,利息应该是上月余额的0.01倍,新余额应该是上月余额加上当月的利息加上当月的付款(通常为负数)。在伪代码中:

this_balance = last_balance + last_balance * 0.01 + this_payment

这是我正在寻找的结果:

> loan
    loan.age payment interest balance
 1:        0    5000     0.00 5000.00
 2:        1    -100    50.00 4950.00
 3:        2    -100    49.50 4899.50
 4:        3    -100    48.99 4848.49
 5:        4    -100    48.49 4796.98
 6:        5    -100    47.97 4744.95
 7:        6    -100    47.45 4692.40
 8:        7    -100    46.92 4639.32
 9:        8    -100    46.39 4585.71
10:        9    -100    45.87 4531.58

我可以用 for 循环解决这个问题,但它在大型投资组合中速度太慢了。对于上下文,使用年金公式的 300 个月贷款比 for 循环快 100 倍(每笔贷款 2 秒对 20 毫秒)。

我试过将 table 连接到自身,我也试过 Data Table 1.9.5 中新增的 shift() 函数,但我无法计算出强制计算从上到下进行的方式,以便新的余额向下波动 table.

我的代码目前使用从年金公式得出的一些金融数学计算出每个时期的余额,但如果利率在贷款的中途发生变化,这种方法将不起作用。

谢谢。

编辑:我认为这个问题已经解决了。解决方案 2b) 来自 下面的 G. Grothendieck 给出了一个通用的解决方案,既适用于这种简单的情况,也可以扩展到更复杂的场景。

1) 尝试 filter:

loan[, c("interest", "balance") := 0][, 
     balance := c(filter(payment, 1.01, method = "recursive"))][,
     interest := c(0, diff(balance) - payment[-1])]

给予:

> loan
    loan.age payment interest  balance
 1:        1    5000  0.00000 5000.000
 2:        2    -100 50.00000 4950.000
 3:        3    -100 49.50000 4899.500
 4:        4    -100 48.99500 4848.495
 5:        5    -100 48.48495 4796.980
 6:        6    -100 47.96980 4744.950
 7:        7    -100 47.44950 4692.399
 8:        8    -100 46.92399 4639.323
 9:        9    -100 46.39323 4585.716
10:       10    -100 45.85716 4531.574

注: 最后一行可以改写为:

         interest := .01 * c(0, balance[-.N])]

或者在data.table的开发版中:

         interest := .01 * shift(balance, fill = 0)[[1]]]

2)减少另一种可能是:

f <- function(balance, payment) payment + 1.01 * balance

loan[, c("interest", "balance") := 0][, 
     balance := Reduce(f, payment, accumulate = TRUE) ][,
     interest := c(0, diff(balance) - payment[-1]) ]

2a) 或者如果有一个 rate 列并且已知 payment 除了第一个值(如问题中所示)是常量) 然后下面的作品。请注意,我们已将 rate 列设为常量,但即使 rate 发生变化,只要常量 payment 的假设成立,以下内容仍然有效:

loan$rate <- .01
g <- function(balance, rate) loan$payment[2] + (1 + rate) * balance

loan[, c("interest", "balance") := 0][, 
     balance := Reduce(g, rate[-1], init = payment[1], accumulate = TRUE) ][,
     interest := c(0, diff(balance) - payment[-1]) ]

2b) 这允许 paymentrate 变化:

loan$rate <- .01
h <- function(balance, i) loan$payment[i] + (1 + loan$rate[i]) * balance

loan[, c("interest", "balance") := 0][, 
     balance := Reduce(h, .I[-1], init = payment[1], accumulate = TRUE) ][,
     interest := c(0, diff(balance) - payment[-1]) ]