Use interest rate term structures for calculations is one of the daily activies that any quant has to accomplish with. I use the many of the curves released by BM&F Bovespa in that page. In order to have the curves always at hand I've written that few lines of code to download and return an interpolator where the only argument is the number of days I want to interpolate.


cal <- create.calendar(name='ANBIMA', holidays=holidaysANBIMA, weekdays=c('saturday', 'sunday'))

.get_curve_url <- function(refdate, ticker) {
    url <- ''
    query <- str_supplant('?Data={refdate}&Data1={sysdate}&slcTaxa={ticker}',
        list(refdate=format(as.Date(refdate), '%d/%m/%Y'),
            sysdate=format(Sys.Date(), '%Y%m%d'),
    paste0(url, query)

get_curve <- function (refdate, ticker='PRE') {
    refdate <- as.Date(refdate)
    url <- .get_curve_url(refdate, ticker)
    doc <- htmlTreeParse(url, useInternalNodes=TRUE)
    num <- xpathSApply(doc, "//td[contains(@class, 'tabelaConteudo')]",
        function(x) gsub('[\r\n \t]+', '', xmlValue(x)))
    num <- sapply(num, function(x) as.numeric(gsub(',', '.', x)), USE.NAMES=FALSE)

    colspan <- as.integer(xpathApply(doc, "//td[contains(@class, 'tabelaTitulo')]",  xmlAttrs )[[2]][3])
    if (colspan == 1) {
        terms <- num[c(TRUE, FALSE)]
        rates <- num[c(FALSE, TRUE)]/100
        log_pu <- log(1 + rates*terms/360)
        rate <- function(pu, term) (pu - 1)*(360/term)
    } else {
        terms <- bizdayse(refdate, num[c(TRUE, FALSE, FALSE)])
        rates <- num[c(FALSE, TRUE, FALSE)]/100
        log_pu <- log((1 + rates)^(terms/252))
        rate <- function(pu, term) pu^(252/term) - 1

    log_price_interpolator <- approxfun(terms, log_pu, method='linear')
    function (term) {
        pu <- exp(log_price_interpolator(term))
        rate(pu, term)*100

So, once you have loaded that code you can get the Brazilian interbank curve by calling:

irbrl <- get_curve('2013-06-13', 'PRE')
irbrl(seq(21, 252, by=21))
##  [1] 7.880000 8.010000 8.158363 8.369100 8.537173 8.655198 8.740000
##  [8] 8.826095 8.895053 8.965071 9.050000 9.121180

The curve for US dollar deposits in Brazil

irusd <- get_curve('2013-06-13', 'DOL')
irusd(seq(30, 360, by=30))
##  [1] 0.3135554 0.6300000 0.8300000 1.0400000 1.1381183 1.2000000 1.2400000
##  [8] 1.2699991 1.2900000 1.3200000 1.3400000 1.3592817

You could compare in the same chart curves of different dates

irbrl_20130613 <- get_curve('2013-06-13', 'PRE')
irbrl_20130611 <- get_curve('2013-06-11', 'PRE')
seq(21, 252, by=21) -> terms
irbrl_20130611(terms) -> d11
irbrl_20130613(terms) -> d13
terms <- terms + Sys.Date()
plot(terms, d11, type='n', xlab='Dates', ylab='Rates', xaxt="n")
axis(1, terms, format(terms, "%b %y"))
points(terms, d11, pch=20, col='steelblue')
points(terms, d13, pch=20, col='darkred')
lines(terms, d11, lwd=2, col='steelblue')
lines(terms, d13, lwd=2, col='darkred')
legend("bottomright", legend=c("2013-06-11", "2013-06-13"), col=c("steelblue", "darkred"), pch=20,lwd=2)

Brazilian Term Structure

The function str_supplant was explained in another post. I mostly use the tickers PRE for deposits in Brazilian Real and DOL for deposits in US Dollar. That code works pretty well for EUR (Euro deposits) interest rates, but it has to be adjusted to handle DIC and DIM tickers (IPCA and IGP-M inflation rates).

As I told before that is a quick and dirt implementation but it is also quite useful. With far none effort you have at hand an interpolator for interest rate term structures that can easily be ported to any other curve feeder.

Other point I'd like to mention is the huge effort, in my opinion, to build a attractive chart using the plot function, bellow I present an example using the ggplot2 package for the same data.

ir_df <- stack(list(`2014-06-11`=d11, `2014-06-13`=d13))
ir_df$date <- terms
ggplot(data=ir_df, aes(x=date, y=values, colour=ind)) + geom_point() + geom_line() + xlab('Dates') + ylab('Rates') + theme(legend.title=element_blank())

Brazilian Term Structure with ggplot2