Вы находитесь на странице: 1из 41

Quaderni SEMeQ

Daniele Marazzina

Interest Rate Modelling: A MATLAB Implementation


Aprile 2007

Quaderno n. 13/2007

Stampato in proprio presso la Segreteria del Dipartimento di Scienze Economiche e Metodi Quantitativi, Universit degli Studi del Piemonte Orientale A. Avogadro

I Lavori pubblicati nella collana riflettono esclusivamente le opinioni degli autori e non impegnano la responsabilit del Dipartimento SEMeQ.

Dipartimento di Scienze Economiche e Metodi Quantitativi Via E. Perrone 18 28100 Novara Tel. 39 (0) 321- 375310 Fax 39 (0) 321 - 375305 e-mail: segreteria.dsemeq@unipmn.it

Interest Rate Modeling: A M ATLAB Implementation


Daniele Marazzina SEMeQ Department, Universit del Piemonte Orientale Via Perrone 18, 28100 Novara, Italy e-mail: daniele.marazzina@eco.unipmn.it Avanade Italy Corso Venezia 46, 20121 Milano, Italy e-mail: danielema@avanade.com

Abstract The aim of this work is to present a M ATLAB implementation of different methods for estimating the term structure of interest rate. More precisely, we implement the exponential functional form of NelsonSiegel and polynomial spline methods (with or without penalty term), considering both coupon bonds, like Italian Btp, and Libor and Swap interest rates. Furthermore, we compare the modelsperformances, considering both computational costs and approximation results.

Introduction

An important tool in the development and testing of nancial theory is the term structure of interest rate as it provides a characterization of interest rates as a function of maturity. The yield curve, or term structure of interest rate, is the set of interest rates for different investment periods or maturities. Yield curve can display a wide variety of shapes. Typically, a yield curve will slope upwards, with longer term rates being higher, although there are plenty of examples of inverted term structures where long rates are less then short rates. In the bond markets the yield curve is found from bond data, while in the money market the yield curve is derived from the prices of a variety of different types of instrument. Cash rates provide information about the short term rates, from one week to about 18 months. These are investments or borrowings where the entire sum of interest plus principal is due at the end of the period, with no interim payments. After about two-year point, Swaps become the dominant instrument: from there it is possible to derive the yield curve until 15-year point. After that, bond can be used. See [5] for further details. Information about the yield curve becomes steadily more sparse as the maturity increases. A good interest rate curve is the most basic requirement for pricing interest rate derivatives: if the curve is bad, the prices it returns will be bad (see [1]). The objective in empirical tting of the term structure is to nd a curve that ts the data sufciently well and it is a sufciently smooth function: the second requirement is at least as important as the rst, even if it is less quantiable (see, for example, [12]). In this paper we consider the methodology of tting the discount function d (or related function, as, for example, the instantaneous forward rate function) by the exponential model of Nelson-Siegel (see [9] and [11]) and polynomial spline methods (see [6] and [7]) with or without penalty term (see [2] and [4]). Moreover, we consider a M ATLAB [13] code written for both Italian Btp data and Libor and Swap data in order to obtain the curves. The outline of the paper is the following: in Section 2 we describe how we can extract the necessary data from coupon bonds and Libor and Swap rates; in Section 3 we introduce the data-tting techniques: more precisely, we describe the Nelson-Siegel model and some methods based on cubic spline. In Section 4 we explain how our M ATLAB code works using the theoretical results introduced in the previous 1

sections. Finally, Section 5 deals with the modelsperformances, considering both computational cost and approximation results.

The Discount Function

The term structure of interest rate can be identied with any of a number of related concepts. In this section we consider the discount function d(t), which describes the present value of 1 Euro repayable in t years. The aim of the algorithm described in this paper is to extract the term structure from a set of coupon bonds (such as the Italian Btp considered), whose prices are largely determined by the present value of their stated payments (see [2]), or a set of Libor and Swap rates. More precisely, in this section we show a way to obtain the values of the discount function at the paymentsdates for both kind of data. For further details, see the examples reported in Appendix A.

2.1

Coupon Bonds

Following [2] and [8], let P (i) be the price of a coupon bond i at a xed date t (value date) and A(i, j ) be its j th payment made at time BP (i, j ); moreover, let mi be the number of remaining payments for the bond i and n be the number of bonds. Then, if we set for i = 1, , n and j = 1, , mi T (i, j ) := 0 [t, BP (i, j )], where 0 [t1 , t2 ] is the distance between the two dates t1 and t2 , computed according to the actual/365 day-count convention (i.e., the day-count convention for bonds), we have
mi

P (i) =
j =1

A(i, j )d(T (i, j ))

i = 1, , n.

(1)

Since the coupon bond i is characterized by a periodic coupon Ci and a facial value Fi , we set A(i, j ) = Ci if j < mi A(i, j ) = Ci + Fi if j = mi , for i = 1, , n. For simplicity, in this paper we consider coupons paid every six months (semi-annual coupons) and we dene Ci = Ci /2, where Ci is the annual payment for the bond i, i = 1, , n. If we now dene T T as the vector containing all the elements of T , sorted in ascending order, and we dene the matrix AA such that AA(i, j ) is the payment of the bond i at time T T (j ) (thus it could be equal to 0 if T T (j ) is not a time to payment for the considered bond), then (1) becomes AA D = P , (2)

where D (i) = d(T T (i)), i = 0, , m, and m is the number of elements of T T (i.e., the number of the global payment times). Considering the bond i, i = 1, , n, its price P (i) (i.e., the price that purchaser pays when buying the bond) is equal to the quoted price (clean price) plus the accrued interest AI (i.e., the interest accumulated between the most recent interest payment and the present time). In order to compute AI , let t1 be the date of the previous coupon payment, t be the value date and t1 be the date of the next coupon payment, then the accrued interest is AI = 0 [t1 , t] Ci 0 [t1 , t] = Ci . 2 0 [t1 , t1 ] 0 [t1 , t1 ]

2.2

Libor and Swap Rates

First of all we consider Libor (London Interbank Offered Rate) rates, which are daily reference rates based on the interest rates at which banks offer to lend funds to other banks. Let n1 be the number of Libors considered, LM be the vector containing the times to maturity of the n1 Libors and LR(i) be the interest rate of the Libor with time to maturity LM (i), i = 1, , n1 : this means that 1 Euro bought at time t (i.e., the value date) gives 1 + LR(i) 1 [t, LP (i)] Euros at time LP (i), where: LP (i) is the payment date, i.e., LP (i) = t + LM (i) if it is a business day, otherwise LP (i) is the rst business day after t + LM (i); 1 [t1 , t2 ] is the distance between the two dates t1 and t2 , computed according to the actual/360 day-count convention, (i.e., the day-count convention for Libors). Thus, if we set T1 (i) := 1 [t, LP (i)], we have d(T1 (i)) = 1 1 = , 1 + LR(i) 1 [t, LP (i)] 1 + LR(i) T1 (i)

and so, reasoning as in the previous subsection, if we dene for each Libor rate i A1 (i) = 1 + LR(i) T1 (i), P1 (i) = 1, we obtain A1 (i) d(T1 (i)) = P1 (i) i = 1, , n 1 . (3)

Now we consider Swaps, which are agreement to exchange one set of cash ow for another. The most commonly traded Swap requires one side to pay a xed rate and the other to pay a oating rate. In order to derive the discount function from Swap rates, we suppose that they have cash ow at one-year intervals. Let t be the value date, SR(i) be the interest rate of the Swap with expiration at i years and SP (i, j ), with 0 < j i, be its j th payment date; we dene T2 (i, j ) := 2 [t, SP (i, j )], where 2 [t1 , t2 ] is the distance between the two dates t1 and t2 , computed according to the 30/360 daycount convention (i.e., the day-count convention for Swaps considering the Euro market). Thus, following [5], we have d(T2 (i)) = 1 SR(i)
i1 j =1 [T2 (i, j )

T2 (i, j 1)] d(T2 (i, j ))

1 + SR(i) [T2 (i) T2 (i, i 1)]

, i = 1, , n2 ,

(4)

where n2 is the maximum expiration time of the Swap considered and we have set T2 (i, 0) = 0 and T2 (i) := T2 (i, i), i.e., its time to maturity. If we dene for i = 1, , n2 A2 (i, j ) = SR(i) [T2 (i, j ) T2 (i, j 1)] if j < i, A2 (i, i) = 1 + SR(i) [T2 (i) T2 (i, i 1)], P2 (i) = 1, then (4) is equivalent to
i

A2 (i, j ) d(T2 (i, j )) = P2 (i) i = 1, , n2 .


j =1

(5)

It is easy to see that in order to use equations (4) and (5) it is necessary to know each Swap rates with expiration from 1 to n2 years. If it is not possible, we obtain the missing Swap rates using linear interpolation, i.e., if we suppose that the values of SR(i 1) and SR(i + 1) are known, while SR(i) is unknown, we set SR(i) = SR(i 1) + SR(i + 1) . 2

See the M ATLAB routine MISSING _S WAP in Section 4.1 for further details and [1] for other interpolation techniques. Reasoning as above, if we now dene n as the total number of nancial instruments considered (i.e., n = n1 + n2 ), T T as the vector containing all the times to payment of both the Libor and the Swap rates (i.e., all the elements T1 (l), l = 1, , n1 and T2 (i, j ), i = 1, , n2 , j = 1, , i, sorted in ascending order), we can dene AA(i, j ) = A1 (i) if i n1 and T T (j ) = T1 (i), AA(i, j ) = A2 (i n1 , p) if i > n1 and T T (j ) = T2 (i n1 , p), P (i) = P1 (i) if i n1 , P (i) = P2 (i n1 ) if i > n1 , for i = 0, , n, j = 1, , m, where m is the size of T T , i.e., the number of payment dates, and p = 1, , n2 . Thus equations (3) and (5) become AA D = P , (6)

where D (i) = d(T T (i)), i = 0, , n. Notice that equation (2) (i.e., the coupon bonds case) and equation (6) (i.e., the Libor and Swap rates case) are of the same type. Thus we will consider their resolution through a tting procedure without any distinction between the kind of data considered.

The Fitting Procedure

The aim of this section is to introduce the data-tting techniques: we start with the Nelson-Siegel model, introduced in [9], then we present six models related with the cubic spline method.

3.1

Nelson-Siegel Model

The Nelson-Siegel model uses a single exponential functional form over the entire maturity range (see [8]). The discount function associated with (1), (3) and (4) is given as d(t) = e1 t (2 +3 )(1e with the constraints 1 > 0, 1 + 2 > 0, > 0. Therefore, considering equations (2) and (6), we impose that D (i) := d(T T (i)) = e1 T T (i) (2 +3 )(1e
T T (i)/ t/

)+3 tet/

(7)

(8)

)+3 T T (i)eT T (i)/

It is easy to understand that we are not sure that it is possible to nd values of 1 , 2 , 3 and which satises AA D = P ; thus the estimation of the discount function requires searching the unknown parameters := {1 , 2 , 3 , } which minimize the sum of the squared errors, i.e., we consider the system AA D = P + E , where E is the errorsvector (which depends on ) and we have to solve the following least square minimization problem: min E T E .

(9)

3.2

Cubic Spline Method

The term spline is used to refer to a wide class of functions that are used in applications requiring data interpolation and/or smoothing (see, for example, [10] for further details). Cubic splines are piecewise polynomial, joined at so-called knot points, characterized by the fact that their rst and second derivatives are continuous functions. A B-spline (or bell spline) is a spline function that has minimal support with respect to a given degree and domain partition; each spline function can be represented as a linear combination of B-splines of the same degree and over the same partition. In Figure 1 we show an example of B-spline basis function (see Appendix B and [2] for further details). Following [2], we have implemented the term structure tting techniques below. 3.2.1 B-spline

Let {i }s i=1 be the set of the B-spline basis functions; rst of all we consider the case in which we parametrize d as a cubic spline, i.e.,
s

d( ) =
i=1

i i ( ).

Figure 1:
Bspline Basis Functions (Knot Points: 0; 2; 4) 1 0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1 0 1 2 3 4 5

0.5

1.5

2.5

3.5

Therefore, if we dene for i = 1, , m and j = 1, , s G(i, j ) = j (T T (i)), we obtain D := G , where = (1 , , s )T . Then we consider the function g ( ) := log (d( )) and we parametrize it as a cubic spline, i.e.,
s

(10)

g ( ) =
i=1

i i ( ),

As it holds d( ) = eg( ) , we have D := exp(G ), where exp is the exponential function which operates element-wise on arrays. Finally we consider the instantaneous forward rate function f ( ) = d log (d( )); d 6 (12) (11)

reasoning as above, it holds d( ) = e Thus, if we parametrize f as a cubic spline, i.e.,


s R
0

f (t) dt

(13)

f ( ) =
i=1

i i ( ),

and we dene the matrix


T T ( i)

IG(i, j ) =
0

j (t) dt,

then we have D := exp(IG ). (14)

Reasoning as for the Nelson-Siegel model, the tting procedure for the three cases above consists of solving the minimization problem associated to the following system AA D = P + E , i.e., since we have to search which minimize E T E , we have to solve the least square minimization problem min[(P AA D )T (P AA D )].

(15)

3.2.2

B-spline with Penalty Term

In a spline the number of basis functions s is determined by the number of knot points: too few or too many parameters can lead to poor estimates. The strategy proposed in [2] is to penalize excess variability in the estimated discount function, reducing the effective number of parameters since the penalty forces implicit relationship between the spline basis functions. If the domain of the spline is [0, T ], we dene the penalty term H as the matrix of dimension s s such that
T

H (i, j ) =
0

i (t)j (t) dt.

The minimization problem associated with the B-spline with penalty tting technique is min[(P AA D )T (P AA D ) + T H ],

(16)

where is the penalty parameter (i.e., a positive real number) and D is dened as in (10), (12) or (14), depending on the function to be parametrized. The penalty parameter controls the penalty matrix H ; naturally, moves inversely to the effective number of parameters: the more becomes a large number, the more the penalty matrix H becomes important in (16). In order to choose the appropriate , we consider the value of which minimizes the so-called Generalized Cross Validation (GCV) function () := ((I Q)Y )T ((I Q)Y ) , (s 2tr(Q))2 7

where Q := X (X T X + H )1 X T , I is the s s identity matrix, tr is the trace operator and X and Y are dened in Table 1. Table 1: Choice of X and Y (X i denotes the ith row of X ) Function to Parametrize W Xi Y d (AA G)i P g AA exp(G ) W (i) (AA G)i P W +X f AA exp(IG ) W (i) (AA IG)i P W + X Intuitively, cross validation starts by looking at a leave-one-out estimator for each data point. If data is not scarce, then the set of available input-output measurements can be divided into two parts: one part for training and one part for testing. A better method, which is intended to avoid the possible bias introduced by relying on any particular division into test and train components, is to partition the original set in several different ways and to compute an average score over the different partitions. This is called leave-one-out cross-validation. The residual values from actual data point and the tted data point from the leaveone-out estimation are averaged to construct the cross validation measure. With few parameters in the estimation the residual will tend to be large, due to a poor overall t, while with an interpolant the perfect t will tend to produce spurious movements and hence large out of sample residuals. Somewhere in between is the lowest value of the cross validation measure and thus the best estimate. See [2] for further details. Notice that in Table 1 is the solution of (16) and thus it depends also on : therefore, in the second and the third case (i.e., when we parametrize g or f ), in order to nd the best we have to nd solving the minimization problem (16) at each step of the GCV-minimization procedure.

The M ATLAB Code

The aim of this section is to present our code; below we report the main le. For further information on the M ATLAB routines used in the following code, such as FMINSEARCH or DAYSDIF, see Appendix C. function main(flag1,flag2) % INPUT % flag1: kind of data % flag1 = 0 -> Btp % flag1 = 1 -> Swap + Libor % % flag2: kind of curve % flag2 = 0 -> Nelson-Siegel % flag2 = 1 -> B-spline (function: d) % flag2 = 2 -> B-spline + Penalty (function: d) % flag2 = 3 -> B-spline (function: g) % flag2 = 4 -> B-spline + Penalty (function: g) % flag2 = 5 -> B-spline (function: f) % flag2 = 6 -> B-spline + Penalty (function: f) %%%%%%%%%%%%%%%%%%%%%%%%%%%% % FIRST STEP: Getting Data % %%%%%%%%%%%%%%%%%%%%%%%%%%%% 8

if flag1==0 [Btp,value_date]=Btp_data; elseif flag1==1 [Libor,Swap,value_date]=Libor_Swap_data; Swap=missing_Swap(Swap); end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % SECOND STEP: Building Matrices and Vectors % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % TT-> vector of global payments (time) % AA-> matrix of global payments (value) % MAT->vector of maturity dates if flag1==0 [P,T,A]=matrix_vector_Btp(value_date,Btp); elseif flag1==1 [P,T,A]=matrix_vector_LS(value_date,Libor,Swap); end [TT,AA,MAT]=matrix_vector(T,A); %%%%%%%%%%%%%%%%%%%%%%%%%%%%% % THIRD STEP: Curve Fitting % %%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Find the vector x of the parameters of the curve % % Options for FMINSEARCH options=optimset(TolFun,1e-9,TolX,1e-9,MaxIter,1e8,MaxFunEvals,1e8); % if flag2==0 %NELSON-SIEGEL x_0=[0.04;-0.02;0.001;2]; %initial value x=fminsearch(NelsonSiegel,x_0,options,AA,P,TT); else %B-SPLINE METHODS K=length(MAT); s=max(3,round(sqrt(K))); %number of knot points + 1 KP=knot_points(s,K,MAT); s=length(KP)+2; %number of B-spline basis function KPa=[KP(1),KP(1),KP(1),KP,KP(end),KP(end),KP(end)];%Augmented knot points if flag2==1 %B-SPLINE (function d) for i=1:length(TT) for j=1:s G(i,j)=BsplineBasis(j,4,TT(i),KPa); %B-spline matrix end end x_0=ones(s-1,1); %initial value x=fminsearch(Bspline,x_0,options,AA*G,P); x=[1;x]; elseif flag2==2 %B-SPLINE + PENALTY (function d) for i=1:length(TT) for j=1:s 9

G(i,j)=BsplineBasis(j,4,TT(i),KPa); end end H=penalty(s,KPa); % Penalty Term % Find the optimal Penalty Parameter lambda=10^10; %initial value lambda=fminsearch(GCV,lambda,options,AA*G,P,H); % Find x x_0=ones(s-1,1); %initial value x=fminsearch(Bspline_penalty,x_0,options,AA*G,P,H,lambda); x=[1;x]; elseif flag2==3 %B-SPLINE (function g) for i=1:length(TT) for j=1:s G(i,j)=BsplineBasis(j,4,TT(i),KPa); end end x_0=ones(s-1,1); x=fminsearch(Bspline_g,x_0,options,AA,G,P); x=[0;x]; elseif flag2==4 %B-SPLINE+PENALTY (function g) for i=1:length(TT) for j=1:s G(i,j)=BsplineBasis(j,4,TT(i),KPa); end end H=penalty(s,KPa); % Penalty Term % Find the optimal Penalty Parameter x_0=ones(s-1,1); %initial value lambda=10^3; % initial value lambda=fminsearch(GCV_g,lambda,options,AA,G,P,H,x_0,s,options); % Find x x=fminsearch(Bspline_penalty_g,x_0,options,AA,G,P,H,lambda); x=[0;x]; elseif flag2==5 %B-SPLINE (function f) IG=intBsplineBasis(TT,s,KP,KPa); % integral of the B-spline basis x_0=ones(s,1); %initial value x=fminsearch(Bspline_f,x_0,options,AA,IG,P); elseif flag2==6 %B-SPLINE+PENALTY (function f) IG=intBsplineBasis(TT,s,KP,KPa); % integral of the B-spline basis H=penalty(s,KPa); % Penalty Term % Find the optimal Penalty Parameter x_0=ones(s,1); %initial value lambda=10^3; %initial value lambda=fminsearch(GCV_f,lambda,options,AA,IG,P,H,x_0,s,options); % Find x x=fminsearch(Bspline_penalty_f,x_0,options,AA,IG,P,H,lambda); 10

end end

4.1

First Step: Getting Data

The rst step of the M ATLAB program is to get the Btp or the Libor and Swap data. If we consider Btp, the program calls the B TP _ DATA routine, which provides all the necessary data. function [Btp,value_date]=Btp_data % Btp -> Btp struct --> [nominal value, clean value, maturity, % rate, number of coupons (for year)] % value_date=12/19/2006; % Btp=[ struct(n_val,100,val,99.94,mat,01/15/2007,rate,2.75,coupons,2) ... struct(n_val,100,val,96.3,mat,02/01/2037,rate,4.00,coupons,2) ]; If instead we consider Libor and Swap, the program calls the L IBOR _S WAP _ DATA routine for the necessary data and then MISSING _S WAP, which uses linear interpolation for the missing Swap rates (see Section 2.2). function [Libor,Swap,value_date]=Libor_Swap_data % value_date=09/21/2006; %%%%%%%%%%%%%%%%%%%%%% % Libor -> duration (in days) - duration (in months) - rate Libor=[ 1, 0, 3.04188; ... 0, 3, 3.37025; ]; %%%%%%%%%%%%%%%%%%%%%% % Swap -> duration (in years) - rate Swap=[ 1, 3.808; ... 30, 4.214; ]; function Swap1=missing_Swap(Swap) % Compute missing Swap using linear interpolation % n=length(Swap); %number of Swaps difference=zeros(n,1); %initialize % difference(i)=n means that between the duration of swap i and i+1 % there are n years-> if n=1 we do nothing, otherwise we create the 11

% missing Swap/Swaps using linear interpolation for i=1:n-1 difference(i)=Swap(i+1,1)-Swap(i,1); end % count=0; for i=1:n count=count+1; Swap1(count,:)=Swap(i,:); for j=1:difference(i)-1 count=count+1; Swap1(count,1)=Swap(i,1)+j; t=Swap1(count,1); t1=Swap(i,1); t2=Swap(i+1,1); s1=Swap(i,2); s2=Swap(i+1,2); Swap1(count,2)=(s1*(t2-t)+s2*(t-t1))/(t2-t1); end end

4.2

Second Step: Building Matrices and Vectors

In the second step, following Section 2, we build the matrix AA and the vector P necessary for the third step: the curve tting. If we consider Btp, the main program calls the MATRIX _ VECTOR _B TP routine, which computes matrices A and T and the vector P (see Section 2.1). function [P,T,A]=matrix_vector_Btp(Date,Btp) % Compute: P -> price vector % T -> matrix of couponspayments (time) % T[i,j]=time to the jth payment of the ith Btp % A -> matrix of couponspayments (value) % A[i,j]=jth payment of the ith Btp % Date is taken as time 0 % % Initialize Matrices and Vector n=length(Btp); % number of Btp P=zeros(n,1); A=[]; T=[]; for i=1:n % 1-compute Previous coupon and Next coupons [Pcoupon,Ncoupons]=PNcoupons(Btp(i),Date); % 2-compute Accrued Interest AI=Btp(i).n_val*(Btp(i).rate/100)*(1/(Btp(i).coupons))*... (daysdif(Pcoupon,Date,3)/daysdif(Pcoupon,Ncoupons(1),3)); % DAYSDIF->Days between dates with day-count basis 3(=actual/365) 12

% 3-compute P P(i)=Btp(i).val+AI; % 4-compute A and T m=length(Ncoupons); % number of next coupons for j=1:m T(i,j)=daysdif(Date,Ncoupons(j),3)/365; A(i,j)=((Btp(i).rate/100)/Btp(i).coupons)*Btp(i).n_val; end A(i,m)=A(i,m)+Btp(i).n_val; %pay the nominal value at maturity end The above routine calls PN COUPON, which computes the previous coupon date and the dates of the next coupons. function [Pcoupon,Ncoupons]=PNcoupons(Btp,Date); % Compute the Previous coupon and the Next coupons date % maturity=Btp.mat; numcoup=Btp.coupons;%number of coupons paid on each year monthcoup=12/numcoup; %months between two coupons % coupon=datenum(maturity); %DATENUM converts date string into serial date number cday=day(maturity);%day of the maturity date cmonth=month(maturity);%month of the maturity date cyear=year(maturity);%year of the maturity date count=0; %number of next coupons while( daysdif(Date,coupon,3)>0 ) %DAYSDIF->days between dates with day-count basis 3(=actual/365) count=count+1; coup(count)=coupon;%next couponsdate temp=cmonth-monthcoup; if temp<=0 cyear=cyear-1; cmonth=12+temp; else cmonth=temp; end coupon=datenum(cyear,cmonth,cday); end Pcoupon=coupon; while( isbusday(Pcoupon)==0 ) % if it is not a business day Pcoupon=Pcoupon+1; end % for i=1:count temp=coup(i); while( isbusday(temp)==0 ) % if it is not a business day 13

temp=temp+1; end Ncoupons(count-i+1)=temp; % ascending order end In the same way, if we consider Libor and Swap, we compute matrix A, T and vector P using the Notice that A, T and P contain the elements of A1 and A2 , T1 and T2 , P1 and P2 , respectively (see Section 2.2).
MATRIX _ VECTOR _LS.

function [P,T,A]=matrix_vector_LS(Date,Libor,Swap) % Compute: P -> price vector % T -> matrix of payments (time) % A -> matrix of payments (value) % Date is taken as time 0 % n1=length(Libor); % number of Libors n2=length(Swap); % number of Swaps cday=day(Date); cmonth=month(Date); cyear=year(Date); % %%%%% % P % %%%%% P=ones(n1+n2,1); % %%%%%%%%%%% % A and T % %%%%%%%%%%% % Libor % daycount -> actual/360 (basis 2 in daysdif) for i=1:n1 % temp is the maturity of the i-th Libor if Libor(i,1)>0 % if the duration is in days temp=datenum(cyear,cmonth,cday+Libor(i,1)); else % if the duration is in months temp=datenum(cyear,cmonth+Libor(i,2),cday); end while( isbusday(temp)==0 ) %if it is not a business day temp=temp+1; end T(i,1)=daysdif(Date,temp,2)/360; A(i,1)=1+(Libor(i,3)/100)*T(i,1); end % % Swap % daycount -> 30/360 (basis 6 in daysdif) for i=1:n2 14

for j=1:Swap(i,1) % temp is the j-th payment date of the i-th Swap temp=datenum(cyear+j,cmonth,cday); while( isbusday(temp)==0 ) %if it is not a business day temp=temp+1; end T(n1+i,j)=daysdif(Date,temp,6)/360; if j==1 %if it is the first payment t=T(n1+i,j); else t=T(n1+i,j)-T(n1+i,j-1); end A(n1+i,j)=(Swap(i,2)/100)*t; end A(n1+i,Swap(i,1))=A(n1+i,Swap(i,1))+1; end At the end, using routine MATRIX _ VECTOR, we compute matrix AA and vector T T (see Section 2) for both the Btp case or the Libor-Swap case. function [TT,AA,MAT]=matrix_vector(T,A) % Compute: % TT-> vector of global payments (time) % AA-> matrix of global payments (value) % MAT->vector of times to maturity % %%%%%% % TT % %%%%%% count=1; for i=1:size(T,2) for j=1:size(T,1) a=T(end+1-j,i); if a==0 %all the remaining element of the column are 0 break % break the j-loop else flag=0; % the date a is not present in TT for k=1:count-1 if TT(k)==a flag=1; % a is already present in T break % break the k-loop end end if flag==0 % if the date a is not present in TT... TT(count)=a; % add a to TT count=count+1; end end 15

end end TT=sort(TT); %Sort in ascending order. %%%%%% % AA % %%%%%% for k=1:length(TT) for i=1:size(A,1) for j=1:size(A,2) if T(i,j)==TT(k) %if the payment date are equal AA(i,k)=A(i,j); break; elseif T(i,j)>TT(k) break; end end end end %%%%%%% % MAT % %%%%%%% for i=1:size(T,1) for j=1:size(T,2) if T(i,j)==0 MAT(i)=T(i,j-1); break; elseif j==size(T,2) MAT(i)=T(i,j); break; end end end MAT=sort(MAT); For further details see the examples reported in Appendix A.

4.3

Third Step: Curve Fitting

In this last step we compute the curves parameters. Notice that both the Btp case and the Libor and Swap case are considered without any distinction. 4.3.1 Nelson Siegel Model

From the MAIN routine we have x_0=[0.04;-0.02;0.001;2]; %initial value x=fminsearch(NelsonSiegel,x_0,options,AA,P,TT); where the N ELSON S IEGEL routine is the following 16

function [f]=NelsonSiegel(x,A,P,T) % f is the quantity to minimize % if x(1)<=0 % x(1) must be positive... f=10^15; elseif x(1)+x(2)<=0 % x(1)+x(2) must be positive... f=10^15; elseif x(4)<=0 % x(4) must be positive... f=10^15; else % if x(1), x(1)+x(2), x(4) is positive... for i=1:length(T) t(i,1)=exp(-x(1)*T(i)-x(4)*(x(2)+x(3))*(1-exp(-T(i)/x(4)))+... x(3)*T(i)*exp(-T(i)/x(4))); end temp=P-A*t; f=0; for i=1:length(temp) f=f+temp(i)^2; end end If we consider Section 3.1, we have x(1):= 1 , x(2):= 2 , x(3):= 3 , x(4):= . Notice that, in order to solve the constrain minimization (9), we impose f=10^15 if (8) is not satised. 4.3.2 B-spline methods

For the B-spline methods, in order to dene the basis functions, in the MAIN program we have K=length(MAT); s=max(3,round(sqrt(K))); %number of knot points + 1 KP=knot_points(s,K,MAT); s=length(KP)+2; %number of B-spline basis functions KPa=[KP(1),KP(1),KP(1),KP,KP(end),KP(end),KP(end)]; %Augmented KP where the KNOT _ POINTS routine is as follows function T=knot_points(s,k,MAT) % Compute the knot points following McCulloch (1971) % These points are used to compute the B-spline basis functions % T(1)=0; for i=2:s-2 h=fix(((i-1)*k/(s-2))); % fix(X) rounds X to the nearest integers towards zero. theta=((i-1)*k/(s-2))-h; T(i)=MAT(h)+theta*(MAT(h+1)-MAT(h)); end T(s-1)=MAT(end); 17

As in [6] and [8], the number of knot points (and thus the number of basis functions) depends on Appendix B we report the following routines:

K . In

B SPLINEBASIS returns the value of B-spline basis functions; this routine is used to compute matrix G,
D B SPLINEBASIS

returns the value of the rst derivative of the B-spline basis functions, returns the value of the second derivative of the B-spline basis functions,

DD B SPLINEBASIS

INT B SPLINEBASIS returns the integrals of the B-spline basis functions: this routine is used to compute matrix IG.

Following Sections 3.2.1 and 3.2.2, in order to compute the set of parameters , we have to consider the minimization problem below. B-spline (parametrized function: d) From the MAIN routine we have x_0=ones(s-1,1); %initial value x=fminsearch(Bspline,x_0,options,AA*G,P); x=[1;x]; where function [f]=Bspline(x,A,b) % B-spline % f is the quantity to minimize % x=[1;x]; %the first term of the vector must be equal to 1 temp=b-A*x; f=0; for i=1:length(temp) f=f+temp(i)^2; end Notice that d(0) = 1, since the present value of 1 Euro repayable in 0 years is actually 1; thus we have to impose 1 = 1 since 0 is the rst knot point and it holds 1 (0) = 1, i (0) = 0 if i = 2, s, where we recall that s is the number of basis functions (see Figure 1 and [2]). For this reason, the minimization procedure involves only the parameters 2 , , s . B-spline with Penalty (parametrized function: d) From the MAIN routine we have

18

H=penalty(s,KPa); % Penalty Term % Find the optimal Penalty Parameter lambda=10^10; %initial value lambda=fminsearch(GCV,lambda,options,AA*G,P,H); % Find x x_0=ones(s-1,1); %initial value x=fminsearch(Bspline_penalty,x_0,options,AA*G,P,H,lambda); x=[1;x]; The penalty term, which is unique for each B-spline with penalty method, is computed by the P ENALTY routine (see Section 3.2.2). function H=penalty(s,KPa) % Compute the Penalty Term % K=length(KPa)-6; H=sparse(s,s); for k=1:K-1 [x,w]=gauleg(KPa(k+3),KPa(k+4),4); for t=1:length(x) f=[]; for i=1:s f(i)=ddBsplineBasis(i,4,x(t),KPa); end for i=1:s for j=1:s H(i,j)=H(i,j)+w(t)*f(i)*f(j); end end end end For the GAULEG routine, which computes the nodes and weights of the Gauss-Legendre quadrature formula, see Appendix B.5. The minimization procedures call the following routines: function f=GCV(lambda,X,Y,H) % GENERAL CROSS VALIDATION % Q=X*inv(X*X+lambda*H)*X; n=length(Y); I=eye(n); %identity matrix of size n T=(I-Q)*Y; theta=2; f=((T)*T)/((n-theta*trace(Q))^2); and

19

function [f]=usa_Bspline_penalty(x,A,b,H,lambda) % f is the quantity to minimize % x=[1;x];%the first term of the vector must be equal to 1 f=((b-A*x))*(b-A*x)+lambda*((x)*H*x); As above, the second minimization procedure involves only the parameters 2 , , s . B-spline (parametrized function: g ) From the MAIN routine we have x_0=ones(s-1,1); x=fminsearch(Bspline_g,x_0,options,AA,G,P); x=[0;x]; where function [f]=Bspline_g(x,C,F,b) % f is the quantity to minimize % x=[0;x]; Pi=C*exp(-F*x); f=((b-Pi))*(b-Pi); Notice that we have imposed 1 = 0 since g (0) = 0 implies d(0) = 1 (see (11) ). B-spline with Penalty (parametrized function: g ) From the MAIN routine we have H=penalty(s,KPa); % Penalty Term % Find the optimal Penalty Parameter x_0=ones(s-1,1); %initial value lambda=10^3; % initial value lambda=fminsearch(GCV_g,lambda,options,AA,G,P,H,x_0,s,options); % Find x x=fminsearch(Bspline_penalty_g,x_0,options,AA,G,P,H,lambda); x=[0;x]; where function e=GCV_g(lambda,AA,G,P,H,b_0,s,options) % GENERAL CROSS VALIDATION % if lambda>0 b=fminsearch(Bspline_penalty_g,b_0,options,AA,G,P,H,lambda); b=[0;b]; W=AA*exp(-G*b); temp=AA*G; 20

for i=1:length(W) Xg(i,:)=(-W(i)).*(temp(i,:)); end Yg=P-W+Xg*b; e=GCV(lambda,Xg,Yg,H); else %constrain: lambda>0 e=10^12; end and function [f]=Bspline_penalty_g(x,C,F,b,H,lambda) % f is the quantity to minimize % x=[0;x]; Pi=C*exp(-F*x); f=(((b-Pi))*(b-Pi))+lambda*((x)*H*x); Notice that GCV_ G call B- SPLINE _ PENALTY _ G in a minimization procedure. Moreover, as above, we have imposed 1 = 0 and the minimization procedures involve only parameters 2 , , s . B-spline (parametrized function: f ) From the MAIN routine we have x_0=zeros(s,1); %initial value x=fminsearch(Bspline_f,x_0,options,AA,IG,P); where function [f]=Bspline_f(x,C,F,b) % f is the quantity to minimize % Pi=C*exp(-F*x); f=((b-Pi))*(b-Pi); Notice that (13) implies d(0) = 1; thus we do not impose any restriction to 1 and the minimization procedure involves 1 , , s . B-spline with Penalty (parametrized function: f ) This case is similar to the B-spline with Penalty (parametrized function: g ) case. We have H=penalty(s,KPa); % Penalty Term % Find the optimal Penalty Parameter x_0=ones(s,1); %initial value lambda=10^3; %initial value lambda=fminsearch(GCV_f,lambda,options,AA,IG,P,H,x_0,s,options); % Find x x=fminsearch(Bspline_penalty_f,x_0,options,AA,IG,P,H,lambda);

21

where function e=GCV_f(lambda,X,IG,P,H,b_0,s,options) % GENERAL CROSS VALIDATION % if lambda>0 b=fminsearch(Bspline_penalty_f,b_0,options,X,IG,P,H,lambda); W=X*exp(-IG*b); temp=X*IG; for i=1:length(W) Xf(i,:)=(-W(i)).*(temp(i,:)); end Yf=P-W+Xf*b; e=GCV(lambda,Xf,Yf,H); else %constrain: lambda>0 e=10^12; end and function [f]=Bspline_penalty_f(x,C,F,b,H,lambda) % f is the quantity to minimize % Pi=C*exp(-F*x); f=(((b-Pi))*(b-Pi))+lambda*((x)*H*x);

Numerical Results

The aim of this section is to present the modelsperformances, considering both computational cost and approximation results. Numerical experiments have been carried out on a Personal Computer with a Pentium IV (2.40 Ghz) processor and 768 MB of RAM, and using M ATLAB 7.0 (R14).

5.1

Btp Case

In this section we deal with the Btp case, which are Italian coupon bonds with semi-annual payments. In the numerical experiments we have considered the Btp quotation with value date 19th December 2006 (see Table 2). First of all we consider the computational cost: the Building Matrices and Vectors step, which does not depend on the tting model considered, takes approximately 8.5 seconds, while in Table 3 we report the elapsed time of the third step of the MAIN routine (i.e., the Curve Fitting steps) for each method considered. Moreover, in the same table we present the residuals |E| of the minimization problems (9) for the Nelson Siegel model, (15) for the B-spline methods, and (16) for the B-spline with penalty methods; for this last class of methods, we also report the best computed with the GCV procedure. From this table, it seems that the best choice from a computational point of view is the B-spline model with the parametrization of the discount function, while if we consider the residual, the best choice seems to be the B-spline method (f ), i.e., we parametrize the instantaneous forward rate function f using B-spline basis functions. Moreover, the B-spline methods with penalty (g ) and (f ) have a great computational cost: this

22

Value 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100

Clean Price 99.94 100.36 100.17 99.7 101.6 101 101.89 99.77 98.92 101.63 98.18 99.69 98.37 98.44 101.6 99.91 101.25 97.74 96.59 106.03 98.73

Expiration 01/15/2007 02/01/2007 03/01/2007 06/01/2007 07/01/2007 10/15/2007 11/01/2007 01/15/2008 02/01/2008 05/01/2008 06/15/2008 09/15/2008 04/15/2009 02/01/2009 05/01/2009 06/15/2009 11/01/2009 01/15/2010 06/15/2010 11/01/2010 03/15/2011

Table 2: Btp Annual Rate Value (%) 2.75 100 6.75 100 4.50 100 3.00 100 6.75 100 5.00 100 6.00 100 3.50 100 2.75 100 5.00 100 2.50 100 3.50 100 3.00 100 3.00 100 4.50 100 3.75 100 4.25 100 3.00 100 2.75 100 5.50 100 3.50 100

Clean Price 105.91 99.57 105.31 104.81 102.22 102.31 102.27 98.6 98.19 110.78 101.96 104.24 96.16 158.78 141.42 131.7 115.18 127.09 124.27 112.94 96.3

Expiration 08/01/2011 09/15/2011 02/01/2012 02/01/2013 08/01/2013 08/01/2014 02/01/2015 08/01/2015 08/01/2016 08/01/2017 02/01/2019 02/01/2020 08/01/2021 11/01/2023 11/01/2026 11/01/2027 11/01/2029 05/01/2031 02/01/2033 08/01/2034 02/01/2037

Annual Rate (%) 5.25 3.75 5.00 4.75 4.25 4.25 4.25 3.75 3.75 5.25 4.25 4.50 3.75 9.00 7.25 6.50 5.25 6.00 5.75 5.00 4.00

Table 3: Btp Data: Timing and Residual Curve Fitting Residual Best (elapsed time) Nelson Siegel 0.406 seconds 1.058905 Bspline (d) 0.313 seconds 0.599565 Bspline+Penalty(d) 0.531 seconds 0.858068 15442.197764 Bspline (g ) 0.437 seconds 0.544416 Bspline+Penalty (g ) 28.922 seconds 0.560438 1273.437583 Bspline (f ) 3.234 seconds 0.471925 Bspline+Penalty (f ) 80.062 seconds 1.641775 52148137.527466 Method

is due to the GCV-minimization procedure, which call another minimization procedure at each step (see Section 3.2.2). Then we show the plots of the discount function d (Figure 2), of the spot rate function h (Figure 3), where h( ) := log (d( )) ,

and of the instantaneous forward rate function f (Figure 4). These gures suggest the following observations, which are important in order to understand the behavior of the different data-tting techniques:

23

Figure 2: Btp Case


Discount Function 1 0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 NelsonSiegel Bspline (d) Bspline + Penalty (d) Bspline (g) Bspline + Penalty (g) Bspline (f) Bspline + Penalty (f)

10

15

20

25

30

Figure 3: Btp Case


Spot Rate 0.043

0.042

0.041

0.04

0.039

0.038

0.037

NelsonSiegel Bspline (d) Bspline + Penalty (d) Bspline (g) Bspline + Penalty (g) Bspline (f) Bspline + Penalty (f)

0.036 0

10

15

20

25

30

24

Figure 4: Btp Case


Instantaneous Forward Rate 0.046

0.044

0.042

0.04 NelsonSiegel Bspline (d) Bspline + Penalty (d) Bspline (g) Bspline + Penalty (g) Bspline (f) Bspline + Penalty (f)

0.038

0.036

0.034 0

10

15

20

25

30

Figure 5: Btp Case


Comparison 0.6

0.4

0.2

0.2 NelsonSiegel Bspline (d) Bspline + Penalty (d) Bspline (g) Bspline + Penalty (g) Bspline (f) Bspline + Penalty (f) 5 10 15 20 25 30 35 40

0.4

0.6

0.8 0

25

discount function from Figure 2 it seems that the different methods for curve construction produce very similar plots; spot rate function from Figure 3 it seems that the Nelson Siegel and the B-spline with penalty (f ) models behave quite different from the other methods after the 15-years point. If we consider the last method, this behavior is due to the large penalty parameter computed with the GCV procedure (see Table 3); instantaneous forward rate function the plots presented in Figure 4 are quite different; the best choices seem to be the Nelson-Siegel and the B-spline with penalty (f ) models, since for the other methods the plotted curves decrease too rapidly after the 20-years point (see [3] for further details). Finally we compare our models with the initial data. More precisely, let P be the vector containing the prices of the considered Btp at the value date, computed using the discount function obtained with a data-tting technique, then in Figure 5 we plot the values P (i) P (i), i = 1, , 42, where 42 is the number of Btp considered.

5.2

Libor and Swap Case

In this section we present the same data as above, considering Libor and Swap rates with value date 21th September 2006 (see Tables 4 and 5). Table 4: Libor Rate (%) Duration (months) 3.04188 1 month 3.06275 2 months 3.06563 3 months

Duration (days) 1 day 7 days 15 days

Rate (%) 3.19325 3.2935 3.37025

Duration (year) 1 2 3 4 5 6 7

Table 5: Swap Rate (%) Duration (year) 3.808 8 3.88 9 3.883 10 3.892 15 3.906 20 3.925 25 3.947 30

Rate (%) 3.973 4.011 4.029 4.066 4.202 4.218 4.214

As above, in Table 6 we compare the different methods considering both the computational cost and the residuals |E|, respectively. The results are in agreement with the Btp case. Notice that the elapsed time for the Building Matrices and Vectors step is approximately 3.5 seconds. Moreover, in Figures 6, 7 and 8 we show the plots of the discount function, of the spot rate function and of the instantaneous forward rate function, respectively. These gures suggest the following observations: discount function in Figure 6 the plots are really similar, as in the Btp case; 26

Figure 6: Libor and Swap Case


Discount Function 1 0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 NelsonSiegel Bspline (d) Bspline + Penalty (d) Bspline (g) Bspline + Penalty (g) Bspline (f) Bspline + Penalty (f)

10

15

20

25

30

Figure 7: Libor and Swap Case


Spot Rate 0.043

0.042

0.041

0.04

0.039

0.038

0.037

NelsonSiegel Bspline (d) Bspline + Penalty (d) Bspline (g) Bspline + Penalty (g) Bspline (f) Bspline + Penalty (f) 5 10 15 20 25 30

0.036 0

27

Figure 8: Libor and Swap Case


Instantaneous Forward Rate 0.048

0.046

0.044

0.042

0.04 NelsonSiegel Bspline (d) Bspline + Penalty (d) Bspline (g) Bspline + Penalty (g) Bspline (f) Bspline + Penalty (f) 5 10 15 20 25 30

0.038

0.036

0.034 0

Figure 9: Libor and Swap Case


x 10 4
3

Comparison

2 NelsonSiegel Bspline (d) Bspline + Penalty (d) Bspline (g) Bspline + Penalty (g) Bspline (f) Bspline + Penalty (f) 5 10 15 20 25 30 35 40

8 0

28

Table 6: Libor and Swap Data: Timing and Residual Method Curve Fitting Residual Best (elapsed time) Nelson Siegel 0.125 seconds 0.011997 Bspline (d) 0.157 seconds 0.006932 Bspline+Penalty(d) 0.360 seconds 0.011889 4.089915 Bspline (g ) 0.157 seconds 0.007672 Bspline+Penalty (g ) 18.828 seconds 0.012356 22.205400 Bspline (f ) 0.920 seconds 0.005384 Bspline+Penalty (f ) 44.875 seconds 0.006086 1.419115

spot rate function from Figure 7 it seems that the B-spline with penalty (g ) method (and not the B-spline with penalty (f ), as in the Btp case) behaves like the Nelson Siegel model: this is due to the different penalty parameter value, since in the Btp case the largest parameter is the one of the B-spline with penalty (f ) method, while in the Libor and Swap case it is the one computed for the B-spline with penalty (g ) model (see Table 6); instantaneous forward rate function Figure 8 suggests that the best plots are the ones derived from the Nelson Siegel and the B-spline with penalty methods, since the classical B-spline methods produce curves which increase or decrease too rapidly after the 20-years points. Finally, as in the previous subsection, in Figure 9 we compare our models with the initial data.

Conclusion

In this paper we have shown how to t smoothing splines or exponential curves (like the Nelson Siegel model) to the term structure of interest rates. We have described the M ATLAB code and we have presented numerical results, comparing the different models. From the numerical experiments, it is clear that it is not possible to nd the best model: the choice of which method to use is subjective and need to be decided on a case by case basis. In fact, if we consider the residual, the best choice is to use smoothing splines which parametrized the instantaneous forward rate function f : this result is in agreement with [2]. Moreover, if we are interested in the instantaneous forward rate function, the best choice seems to be the Nelson Siegel model. Following [2], we have also presented methods with a penalty term: these methods behaves better than the classical B-spline methods if we consider the instantaneous forward rate function, but they are characterized by high computational costs due to the GCV procedure in order to compute the best penalty parameter. Notice that in [2] the authors use a great number of knot points and thus the penalty term is necessary in order to obtain well-behaved curves, while in this paper we have followed [6] and [8], using few knot points.

29

Building Matrices and Vectors: Examples

The aim of this section is to explain Sections 2 and 4.2 with two examples: one for the Btp case and the other for the Libor and Swap case.

A.1

Btp Case

In this section we consider the Btp quotation with value date 19th December 2006 reported in Table 7. Table 7: Btp Clean Price Expiration 99.94 01/15/2007 99.7 06/01/2007 99.77 01/15/2008 101.63 05/01/2008 98.18 06/15/2008

Facial Value 100 100 100 100 100

