R中Loop的矢量化:债券的现金流

时间:2017-12-21 16:05:40

标签: r for-loop vectorization

我需要计算以不规则方式摊还的债券的美元摊销(债务偿还)值。例如,我创建了以下摊销方案:

  • 期间1:无摊还
  • 期间2:摊还10%的债务
  • 期间3:摊还剩余债务的30%
  • 期间4:摊销剩余债务的100%

下面是适用于上述示例的计算代码,考虑使用for循环的1000美元债务。

# Vector with amortization values (in % of outstanding balance)
prc_amortization = c(0, 10, 30, 100)

# Value for initial balance
initial_balance = 1000

# Dataframe
df = data.frame(initial_balance = c(initial_balance, rep(NA, 3)),
                prc_amortization = prc_amortization,
                amortization = NA,
                final_balance = NA)

# Calculation of amortization values in $, leading to updated balances
for (i in 1:4) {
  df$amortization[i] = df$initial_balance[i]*df$prc_amortization[i]/100
  df$final_balance[i] = df$initial_balance[i] - df$amortization[i]
  if (i<4) {df$initial_balance[i+1] = df$final_balance[i]}
}

# Results
df
  initial_balance prc_amortization amortization final_balance
1            1000                0            0          1000
2            1000               10          100           900
3             900               30          270           630
4             630              100          630             0

由于我会进行多次这些计算,因此我觉得需要尽快运行此代码。

有没有办法以矢量化方式完成这些计算?

这里棘手的部分是,对于任何给定的时期,我需要知道初始余额,以便计算$中的摊销。

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

您的问题是您的摊还时间表是相对于上一期。您需要找到相对于前期余额的有效绝对摊销。

例如,第二期的摊销是剩余余额的10%,仍然是初始余额的100%。第三期为余额的30%,即90%(扣除10%后),因此第一期的绝对摊销为90%×30%= 27%。同样的第四个时期。这可以通过以编程方式/冗长方式完成:

effective_prc_amortization <- numeric(length(prc_amortization))
for (i in seq_along(effective_prc_amortization)) {
  prevsum <- if (i == 1) 1 else 1 - sum(effective_prc_amortization[1:(i-1)])
  effective_prc_amortization[i] <- prevsum * prc_amortization[i]/100
}
effective_prc_amortization
# [1] 0.00 0.10 0.27 0.63

由此,您可以轻松计算任意期间,只知道初始余额,而不需要前一期间的余额。

# amortization
effective_prc_amortization * initial_balance
# [1]   0 100 270 630
# final_balance
initial_balance - cumsum(effective_prc_amortization * initial_balance)
# [1] 1000  900  630    0

其他观点:

# percentage remaining
cumprod(1 - c(0,10,30,100)/100)
# [1] 1.00 0.90 0.63 0.00

# value remaining
1000 * cumprod(1 - c(0,10,30,100)/100)
# [1] 1000  900  630    0