Search code examples
rfinancequantitative-financecomputational-finance

How to estimate static yield curve with 'termstrc' package in R?


I am trying to estimate the static yield curve for Brazil using termstrc package in R. I am using the function estim_nss.couponbonds and putting 0% coupon-rates and $0 cash-flows, except for the last one which is $1000 (the face-value at maturity) -- as far as I know this is the function to do this, because the estim_nss.zeroyields only calculates the dynamic curve. The problem is that I receive the following error message:

"Error in (pos_cf[i] + 1):pos_cf[i + 1] : NA/NaN argument In addition: Warning message: In max(n_of_cf) : no non-missing arguments to max; returning -Inf "

I've tried to trace the problem using trace(estim_nss.couponbons, edit=T) but I cannot find where pos_cf[i]+1 is calculated. Based on the name I figured it could come from the postpro_bondfunction and used trace(postpro_bond, edit=T), but I couldn't find the calculation again. I believe "cf" comes from cashflow, so there could be some problem in the calculation of the cashflows somehow. I used create_cashflows_matrix to test this theory, but it works well, so I am not sure the problem is in the cashflows.

The code is:

#Creating the 'couponbond' class
ISIN <- as.character(c('ltn_2017','ltn_2018', 'ltn_2019', 'ltn_2021','ltn_2023')) #Bond's identification

MATURITYDATE <- as.Date(c(42736, 43101, 43466,  44197,  44927), origin='1899-12-30') #Dates are in system's format

ISSUEDATE <- as.Date(c(41288,41666,42395, 42073, 42395), origin='1899-12-30') #Dates are in system's format

COUPONRATE <- rep(0,5) #Coupon rates are 0 because these are zero-coupon bonds

PRICE <- c(969.32,  867.77, 782.48, 628.43, 501.95) #Prices seen 'TODAY'

ACCRUED <- rep(0.1,5) #There is no accrued interest in the brazilian bond's market

#Creating the cashflows sublist
CFISIN <- as.character(c('ltn_2017','ltn_2018', 'ltn_2019', 'ltn_2021', 'ltn_2023')) #Bond's identification

CF <- c(1000,1000,1000,1000,1000)# The face-values

DATE <- as.Date(c(42736,    43101,  43466,  44197,  44927), origin='1899-12-30') #Dates are in system's format

CASHFLOWS <- list(CFISIN,CF,DATE)
names(CASHFLOWS) <- c("ISIN","CF","DATE")

TODAY <- as.Date(42646, origin='1899-12-30')

brasil <- list(ISIN,MATURITYDATE,ISSUEDATE,
               COUPONRATE,PRICE,ACCRUED,CASHFLOWS,TODAY)

names(brasil) <- c("ISIN","MATURITYDATE","ISSUEDATE","COUPONRATE",
                   "PRICE","ACCRUED","CASHFLOWS","TODAY")

mybonds <- list(brasil)

class(mybonds) <- "couponbonds"

#Estimating the zero-yield curve
ns_res <-estim_nss.couponbonds(mybonds, 'brasil' ,method = "ns")

#Testing the hypothesis that the error comes from the cashflow matrix
cf_p <- create_cashflows_matrix(mybonds[[1]], include_price = T)
m_p <- create_maturities_matrix(mybonds[[1]], include_price = T)
b <- bond_yields(cf_p,m_p)

Note that I am aware of this question which reports the same problem. However, it is for the dynamic curve. Besides that, there is no useful answer.


Solution

  • Your code has two problems. (1) doesn't name the 1st list (this is the direct reason of the error. But if modifiy it, another error happens). (2) In the cashflows sublist, at least one level of ISIN needs more than 1 data.

      # ... 
    CFISIN <- as.character(c('ltn_2017','ltn_2018', 'ltn_2019', 
                             'ltn_2021', 'ltn_2023',  'ltn_2023'))   # added a 6th element
    CF <- c(1000,1000,1000,1000,1000,  1000)                         # added a 6th
    DATE <- as.Date(c(42736,43101,43466,44197,44927,  44928), origin='1899-12-30') # added a 6th
    
    CASHFLOWS <- list(CFISIN,CF,DATE)
    names(CASHFLOWS) <- c("ISIN","CF","DATE")
    TODAY <- as.Date(42646, origin='1899-12-30')
    brasil <- list(ISIN,MATURITYDATE,ISSUEDATE,
                   COUPONRATE,PRICE,ACCRUED,CASHFLOWS,TODAY)
    names(brasil) <- c("ISIN","MATURITYDATE","ISSUEDATE","COUPONRATE",
                       "PRICE","ACCRUED","CASHFLOWS","TODAY")
    
    mybonds <- list(brasil = brasil)                      # named the list
    
    class(mybonds) <- "couponbonds"
    ns_res <-estim_nss.couponbonds(mybonds, 'brasil', method = "ns")
    
    Note: the error came from these lines
    bonddata <- bonddata[group]    # prepro_bond()'s 1st line (the direct reason).
    
    # cf <- lapply(bonddata, create_cashflows_matrix)   # the additional error
    create_cashflows_matrix(mybonds[[1]], include_price = F)  # don't run