consider a time series with annual resolution. For each year, there is a corresponding cash flow. Here is an example:
# Create example data:
set.seed(1)
dat <-
data.frame(year = 1:5, cash.flow = runif(5, 100, 1000))
resulting in
year cash.flow
1 1 338.9578
2 2 434.9115
3 3 615.5680
4 4 917.3870
5 5 281.5137
For each year
I'd like to compute the net present value of all remaining cash flows - point of reference beeing that specific year.
As an example: If we compute the NPV for year == 3
, we only consider the cash.flow
(s) for year >= 3
. We discount these from the year
they occur to our current year
(beeing 3
). To get the NPV @ year == 3
, we just sum up those discounted cash flows.
So far, I'm able to do that using a for
-loop:
library(dplyr)
interest.rate <- 0.02
# Compute NPVs using for-loop:
for(i in 1:nrow(dat)){
dat$npv[i] <-
sum(
dat %>%
filter(year >= i) %>%
mutate(year.corrected = year - i,
cash.eq = 1/((1+interest.rate)^(year.corrected)) * cash.flow) %>%
pull(cash.eq)
)
}
resulting in
year cash.flow npv
1 1 338.9578 2481.5558
2 2 434.9115 2185.4500
3 3 615.5680 1785.5493
4 4 917.3870 1193.3809
5 5 281.5137 281.5137
However, my actual dataset is far bigger, so I'm keen at avoiding loops. I've tried dplyr's summarise()
in combination with group_by(year)
, but I didn't manage to "dynamize" the timespan to which the cash flows should be discounted.
So: How can I achive the result given above in a more efficient manner?
PS: I'm sorry if the general problem has been answered before in a non-financial context, but I'm unable to verbalize it in a more general way...
In the question year
is consecutive so assuming that that is the case define an npv
function and apply it using rollapply
with align = "left"
and partial = TRUE
.
Note that npv
in the jrvFinance package could be substituted for the npv
defined below without changing the pipeline.
library(dplyr)
library(zoo)
npv <- function(x, rate) sum(1/(1 + rate)^seq(0, length(x)-1) * x)
dat %>%
mutate(npv = rollapply(cash.flow, n(), npv, rate = interest.rate,
partial = TRUE, align = "left"))
giving:
year cash.flow npv
1 1 338.9578 2481.5558
2 2 434.9115 2185.4500
3 3 615.5680 1785.5493
4 4 917.3870 1193.3809
5 5 281.5137 281.5137
The input (from question):
set.seed(1)
interest.rate <- 0.02
dat <- data.frame(year = 1:5, cash.flow = runif(5, 100, 1000))