Annual Interest Rate (%) 2.75 3.00 3.50 5.00 2.50

We now consider the rst bond of Table 7: following Section 2.1, we have m1 = 1, i.e, there is only 1 payment date for the rst bond; F1 = 100, i.e., the facial value; = 1.375, i.e., the facial value multiplied by the semi-annual interest rate. C1 = 100 2.75% 2 Reasoning in the same way for all the elements of Table 7, we have 101.375 0 0 101.5 0 0 . A= 1 . 75 1 . 75 101 . 75 2.5 102.5 2.5 1.25 1.25 101.25 Moreover, we have BP = and thus T = 28 164 28 133 178 0 0 0 0 209 392 317 499 363 545 , 01/16/07 06/01/07 01/16/07 05/01/07 06/15/07 01/15/08 05/01/08 06/16/08

07/16/07 11/01/07 12/17/07

where we recall that T contains the days between the value date and the payment dates of the Btp BP , computed according to the actual/365 day-count convention. Now we can compute vector T T , i.e., the vector containing all the non-zero elements of T TT = 28 133 164 178 209 317 30 363 392 499 545 ;

and thus we dene matrix AA as follows 101.375 0 0 0 0 0 0 0 0 0 0 0 101.5 0 0 0 0 0 0 0 AA = 1 . 75 0 0 0 1 . 75 0 0 101 . 75 0 0 0 2.5 0 0 0 2.5 0 0 102.5 0 0 0 0 1.25 0 0 1.25 0 0 101.25

Notice that in the M ATLAB code (see Section 4) both the elements of T and T T are computed in years and not in days. Moreover, in order to compute the payment dates (and thus BP ), we have to check if each date is a business day: in our code, we have used the M ATLAB function ISBUSDAY, which is based on the US calendar (that is why the 15th January 2007 is considered as holiday and thus the payment date of the rst bond is 16th January 2007). Finally, if we sum the clean prices and the accrued interests, we obtain 101.104617486339 99.848351648352 P = 101.252240437158 . 102.292983425414 98.207472527473

A.2

Libor and Swap

Now we consider the Libor and Swap interest rates with value date 21th September 2006 reported in Tables 8 and 9, respectively. Table 8: Libor Duration Interest Rate (%) 1 day 3.04188 7 days 3.06275 15 days 3.06563

Table 9: Swap Duration Interest Rate (%) 1 year 3.808 2 years 3.88 3 years 3.883 First of all, we consider the Libor case: from Table 8, we obtain LR = LM = thus, following Section 2.2, we have LP = T1 = 09/22/06 09/28/06 10/06/06 0.041667 , 0.0304188 1 7 15 0.0306275 0.0306563 ; ,

0.002778 0.019444 31

and so A1 = 1.000084 1.000595 1.001278 ;

notice that in this example the elements of LM are computed in days, while the elements of T1 are computed in years, using the actual/360 day-count convention. Now we consider the Swap case: from Table 9 we obtain SR = and 09/21/07 SP = 09/21/07 09/22/08 . 09/21/07 09/22/08 09/21/09 Recalling that the value date is 09/21/06, using the 30/360 day-count convention, we have 1 0 0 T2 = 1 2.002778 0 . 1 2.002778 3 We recall that in order to compute the payment dates, we have to check if each date is a business day, otherwise we have to look for the next business day: this is the reason why T2 (2, 2) = 2.002778. Finally, following Section 2.2, we calculate matrix A2 1.03808 0 0 A2 = 0.0388 1.038908 0 . 0.03883 0.038938 1.038722 0.03808 0.0388 0.03883

If we now compute vector T T , i.e., the vector containing all the non-zero elements of T1 and T2 TT = 0.002778 0.019444 0.041667 1 2.002778 3 ,

we can dene matrix AA as follows 1.000084 0 0 0 0 0 0 1.000595 0 0 0 0 0 0 1 . 001277 0 0 0 AA = 0 0 0 1.03808 0 0 0 0 0 0.0388 1.038908 0 0 0 0 0.03883 0.038938 1.038722

Notice that in the MATRIX _ VECTOR _LS routine (see Section 4.2) the elements of A1 and A2 are stored in a unique matrix A 1.000084 0 0 0 0 1.000595 1.001278 0 0 ; A= 0 0 1.03808 0.0388 1.038908 0 0.03883 0.038938 1.038722 32

in the same way, the elements of T1 and T2 are stored in T as follows 0.002778 0 0 0 0 0.019444 0.041667 0 0 . T = 1 0 0 1 2.002778 0 1 2.002778 3

Bspline Routines
In this section, we present the following routines: 1. B SPLINEBASIS computes the value of B-spline basis functions; 2. 3. 4. 5.
D B SPLINEBASIS

computes the value of the rst derivative of the B-spline basis functions; computes the value of the second derivative of the B-spline basis functions; returns the integrals of the B-spline basis functions;

DD B SPLINEBASIS INT B SPLINEBASIS GAULEG

computes the nodes and weights of the Gauss-Legendre quadrature formula.

B.1

B SPLINE BASIS

function F=BsplineBasis(k,r,x,d) % B-spline Basis Function % k -> consider the kth basis function % r -> r-1 is the degree of the spline % x -> is the the point in which I evaluate the function % d -> augmented knot points % if (k+r-1<5 & k<5) if (x<d(5)) F=((d(5)-x)/(d(5)-d(1)))^(r-1); else F=0; end elseif (k+1>length(d)-4 & k+r>length(d)-4) if (x>=d(end-4)) F=((x-d(end-4))/(d(end)-d(end-4)))^(r-1); else F=0; end else if r==1 if (x>=d(k) & x<d(k+1)) F=1; else 33

F=0; end else f1=BsplineBasis(k,r-1,x,d); f2=BsplineBasis(k+1,r-1,x,d); F=((f1*(x-d(k)))/(d(k+r-1)-d(k)))+... ((f2*(d(k+r)-x))/(d(k+r)-d(k+1))); end end

B.2

D B SPLINE BASIS

function F=dBsplineBasis(k,r,x,d) % First Derivative of B-spline Basis Function % k -> consider the kth basis function % r -> r-1 is the degree of the spline % x -> is the vector of the points in which I evaluate the function % d -> augmented knot points (necessary to define the basis function) % if r<2 F=0; else if (k+r-1<5 & k<5) if (x<d(5)) F=(r-1)*(((d(5)-x)/(d(5)-d(1)))^(r-2))*(-1/(d(5)-d(1))); else F=0; end elseif (k+1>length(d)-4 & k+r>length(d)-4) if (x>=d(end-4)) F=(r-1)*(((x-d(end-4))/(d(end)-d(end-4)))^(r-2))*... (1/(d(end)-d(end-4))); else F=0; end else f1=BsplineBasis(k,r-1,x,d); f2=BsplineBasis(k+1,r-1,x,d); d1=dBsplineBasis(k,r-1,x,d); d2=dBsplineBasis(k+1,r-1,x,d); F=((f1+(x-d(k))*d1)/((d(k+r-1)-d(k))))+... ((-f2+(d(k+r)-x)*d2)/(d(k+r)-d(k+1))); end end end

34

B.3

DD B SPLINE BASIS

function F=ddBsplineBasis(k,r,x,d) % Second Derivative of B-spline Basis Function % k -> consider the kth basis function % r -> r-1 is the degree of the spline % x -> is the vector of the points in which I evaluate the function % d -> augmented knot points (necessary to define the basis function) % if r<3 F=0; else if (k+r-1<5 & k<5) if (x<d(5)) F=(r-1)*(r-2)*(((d(5)-x)/(d(5)-d(1)))^(r-3))*... ((-1/(d(5)-d(1)))^2); else F=0; end elseif (k+1>length(d)-4 & k+r>length(d)-4) if (x>=d(end-4)) F=(r-1)*(r-2)*(((x-d(end-4))/(d(end)-d(end-4)))^(r-3))*... ((1/(d(end)-d(end-4)))^2); else F=0; end else d1=dBsplineBasis(k,r-1,x,d); d2=dBsplineBasis(k+1,r-1,x,d); dd1=ddBsplineBasis(k,r-1,x,d); dd2=ddBsplineBasis(k+1,r-1,x,d); F=((d1+(x-d(k))*dd1+d1)/((d(k+r-1)-d(k))))+... ((-d2+(d(k+r)-x)*dd2-d2)/(d(k+r)-d(k+1))); end end end

