library(data.table)
q <- c(0.001,
0.002,
0.003,
0.003,
0.004,
0.004,
0.005,
0.007,
0.009,
0.011)
w <- c(0.05,
0.07,
0.08,
0.10,
0.14,
0.20,
0.20,
0.20,
0.10,
0.04)
P <- 100
S <- 25000
r <- 0.02
dt <- as.data.table(cbind(q,w))
npv <- function(cf, r, S, P) {
cf[, inforce := shift(cumprod(1 - q - w), fill = 1)
][, lapses := inforce * w
][, deaths := inforce * q
][, claims := deaths * S
][, premiums := inforce * P
][, ncf := premiums - claims
][, d := (1/(1+r))^(.I)
][, sum(ncf*d)]
}
npv(dt,r,S,P)
#> [1] 50.32483
microbenchmark::microbenchmark(npv(dt,r,S,P))
#> Unit: milliseconds
#> expr min lq mean median uq max neval
#> npv(dt, r, S, P) 2.5791 2.71035 2.964293 2.85625 3.10385 6.0357 100
Created on 2021-01-15 by the reprex package (v0.3.0)
Nice, @paddyhoran. I have not used rust so played with it here: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=255a33e84c70e3bcd43258ddbaa66f27 Looks like the answer matches the other above.
Also looks like your algorithm for the problem is more efficient overall. It's over 2x faster than the prior Julia fastest Julia version above. Code and benchmark: