Upload
oliver-woods
View
218
Download
0
Tags:
Embed Size (px)
Citation preview
Advanced Term Structure Advanced Term Structure PracticePractice
Chapter 7
Copyright 2002 David Heath
Forward curve, March 25, 2002Forward curve, March 25, 2002
March 25, 2002 Forward Rates
0
0.01
0.02
0.03
0.04
0.05
0.06
0.07
0.08
0 1 2 3 4 5 6 7 8 9 10
Maturity
Ra
te
Pricing of Coupon InstmtsPricing of Coupon Instmts
Model Market
Instrument Price Bid Ask
5 3/4 Aug 03 103:12 103:12 103:13
11 1/8 Aug 03 110:22 110:20 110:21
6 ½ Feb 10 106:26 107:00 107:01
Term Structure EvolutionTerm Structure Evolution
Basic securities: pure discount bonds forward curve f(t, . ) such that pdb prices are: B(t,T) =
exp(-tT f(t,u)du)
HJM equation of motion of forward curve dtf(t,T) = (t,T,) dW(t) + (t) dt
Under martingale measure, is determined by (to make discounted bond prices martingales)
Two favorite forms of : (T-t) or (T-t)*Min(f(t,T),M)
Discrete time modelDiscrete time model
Suppose we know W(t), W(t+t) and f(t,T) Can we compute f(t+t,T)?
Integrating the HJM equation we get f(t+t,T)-f(t,T) = tt+t (T-u)dW(u) + drift
Fact: Conditional expectation of integral given W(t) and W(t+t) is: (W(t+t)-W(t)) * ( T-(t+t) T-t (v)dv) / (t))
Drift is chosen to make pdb prices martingales.
Choosing the driftChoosing the drift
Recall Forward curves are thought of as “locally flat” Think of rate on interval as “rate at center”
Basic method of computation: For each of many T’s (the centers of ftimes intevals): set W(t+t)-W(t) = W(t) = scaled jumpsin
and compute the cond expect of the integral to get a first guess of f(t+t,T) in up and down states (still need to get the drift …)
Basic method (continued) .. Make sure that t+t is an ftime Compute the integral so far of the up and down
curves from t+t to first ftime after T; call these Iup and Idown, (and Iin for f(t, . ))
Notice that adding to last forward curve values (in up and down states) adds *(L = length of ftime interval) to Iup and Idown.
Choose to satisfy: 0.5 * (exp(-(Iup+L))+exp(-(Idown+L))) = exp(-Iin)
Get = (ln( (exp(-Iup)+exp(-Idown))/2 ) + Iin) / L
Sample adjustment codeSample adjustment code
// Copy the unchanged part of the term structurei = 0;while((InputTs->times[i]) <= tplusdt){
up_times[i] = InputTs->times[i];down_times[i] = InputTs->times[i];up_irates[i] = InputTs->integrated_rates[i];down_irates[i] = InputTs->integrated_rates[i];i++;}
i--;
i0 = i;inint = InputTs->integrated_rates[i];upint = inint;downint = inint;
for(i=i0; (i+1)<InputTs->npoints; i++){up_times[i+1] = InputTs->times[i+1];down_times[i+1] = InputTs->times[i+1];
delft = (InputTs->times[i+1]) - (InputTs->times[i]);inrate = ((InputTs->integrated_rates[i+1])-
(InputTs->integrated_rates[i]))/delft;bigt = ((InputTs->times[i+1]) + (InputTs-
>times[i]))/2.;
df = jumpsize * (SigmaIntegral(bigt-tplusdt , bigt- timenow)/dt);
uprate = inrate + df;
downrate = inrate - df;
// in above two lines, could try * exp(df) or * exp(-df) to get //proportional model (more later)
upint += uprate * delft;
downint += downrate * delft;
inint += inrate * delft;
drift_term = log(0.5*(exp(-upint)+exp(-downint))) + inint;
upint += drift_term;
downint += drift_term;
up_irates[i+1] = upint;
down_irates[i+1] = downint;
}
Note: above are “code fragments” -- stuff needs to be added to make it all work!
Proportional modelsProportional models
Unfortunately solutions to the HJM eqn: dtf(t,T) = (T-t) f(t,T) dW(t) + dt explode with pos. prob. in any interval
Hence use: dtf(t,T) = (T-t) Min(f(t,T),M) dW(t) + dt Choose M big, like 1.00
For shallow trees this doesn’t matter much But: as steps get tinier, it matters more & more
Proportional Models (cont’d)Proportional Models (cont’d)
For non-proportional models we coded:df = jumpsize * (SigmaIntegral(bigt-tplusdt , bigt-
timenow)/dt);
uprate = inrate + df;
downrate = inrate - df;
For proportional models we can useif(inrate < M) { uprate = inrate * exp(df);
downrate = inrate * exp(-df);}
else { uprate = inrate + M * df;
downrate = inrate - M * df;}
Assignment for next weekAssignment for next week
Build a class to implement the evolution of term structures (TermStructureEvolution)
Data elements: int nsigtimes; double *sigtimes, *sigvals;
Make TermStructure Evolution a friend of the class TermStructure
TermStructureEvolutionTermStructureEvolution Methods
TermStructureEvolution(char* filename); Constructor; reads sigma function from a file (see the
sample file; it contains a table of values to be linearly interpolated)
~TermStructureEvolution(); Destructor
double Sigma(double t); Returns the value of the sigma function at t computed by linear interpolation of stored values
TermStructureEvolutionTermStructureEvolution
double SigmaIntegral(double tleft, double tright);
Returns the integral of sigma from tleft to tright Since sigma is piecewise linear, can get exact
answer
TermStructure** NewTermStructures( double timenow, double dt, double jumpsize, TermStructure * InputTs);
TermStructureEvolutionTermStructureEvolution
NewTermStructures (cont’d) Returns an array of (2) pointers to
termstructures. These point to the up- and down- term structures which result from one step of evolution from the InputTs = Input Term Structure (using HJM equation).
jumpsize is the size of the W to use. Note: could eventually do 2- or 3-factor
model; would then return more pointers
Test TermStructureEvolutionTest TermStructureEvolution
Write a main program to Read in a term structure (you just did this part) Subdivide the term structure every 1/4 of a year Be sure that 0.25 years is an “ftime” Use NewTermStructures to generate values
corresponding to DT = 0.25 years of evolution for a non-proportional model with (t,T)=.01
Print out the input and two output term structures and graph all three
Advanced Term Structure Advanced Term Structure PracticePractice
Chapter 8
Copyright 2002 David Heath
Putting it all togetherPutting it all together
You have already Developed simulation to value securities Used “tricky trees” to value securities Built the class TermStructure Built the class TermStructureEvolve
Objective Combine to build term structure valuator Test your valuator
First task (assignment) First task (assignment)
Write a program to use your classes TermStructure and TermStructureEvolve to value a call on a zero-coupon bond Use the table jumpsin Use “bonds.in” for the initial term structure Use “sigma.in” for the sigma function
Second taskSecond task
Test the code Try a call with strike 0 and exercise a year from
now (=March 9, 2000 for the bond data) on a zero-coupon bond maturing 6 years from now. Also, price the “zero” now. (must get =)
Try a call with strike = 100 maturing 10 years from now on a “zero” maturing in 20 years. Is your answer Correct? Reasonable?
SwaptionsSwaptions
A “vanilla swap” Two parties
One pays a “fair” floating rate on “notional amount” Other pays fixed “coupons” on notional
Often is entered into when a corporation issues fixed coupon bonds but wants to pay floating
Sometimes the first payment is omitted At time of initiation, coupon rate is set so
that net present value of the swap is 0
Analyzing a vanilla swapAnalyzing a vanilla swap
We’ll ignore possibility of default (for now) Decompose deal into two sub-deals
A loan of the notional at floating rate A bond with a fixed coupon Notice: Notional payments cancel; actual
payments are made only for interest (&coupon) The price ALL payments associated with a
floating rate loan is zero (must include initial and terminal exchange of notional)
Analysis of vanilla swap cont’dAnalysis of vanilla swap cont’d
Hence: Value of swap for the receiver (of fixed rate) is value of all cash flows (including notional at both ends) of a bond so = “bond price” - notional.
“Fair” coupon rate is that which makes value equal to 0
How? Pricing is linear in coupon, so: Price with 0 and some other coupon Interpolate/extrapolate to get fair coupon rate
Third taskThird task Write a new method for the class
TermStructure which values a swap: double swap_value(tnow, tstart, tbetween,
ncoupons, annual_coupon) Returns value of swap with notional of 100 Each coupon is = tbetween*annual_coupon tstart is start date of swap; coupon payments occur
at tstart + k * tbetween for k = 1, 2, … ncoupons; notioanl repayment occurs at last of these
Include only those payments after timenow! but subtract notional from discounted value
Might want to remove “accrued coupon” (~bond)
Fourth taskFourth task Write a new method for the class
TermStructure which computes a swap rate double swap_rate(tnow, tstart, tbetween,
ncoupons) Should return the “fair” annual coupon Arguments have same meaning How: call swap_value with annual coupon = 0
and annual coupon = 10 and then use linearity to find annual coupon for which value = 0.
May assume tstart >= tnow
SwaptionsSwaptions
The bonds which “caused” the swap to exist are often “callable” -- the bonds can be repurchased for some preset price (like 110) at coupon dates. (American-style option)
=> Banks are often long optionality Banks hedge with each other via European
swaptions.
““m by n” swaptionsm by n” swaptions
An “m by n” European swaption gives its holder the option to enter into an “n-year-long” swap at the end of m years from now
Deal can thus last m+n years altogether Swap rate will be the “fair” swap rate for a
swap from year m to year m+n TODAY. “Strike price” is 0. This can be priced as an option on a bond
Fifth taskFifth task Use your swap_rate code to find today’s
fair swap rate for a swap starting 3 years from today and lasting until 8 years from today Assume the fixed rate will be paid quarterly
Price a “3x5 payer swaption” whose holder has the right to pay fixed and receive floating (equivalent to selling the bond for 100) Price this swaption by pricing a put on the
appropriate bond
The Hull-White (extended The Hull-White (extended Vasicek) model (see Hull)Vasicek) model (see Hull)
Model: dtr(t) = a((t)-r)dt + dW(t)
Written in HJM form, this model is dtf(t,T)=exp(-a (T-t)) dW(t) + (t,T) dt
Thus we use (t,T) = exp(-a (T-t)) Hull gives a formula for pricing a call on a
pure discount bond in this model (see page 434 of Third Edition):
European call on a “zero”European call on a “zero”
Price of the call: L P(0,s) (h) - X P(0,T) (h - P)
L = Principal of the bond T = Expiration date of the call X = Strike price s = Date at which bond matures (so s T) h = (1/ P) ln( (L P(0,s)) / (X P(0,T)) )
+ P /2 . P = (/a) [1-exp(-a(s-T))] (1-exp(-2aT))/(2a)
Sixth TaskSixth Task Try the Hull-White model with a = .1,
= .015 (and t is measured in years). Build a new “sigma.in” file containing a table of
values of the sigma function for arguments 0, 0.25, 0.5, 0.75, …, 10.0 (41 values in all)
Price European calls today (at t=0 on March 9, 2000) with strikes 70, 72, …, 90 which expire at t=2 on a pure discount bond paying 100 at t=5 using the “bonds.in file” for the forward curve
Compare your values with those obtained from Hull’s (Jamshidian’s) formula