B.4

INT B SPLINE BASIS

function IG=intBsplineBasis(T,s,KP,d) % Integral of the cubic B-spline basis function % IG[i,j]=int_{0}^{T(i)} B(j) dx % where B(j) is the jth basis function % KP -> Knot Points % d -> Augmented Knot Points % IG=zeros(length(T),s); for i=1:length(T) 35

for ii=1:length(KP) if T(i)>KP(ii) if ii<length(KP) t=min(T(i),KP(ii+1)); else t=T(i); end [x,w]=gauleg(KP(ii),t,4); for j=1:s for jj=1:length(x) temp=BsplineBasis(j,4,x(jj),d); IG(i,j)=IG(i,j)+temp*w(jj); end end else %the integral between 0 and T(i) has already been computed break %stop the ii-loop and change the value of i end end end

B.5

GAULEG

function [xx,ww]=gauleg(a,b,n) % Gauss-Legendre quadrature formula % Computes the Gauss-Legendre nodes xx and weights ww % of order n for the interval (a,b) % m=(n+1)/2; xm=0.5*(b+a); xl=0.5*(b-a); for i=1:m z=cos(pi*(i-0.25)/(n+0.5)); while 1 % do untill break p1=1.0; p2=0.0; for j=1:n p3=p2; p2=p1; p1=((2.0*j-1.0)*z*p2-(j-1.0)*p3)/j; end pp=n*(z*p1-p2)/(z*z-1.0); z1=z; z=z1-p1/pp; if (abs(z-z1)<eps), break, end end xx(i)=xm-xl*z; xx(n+1-i)=xm+xl*z;

36

ww(i)=2.0*xl/((1.0-z*z)*pp*pp); ww(n+1-i)=ww(i); end

M ATLAB Routines
The following informations are taken from the M ATLAB [13] manual.

C.1

DAYSDIF

- Days between dates for any day count basis

DAYSDIF returns the number of days between D1 and D2 using the given day count basis. Enter dates as serial date numbers or date strings. D = daysdif(D1, D2) D = daysdif(D1, D2, Basis) Inputs: D1 - [Scalar or Vector] of dates. D2 - [Scalar or Vector] of dates. Optional Inputs: Basis - [Scalar or Vector] of day-count basis. Valid Basis are: 0 = actual/actual (default) 1 = 30/360 2 = actual/360 3 = actual/365 4 - 30/360 (PSA compliant) 5 - 30/360 (ISDA compliant) 6 - 30/360 (European) 7 - act/365 (Japanese)

C.2

DATENUM

- Serial date number

N = DATENUM(S) converts the string or date vector S into a serial date number. Date numbers are serial days where 1 corresponds to 1-Jan-0000. Certain formats may not contain enough information to compute a date number. In those cases, missing values will in general default to 0 for hours, minutes and seconds, will default to January for the month, and 1 for the day of month. The year will default to the current year. Date strings with 2 character years are interpreted to be within the 100 years centered around the current year. N = DATENUM(Y,M,D) and N = DATENUM([Y,M,D]) return the serial date numbers for corresponding elements of the Y,M,D (year,month,day) arrays. Y, M, and D must be arrays of the same size (or any can be a scalar). Examples: n = datenum(19-May-2000) returns n = 730625.

37

n = datenum(2001,12,19) returns n = 731204. n = datenum(2001,12,19,18,0,0) returns n = 731204.75.

C.3

FMINSEARCH

- Multidimensional unconstrained nonlinear minimization

X = FMINSEARCH(FUN,X0) starts at X0 and attempts to nd a local minimizer X of the function FUN. FUN accepts input X and returns a scalar function value F evaluated at X. X0 can be a scalar, vector or matrix. X = FMINSEARCH(FUN,X0,OPTIONS) minimizes with the default optimization parameters replaced by values in the structure OPTIONS, created with the OPTIMSET function. FMINSEARCH uses these options: Display, TolX, TolFun, MaxFunEvals, MaxIter, FunValCheck, and OutputFcn. [X,FVAL]= FMINSEARCH(...) returns the value of the objective function, described in FUN, at X. [X,FVAL,EXITFLAG] = FMINSEARCH(...) returns an EXITFLAG that describes the exit condition of FMINSEARCH. Possible values of EXITFLAG and the corresponding exit conditions are: 1 - FMINSEARCH converged to a solution X. 0 - Maximum number of function evaluations or iterations reached. -1 - Algorithm terminated by the output function. FMINSEARCH uses the Nelder-Mead simplex (direct search) method.

C.4

ISBUSDAY

- True for dates that are business days

T = ISBUSDAY(D,HOL,WEEKEND) Inputs: D - a vector of dates in question. Optional Inputs: HOL - a user-dened vector of holidays. The default is a predened US holidays (in holidays.m). WEEKEND - a vector of length 7, containing 0 and 1, with the value of 1 to indicate weekend day(s). The rst element of this vector corresponds to Sunday. Thus, when Saturday and Sunday are weekend then WEEKDAY = [1 0 0 0 0 0 1]. The default is Saturday and Sunday weekend. Outputs: T = - 1 if D is business day and 0 if otherwise.

C.5

OPTIMSET

- Create/alter OPTIM OPTIONS structure

OPTIONS = OPTIMSET(PARAM1,VALUE1,PARAM2,VALUE2,...) creates an optimization options structure OPTIONS in which the named parameters have the specied values. Any unspecied parameters are set to [] (parameters with value [] indicate to use the default value for that parameter when OPTIONS is passed to the optimization function). OPTIMSET PARAMETERS for MATLAB: Display - Level of display [ off | iter | notify | nal ] MaxFunEvals - Maximum number of function evaluations allowed [ positive integer ]

38

MaxIter - Maximum number of iterations allowed [ positive scalar ] TolFun - Termination tolerance on the function value [ positive scalar ] TolX - Termination tolerance on X [ positive scalar ] FunValCheck - Check for invalid values, such as NaN or complex, from user-supplied functions [ off | on ] OutputFcn - Name of installable output function [ function ]. This output function is called by the solver after each iteration.

References
[1] Revisiting The Art and Science of Curve Building, FINCAD News, December 2005 Issue. [2] M. Fisher, D. Nychka, D. Zervos, Fitting the Term Structure of Interest Rates with Smoothing Splines, Board of Governors of the Federal Reserve System (U.S.), Finance and Economics Discussion Series, Vol. 95-1, 1994. [3] P. Hagan, G. West, Interpolation Methods for Curve Construction, Applied Mathematical Finance, Vol. 13-2, 2006. [4] M. Ioannides, A Comparison of Yield Curve Estimation Techniques Using UK Data, Journal of Banking & Finance, Vol. 27, 2003. [5] J. James, N. Webber, Interest Rate Modelling, John Wiley & Sons, 2000. [6] J.H. McCulloch, Measuring the Term Structure of Interest Rate, Journal of Business, Vol. XLIV, 1971. [7] J.H. McCulloch, The Tax-Adjusted Yield Curve, The Journal of Finance, Vol. XXX-3, 1975. [8] S.K. Nawalkha, G.M. Soto, N.K. Beliaeva, Interest Rate Risk Modeling: The Fixed Income Valuation Course, John Wiley & Sons, 2005. [9] C.R. Nelson, A.F. Siegel, Parsimonious Modeling of Yield Curves, Journal of Business, Vol. 60-4, 1987. [10] A. Quarteroni, R. Sacco, F. Saleri, Numerical Mathematics, Springer, 2000. [11] A.F. Siegel, C.R. Nelson, Long-Term Behaviour of Yield Curves, Journal of Financial and Quantitative Analysis, Vol. 23-1, 1988. [12] O.A. Vasicek, H.G. Fong, Term Structure Modeling Using Exponential Splines, The Journal of Finance, Vol. XXXVII-2, 1982. [13] www.mathworks.com

39

Вам также может понравиться