【问题标题】:Is there a way to vectorize calculating interest dollars dependent on previous dollar values有没有办法根据以前的美元价值向量化计算利息美元
【发布时间】:2022-11-01 12:50:41
【问题描述】:

我正在模拟年度现金流,并将利息应用于每年的累积余额。我目前的算法是通过遍历每一行来计算利息并将利息添加到明年的期初余额的期末余额中来完成的。问题是我需要多次运行这个模拟多年,并且运行时间变得越来越长。有没有办法将此算法矢量化或实施其他变通方法以减少运行时间?谢谢!

此示例以 5% 的利率完成

我已经研究过使用 lag() 函数来计算每个模拟年的累积余额和利息,但这需要使用 lag() 的次数等于模拟年数才能计算期末余额和运行进入相同的运行时间问题。

SAS 实现在 DATA 步中使用 RETAIN 语句。该算法在 SAS 中运行得很快,但我正在寻找 R 实现。

【问题讨论】:

  • 不要使用图片提供数据。创建一个 R 数据框并使用 dput()。将结果粘贴到您的问题中。如果您花时间为那些试图帮助您的人提供便利,您会更快地得到回复。

标签: r optimization sas simulation


【解决方案1】:

第一步可能是将此问题视为同时计算许多模拟,例如 1000,然后每年递增。所以100年后的余额是

set.seed(123)
n_rep = 1000; n_year = 100
starting_balance <- rep(0, n_rep)
for (i in 1:n_year) {
    random_cash_flow <- runif(1000, 100, 200)
    end_balance <- starting_balance + random_cash_flow
    interest_earned <- end_balance * 0.05
    ## starting balance 'after' year i
    starting_balance <- end_balance + interest_earned
}

总结是

> summary(starting_balance)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.
 374016  402199  409945  410507  418489  448537

【讨论】:

    【解决方案2】:

    我认为没有办法避免在此处使用循环(或像我所做的那样在Reduce 中隐藏循环),因为您依赖于前一行来计算当前行。

    但是您应该能够以相对速度执行此操作,因为一旦您拥有end_balance,您就可以找出其余部分而无需循环:

    simflow <- function(cash_flow, rate) {
        end_balance <- Reduce((x,y) x*(1 + rate) + y, cash_flow, accumulate=TRUE)
        data.frame(
            starting_balance = end_balance - cash_flow,
            cash_flow,
            end_balance,
            interest_earned = end_balance * rate
        )
    }
    
    cash_flow <- c(167,193,6,195,23,20,143,181)
    simflow(cash_flow, rate=0.05)
    ##  starting_balance cash_flow end_balance interest_earned
    ##1           0.0000       167    167.0000         8.35000
    ##2         175.3500       193    368.3500        18.41750
    ##3         386.7675         6    392.7675        19.63838
    ##4         412.4059       195    607.4059        30.37029
    ##5         637.7762        23    660.7762        33.03881
    ##6         693.8150        20    713.8150        35.69075
    ##7         749.5057       143    892.5057        44.62529
    ##8         937.1310       181   1118.1310        55.90655
    

    100 年在 ~ 35 秒内复制了 100,000 次:

    system.time({
        replicate(100000, simflow(sample(cash_flow, 100, replace=TRUE), rate=0.05))
    })
    ##   user  system elapsed 
    ##  35.19    0.36   35.55 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-12
      • 1970-01-01
      • 2012-09-05
      相关资源
      最近更新 更多