[This article was first published on K & L Fintech Modeling, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

This post implements Black-Derman-Toy (BDT) interest rate tree using R. This implementation is based on the previous post for BDT model.

# R Implementation of BDT Interest Rate Tree

We implement BDT tree according to the content of the previous post. The previous post below explains BDT model and provides Excel illustration for the clear understanding.

Like previous post, we try to replicate BDT paper’s result.

### Two Requirements for No-arbitrage Condition

As stated in previous post, for BDT short rate tree to be arbitrage free, this interest rate tree should fit a given initial term structure exactly. \begin{align} P_{…u} &= \frac{1}{2}\frac{P_{…uu}+P_{…ud}}{1+r_{…u}} \\ P_{…d} &= \frac{1}{2}\frac{P_{…du}+P_{…dd}}{1+r_{…d}} \end{align} Cross-sectional (at the same time) two adjacent short rates and spot rates are given the following intra volatility restrictions. ($$\Delta t = 1$$) \begin{align} \sigma_t^r = \frac{1}{2}\log\left(\frac{r_{…u}}{r_{…d}}\right) \end{align} \begin{align} \sigma_t^y = \frac{1}{2}\log\left(\frac{y_{u}}{r_{d}}\right) \end{align}

### R code

Using the above two constraints, we use R optimization to solve for the 8 unknown variables problem. The objective function returns sum of two distances between market and model quantities: discount factors and yield volatilities.

 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 #========================================================## Quantitative ALM, Financial Econometrics & Derivatives # ML/DL using R, Python, Tensorflow by Sang-Heon Lee ## https://kiandlee.blogspot.com#——————————————————–## Black-Derman-Toy Interest Rate Tree#========================================================# graphics.off()  # clear all graphsrm(list = ls()) # remove all files from your workspace #————————————————# construct short rate tree (rt)#————————————————generate_BDT_tree <– function(v.rd, v.rv, nmat) {        df.rt  <– matrix(0, nmat, nmat)     df.rt[1,1] <– v.rd[1] # r0    for(t in 2:nmat) {        df.rt[t,t] <– v.rd[t]        for(s in (t–1):1) { # cross-sectional iteration            df.rt[s,t] <– df.rt[s+1,t]*exp(2*v.rv[t])        }    }    return(df.rt)} #————————————————# discount cash flow at maturity using BDT tree#————————————————pricing_BDT_tree <– function(df.BDT_tree, v.cf, nmat) {        df.rt <– df.BDT_tree    t     <– nmat    df.pt <– matrix(0, t+1, t+1)    df.pt[,t+1] <– v.cf # cash flow at maturity        for(b in t:1) { # backward induction        for(s in 1:b) { # cross-sectional iteration            df.pt[s,b] <– 0.5*           (df.pt[s,b+1]+df.pt[s+1,b+1])/(1+df.rt[s,b])        }    }    return(df.pt)} #————————————————# objective function#————————————————# v.unknown : rd, rdd, …, rv2, rv3, …# df.mkt    : data.frame for mat, y, yv#————————————————objfunc_BDT_tree <– function(v.unknown, df.mkt) {        v.unknown <– v.unknown^2 # non-negativity     nmat <– length(df.mkt$mat) # short rate and its volatility v.rd <– c(df.mkt$y[1], v.unknown[1:(nmat–1)])    v.rv <– c(df.mkt$yv[1],v.unknown[nmat:(2*(nmat–1))]) # construct rate tree(rt) df.rt <– generate_BDT_tree(v.rd, v.rv, nmat) #———————————————— # make a price tree for each maturity # calculate discount factor difference # calculate yield volatility difference #———————————————— v.df_diff <– v.yv_diff <– rep(0,nmat–1) for(t in 2:nmat) { df.pt <– pricing_BDT_tree(df.rt, 1, t) # difference between model and # market discount factor at time 0 v.df_diff[t–1] <– df.pt[1,1] – 1/(1+df.mkt$y[t])^t                # difference between yield volatilities         # from up & down discount factors (model) and        # market discount factors        yu <– (1/df.pt[1,2])^(1/(t–1))–1        yd <– (1/df.pt[2,2])^(1/(t–1))–1        yv <– log(yu/yd)/2        v.yv_diff[t–1] <– yv – df.mkt$yv[t] } return(sqrt(sum(v.df_diff^2) + sum(v.yv_diff^2)))} #————————————————# Main#———————————————— # Input data : maturity, yield, yield volatilitydf.mkt <– data.frame( mat = c(1, 2, 3, 4, 5), y = c(0.1, 0.11, 0.12, 0.125, 0.13), yv = c(0.2, 0.19, 0.18, 0.17, 0.16)) # initial guess for short rate and volatility# short rate : rd, rdd, rddd, rdddd# short rate volatilities : rv2, rv3, rv4, rv5v.initial_guess <– c(0.1, 0.1, 0.1, 0.1, # rd 0.19, 0.18, 0.17, 0.16) # rvv.initial_guess <– sqrt(v.initial_guess) # calibration of BDT treem<–optim(v.initial_guess, objfunc_BDT_tree, control = list(maxit=5000, trace=2, reltol = 1e–16), method=c(“BFGS”),df.mkt = df.mkt) # transform and split parametersv.param_trans <– m$par^2nmat <– 5 # final calibrated parameters# short rate : r0, rd, rdd, rddd, rdddd(v.rd <– c(df.mkt$y[1], v.param_trans[1:(nmat–1)]))# short rate volatilities : rv1, rv2, rv3, rv4, rv5(v.rv <– c(df.mkt$yv[1], v.param_trans[nmat:(2*(nmat–1))])) # final BDT short rate tree(df.rt <– generate_BDT_tree(v.rd, v.rv, nmat)) # final BDT price tree (5-year)(pricing_BDT_tree(df.rt, 1, nmat)) Colored by Color Scripter cs

The above R code is implemented from the logic of the previous post.

generate_BDT_tree() function returns a BDT short rate tree with arguments of unknown short rates and its volatilities. pricing_BDT_tree() function uses backward induction to discount cash flows at maturity using the BDT short rate tree and returns a price tree. Of course, the first element of the price tree is the price of zero coupon bond.

objfunc_BDT_tree() function is the objective function to be minimized, which returns a sum of squared errors of discount factors and yield volatilities. In the objective function, unknown variables are squared because yield volatility is always non-negative and in lognormal model, interest rate is non-negative.

Running the above R code, we can obtain the following results which are the same as that of the previous post.

 12345678910111213141516171819202122232425 > # final calibrated parameters>> # short rate : r0, rd, rdd, rddd, rdddd[1] 0.10000000 0.09791528 0.09760006 0.08717225 0.08653488>> # short rate volatilities : rv1, rv2, rv3, rv4, rv5[1] 0.2000000 0.1899992 0.1719859 0.1526818 0.1352092> > # final BDT short rate tree (5-year)     [,1]       [,2]       [,3]       [,4]       [,5][1,]  0.1 0.14317978 0.19418699 0.21788708 0.25524429[2,]  0.0 0.09791528 0.13766867 0.16055127 0.19476675[3,]  0.0 0.00000000 0.09760006 0.11830307 0.14861875[4,]  0.0 0.00000000 0.00000000 0.08717225 0.11340505[5,]  0.0 0.00000000 0.00000000 0.00000000 0.08653488> > # final BDT price tree (5-year)          [,1]      [,2]      [,3]      [,4]      [,5] [,6][1,] 0.5427603 0.5509767 0.5888395 0.6706866 0.7966577    1[2,] 0.0000000 0.6430960 0.6708913 0.7356824 0.8369835    1[3,] 0.0000000 0.0000000 0.7412386 0.7908217 0.8706109    1[4,] 0.0000000 0.0000000 0.0000000 0.8363453 0.8981457    1[5,] 0.0000000 0.0000000 0.0000000 0.0000000 0.9203570    1[6,] 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000    1> Colored by Color Scripter cs

### Concluding Remarks

From this post, we have implemented BDT short rate tree using R’s optimization routine. This will be used for pricing a fixed income derivatives such as callable bonds and for generating interest rate scenarios for multi-stage stochastic linear programming. $$\blacksquare$$

To leave a comment for the author, please follow the link and comment on their blog: K & L Fintech Modeling.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

# Never miss an update! Subscribe to R-bloggers to receive e-mails with the latest R posts.(You will not see this message again.)

Click here to close (This popup will not appear again)