swap to forward rates

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

swap to forward rates

Thomas Steiner
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
about your results.

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

_______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-sig-finance
Reply | Threaded
Open this post in threaded view
|

Re: swap to forward rates

Thomas Steiner
Dear David,
thanks for you answer.

> There are many algorithms for constructing a yield curve from market
> data.
> They all give different answers, some wildly.

But why?
Describing the term structure of interest rates by forward rates is
mathematically equivalent (no market model assumed, just no arbitrage)
to tell the swap rates. So there should be an exact way in principle,
no?

> I don't see how you can get the first fwd rate without at least one
> cash.

I mentioned this at the end of my message: I will add this later,
right now I assume that the first point in the swap curve is a cash
yield.

> You will also get quite different results by not taking market
> conventions into account.

Thanks, I didn't know that - I thought that results should be at about
the same (not 60bps difference).

> This is one big reason why people are willing
> to spend serious money for yield curve sotware.

I am working at university and I try to find the cheapest way possible...

Can you give any of your results with my rates, just to compare?
Any other comments, hints?
Thomas

_______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-sig-finance
Reply | Threaded
Open this post in threaded view
|

Re: swap to forward rates

Krishna Kumar-2
In reply to this post by Thomas Steiner
To re-emphasize what David has mentioned and what was in the earlier
West-Hagan paper, depending on the
interpolation technique used one can get completely different set of
rates. And people use smoothness and other criteria
to pick the method. If you play around with different interpolation like
cubic spline in akima and other interpolation methods
that are in CRAN you will notice that the forward is smooth for some and
jagged for others.
What I sent is a very rudimentary - curve-101, perhaps you should also
look at these additional documents as well ,

http://www.fincad.com/newsletter.asp?i=1180&a=2180
http://www.bankofcanada.ca/en/res/wp/2000/wp00-17.pdf
http://www.hfb.de/Dateien/Arbeitsbericht2.pdf

{Most banks have people who are specialized in just building curves..}
The reason why it is good to go via discount factors is that some of the
curves are blended meaning they have a mix of
instrument like repos or muni instruments. In other cases people use E$
futures or other market instruments. The criteria on what
instruments to use in your curve, is typically a) liquidity and b) your
positions in the markets.  Because you want to compute the correct
funding for your positions.

Finally you need to get the day counts right that is important and the
recent email on seq.date might help you on this.

Hope this helps,
Kris


Thomas Steiner wrote:

>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
>about your results.
>
>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
>
>_______________________________________________
>[hidden email] mailing list
>https://stat.ethz.ch/mailman/listinfo/r-sig-finance
>
>  
>

_______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-sig-finance
Reply | Threaded
Open this post in threaded view
|

Re: swap to forward rates

Thomas Steiner
In reply to this post by Thomas Steiner
Thanks for your answers David and Kris. I keep on working out the best
solution for me.

> Good luck! This is a very gnarly topic.

Still I did not get the basic message: why should there be different
methods to calculate forward rates from spanning swap rates? I am just
so impressed by the follwoing quote of Rebonato (Interest rate option
models, 2nd ed., p. 15):

In general, n discrete discount factors can allways be found, for any
viable set of n spanning equilibrium swap rates, as the solution of a
linear [n x n] problem.
This result is improtant, not simply because it shows that equilibrium
swap rates are yet another set equivalent quantities that can be used
to describe the yield curve, but because it shows that the somewhat
privileged role enjoyed by forward rates in term structure modelling
might be more the result of historical accident then of some
fundamental finacial reason.

I'd say that this means, that there is ONE way to come from n swap
rates to n (discrete) forward rates. If I want to have more forward
rates or at some other points in time, I totally agree, that you will
need interpolation and that there are many ways to do so.
I think the best way would be to start with n swap rates, get n exact
forward rates and THEN try to interpolate; eg with Nelson-Siegel,
Splines, Vasicek's family or whatsoever.

Thomas

_______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-sig-finance