[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.
If you have already implemented this yourself somewhere, please
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