# In this example we valuate a bond using the yield curve for Portugal
# (source: EIOPA)

library(readxl)
library(dplyr)
library(FinancialMath)

# EIOPA Yields
yields <- read_xlsx(
  path = "Examples/interestRateData2026.xlsx",
  sheet = "RFR_spot_no_VA",
  range = "B2:AQ152"
)

# Our example bond has a maturity of 5 years and the following characteristics:
coupon.rate <- 0.05
face.value <- 100
maturity <- 5


# Extract data of interest from EIOPA file
annual.yields <- yields %>%
  select(month, Portugal) %>% 
  # get the yields corresponding to "whole years"
  # (those which divided by 12 give remainder 0)
  filter(month %% 12 == 0) %>% 
  mutate(time = month/12) %>% 
  rename(annual.y_t = 2) %>% 
  # The maturity is 5 years in this example
  head(n = maturity) %>% 
  select(time, annual.y_t)
annual.yields

# Continuous yield
annual.yields <- annual.yields %>% 
  # Price of 1 euro
  mutate(P_t = (1 + annual.y_t)^(-time)) %>% 
  # Continuous yield
  mutate(cont.y_t = -log(P_t)/time)

annual.yields

# Introducing the lag() function
annual.yields %>% mutate(lag = lag(cont.y_t))

# Forward Rates compatible with the continuous yield
annual.yields <- annual.yields %>% 
  # (Possible) Forward rates
  mutate(fw_t = lag(cont.y_t) + time * (cont.y_t - lag(cont.y_t))) %>% 
  # The first forward rate is NA because there is no value for the yield at time 0.
  # By definition, the forward rate at time t = 1 is the spot rate itself:
  # "The spot rate is the average of forward rates in the interval (0, t)"
  mutate(fw_t = if_else(is.na(fw_t), cont.y_t, fw_t))
  
annual.yields

# Pricing the bond
bond.price.tbl <- annual.yields %>% 
  rename(t = time, y = annual.y_t) %>% 
  mutate(
    # Payments of our bond
    c_t = c(rep(coupon.rate * face.value, maturity)) + c(rep(0,maturity - 1), face.value),
    # Finally, the bond price using the yield curve
    `PV of c_t` = P_t*c_t
    )
bond.price.tbl

totals <- bond.price.tbl %>%
  summarize(total.payments = sum(c_t), bond.price = sum(`PV of c_t`))

totals
totals$bond.price

# Now let us compute the average yields: avg.i.annual for annual compounding and
# avg.y.cont for continuous compounding.

# Annual Compounding - Average yield 
# We use the IRR function, which stands for Internal Rate of Return
# (IRR is a discount rate that makes the net present value (NPV) of all cash
# flows equal to zero)
avg.i.annual <- FinancialMath::IRR(
  cf0 = -totals$bond.price,
  cf = bond.price.tbl$c_t, 
  times = bond.price.tbl$t
  )
avg.i.annual

# Continuous compounding - average yield
avg.y.cont <- log(1 + avg.i.annual)
avg.y.cont

# Let us check our formulae.
check <- bond.price.tbl %>% 
  select(t,c_t) %>% 
  mutate(
    annual.comp = c_t * (1 + avg.i.annual)^(-t),
    cont.comp = c_t * exp(-t * avg.y.cont)
  )
check
# View(check)

check.totals <- check %>% summarize(across(ends_with("comp"), sum))
check.totals
check.totals$annual.comp == check.totals$cont.comp
