Search code examples
rfinance

How to compute the NPV dynamically for each point in time up to the end of my time series?


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...


Solution

  • 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
    

    Note

    The input (from question):

    set.seed(1)
    interest.rate <- 0.02
    dat <- data.frame(year = 1:5, cash.flow = runif(5, 100, 1000))