[R-sig-finance] swap to forward rates

Thomas Steiner finbref.2006 at gmail.com
Wed Feb 22 16:49:06 CET 2006

Again, I want to calculate forward rates from swap rates.
Krishna Kumar was already very kind to help me here (24.1.06) and he
provided an algorithm, I did not understand. So I now figured out my
own one and unfortunately the two results do not coincide but both
appear very plausible.

How can you help me?
If you have a lot of time, check my algorithm or my formula.
compare my results with yours and with those of Kris. And let me know

Perhaps you can have a quick look at this and verify the results.

I have EUR-swap rates for 2Y, 3Y, 5Y, 7Y, 10Y, 20Y and 30Y, eg for 2005-12-13:

sc=list(
maturity=c(2,3,5,7,10,20),
tenors=c(2,1,2,2,3,10),    #the difference between two dates (=\tau_i)
rate=c(0.02982,0.03074,0.03230,0.03354,0.03533,0.03861),
date="2005-12-13"
);

#Kris' way from swap via discount to forward rates:
swap2discount<-function(swapcrv) {
n<-length(swapcrv$rate) dfcrv<-list() dfcrv$maturity    <- swapcrv$maturity dfcrv$discount    <- 1/(1+swapcrv$tenors*swapcrv$rate)
dfcrv$discount[-1]<- dfcrv$discount[-1]*(1-(cumsum(swapcrv$tenors[-n]*dfcrv$discount[-n]))*swapcrv$rate[-1]) dfcrv$date=swapcrv$date return(dfcrv) } discount2fwd<-function(dfcurve,times=dfcurve$maturity) {
times<-c(0,times)
n<-length(times)
fwd<-array(0,n)
df.tenor<-array(0,n)
df.tenor<-approx(x=dfcurve$maturity,y=dfcurve$discount,xout=times,rule=2)$y df.tenor[1]<-1 fwd<-(df.tenor[-n]/df.tenor[-1] -1)/diff(times) fwd<-c(fwd[1],fwd) return(list(maturity=times,rate=fwd,date=dfcurve$date))
}
dc=swap2discount(sc)
discount2fwd(dc)
#gives rates:  0.02982000 0.03264006 0.03592894 0.04081783 0.04582491 0.05007956

#my function:
# from Brigo/Mercurio, p.15; solve the last equation on this page for F_\beta:
# $$\1+\tau_\beta F_\beta = \frac{1+S_{\alpha,\beta}(t) \tau_\beta}{\Pi_{j=\alpha+1}^{\beta-1}(1+\tau_jF_j) - S_{\alpha,\beta}(t)\Sum_{i=\alpha+1}^{\beta-1}\tau_i\Pi_{j=i+1}^{\beta-1}(1+\tau_jF_j) }$$
swap2fwd<-function(sc) {
fwd=array(dim=length(sc$rate)) fwd[1]=sc$rate[1]
fwd[2]=( (1+sc$rate[2]*sc$tenors[2])/(1+sc$tenors[1]*fwd[1]-sc$rate[2]*sc$tenors[1])-1 ) / sc$tenors[2]
n<-length(sc$maturity) for (t in 3:n) { cumpr=rev(c(1, cumprod(1+sc$tenors[(t-1):2]*fwd[(t-1):2]) ))
su=sum( sc$tenors[1:(t-1)] * cumpr ) fwd[t]=(1+sc$rate[t]*sc$tenors[t]) / ( prod(1+sc$tenors[1:(t-1)]*fwd[1:(t-1)])-sc$rate[t]*su ) fwd[t]=(fwd[t]-1)/sc$tenors[t]
}
return(list(
maturity=sc$maturity,rate=fwd,date=sc$date
))
}
swap2fwd(sc)
#gives 0.02982000 0.03264006 0.03485760 0.03705553 0.04046209 0.04409305

My results are a bit lower then Kris'. What do you suggest me to use
now? A pro's solution I don't understand or my own answer?
If I add the 30Y swap rate (0.03922), results are strage again in both
cases (too high and to low respectively).

What I did not take into account are daycount conventions and the fact
the the very first point in the swap curve should be a cash rate. This
will come later...

Any help, hint and comparison is very welcome.
Thomas