Pricing Floating Legs of Interest Rate Swaps with R

Articles From: curiousfrm.com
Website: curiousfrm.com

Davide Magno

By:

Author of the Blog curiousfrm.com

Overview

In this post we will close the trilogy on (old style) swap pricing. In particular, we will download the variable rate data, which is needed to calculate the variable leg accrual.

Download the Data

To learn how to download the code via Quandl, visit Davide’s website https://www.curiousfrm.com/2019/07/downloading-variable-rate/. To recap:

  • Part 1 of this series gave the general idea behind tidy pricing interest rate swaps using a 7 lines pipe
  • Part 2 went much more into detail and priced some real world contract comparing the results obtained vs Bloomberg.
  • The only part missing was calculating the accrual for the floating leg. To do this we need the information about the historical level of the interest rate to which the leg is linked. For standard EUR contracts, this rate is the 6 months’ EURIBOR. For those of you who are interested in understanding more what this rate is, see this link.

This post will continue below with a focus on the R packages and sample code.

R Packages and Functions

Let’s look at the code now. The function that gets modified the most is the SwapCashflowYFCalculation which I have re-named as CashFlowPricing one which now looks as follows:

CashFlowPricing  <- function(today, start.date, maturity.date, type,
                                     time.unit, dcc, calendar) {
  # Part 1: Calculate the whole cashflow dates
  cashflows <- seq(from = 0,
                   to = (lubridate::year(maturity.date) -
                           lubridate::year(start.date)) * 12,
                   by = time.unit) %>%
    purrr::map_dbl(~RQuantLib::advance(calendar = calendar,
                                       dates = start.date,
                                       n = .x,
                                       timeUnit = 2,
                                       bdc = 1,
                                       emr = TRUE)) %>%
    lubridate::as_date() %>%
    {if (start.date < today) append(today, .) else .}

  # Part 2: calculate accrual and rate fixing days
  accrual.date <- cashflows[today - cashflows > 0]

  if (!identical(as.double(accrual.date), double(0))) {
    accrual.date  %<>%  max()
    if (stringr::str_detect(type, "floating")) {
      fixing.date <- accrual.date %>%
        {RQuantLib::advance(calendar = calendar,
                            dates = .,
                            n = -2,
                            timeUnit = 0,
                            bdc = 1,
                            emr = TRUE)}
    } else {
      fixing.date <- NULL
    }
    accrual.yf <- accrual.date %>%
      {RQuantLib::yearFraction(today, ., dcc)} %>%
      `*`(-1)
  } else {
    fixing.date <- NULL
    accrual.yf <- 0
  }

  # Part 3: Tidy and return the list of relevant dates
  cashflows %<>%
    purrr::map_dbl(~RQuantLib::yearFraction(today, .x, dcc)) %>%
    tibble::tibble(yf = .) %>%
    dplyr::filter(yf >= 0)

  return(list(cashflows = cashflows, accrual.yf = accrual.yf,
              fixing.date = fixing.date))
}

Reviewing the Output

Let’s analyze the code:

  • Part 1 is actually the core of the previously described code.
  • Part 2 is the new code. accrual.date is the date from which the accrual starts to be calculated. This gets converted into a year fraction and saved into accrual.yf. The if statement calculates the date at which the floating EURIBOR rate has to be snapped from Quandl only for the floating rate. This date is stored in the fixing.date variable and it considers a 2 days lag which is standard for the European market.
  • Part 3 finally converts and returns all the future cash flows in terms of year fraction

You can note that we now calculate the cashflows for the floating leg even if it will note be used by the OLDParSwapRate function. This will be needed for future developments when we will introduce the OIS discounting…(stay tuned!!)

I can now calculate the accrual, and for this purpose I developed a brand new function called CalculateAccrual

CalculateAccrual <- function(swap.dates, leg.type, swap, direction) {
  # Part 1: calculate the accrual rate
  if (!is.null(swap.dates$fixing.date)) {
    rate <- Quandl::Quandl("BOF/QS_D_IEUTIO6M",
                           start_date = swap.dates$fixing.date,
                           end_date = swap.dates$fixing.date) %>%
      tibble::as_tibble(.) %>%
      dplyr::select(Value) %>%
      as.double %>%
      `/`(100)
  } else {
    rate <- swap$strike
  }
  # Part 2: Calculate the value of the accrual
  swap.dates %>%
    purrr::pluck("accrual.yf") %>%
    `*`(swap$notional * rate * switch(leg.type, "pay" = -1, "receive" = 1))
}

This is smaller and easier function:

  • Part 1: for floating legs we use Quandl to download the needed data and extract the rate information. For the fixed one, we just use the strike of the swap.
  • Part 2: we calculate the actual accrual amount using the classical function

Final Results

Let’s see the final result on the 25 years’ swap we use as test:

## # A tibble: 1 x 7
##   swap.id  clean.mv dirty.mv accrual.pay accrual.receive     par    pv01
##   <chr>       <dbl>    <dbl>       <dbl>           <dbl>   <dbl>   <dbl>
## 1 Swap 25y -881815. -874994.       5441.           1379. 0.00771 -12394.

Visit curiousfrm.com to read the rest of the article, and learn how Davide compares the results vs Bloomberg data, and how his algorithm identifies the floating & fixed legs depending on the type of the swap: https://www.curiousfrm.com/2019/07/downloading-variable-rate/

Davide Magno is a professional financial engineer with more than 10 years of experience of managing complex financial quantitative tasks for banks, insurances and funds. He is passionate about both quantitative finance and data science: he is the author of the blog curiousfrm.com that aims at solving financial problems using modern data science coding languages and techniques. He is currently Head of Financial Risk Management in Axa Life Europe dac. Opinions expressed are solely his and do not express the views or opinions of his current employer.

Disclosure: Interactive Brokers

Information posted on IBKR Campus that is provided by third-parties does NOT constitute a recommendation that you should contract for the services of that third party. Third-party participants who contribute to IBKR Campus are independent of Interactive Brokers and Interactive Brokers does not make any representations or warranties concerning the services offered, their past or future performance, or the accuracy of the information provided by the third party. Past performance is no guarantee of future results.

This material is from curiousfrm.com and is being posted with its permission. The views expressed in this material are solely those of the author and/or curiousfrm.com and Interactive Brokers is not endorsing or recommending any investment or trading discussed in the material. This material is not and should not be construed as an offer to buy or sell any security. It should not be construed as research or investment advice or a recommendation to buy, sell or hold any security or commodity. This material does not and is not intended to take into account the particular financial conditions, investment objectives or requirements of individual customers. Before acting on this material, you should consider whether it is suitable for your particular circumstances and, as necessary, seek professional advice.

Disclosure: Forex

There is a substantial risk of loss in foreign exchange trading. The settlement date of foreign exchange trades can vary due to time zone differences and bank holidays. When trading across foreign exchange markets, this may necessitate borrowing funds to settle foreign exchange trades. The interest rate on borrowed funds must be considered when computing the cost of trades across multiple markets.