Sie sind auf Seite 1von 248

Financial Numerical Recipes in C++.

Bernt Arne degaard April 2007

5.4

Bond calculations with a general term structure and continous compounding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

60
63 63 64 65 68 68 69 69 70 71 71 72 72 72 72 73 77 77 78 78 78 80 85 85 87 88 88 88 88 88 89 91 93 94 94 94 96 97 97 97 98 99

Contents
1 On C++ and programming. 1.1 Compiling and linking . . . . . . . . . . . . 1.2 The structure of a C++ program . . . . . . 1.2.1 Types . . . . . . . . . . . . . . . . . 1.2.2 Operations . . . . . . . . . . . . . . 1.2.3 Functions and libraries . . . . . . . . 1.2.4 Templates and libraries . . . . . . . 1.2.5 Flow control . . . . . . . . . . . . . . 1.2.6 Input Output . . . . . . . . . . . . . 1.2.7 Splitting up a program . . . . . . . . 1.2.8 Namespaces . . . . . . . . . . . . . . 1.3 Extending the language, the class concept. 1.3.1 date, an example class . . . . . . . . 1.4 Const references . . . . . . . . . . . . . . . . 1.5 Other C++ concepts . . . . . . . . . . . . . . Matrix Tools 2.1 The rst screen . . . . . . . . . . . . . 2.2 Linear algebra . . . . . . . . . . . . . . 2.2.1 Basic matrix operations . . . . 2.2.2 Arithmetic Matrix Operations. 2.3 Solving linear equations . . . . . . . . 2.4 Element by element operations . . . . 2.5 Function denitions . . . . . . . . . . 2.6 m les . . . . . . . . . . . . . . . . . . 2.7 Flow control . . . . . . . . . . . . . . . 2.8 Plotting . . . . . . . . . . . . . . . . . 2.9 Libraries . . . . . . . . . . . . . . . . . 2.10 References . . . . . . . . . . . . . . . .

6 5 5 5 5 6 6 7 8 8 8 9 9 9 15 15 16 17 17 17 18 21 22 23 23 23 23 23 23 24 24 25 28 32 33 33 34

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

The Mean Variance Frontier 6.1 Setup . . . . . . . . . . . . . . . . . . . . . . 6.2 The minimum variance frontier . . . . . . . . 6.3 Calculation of frontier portfolios . . . . . . . 6.4 The global minimum variance portfolio . . . . 6.5 Ecient portfolios . . . . . . . . . . . . . . . 6.6 The zero beta portfolio . . . . . . . . . . . . . 6.7 Allowing for a riskless asset. . . . . . . . . . . 6.8 Ecient sets with risk free assets. . . . . . . . 6.9 Short-sale constraints . . . . . . . . . . . . . . 6.10 The Sharpe Ratio . . . . . . . . . . . . . . . . 6.11 Equilibrium: CAPM . . . . . . . . . . . . . . 6.11.1 Treynor . . . . . . . . . . . . . . . . . 6.11.2 Jensen . . . . . . . . . . . . . . . . . 6.12 Working with Mean Variance and CAPM . . . 6.13 Mean variance analysis using matrix libraries Futures algoritms. 7.1 Pricing of futures contract.

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

Binomial option pricing 8.1 Options . . . . . . . . . . . . . . . . . . . . . . . 8.2 Pricing . . . . . . . . . . . . . . . . . . . . . . . . 8.3 Multiperiod binomial pricing . . . . . . . . . . . Basic Option Pricing, the Black Scholes formula 9.1 The formula . . . . . . . . . . . . . . . . . . 9.2 Understanding the why's of the formula . . 9.2.1 The original Black Scholes analysis . 9.2.2 The limit of a binomial case . . . . . 9.2.3 The representative agent framework 9.3 Partial derivatives. . . . . . . . . . . . . . . 9.3.1 Delta . . . . . . . . . . . . . . . . . . 9.3.2 Other Derivatives . . . . . . . . . . . 9.3.3 Implied Volatility. . . . . . . . . . . 9.4 References . . . . . . . . . . . . . . . . . . .

The value of time 3.1 Present value . . . . . . . . . . . . . . . . . 3.2 One interest rate with annual compounding 3.2.1 Internal rate of return. . . . . . . . . 3.3 Continously compounded interest . . . . . . 3.3.1 Present value . . . . . . . . . . . . . 3.4 Further readings . . . . . . . . . . . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

10 Warrants 10.1 Warrant value in terms of assets . . . . . . . . . . 10.2 Valuing warrants when observing the stock value 10.3 Readings . . . . . . . . . . . . . . . . . . . . . . . 11 Extending the Black Scholes formula 11.1 Adjusting for payouts of the underlying. . . . . . 11.1.1 Continous Payouts from underlying. . . . 11.1.2 Dividends. . . . . . . . . . . . . . . . . . . 11.2 American options . . . . . . . . . . . . . . . . . . 11.2.1 Exact american call formula when stock is paying one dividend. . . . . . . . . . . . . 11.3 Options on futures . . . . . . . . . . . . . . . . . 11.3.1 Black's model . . . . . . . . . . . . . . . . 11.4 Foreign Currency Options . . . . . . . . . . . . . 11.5 Perpetual puts and calls . . . . . . . . . . . . . . 11.6 Readings . . . . . . . . . . . . . . . . . . . . . . . 12 Option pricing with binomial approximations 12.1 Introduction . . . . . . . . . . . . . . . . . . . 12.2 Pricing of options in the Black Scholes setting 12.2.1 European Options . . . . . . . . . . . 12.2.2 American Options . . . . . . . . . . . 12.2.3 Matlab implementation . . . . . . . . .

Bond Pricing with a at term structure 4.1 Flat term structure with discrete, annual compounding . . . . . . . . . . . . . . . . . . . . . . 4.1.1 Bond Price . . . . . . . . . . . . . . . . . 4.1.2 Yield to maturity . . . . . . . . . . . . . . 4.1.3 Duration . . . . . . . . . . . . . . . . . . . 4.1.4 Measuring bond sensitivity to interest rate changes . . . . . . . . . . . . . . . . . 4.2 Continously compounded interest . . . . . . . . . 4.3 Further readings . . . . . . . . . . . . . . . . . . The term structure of interest rates and an object lesson 5.1 The interchangeability of discount factors, spot interest rates and forward interest rates . . . . . 5.2 The term structure as an object . . . . . . . . . . 5.2.1 Base class . . . . . . . . . . . . . . . . . . 5.2.2 Flat term structure. . . . . . . . . . . . . 5.3 Using the currently observed term structure. . . . 5.3.1 Linear Interpolation. . . . . . . . . . . . . 5.3.2 Interpolated term structure class. . . . . .

34 35 35 38 40 44 47
48

49 51 51 53 54 55 57

99 102 102 103 104 105


106 106 107 107 108 110

. . . . .

. . . . .

12.3 How good is the binomial approximation? 12.3.1 Estimating partials. . . . . . . . . 12.4 Adjusting for payouts for the underlying 12.5 Pricing options on stocks paying dividends a binomial approximation . . . . . . . . . 12.5.1 Checking for early exercise in the mial model. . . . . . . . . . . . . . 12.5.2 Proportional dividends. . . . . . . 12.5.3 Discrete dividends . . . . . . . . . 12.6 Option on futures . . . . . . . . . . . . . . 12.7 Foreign Currency options . . . . . . . . . 12.8 References . . . . . . . . . . . . . . . . . .
13 Finite Dierences 13.1 Explicit Finite dierences 13.2 European Options. . . . . 13.3 American Options. . . . . 13.4 Implicit nite dierences . 13.5 An example matrix class . 13.6 Finite Dierences . . . . . 13.7 American Options . . . . 13.8 European Options . . . . 13.9 References . . . . . . . . .

. . . . . . . . . . . . using . . . . bino. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

112 113 116 117 117 117 119 121 123 124
125 125 125 127 130 130 130 130 133 134 135

19 Alternatives to the Black Scholes type option formula 176 19.1 Merton's Jump diusion model. . . . . . . . . . . 176 19.2 Hestons pricing formula for a stochastic volatility model . . . . . . . . . . . . . . . . . . . . . . . . 178 20 Pricing of bond options, basic models 181 20.1 Black Scholes bond option pricing . . . . . . . . . 181 20.2 Binomial bond option pricing . . . . . . . . . . . 183 21 Credit risk 185 21.1 The Merton Model . . . . . . . . . . . . . . . . . 185 21.2 Issues in implementation . . . . . . . . . . . . . . 186 22 Term Structure Models 22.1 The Nelson Siegel term structure approximation 22.2 Extended Nelson Siegel models . . . . . . . . . . 22.3 Cubic spline. . . . . . . . . . . . . . . . . . . . . 22.4 Cox Ingersoll Ross. . . . . . . . . . . . . . . . . . 22.5 Vasicek . . . . . . . . . . . . . . . . . . . . . . . 22.6 Readings . . . . . . . . . . . . . . . . . . . . . . . 187 187 190 192 195 198 199

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

14 Option pricing by simulation 14.1 Simulating lognormally distributed random variables . . . . . . . . . . . . . . . . . . . . . . . . . 14.2 Pricing of European Call options . . . . . . . . . 14.3 Hedge parameters . . . . . . . . . . . . . . . . . . 14.4 More general payos. Function prototypes . . . . 14.5 Improving the eciency in simulation . . . . . . 14.5.1 Control variates. . . . . . . . . . . . . . . 14.5.2 Antithetic variates. . . . . . . . . . . . . . 14.6 More exotic options . . . . . . . . . . . . . . . . . 14.7 References . . . . . . . . . . . . . . . . . . . . . . 15 Approximations 15.1 The Johnson (1983) approximation . . . . . . . . 15.2 An approximation to the American Put due to Geske and Johnson (1984) . . . . . . . . . . . . . 15.3 A quadratic approximation to American prices due to BaroneAdesi and Whaley. . . . . . . . . . 15.4 An alternative approximation to american options due to Bjerksund and Stensland (1993) . . 15.5 Readings . . . . . . . . . . . . . . . . . . . . . . . 16 Average, lookback and other exotic options 16.1 Bermudan options . . . . . . . . . . . . . . . . . 16.2 Asian options . . . . . . . . . . . . . . . . . . . . 16.3 Lookback options . . . . . . . . . . . . . . . . . . 16.4 Monte Carlo Pricing of options whose payo depend on the whole price path . . . . . . . . . . . 16.4.1 Generating a series of lognormally distributed variables . . . . . . . . . . . . . . 16.5 Control variate . . . . . . . . . . . . . . . . . . . 16.6 References . . . . . . . . . . . . . . . . . . . . . .

23 Binomial Term Structure models 200 23.1 The Rendleman and Bartter model . . . . . . . . 200 23.2 Readings . . . . . . . . . . . . . . . . . . . . . . . 202 24 Interest rate trees 24.1 The movement of 24.2 Discount factors . 24.3 Pricing bonds . . 24.4 Callable bond . . 24.5 Readings . . . . . 203 203 204 205 207 209 210 210 210 210 212 214

135 136 137 139 140 140 141 144 145


146 146

interest rates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

148 151 154 156


157 157 159 160

25 Building term structure trees using the Ho and Lee (1986) approach 25.1 Intro . . . . . . . . . . . . . . . . . . . . . . . . . 25.2 Building trees of term structures . . . . . . . . . 25.3 Ho Lee term structure class . . . . . . . . . . . . 25.4 Pricing things . . . . . . . . . . . . . . . . . . . . 25.5 References . . . . . . . . . . . . . . . . . . . . . .

26 Term Structure Derivatives 215 26.1 Vasicek bond option pricing . . . . . . . . . . . . 215 A Normal Distribution approximations. A.1 The normal distribution function . . . . . . . . . A.2 The cumulative normal distribution . . . . . . . . A.3 Multivariate normal . . . . . . . . . . . . . . . . A.4 Calculating cumulative bivariate normal probabilities . . . . . . . . . . . . . . . . . . . . . . . . A.5 Simulating random normal numbers . . . . . . . A.6 Cumulative probabilities for general multivariate distributions . . . . . . . . . . . . . . . . . . . . . A.7 References . . . . . . . . . . . . . . . . . . . . . . B C++ concepts C Interfacing to external libraries C.1 Newmat . . . . . . . . . C.2 IT++ . . . . . . . . . . C.3 GSL . . . . . . . . . . . C.3.1 The evaluation of C.4 Internet links . . . . . . D Summarizing routine names 217 217 217 218

218 221 222 222


223 225 225 225 225 225 225 227

162 162 165 166

17 Generic binomial pricing 167 17.1 Introduction . . . . . . . . . . . . . . . . . . . . . 167 17.2 Delta calculation . . . . . . . . . . . . . . . . . . 171 18 Trinomial trees 172 18.1 Intro . . . . . . . . . . . . . . . . . . . . . . . . . 172 18.2 Implementation . . . . . . . . . . . . . . . . . . . 172 18.3 Further reading . . . . . . . . . . . . . . . . . . . 175

. . . . . . . . . . . . N3 . . . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

Installation 237 E.1 Source availability . . . . . . . . . . . . . . . . . 237

Acknowledgements.

242

This book is a a discussion of the calculation of specic formulas in nance. The eld of nance has seen a rapid development in recent years, with increasing mathematical sophistication. While the formalization of the eld can be traced back to the work of Markowitz (1952) on investors mean-variance decisions and Modigliani and Miller (1958) on the capital structure problem, it was the solution for the price of a call option by Black and Scholes (1973); Merton (1973) which really was the starting point for the mathematicalization of nance. The elds of derivatives and xed income have since then been the main elds where complicated formulas are used. This book is intended to be of use for people who want to both understand and use these formulas, which explains why most of the algorithms presented later are derivatives prices. This project started when I was teaching a course in derivatives at the University of British Columbia, in the course of which I sat down and wrote code for calculating the formulas I was teaching. I have always found that implementation helps understanding these things. For teaching such complicated material it is often useful to actually look at the implementation of how the calculation is done in practice. The purpose of the book is therefore primarily pedagogical, although I believe all the routines presented are correct and reasonably ecient, and I know they are also used by people to price real options. To implement the algorithms in a computer language I choose C++. My students keep asking why

anybody would want to use such a backwoods computer language, they think a spreadsheet can solve all the worlds problems. I have some experience with alternative systems for computing, and no matter what, in the end you end up being frustrated with higher end languages, such as (Not to mention the straitjacket which is is a spreadsheet.)

Matlab
C++

og

Gauss

and going back to implementation in a

standard language. In my experience with empirical nance I have come to realize that nothing beats knowledge a

real

computer language. This used to be

pyex,

then

g,

and now it is

. All example

algorithms are therefore coded in C++. I do acknowledge that matrix tools like

wtl

are very good for

rapid prototyping and compact calculations, and will in addition to C++ in places also illustrate the use of

wtl.
The

The manuscript has been sitting on the internet a few of years, during which it has been visited by a large number of people, to judge by the number of mails I have received about the routines.

present (2007) version mainly expands on the background discussion of the routines, this is much more extensive. I have also added a good deal of introductory material on how to program in C++, since a number of questions make it obvious this manuscript is used by a number of people who know nance but not C++. All the routines have been made to conrm to the new ISO/ANSI C++ standard, using such concepts as namespaces and the standard template library. The current manscript therefore has various intented audiences. Primarily it is for students of nance who desires to see a complete discussion and implementation of some formula. But the manuscript is also useful for students of nance who wants to learn C++, and for computer scientists who want to understand about the nance algorithms they are asked to implent and embed into their programs. In doing the implementation I have tried to be as generic as possible in terms of the C++ used, but I have taken advantage of a some of the possibilities the language provides in terms of abstraction and modularization. This will also serve as a lesson in why a

real

computer language is useful. For example

I have encapsulated the term structure of interest rate as an example of the use of

lsses.

This is not a textbook in the underlying theory, for that there are many good alternatives. For much of the material the best textbooks to refer to are Hull (2006) and McDonald (2006), which I have used as references. The notation of the present manuscipt is also similar to these books.

Chapter 1

On C++ and programming.


Contents
1.1 1.2 Compiling and linking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The structure of a C++ program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 5

Types . . . . . . . . . . . . . . Operations . . . . . . . . . . . Functions and libraries . . . . . Templates and libraries . . . . Flow control . . . . . . . . . . Input Output . . . . . . . . . . Splitting up a program . . . . . Namespaces . . . . . . . . . . . 1.3 Extending the language, the class concept. 1.3.1 date, an example class . . . . . 1.4 Const references . . . . . . . . . . . . . .
1.5

1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

5 6 6 7 8 8 8 9
9

. . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . .

9
15 15

. . . . . . . . . . . . . . . . . . . . . . . . . . . Other C++ concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

In this chapter I introduce C++ and discuss how to run programs written in C++. This is by no means a complete reference to programming in C++, it is designed to give enough information to understand the rest of the book. This chapter also only discusses a subset of C++, it concentrates on the parts of the language used in the remainder of this book. For really learning C++ a textbook is necessary. I have found Lippman and Lajoie (1998) an excellent introduction to the language. on the language is Stroustrup (1997).

1 The authorative source

1.1

Compiling and linking

To program in C++ one has to rst write a separate le with the program, which is then into low-level instructions (machine language) and

linked

compiled

with libraries to make a complete executable

program. The mechanics of doing the compiling and linking varies from system to system, and we leave these details as an exercise to the reader.

1.2

The structure of a C++ program

The rst thing to realize about C++ is that it is a strongly typed language. Everything must be declared before it is used, both variables and functions. C++ has a few basic building blocks, which can be grouped into types, operations and functions.

1.2.1 Types
The types we will work with in this book are Here are some example denitions

ool, int, long, doule

and

string.

1 s lerned g++ from the previous edition of the ookD vippmn @IWWPAF prom wht s n tell the present editions still seems like good wy of lerning the lngugeD ut g++ hs hnged lot in reent yersF

ool thisistrueatrueY int i a HY long j a IPQRSTUVWY doule pi a QFIRISWPTSQSVWUWQPQVRTPTRQY string s@4this is string4AY

classes, of which more later.


1.2.2 Operations

The most important part of C++ comes from the fact that these basic types can be expanded by use of

To these basic types the common mathematical operations can be applied, such as addition, subtraction, multiplication and division:

int int int int

i j n m

a a a a

IHH IHH IHH IHH

C E B G

SHY SHY PY PY string


type. Such

These operations are dened for all the common datatypes, with exception of the operations can be dened by the programmer for other datatypes as well.

Increment and decrement

In addition to these basic operations there are some additional operations with

their own shorthand. An example we will be using often is incrementing and decrementing a variable. When we want to increase the value of one item by one, in most languages this is written:

int iaHY i a iCIY i a iEIY


In

gCC

this operation has its own shorthand

int iaHY iCCY iEEY


While this does not seem intuitive, and it is excusable to think that this operation is not really necessary, it does come in handy for more abstract data constructs. For example, as we will see later, if one denes a

dte

class with the necessary operations, to get the next date will simply be a matter of

dte d@IDIDIWWSAY dCCY


These two statements will result in the date in

being 2jan95.

1.2.3 Functions and libraries


In addition to the basic mathematical operations there is a large number of additional operations that can be performed on any type. However, these are not parts of the core language, they are implemented as standalone functions (most of which are actually written in in the large

library

or C++). These functions are included

that comes with any C++ installation. Since they are not part of the core language

they must be dened to the compiler before they can be used. Such denitions are performed by means of the

include

statement.

For example, the mathematical operations of taking powers and performing exponentiation are dened in the mathematical library

mth.

In the C++ program one will write

5inlude `mthb mth


and is actually a le with a large number of function dentions, among which one nds

which calculates

b a eI .

xn , and exp@rA which calculates er .

pow@xDnA

The following programming stub calculates

a a PP

5inlude `mthb doule a pow@PDPAY doule a exp@IAY


which will give the variables

and

values of 4 and 2.718281828..., respectively.

1.2.4 Templates and libraries


The use of libraries is not only limited to functions. Also included in the standard library is generic

data structures, which can be used on any data type. The example we will be considering the most is the

vetor`b,

which denes an array, or vector of variables.

5inlude `vetorb vetor`douleb w@PAY wHaIFHY wIaPFHY wFpushk@QAY


This example denes an array with three elements of type double

M aR

I P Q

Q S

Note some pecularities here. When rst dening the vector with the statement

vetor`douleb w@PAY
we dened an array of 2 elements of type

doule,

which we then proceeded to ll with the values 1 and

2. When lling the array we addressed each element directly. Note that in the statement

wHaIFHY
lies one of the prime traps for programmers coming to arrays starts at zero, not at one. The last statement,

wH

really means the

rst

or C++ from another language. element of the array.

Indexing of

wFpushk@QAY
shows the ability of the programmer of changing the size of the array after it has been dened.

pushk

is a standard operation on arrays which pushes the element onto the back of the array, extending the size of the array by one element. Most programming languages do not allow the programmer to specify variable-sized arrays on the y. In

for each array, and hope that we would not need to exceed that length. The

pyex or sl we would usually have to set a maximum length vetor<> template of C++

gets rid of the programmers need for bookkeeping in such array manipulations.

1.2.5 Flow control


To repeat statements several times one will use on of the possibilities for ow control, such as the or

while

constucts. For example, to repeat an operation

times one can use the following

for

for

loop:

for @int iaHY i`nY iCCA { someopertion@iAY }Y


The

for

statement has tree parts. The rst part gives the initial condition (iaH). The next part the

terminal condition (i

The last part is the increment statement (iCC), saying what to do in each iteration. In this case the value of of

<n),

which says to stop when

i<n

is not fullled, which is at the

n'th

iteration.

g's

is increased by one in each iteration. This is the typical

reputation for terseness is the possibility of elaborate

for

for

statement. One of the causes

constructs, which end up being almost

impossible to read. In the algorithms presented in this book we will try to avoid any obfuscated statements, and stick to the basic cases.

for

1.2.6 Input Output


For any program to do anything useful it needs to be able to output its results. operations is dened in a couple of libraries, Input and output

iostrem

and

fstrem.

The rst covers in/output to

standard terminals and the second in/output to les. To write to standard output

out

(the terminal), one will do as follows:

5inlude `iostremb out `` 4his is test4 `` endlY


To write to a le "testFout", one will do as follows:

5inlude `fstremb ofstrem outfY outfFopen@4testFout4AY outf `` 4his is test4 `` endlY outfFler@AY outfFlose@AY
1.2.7 Splitting up a program
Any nontrivial program in C++ is split into several pieces. Usually each piece is written as a function which returns a value of a given type. To illustrate we provide a complete example program, shown in

C++ Code 1.1.


The program denes a function performing the mathematical power operation, culates

xn

through the identity

xn

en ln@xA .

power@xDnA

which cal-

This function is then used to calculate and print the rst

5 powers of 2. When compiled, linked and run, the program will provide the following output

PI PP PQ PR PS

a a a a a

P R V IT QP

#include <iostrem> GG input output opertions #include <mth> GG mthemtis lirry using namespace std; GG the ove is prt of the stndrd nmespe
double power(double x, double n){

GG de(ne simple power funtion double p = exp(n*log(x)); return p;

};

int min(){ for (int n=1;n<6;n++){


}; };

out << " 2^" << n << " = " << power(2,n) << endl;

C++ Code 1.1: 1.2.8 Namespaces

A complete program

To help in building large programs, the concept of a

nmespe was introduced.

Namespaces are a means

of keeping the variables and functions dened local to the context in which they are used. For now it is necessary to know that any function in the standard C++ library lies in its own namespace, called the standard namespace. To actually access these library functons it is necessary to explicitly specify that one wants to access the standard namespace, by the statement

using nmespe stdY


Instead of such a general approach, one can also specify the namespace on an element by element basis, but this is more a topic for specialized C++ texts, for the current purposes we will allow all routines access to the whole standard namespace.

1.3

Extending the language, the class concept.

One of the major advances of C++ relative to other programming languages is the programmers ability to extend the language by creating new data types and dening standard operations on these data types. This ability is why C++ is called an object oriented programming language, since much of the work in programming is done by creating

objects.

An object is best though of as a data structure with operations

on it dened. How one uses an object is best shown by an example.

1.3.1 dte, an example class


Consider the abstract concept of a date. A date can be specied in any number of ways. Let us limit ourselves to the Gregorian calendar. 12 august 2003 is a common way of specifying a date. However, it can also be represented by the strings:  PHHQGVGIP,  IPGVGPHHQ and so on, or by the number of years since 1 january 1900, the number of months since January, and the day of the month (which is how a UNIX programmer will think of it). However, for most people writing programs the representation of a date is not relevant, they want to be able to enter dates in some abstract way, and then are conserned with such questions as:

  

Are two dates equal? Is one date earlier than another? How many days is it between two dates?

A C++ programmer will proceed to use a

class that embodies these uses of the concept of a date.

Typically

one will look around for an extant class which has already implemented this, but we will show a trivial such date class as an example of how one can create a class.

class dte { protected: int yer ; int month int dy ; public:

dte(); dte(const int& d, const int& m, const int& y);


bool vlid() const; int dy() const; int month() const; int yer() const;

void set dy (const int& dy ); void set month (const int& month void set yer (const int& yer );

);

dte dte dte dte


};

operator operator operator operator

++();

GG pre(x GG post(x (); GG pre(x (int); GG post(x


++(int);

bool bool bool bool bool bool

operator operator operator operator operator operator

== (const != (const

dte&, const dte&); GG omprison opertors dte&, const dte&); < (const dte&, const dte&); > (const dte&, const dte&); <= (const dte&, const dte&); >= (const dte&, const dte&);

Header le 1.1:


A class is dened in a header le, as shown in chosen the three integers

Dening a

dte

class

Header le 1.1. As internal representation of the date is dy, month and yer. This is the data structure which is then manipulated

by the various functions dened below. The functions are used to

    

Create a date variable:

dte@onst int8 dD onst int8 mD onst int8 yAY dy@A, month@A


and and

Functions outputting the date by the three integer functions Functions setting the date

yer@A.
which are used

setdy@intA, setmonth@intA CC
and and

setyer@intA,

by providing an integer as arguments to the function. Increment and decrement functions Comparison functions

! 3E. dte

`, `a, b, ba, aa

After including this header le, programmers using such a class will then treat an object of type just like any other. For exmple,

10

dte d@IDIDPHHIAY CCdY


would result in the

dte

object

containing the date 2 january 2001.

Any C++ programmer who want to use this

what are the possible functions one can use with a

dte object will only need to look at the header le to know dte object, and be happy about not needing to know dte
object is specied by the header le. This is the

anything about how these functions are implemented. This is the encapsulation part of object oriented programming, all relevant information about the

only point of interaction, all details about implementation of the class objects and its functions is not used in code using this object. In fact, the user of the class can safely ignore the class' privates, which is only good manners, anyway. Let us look at the implementation of this.

C++ Code 1.2


valid.

denes the basic operations, initialization, setting the date, and checking whether a date is

#include "date.h"

dteXXdte(){ yer

= 0;

month

= 0;

dy

= 0;};

dteXXdte(const int& dy, const int& month, const int& yer){ dy = dy; month = month; yer = yer;
};

int dteXXdy() const { return dy ; }; int dteXXmonth() const { return month ; int dteXXyer() const { return yer ; };

};

void dteXXset dy (const int& dy) { dteXXdy = dy; }; void dteXXset month(const int& month) { dteXXmonth = month; void dteXXset yer (const int& yer) { dteXXyer = yer; }; bool dteXXvlid() const

};

GG his funtion will hek the given dte is vlid or notF GG sf the dte is not vlid then it will return the vlue flseF GG xeed some more heks on the yerD though if (yer <0) return false; if (month >12 j j month <1) return false; if (dy >31 j j dy <1) return false; if ((dy ==31 && ( month ==2 j j month ==4 j j month
if return false;

==6

j j month

==9

j j month

==11) ) )

( dy ==30 && month ==2) return false; GG should lso hek for lep yersD ut for now llow for fe PW in ny yer

return true;
};

C++ Code 1.2:

Basic operations for the date class

11

For many abstract types it can be possible to dene an ordering. For dates there is the natural ordering.

C++ Code 1.3

shows how such comparison operations is dened.

#include "date.h"
bool operator == (const dte& dI,const dte& dP){ GG hek for equlity if (! (dI.vlid() && (dP.vlid())) ) { return false; }; GB if dtes not vlidD not ler wht to doF return
}; ((dI.dy()==dP.dy()) && (dI.month()==dP.month()) && (dI.yer()==dP.yer()));

lterntiveX throw exeption BG

bool operator < (const dte& dI, const dte& dP){ if (! (dI.vlid() && (dP.vlid())) ) { return false; }; GG see ove remrk if (dI.yer()==dP.yer()) { GG sme yer if (dI.month()==dP.month()) { GG sme month return (dI.dy()<dP.dy());
}

else
}; }

return (dI.month()<dP.month());

else
}; };

return (dI.yer()<dP.yer());

GG di'erent yer

GG remining opertors de(ned in terms of the ove


bool operator <=(const dte& dI, const dte& dP){ if (dI==dP) { return true; } return (dI<dP);
}

bool operator >=(const dte& dI, const dte& dP) if (dI==dP) { return true;}; return (dI>dP);
};

bool operator bool operator

> (const dte& dI, const dte& dP)


!=(const

return

!(dI

<=dP);};

dte& dI, const dte& dP){ return

!(dI==dP);}

C++ Code 1.3:

Comparison operators for the date class

12

C++ Code 1.4

shows operations for nding previous and next date, called an

iteration

operator.

#include "date.h"

dte next dte(const dte& d){ if (!d.vlid()) { return dte(); }; GG dte ndt=dte((d.dy()+1),d.month(),d.yer()); GG (rst try dding dy if (ndt.vlid()) return ndt; ndt=dte(1,(d.month()+1),d.yer()); GG then try dding month if (ndt.vlid()) return ndt; ndt = dte(1,1,(d.yer()+1)); GG must e next yer return ndt;
}

dte previous dte(const dte& d){ if (!d.vlid()) { return dte(); }; GG return the defult dte dte pdt = dte((d.dy()1),d.month(),d.yer()); if (pdt.vlid()) return pdt; GG try sme month pdt = dte(31,(d.month()1),d.yer()); if (pdt.vlid()) return pdt; GG try previous month pdt = dte(30,(d.month()1),d.yer()); if (pdt.vlid()) return pdt; pdt = dte(29,(d.month()1),d.yer()); if (pdt.vlid()) return pdt; pdt = dte(28,(d.month()1),d.yer()); if (pdt.vlid()) return pdt; pdt = dte(31,12,(d.yer()1)); GG try previous yer return pdt;
};

dte dteXXopertor ++(int){ GG post(x opertor dte d = *this; *this = next dte(d); return d;
}

dte dteXXopertor ++(){ GG pre(x opertor *this = next dte(*this); return *this;
}

dte dteXXopertor (int){ GG post(x opertorD return urrent vlue dte d = *this; *this = previous dte(*this); return d;
}

dte dteXXopertor (){ GG pre(x opertorD return new vlue *this = previous dte(*this); return *this;
};

C++ Code 1.4:

Iterative operators for the date class

13

Exercise 1.1.
The function

vlid@A

in the date class accepts february 29'th in every year, but this should ideally only

happen for leap years. Modify the function to return a

flse

if the year is not a leap year.

Exercise 1.2.
A typical operating system has functions for dealing with dates, which your typical C++ implementation can call. Find the relevant functions in your implementation, and 1. Implement a function querying the operating system for the current date, and return this date. 2. Implement a function querying the operating system for the weekday of a given date, and return a representation of the weekday as a member of the set:

{4mon4D4tue4D4wed4D4thu4D4fri4D4st4D4sun4}
3. Reimplement the

vlid@A

function using a system call.

Exercise 1.3.
Once the date class is available, a number of obvious functions begs to be implemented. How would you 1. Add a given number of days to a date? 2. Go to the end or beginning of a month? 3. Find the distance betwen two dates (in days or in years)? 4. Extract a date from a string? (Here one need to make some assumptions about the format)

Exercise 1.4.
Take a look at how dates are dealt with in various computing environments, such as the operating system (nix,

indows),

applications (Spreadsheets), programming languages, etc. At what level of abstraction is

the interface? Do you need to know how dates are implemented? For those with access to both

indows,

why would you say that

wtl

has an o-by-one problem relative to

indows?

wtl

and

14

1.4

Const references
Consider two alternative calls to a function,

Let us now discuss a concept of more technical nature. dened by function calls:

somefuntion@doule rAY somefuntion@onst doule8 rAY


They both are called by an argument which is a double, and that argument is guaranteed to not be changed in the calling function, but they work dierently. In the rst case a copy of the variable

referenced to in the argument is created for use in the function, but in the second case one uses the same variable, the argument is a

reference

to the location of the variable. The latter is more ecient,

in particular when the argument is a large class. However, one worries that the variable referred to is changed in the function, which in most cases one do not want. Therefore the

onst

qualier, it says

that the function can not modify its argument. The compiler will warn the programmer if an attempt is made to modify such a variable. For eciency, in most of the following routines arguments are therefore given as as constant references.

1.5

Other C++ concepts

A number of other C++ concepts, such as function prototypes and templates, will be introduced later in particular contexts. They only appear in a few places and is better introduced where they are used.

15

Chapter 2

Matrix Tools
Being computer literate entails being aware of a number of computer tools and being able to choose the most suitable tool for the problem at hand. Way to many people turns this around, and want to t

any problem to the computer tool they know. The tool that very often is students is a spreadsheet like

Excel.

the

tool for business school

Of course, a spreadsheet is very useful for very many business

applications. However, it is not the best tool for more computationally intensive tasks. While the bulk of the present book concerns itself with C++, in many applications in nance a very handy tool is a language for manipulating vectors and matrices using linear algebra. There are a lot

of dierent possible programs that behaves very similarly, with a syntax taken from the mathematical formulation of linear algebra. An early tool of this sort was

matlab, with a large number of programs


sil. wtl
Tools that are similar, but more

copying much of the syntax of this program. As a result of this there is a proliferation of programs with similar syntax to

wtl

doing similar analysis. General tools include the commercial package

sold by Mathworks, the public domain programs

otve

geared towards econometrics, include Gauss, Ox and

and

with its public domain clone

As for what

program to install, there is no right answer. For the basic learning of how these tools work, any of the mentioned packages will do the job. For students on a limited budget the public domain tools

otve, sil and R are obvious candidates. All of them perform the basic operations done by the commercial wtl package, and good for learning the basics of such a matrix tool.
All of these tools are programs that lets the user manipulate vectors and matrices using very compact notation. While compact notation is always prone to tense, making programs using it unreadable, this is not such a large problem in

wtl,

the notation tends to be so close how a mathematician would

write them that programs can be relatively easy to follow. There are some pitfalls for the unwary user, in particular it is easy to miss the dierence between a command operating on a whole matrix and the corresponding element by element operation. where the operator operator For example, consider the following short example,

means that the matrix

is taken to the power 2 (multiplied with itself), and the

means that each element of the matrix

is taken to the power 2. The two commands give

very dierent answers.

bb e a I I Y I I e a I I I I bb eP ns a P P P P bb eFP ns a I I I I
The rest of this chapter gives an introduction to a tool like this.

16

2.1

The rst screen

How you start the particular tool you are using depend both on which program and which operating system you are working on. The details of how to start it is left as an exercise to the reader. The tools are interactive, they present you with a prompt, and expect you to start writing commands. We will

bb
as the prompt, which means that the program is ready to receive commands. In the text output of the matrix tool will be shown typewritten as:

bb

e a ID PD QY

RD SD T e,
the matrix tool will respond to this command by printing

This particular command denes a matrix the matrix that was just dened:

e a I P Q R S T

2.2

Linear algebra

To use such a tool you need some knowledge of linear algebra. We assume the reader have this basic knowledge, if not a quick perusal of a standard mathematical text on linear algebra is called for.

2.2.1 Basic matrix operations


In matrix algebra a set of mathematical rules are given for operating on the basic elements real numbers, vectors, and matrices. In

wtl

the type of each variable is determined when you rst dene it.

bb aI a I bb aP a P bb aQ a Q bb yaIYPYQ y a I P Q bb xaIDPDQ x a I P Q bb eaI P QYR S T e a I P Q R S T


Observe that when lling in a vector or a matrix a space or a comma means a new number, a semicolon a new row. To suppress the printing of what you just dened, end the line with a semicolon:

17

bb eaIDPDQDRY bb eaIDPDQDR e a I P Q R bb
You can also use dened variables to dene new variables, as long as the dimensions make sense. For example, given the above denitions:

bbfa f a Q I bb g a g a I P R S I P bb h a errorX errorX

x P Q eYx Q T Q e y numer of rows must mth evluting ssignment expression ner line PPD olumn Q wtl

If the dimensioning is wrong, you get an error message, and the variable is not dened. To see what is in a variable, tell to print the value by giving the name:

bb a I bb e e a I P Q R S T
Note that

wtl

is case-sensitive, both

and

are dened.

2.2.2 Arithmetic Matrix Operations.


We now get to the important parts of

wtl,

namely, its builtin matrix arithmetic. Given the de-

nitions above, let us add and subract a few elements according to the rules of matrix algebra. We rst show how to manipulate numbers and vectors:

bb aI a I bb aP a P bb C ns a Q bb xaI P x a I P bb yaR Q y a R Q bb xCy ns a

Q R Q R P I P I

18

S S S bb yEx ns a Q I EI bb BxCBy ns a W V U

S EQ T

similarly, for matrices:

eaI P QY R S T e a I P Q R S T bb faT S RY Q P I f a T S R Q P I bb eCf ns a U U U U U U bbeEf ns a ES EQ EI I Q S bb BeCBf ns a IQ IP II IH W V b eBf9 ns a PV IH UQ PV


In linear algebra, you need to be aware that matrix multiplication is not element by element multiplication, it is a much more complex operation, where all possible vector combinations are multiplied with each other. When multiplying matrices, you need to be more careful about dimensions, but in terms of notation it is just like vector multiplication.

bb eaI P QYR S T e a I P Q R S T bb f a I PYQ RY S T f a I P Q R S T bb eBf ns a PP PV RW TR


19

bb fBe ns a W IP IS IW PT QQ PW RH SI
For these matrices, both

AB

and

BA

are dened operations, but note that the results are dierent, in

fact, even the dimension of the product is dierent. If we let

be a

P P matrix, then multiplying AB is an error.

bb faI PYQ R f a I P Q R bb eBf errorX nononformnt mtries @opI is PxQD opP is PxPA bb fBe ns a W IP IS IW PT QQ
Let us now discuss some standard matrix concepts. The transpose of a matrix

is found in

wtl

as

e9:

bb e e a I P Q R S T bb e9 ns a I R P S Q T
Two special matrices are the

null

and

identity

matrices:

bb null a zeros@QDQA null a H H H H H H H H H bb ident a eye@QDQA ident a I H H H I H H H I


The

rank

of a matrix is is the number of independent rows or columns in the matrix, and calculated as

bb ehi e a I P Q R S T
20

bb rnk@eA ns a P
The

inverse

of a square matrix

or in mathematical notation

e is the matrix inv@eA AAI a I.

such that

A*inv(A) equals the identity matrix,

bb haI PYI h a I P I R bb inv@hA ns a PFHHHHH EHFSHHHH bb hEI ns a PFHHHHH EHFSHHHH

EIFHHHHH HFSHHHH EIFHHHHH HFSHHHH

To make sure that this

is

the inverse, multiply

and

inv@hA:

bb h B inv@hA ns a I H H I
Determinant

bb f f a I P Q R bb det@fA ns a EP

2.3

Solving linear equations

Consider the basic linear equation

Ax a b
This equation has a dened solution if the rank of

equals the rank of

Ajb.

If

is nonsingular, we

solve the linear equation by nding the unique solution

x a A1 b
Consider the linear equation

QxI C RxP a S RxI C TxP a V


Write this in matrix form by dening

Aa

Q R R T

21

ba S
V

Let us rst check that this system is solvable

bb e a Q RYR T e a Q R R T bb aSYV a S V bb rnk@eA ns a P bb rnk @e A ns a P


Note how to create the augmented matrix square, we can calculate the solution as

Ajb by e .

The rank of the two is the same. Since

is

bb inverse@eA ns a QFHHHH EPFHHHH EPFHHHH IFSHHH bb x a inverse@eA B x a EI P


The solution to the system of equations is

xa

I
P

In this case we calculated the solution by nding the inverse.

But you should be aware that solving

the system of equations by calculation of the inverse is not the numerically most stable way of doing the calculation. operator

wtl

has built in a direct linear matrix solver, which is invoked by the

left division

bb x a e x a EI P
This solves the system of equations directly, and it is usually the preferred way to do this operation, unless the inverse is needed for other purposes.

2.4

Element by element operations

When a command is prexed with a period, it means the command applies to each element of a vector or matrix, not the vector or matrix.

22

For example, with the two vectors below, consider the dierence in multiplying the two and doing an element by element multiplication:

b xaI P Q x a I P Q b taI P Q t a I P Q bb xBt9 ns a IR b xFBt ns a I R W


Similarly, when taking the exponent of a matrix

b eaI IYI I e a I I I I bb eIH ns a SIP SIP SIP SIP bb eFIH ns a I I I I

2.5 2.6 2.7 2.8

Function denitions m les Flow control Plotting


wtl
is its ability to produce plots graphing mathematical

A very important use for a tool like

relationships. For illustrating mathematical relations a two or three dimensional picture than the thousands words of the old adage.

can

be better

2.9 2.10

Libraries References

You need the manual for your chosen package.

23

Chapter 3

The value of time


Contents
3.1 3.2 3.3 3.4 Present value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . One interest rate with annual compounding . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 25

3.2.1 3.3.1

Internal rate of return. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Present value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

28
32

Continously compounded interest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Further readings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

33
33

Finance as a eld of study is sometimes somewhat ippantly said to deal with the value of two things:

time

and

risk.

While this is not the whole story, there is a deal of truth in it. These are the two issues

which is always present. We start our discussion by ignoring risk and only considering the implications of the fact that anybody prefers to get something earlier rather than later, or the value of time.

3.1

Present value

t.

The present value is the current value of a stream of future payments. Let Suppose we have

future cash ows that occur at times

tI ; tP ; ; tN .
tN

Ct

be the cash ow at time

C1
0
To nd the

C2
t2

CN

t1

E
time

present value of these future cash ows one need a set of prices of future cash ows. Suppose dt is the price one would pay today for the right to receive one dollar at a future date t. Such a price is also called a discount factor. To complicate matters further such prices will dier depending on the
riskiness of the future cash ows. For now we concentrate on one particular set of prices, the prices of

riskless

future cash ows. We will return to how one would adjust the prices for risky cash ows.

If one knows the set of prices for future claims of one dollar,

dI ; dP ; : : : ;, one would calculate the present

value as the sum of the present values of the dierent elements.

PV a

N iaI

dti Cti
Ct1
0

Ct2
t2

CtN
tN

t1

E
time

dt1 Ct1 dt2 Ct2 dtN CtN

' '

'

However, knowing this set of current prices for cash ows at all future dates is not always feasible, and some way has to be found to simplify the data need inherent in such general present value calculations.

24

3.2

One interest rate with annual compounding

The best known way to simplify the present value calculation is to rewrite the discount factors in terms of interest rates, or yields, through the relationship:

dt a
where

I @I C rt At

rt is the interest rate (usually termed the spot rate) relevant for a t-period investment. To further r is constant for all periods. This is termed a at term structure. We will in the next chapter relax this simplifying assumption. The prices for valuing the future payments dt is calculated from this interest rate:
simplify this calculation one can impose that this interest rate

dt a

I ; @I C rAt
as

In this case one would calculate the present value of a stream of cash ows paid at discrete dates

t a I; P; : : : N PV a

@I C rAt taI

Ct

:
C++ Code 3.1.

The implementation of this calculation is shown in

#include <mth> #include <vetor> using namespace std; #include <iostrem> double sh )ow pv disrete(const vetor<double>& )ow times, const vetor<double>& )ow mounts, const double& r){ double =0.0; for (int t=0; t<)ow times.size();t++) { += )ow mounts[t]/pow(1.0+r,)ow times[t]);
};

return ;
};

C++ Code 3.1: Example

Present value with discrete compounding

An investment project has an investment cost of 100 today, and produces cash ows of 75 each of the next two years. What is the Net Present Value of the project?

25

wtl

program:

g=[100 75 75] t=[0 1 2] r = 0.1 d=(1/(1+r)).^t x=g*d'


Output from

wtl

program:

g a EIHH US US t a H I P r a HFIHHHH d a IFHHHHH HFWHWHW HFVPTRS x a QHFITS


C++ program:

vetor<double> )ows; )ows.push k(100.0); )ows.push k(75); )ows.push k(75); vetor<double> times; times.push k(0.0); times.push k(1); times.push k(2); double r=0.1; out << " Present value, 10 percent discretely compounded interest = " << sh )ow pv disrete(times, )ows, r) << endl;
Output from C++ program:

resent vlueD IH perent disretely ompounded interest a QHFITSQ


Given the assumption of a discrete, annual interest rate, there are a number of useful special cases of cash ows where one can calculate the present value in a simplied manner. Some of these are shown in the following exercises.

Exercise 3.1.
A perpetuity is a promise of a payment of a xed amount there is a xed interest rate

r.

each period for the indenite future. Suppose

1. Show that the present value of this sequence of cash ows is calculated simply as

PV a
Exercise 3.2.
A

ICr taI

X r X and g, i.e, the time 2 payment is X @IC gA, the time 3 payment

growing perpetuity

is again an innite sequence of cashows, where the payment the rst year is

each consequent payment grows by a constant rate is

X @I C gAP , and so on.


I

1. Show that the present value of this perpetuity simplies to

PV a
Exercise 3.3.
An

X X @I C gAtI a I t @I C rA rg taI T
periods into the future. Consider

annuity

is a sequence of cashows for a given number of years, say

an annuity paying a xed amount

each period. The interest rate is

r.

26

1. Show that the present value of this sequence of cash ows can be simplied as

PV a
Exercise 3.4.
An

T taI

@I C rAt

aX

I I r r @I C rAT

growing annuity

is a sequence of cashows for a given number of years, say

where each payment grows by a given factor each year. Consider a period. After that, the payments grows at a rate of the third

X @I C gAP , and so on.


T

g per year, i.e.

T periods into the future, T -period annuity that pays X the rst the second year the cash ow is X @I C g A,

1. Show that the present value of this growing annuity can be simplied as

X @I C gA@tIA I PV a aX ICg t @I C rA rg ICr taI




T

rg

Exercise 3.5.
Rank the following cash ows in terms of present value. Use an interest rate of 5%. 1. A perpetuity with an annual payment of $100. 2. A growing perpetuity, where the rst payment is $75, and each subsequent payment grows by 2%. 3. A 10-year annuity with an annual payment of $90. 4. A 10 year growing annuity, where the rst payment is $85, and each subsequent payment grows by 5%.

27

3.2.1 Internal rate of return.


In addition to its role in simplifying present value calculations, the interest rate has some further use. The percentage return on an investment is a summary measure of the investment's protability. Saying that an investment earns 10% per year is a good way of summarizing the cash ows in a way that does not depend on the amount of the initial investment. The return is thus a relative measure of protability. To estimate a return for a set of cash ows we calculate the

internal rate of return.

The internal

rate of return for a set of cash ows is the interest rate that makes the present value of the cash ows equal to zero. When there is a uniquely dened internal rate of return we get a relative measure of the protability of a set of cash ows, measured as a return, typically expressed as a percentage. Note some of the implicit assumptions made here. We assume that the same interest rate applies at all future dates (i.e. a at term structure). The IRR method also assumes intermediate cash ows are reinvested at the internal rate of return. Suppose the cash ows are of the equation

CH ; CI ; CP ; : : : CT .

Finding an internal rate of return is nding a solution

@I C y At taI

Ct

CH a H
T
becomes large, there in no way to nd an explicit

Note that this is a polynomial equation, and as

solution to the equation. It therefore needs to be solved numerically. For well behaved cash ows, where we know that there is one IRR, the method implemented in process called bisection.

C++ Code 3.2

is suitable, it is an iterative

It is an adaption of the bracketing approach discussed in (Press, Teukolsky,

Vetterling, and Flannery, 1992, Chapter9),

28

#include <mth> #include <lgorithm> #include <vetor> using namespace std; #include "fin_recipes.h"
const double iy=

1e30;
{

double sh )ow irr disrete(const vetor<double>& )ow times, const vetor<double>& )ow mounts)

GG simple minded irr funtionF ill (nd one root @if it existsFA GG dpted from routine in xumeril eipes in gF if ()ow times.size()!=)ow mounts.size()) return iy; const double eggeg = 1.0e5; const int we siesyx = 50; double xI = 0.0; double xP = 0.2;

GG rete n initil rketD with root somewhere etween otDtop double fI = sh )ow pv disrete()ow times, )ow mounts, xI); double fP = sh )ow pv disrete()ow times, )ow mounts, xP); int i; for (i=0;i<we siesyx;i++) { if ( (fI*fP) < 0.0) { break; }; GG if (fs(fI)<fs(fP)) { fI = sh )ow pv disrete()ow times,)ow mounts, xI+=1.6*(xIxP));
}

else
};

fP

sh )ow pv disrete()ow times,)ow mounts, xP+=1.6*(xPxI));

if (fP*fI>0.0) { return iy; }; double f = sh )ow pv disrete()ow times,)ow mounts, xI); double rt; double dx=0; if (f <0.0) {

};

rt = xI; dx=xPxI;

else

rt = xP; dx = xIxP; dx *= 0.5; double x mid = rt+dx; double f mid = sh )ow pv disrete()ow times,)ow mounts, x mid); if (f mid<=0.0) { rt = x mid; } if ( (fs(f mid)<eggeg) j j (fs(dx)<eggeg) ) return x mid;

};

for (i=0;i<we siesyx;i++){

}; };

return iy; GG errorF

C++ Code 3.2:

Estimation of the internal rate of return

29

Example
We are considering an investment with the following cash ows at dates

H, I and P:

CH a IHH; CI a IH; CP a IIH


1. The current interest rate (with discrete, annual compounding) is 5%. Determine the present value of the cash ows. 2. Find the internal rate of return of this sequence of cash ows.

wtl

program:

g=[100 10 110] t=[0 1 2] r = 0.05 d=(1/(1+r)).^t x=g*d' s = irr(g)


Output from

wtl

program:

g a EIHH IH IIH t a H I P r a HFHSHHHH d a IFHHHHH HFWSPQV HFWHUHQ x a WFPWUI s a HFIHHHHH


C++ program:

vetor<double> )ows; )ows.push k(100.0); )ows.push k(10.0); )ows.push k(110.0); vetor<double> times; times.push k(0.0); times.push k(1); times.push k(2); double r=0.05; out << " present value, 5 percent discretely compounded interest = " ; out << sh )ow pv disrete(times, )ows, r) << endl; out << " internal rate of return, discrete compounding = "; out << sh )ow irr disrete(times, )ows) << endl;
Output from C++ program:

present vlueD S perent disretely ompounded interest a WFPWUHS internl rte of returnD disrete ompounding a HFI

30

In addition to the above economic qualications to interpretations of the internal rate of return, we also have to deal with technical problem stemming from the fact that any polynomial equation has potentially several solutions, some of which may be imaginary. By imaginary here we mean that we move away from the real line to the set of complex numbers. In economics we prefer the real solutions, complex interest rates are not something we have much intuition about... To see whether we are likely to have problems in identifying a single meaningful IRR, the code shown in code 3.3 implements a simple check. It is only a necessary condition for a unique IRR, not sucient, so you may still have a well-dened IRR even if this returns false. The rst test is just to count the number of sign changes in the cash ow. From Descartes rule we know that the number of real roots is one if there is only one sign change. If there is more than one change in the sign of cash ows, we can go further and check the for sign changes (See Norstrom (1972)).

aggregated

cash ows

#include <mth> #include <vetor> using namespace std;


inline int sgn(const double& r){ if (r>=0) {return
1;}

else {return

1;}; };

bool sh )ow unique irr(const vetor<double>& )ow times, const vetor<double>& )ow mounts) { int sign hnges=0; GG (rst hek hesrtes rule for (int t=1;t<)ow times.size();++t){ if (sgn()ow mounts[t 1]) !=sgn()ow mounts[t])) sign hnges++;

if (sign hnges==0) return false; GG n not (nd ny irr if (sign hnges==1) return true; double e
= )ow mounts[0]; GG hek the ggregte sh )owsD due to xorstrom sign hnges=0; for (int t=1;t<)ow times.size();++t){ if (sgn(e) != sgn(e+=)ow mounts[t])) sign hnges++; };

};

if (sign hnges<=1) return true; return false;


}

C++ Code 3.3:

Test for uniqueness of IRR

A better way to gain an understanding for the relationship between the interest rate and the present value is simply to plot the present value as a function of the interest rate. The following picture illustrates the method for two dierent cash ows. Note that the set of cash ows on the right has two possble interest rates that sets the present value equal to zero.

10 pv(r) 0

2 pv(r) 0 1

5 0

0 -1

-2 -5

-3 -10 -4

-15 0 0.02 0.04 0.06 0.08 0.1 0.12

-5 -0.2

-0.15

-0.1

-0.05

0.05

0.1

0.15

0.2

CH a IHH; CI a IH; CP a IHH

CH a IHH; CI a PHI; CP a IHH

31

Exercise 3.6.
An alternative way of estimating the IRR is to use an external subroutine that nds the root of a polynomial equation. Search for a suitable general subroutine for root nding and replace the IRR estimation with a call to this subroutine.

3.3

Continously compounded interest

Such discrete compounding as we have just discussed is not the only alternative way to approximate the discount factor. The discretely compounded case assumes that interest is added at discrete points in time (hence the name). However, an alternative assumption is to assume that interest is added continously. If compounding is continous, and one dollar at a future date

t as

r is the interest rate, one would calculate the current price dt of reciving

dt a ert ;
Formula 3.1 summarizes some rules for translating between continously compounded and discretly compounded interest rates.

r a n ln I C

rn  n

rn a n e n I
Future value Present value

a ert a ert

Notation: rn : interest rate with discrete compounding, n: compounding periods per year. r: interest rate with continuous compounding, t: time to maturity.

Formula 3.1: Example

Translating between discrete and continous compounding

1. Given a 15% interest rate with monthly compounding, calculate the equivalent interest rate with continuous compounding. 2. Given a 12% interest rate with continuous compounding, nd the equivalent interest rate with quarterly compounding. Carrying out the calculations: 1. 2. Using

:IS rIP a IS7, r a IP ln I C HIP a IR:WI7

r r a IP7 , rR a n e n I a R e 0:412 I a IP:IV7

wtl

to do the calculations:

wtl
r rR

program:

= 12 * = 4 * (

log( 1+0.15/12) exp(0.12/4) 1 )

Output from

wtl

program:

r a HFIRWHU rR a HFIPIVP
32

3.3.1 Present value


Applying this to a set of cash ows at future dates calculation:

tI ; tP ; : : : ; tn ,

we get the following present value

PV a

n iaI

erti Cti
C++ Code 3.4.

This calculation is implemented in

#include <mth> #include <vetor> using namespace std;


double sh )ow pv( const vetor<double>& )ow times, const vetor<double>& )ow mounts, const double& r){ double =0.0; for (int t=0; t<)ow times.size();t++) {

+=

)ow mounts[t]

exp(r*)ow times[t]);

};

return ;
};

C++ Code 3.4:

Present value calculation with continously compounded interest There is a

In much of what follows we will work with the case of continously compounded interest.

number of reasons why, but a prime reason is actually that it is easier to use continously compounded interest than discretely compounded, because it is easier to deal with uneven time periods. Discretely compounded interest is easy to use with evenly spaced cash ows (such as annual cash ows), but harder otherwise.

3.4

Further readings

The material in this chapter is covered in most standard textbooks of corporate nance (e.g. Brealey and Myers (2002) or Ross, Westereld, and Jae (2005)) and investments (e.g. Bodie, Kane, and Marcus (2005), Haugen (2001) or Sharpe, Alexander, and Bailey (1999)).

33

Chapter 4

Bond Pricing with a at term structure


Contents
4.1 Flat term structure with discrete, annual compounding . . . . . . . . . . . . . . . . . . . . . . 34

4.1.1 4.1.2 4.1.3 4.1.4


4.2 4.3

Bond Price . . . . . . . . . . Yield to maturity . . . . . . . Duration . . . . . . . . . . . Measuring bond sensitivity to

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . interest rate changes

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

35 35 38 40
44 47

Continously compounded interest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Further readings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

In this section we use the present value framework of the previous chapter to price bonds and other xed income securities. What distinguishes bonds is that the future payments are set when the security is issued. The simplest, and most typical bond, is a xed interest, constant maturity bond with no default risk. There is however a large number of alternative contractual features of bonds. The bond could for example ba an annuity bond, paying a xed amount each period. For such a bond the principal amount outstanding is paid gradually during the life of the bond. The interest rate the bond pays need not be xed, it could be a oating rate, the interest rate paid could be a function of some market rate. Many bonds are issued by corporations, and in such cases there is a risk that the company issued the bond defaults, and the bond does not pay the complete promised amount. Another thing that makes bond pricing dicult in practice, is that interest rates tend to change over time. We start by assuming that all the promised payments are certain. Then the bond current price

BH is found as the present value of these payments. T


periods from now.

The rst step of pricing

is to use the terms of the bond to nd the promised payments. We start by considering a xed interest bond with no default risk. Such bonds are typically bonds issued by governments. The bond is a promise to pay a face value

at the maturity date

percentage amount of the face value as coupon

C.
Q

Each period the bond pays a xed

The cash ows from the bond thus look as follows.

ta
Coupon Face value Total cash ows

CI a C CP a C
T taI

T C F CT a C C F

In general a bond price is found as the present value

BH a dI CI C dP CP C C dT CT a
where

dt Ct dt . t.
To fully specify the In this chapter we will work with a specially simple

dt

is the discount factor, or the time 0 price of a payment of 1 at time

problem it is necessary to nd all discount factors

speciction of the term structure, namely that it is at, and specied by the interest rate

r.

4.1

Flat term structure with discrete, annual compounding


 t

This is the simplest possible specication of a term structure,

I dt a ICr

I @I C rAt
34

4.1.1 Bond Price


The current bond price (

BH ) is the present value of the cash ows from the bond



(4.1)

T I Ct BH a Ct a @I C rAt @I C rAt taI taI

T 

CT a C C F , and show how the bond price will be calculated using wtl.
Example

If we continue with the example of a standard xed interest bond, where

Ct a C

when

t<T

and

A 3 year bond with a face value of $100 makes annual coupon payments of 10%. The current interest rate (with annual compounding) is 9%. 1. Determine the current bond price. The current bond price:

IH IIH IH BH a @ICH:HWA1 C @ICH:HWA2 C @ICH:HWA3 a IHP:SQI.

Here are the calculations:

wtl

program:

g =[10,10,110] t = 1:3 r = 0.09 d=(1./(1+r).^t) f= d * g'


Output from

wtl

program:

g a IH IH IIH t a I P Q r a HFHWHHHH d a HFWIURQ HFVRITV HFUUPIV f a IHPFSQ


C++ program:

vetor<double> )ows; )ows.push k(10); )ows.push k(10); )ows.push k(110); vetor<double> times; times.push k(1); times.push k(2); times.push k(3); double r=0.09; out << " bonds price = " << onds prie disrete(times, )ows, r) << endl;
Output from C++ program:

onds prie
C++ Code 4.1. 4.1.2 Yield to maturity

a IHPFSQI

The general code in C++ for calculating the bond price with discrete annual compounding is shown in

Since bonds are issued in terms of interest rate, it is also useful to nd an interest rate number that summarizes the terms of the bond. The obvious way of doing that is asking the question: What is the internal rate of return on the investment of buying the bond now and keeping the bond to maturity?

35

#include <mth> #include <vetor> using namespace std;


double onds prie disrete(const vetor<double>& times, const vetor<double>& sh)ows, const double& r) { double p=0; for (int i=0;i<times.size();i++) {

+=

sh)ows[i]/(pow((1+r),times[i]));

};

return p;
};

C++ Code 4.1:

Bond price calculation with discrete, annual compounding.

The answer to that question is the yield to maturity of a bond. The yield to maturity is the interest rate that makes the present value of the future coupon payments equal to the current bond price, that is, for a known price

BH , the yield is the solution y to the equation

BH a

@I C y At taI

Ct

(4.2)

This calculation therefore has the same qualications as discussed earlier calculating IRR, it supposes reinvestment of coupon at the bond yield (the IRR). There is much less likelihood we'll have technical problems with multiple solutions when doing this yield estimation for bonds, since the structure of cash ows is such that there exist only one solution to the equation. The algorithm for nding a bonds yield to maturity shown in

C++ Code 4.2

is thus simple

bisection. We know that the bond yield is above zero and set zero as a lower bound on the bond yield. We then nd an upper bound on the yield by increasing the interest rate until the bond price with this interest rate is negative. We then bisect the interval between the upper and lower until we are close enough.

C++ Code 4.2

implements this idea.

#include <mth> using namespace std; #include "fin_recipes.h"


double onds yield to mturity disrete( const vetor<double>& times, const vetor<double>& sh)ows, const double& ondprie) { const double eggeg = 1e 5; const int we siesyx = 200; double ot=0, top=1.0; while (onds prie disrete(times, sh)ows, top) > ondprie) { top = top*2; double r = 0.5 * (top+ot); for (int i=0;i<we siesyx;i++){ double di' = onds prie disrete(times, sh)ows,r) ondprie; if (fs(di' )<eggeg) return r; if (di' >0.0) { ot=r;} else { top=r; };

};

= 0.5 * (top+ot);

};

return r;
};

C++ Code 4.2:

Bond yield calculation with discrete, annual compounding

36

Example
A 3 year bond with a face value of $100 makes annual coupon payments of 10%. The current interest rate (with annual compounding) is 9%. 1. Find the bond's current price. 2. Find the bond's yield to maturity.

wtl

program:

g = [ 10 10 110 ]; t = 1:3; r=0.09; f = g * (1./((1+r).^t))' y = irr([f g ])


Output from

wtl

program:

f a IHPFSQ y a HFHWHHHH
C++ program:

vetor<double> )ows; )ows.push k(10); )ows.push k(10); )ows.push k(110); vetor<double> times; times.push k(1); times.push k(2); times.push k(3); double r=0.09; double f = onds prie disrete(times, )ows, r); out << " Bond price, 9 percent discretely compounded interest = " << f << endl; out << " bond yield to maturity = " << onds yield to mturity disrete(times, )ows, f) << endl;
Output from C++ program:

fond prieD W perent disretely ompounded interest a IHPFSQI ond yield to mturity a HFHW

37

4.1.3 Duration
When holding a bond one would like to know how sensitive the value of the bond is to changes in economic environment. The most relevent piece of the economic environment is the current interest

rate. An important component of such calculation is the

duration

of a bond. The duration of a bond

should be interpreted as the weighted average maturity of the bond, and is calculated as

Duration

Ct t t @ICrAt
Bond Price

; t,
and

(4.3)

where

Ct

is the cash ow in period

the interest rate.

Using the bond price calculated in

equation 4.1 we calculate duration as

Da

t t

@ICrtAt C @ICtrAt
C++ Code 4.3.

tC

(4.4)

which is shown in

#include <mth> #include <vetor> using namespace std;


double onds durtion disrete(const vetor<double>& times, const vetor<double>& sh)ows, const double& r) { double f=0; double h=0; for (int i=0;i<times.size();i++){

h f

+= +=

times[i] * sh)ows[i] / pow(1+r,times[i]); sh)ows[i] / pow(1+r,times[i]);

};

return h/f;
};

C++ Code 4.3:

Bond duration using discrete, annual compounding and a at term structure

An alternative approach to calculating duration is calculate the yield to maturity use that in estimating the bond price. This is called yield to maturity, from

Macaulay Duration.

for the bond, and

First one calculates

y,

the

Bond price

@I C y At taI
t t
t @ICyAt C @ICtyAt

Ct

and then use this

y in the duration calculation:


a
tC
(4.5)

Macaulay duration

C++ Code 4.4

implements this calculation.

Note though, that in the present case, with a at term structure, these should produce the same number. If the bond is priced correctly, the yield to maturity must equal the current interest rate. If two calculations in equations (4.4) and (4.5) obviously produces the same number.

ray

the

Example
A 3 year bond with a face value of $100 makes annual coupon payments of 10%. The current interest rate (with annual compounding) is 9%.

38

#include "fin_recipes.h"
double onds durtion muly disrete(const vetor<double>& times, const vetor<double>& sh)ows, const double& ond prie) { double y = onds yield to mturity disrete(times, sh)ows, ond prie); return onds durtion disrete(times, sh)ows, y); GG use w in durtion lultion
};

C++ Code 4.4:

Calculating the Macaulay duration of a bond

1. Determine the current bond price. 2. Calculate the duration using the current interest rate. 3. Calculate the duration using the MaCaulay denition. Need to calculate the following: The current bond price: The bond's duration:

IH IH IIH BH a @ICH:HWA1 C @ICH:HWA2 C @ICH:HWA3 a IHP:SQI. IIH IH D a IHPISQI I:HW C IP:HW2 C Q:IIH a P:UR : I HW3

wtl

program:

g =[10,10,110]; t = 1:3; r = 0.09; f= g * (1./(1+r).^t)' h= (1/f)*t.* g * (1./(1+r).^t)' y = irr([f g ]) hw= (1/f)*t.* g * (1./(1+y).^t)'
Output from

wtl

program:

f a IHPFSQ h a PFUQWH y a HFHWHHHH hw a PFUQWH


C++ program:

vetor<double> )ows; )ows.push k(10); )ows.push k(10); )ows.push k(110); vetor<double> times; times.push k(1); times.push k(2); times.push k(3); double r=0.09; double f = onds prie disrete(times, )ows, r); out << " bonds price = " << f << endl; out << " bond duration = " << onds durtion disrete(times, )ows, r) << endl; out << " bond macaulay = " << onds durtion muly disrete(times, )ows, f) << endl;
Output from C++ program:

onds prie a IHPFSQI ond durtion a PFUQVWS ond muly a PFUQVWS

39

4.1.4 Measuring bond sensitivity to interest rate changes


Now, the reason for why we say that we can measure the sensitivity of a bond price using duration. To a rst approximation, be calculated

BH , the change in the bond price for a small change in the interest rate r, can

% I D r r BH C where D is the bond's duration. For simplicity one often calculates the term in front of the y D above, ICy directly and terms it the bond's modied duration.
BH
Modied Duration

in the

a D a

ICr

The sensitivity calculation is then

BH

BH

% D r
y, and is then D

The modied duration is also written in term's of the bond's yield to maturity

D a
C++ Code 4.5

ICy
shows this calculation.

#include <vetor> using namespace std; #include "fin_recipes.h"


double onds durtion modi(ed disrete (const vetor<double>& times, const vetor<double>& sh)ows, const double& ond prie){ double y = onds yield to mturity disrete(times, sh)ows, ond prie); double h = onds durtion disrete(times, sh)ows, y); return h/(1+y);
};

C++ Code 4.5:

Modied duration

Approximating bond price changes using duration is illustrated in the following gure.

T
bond price

d d d d d d d d d d d d
yield Duration measures of tangent.

'angle E

40

The modied duration measures the angle of the tangent at the current bond yield.

Approximating

the change in bond price with duration is thus only a rst order approximation. To improve on this approximation we also need to account for the curvature in the relationship between bond price and interest rate. To quantify this curvature we calculate the

convexity

of a bond.

Convexity

a Cx a

T I Ct @t C tP A BH @I C rAP taI @I C rAt

(4.6)

This calculation is implemented in

C++ Code 4.6.

To improve on the estimate of how the bond price

#include <mth> #include "fin_recipes.h"


double onds onvexity disrete(const vetor<double>& times, const vetor<double>& sh)ows, const double& r) { double gx=0; for (int i=0;i<times.size();i++){
};

gx+= sh)ows[i]*times[i]*(times[i]+1)/(pow((1+r),times[i]));

double f=onds prie disrete(times, sh)ows, r); return (gx/(pow(1+r,2)))/f;


};

C++ Code 4.6:

Bond convexity with a at term structure and annual compounding

change when the interest rates changes you will then calculate

BH

BH

% D y C I Cx @yAP P
@BH )
T
Modied duration

Formula 4.1 summarizes the above calculations.

Bond Price

BH a

@I C rAt taI
T

Ct

D a
Convexity

ICy

Yield to maturity

y solves

@CxA
T I Ct @t C tP A BH @I C rAP taI @I C rAt

BH a
Duration

@D A I

Ct @I C y At taI
T

Cx a

Da

tCt BH taI @I C rAt tCt BH taI @I C yAt


I
T

Approximating bond price changes

BH

Macaulay duration

BH BH

% D y
I % D y C P Cx @yAP

Da

BH

Ct : Cash ow at time t, r: interest rate, y: bond yield to maturity, B0 : current bond price. Bond pays coupon at evenly spaced dates t a I; P; Q : : : ; T .

Formula 4.1:

Bond pricing formulas with a at term structure and discrete, annual compounding

41

Example
A 3 year bond with a face value of $100 makes annual coupon payments of 10%. The current interest rate (with annual compounding) is 9%. 1. Determine the current bond price. 2. Suppose the interest rate changes to 10%, determine the new price of the bond by direct calculation. 3. Use duration to estimate the new price and compare it to the correct price. 4. Use convexity to improve on the estimate using duration only. Need to calculate the following: The current bond price:

IH IH IIH BH a @ICH:HWA1 C @ICH:HWA2 C @ICH:HWA3 a IHP:SQI. I IIH C PIH2 C QIIH a P:UR The bond's duration: D a 3 IP I D IHP:SQI a:HW:UR a:HW:SI. I:HW The modied duration: D a ICr IHW P : @ICIAIH C @P2 CPA2IH C @QCQ2 A3IIH  a V:WQ. I 2 I The convexity: Cx a @ICH:HWA IHP:SQI I:HW I:HW I:HW
Here are the calculations:

wtl

program:

g =[10,10,110]; t = 1:3; r = 0.09; f= g * (1./(1+r).^t)' h= (1/f)*t.* g * (1./(1+r).^t)' gx= (1/(1+r)^2) * (1/f)*t.^2.*g newf=g* (1./(1+0.1).^t)'
Output from

* (1./(1+r).^t)'

wtl

program:

f a IHPFSQ h a PFUQWH gx a TFTPUP newf a IHHFHH


C++ program:

vetor<double> )ows; )ows.push k(10); )ows.push k(10); )ows.push k(110); vetor<double> times; times.push k(1); times.push k(2); times.push k(3); double r=0.09; double f = onds prie disrete(times, )ows, r); out << " bonds price = " << f << endl; out << " bond duration = " << onds durtion disrete(times, )ows, r) << endl; out << " bond duration modified = " << onds durtion modi(ed disrete(times, )ows, f) << endl; out << " bond convexity =" << onds onvexity disrete(times, )ows, r) << endl; out << " new bond price = " << onds prie disrete(times, )ows, 0.1);
Output from C++ program:

onds prie a IHPFSQI ond durtion a PFUQVWS ond durtion modified a PFSIPV ond onvexity aVFWQPRV new ond prie a IHH

42

Using these numbers to answer the questions, let us see what happens when the interest rate increases to 10%. This means the bond will be selling at par, equal to 100, which can be conrmed with direct computation:

C C a IHH BH a @I C H:IAI @I C H:IAP @I C H:IAQ


Using duration to estimate the change in the bond price for a unit change in the interest rate:

IH

IH

IIH

BH

BH

a D y a P:SI H:HI a H:HPSI


 

Using this duration based number to estimate the new bond price.

BH B a BH C BH a IHP:SQI H:HPSI IHP:SQI a WW:WSU

BH

Additionally using convexity in estimating the change in the bond price:

BH

BH

I I a D y C Cx y P a P:SI H:HI C V:WQ@H:HIAP a H:HPSI C H:HHHRR a H:HPRTS P P


   

BH B a IHP:SQI I C BH a IHP:SQI@I H:HPRTSA a IHH:HHQT

BH

Exercise 4.1.

Perpetual duration [4]


The term structure is at with annual compounding. Consider the pricing of a perpetual bond. Let per period cash ow

C be the

BH a

@I C rAt taI

C r

1. Determine the rst derivative of the price with respect to the interest rate. 2. Find the duration of the bond.

Exercise 4.2.
[5] Consider an equally weighted portfolio of two bonds, A and B. Bond A is a zero coupon bond with 1 year to maturity. Bond B is a zero coupon bond with 3 years to maturity. Both bonds have face values of 100. The current interest rate is 5%. 1. Determine the bond prices. 2. Your portfolio is currently worth 2000. Find the number of each bond invested. 3. Determine the duration of the portfolio. 4. Determine the convexity of your position.

43

4.2

Continously compounded interest

We will go over the same concepts as covered in the previous section on bond pricing. There are certain subtle dierences in the calculations. Formula 4.2 corresponds to the earlier summary in formula 4.1.

Bond Price

BH : BH a erti A Cti

Convexity

Cx: BH
I

Yield to maturity

y solves: BH a Cti eyti D:


i

Cx a

Cti tP erti i

Approximating bond price changes

Duration

Da Da

BH BH
I

ti Cti erti ti Cti eyti

BH

BH BH

% Dy
I % Dy C P Cx @yAP

Macaulay duration

BH

Bond paying cash ows Ct1 ; Ct2 ; : : : at times t1 ; t2 ; : : :. Notation: B0 : current bond price. e: natural exponent.

Formula 4.2:

Bond pricing formulas with continously compounded interest and a at term structure

Some important dierences is worth pointing out. When using continously compounded interest, one does not need the concept of

modied duration.

In the continously compounded case one uses the

calculated duration directly to approximate bond changes, as seen in the formulas describing the approximation of bond price changes. Note also the dierence in the divide by

@I C y AP

convexity

calculation, one does not

in the continously compounded formula, as was done in the discrete case. and

C++ Code 4.7, C++ Code 4.8, C++ Code 4.9

C++ Code 4.10

show continously compounded analogs of the

earlier codes for the discretely compounded case.

#include <mth> #include <vetor> using namespace std;


double onds prie(const vetor<double>& sh)ow times, const vetor<double>& sh)ows, const double& r) { double p=0; for (int i=0;i<sh)ow times.size();i++) {

+=

exp(r*sh)ow times[i])*sh)ows[i];

};

return p;
};

C++ Code 4.7:

Bond price calculation with continously compounded interest and a at term structure

44

#include <mth> #include <vetor> using namespace std;


double onds durtion(const vetor<double>& sh)ow times, const vetor<double>& sh)ows, const double& r) { double =0; double hI=0; for (int i=0;i<sh)ow times.size();i++){

+= sh)ows[i] * exp(r*sh)ow times[i]); hI += sh)ow times[i] * sh)ows[i] * exp(r*sh)ow times[i]);


/

};

return hI
};

C++ Code 4.8:

Bond duration calculation with continously compounded interest and a at term structure

#include "fin_recipes.h"
double onds durtion muly(const vetor<double>& sh)ow times, const vetor<double>& sh)ows, const double& ond prie) { double y = onds yield to mturity(sh)ow times, sh)ows, ond prie); return onds durtion(sh)ow times, sh)ows, y); GG use w in durtion
};

C++ Code 4.9:

Calculating the Macaulay duration of a bond with continously compounded interest and a

at term structure

#include <mth> #include "fin_recipes.h"


double onds onvexity(const vetor<double>& times, const vetor<double>& sh)ows, const double& r ) { double g=0; for (int i=0;i<times.size();i++){

+=

sh)ows[i]

pow(times[i],2)

exp(r*times[i]);

};

double f=onds prie(times, sh)ows,r); return g/f;


};

C++ Code 4.10:

Bond convexity calculation with continously compounded interest and a at term structure

45

Example
A 3 year bond with a face value of $100 makes annual coupon payments of 10%. The current interest rate (with continous compounding) is 9%. 1. Calculate the bond's price, yield to maturity, duration and convexity. 2. Suppose the interest rate falls to 8%. Estimate the new bond price using duration, and compare with the actual bond price using the correct interest rate. Calculations:

wtl

program:

g =[10,10,110] t = 1:3 r = 0.09 d=(1./(1+r).^t) f = g * d' h=1/f*g.*t*d' hdj=h/(1+r) r=0.1 tulf = g*(1./(1+r).^t)'
Output from

wtl

program:

g a IH IH IIH t a I P Q r a HFHWHHHH d a HFWIURQ HFVRITV HFUUPIV f a IHPFSQ h a PFUQWH hdj a PFSIPV r a HFIHHHH tulf a IHHFHH
C++ program:

vetor<double> )ows; )ows.push k(10); )ows.push k(10); )ows.push k(110); vetor<double> times; times.push k(1); times.push k(2); times.push k(3); double r=0.09; double f = onds prie(times, )ows, r); out << " bonds price = " << f << endl; out << " bond duration = " << onds durtion(times, )ows, r) << endl; out << " bond convexity =" << onds onvexity(times, )ows, r) << endl; out << " new bond price = " << onds prie(times, )ows, 0.08);
Output from C++ program:

onds prie ond durtion ond onvexity new ond prie


Exercise 4.3.

a IHIFRTR a PFUQUSQ aUFVTUUW a IHRFPVP

46

I I D a B0 i ti Cti erti and the Macaulay dention: D a B0 i ti Cti eyti , where BH is the current bond price, Cti is the coupon payment at date ti , r is the current interest rate and y is the bond's yield to
denition maturity. 1. Show that these two denitions will produce the same number if the bond is correctly priced.

The term structure is at, and compounding is continous. Consider two denitions of duration, the usual

4.3

Further readings

The material in this chapter is covered in most standard textbooks on investments (e.g. Bodie et al. (2005), Haugen (2001) or Sharpe et al. (1999)). More details can be found in textbooks on xed income, such as Sundaresan (2001).

47

Chapter 5

The term structure of interest rates and an object lesson


Contents
5.1 5.2 The interchangeability of discount factors, spot interest rates and forward interest rates . . . . . The term structure as an object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 51

5.2.1 5.2.2
5.3

Base class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Flat term structure. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Linear Interpolation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Interpolated term structure class. . . . . . . . . . . . . . . . . . . . . . . . . . .

51 53
54

Using the currently observed term structure. . . . . . . . . . . . . . . . . . . . . . . . . . . .

5.3.1 5.3.2
5.4

55 57
60

Bond calculations with a general term structure and continous compounding . . . . . . . . . . .

In this chapter we expand on the analysis of the previous chapter by relaxing the one interest rate assumption used there and allow the spot rates to change as you change the time you are discounting over. Recall that we said that the present value of a set of cash ows is calculated as

PV a

N iaI

dti Cti
Ct1
0

Ct2
t2

CtN
tN

t1

E
time

dt1 Ct1 dt2 Ct2 dtN CtN

' '

'

To make this applicable to cash ows received at any future date number of discount factors approximate interest rate

dt , but with more exibility than the extremely strong assumption that there is one xed r, and that the discount factor for any time t is calculated as either dt a I=@I C rAt (discrete rt (continuous compounding), which we used in the previous chapter. compounding), or dt a e
In this chapter we rst show that this approximation of the discount factors can be done in either terms of discount factors directly, interest rates, or forward rates. Either of these are useful ways of formulating a term structure, and either of them can be used, since there are one to one transformations between either of these three. We then go on to demonstrate how a feature of C++, the ability to create an abstract datatype as an object, or class, is very useful for the particular application of dening and using a term structure. It is in fact this particular application, to create a term structure class, which really illustrates the power of C++, and why you want to use an object oriented language instead of classical langues like

dt .

we potentially need an innite

This is not feasible, so some lower dimensional way needs to be found to

pyex

and

C, or matrix languages like quss or wtl for many nancial calculations.

48

5.1

The interchangeability of discount factors, spot interest rates and forward interest rates

The term structure can be specied in terms of either discount factors, spot interest rates or forward interest rates.

nd the current value

t) payment of one dollar. To Ct , we calculate P V a dt Ct . This discount factor can also be specied in terms of interest rates, where we let rt be the relevant interest rate (spot rate) for discounting r t a t-period cashow. Then we know that the present value P V a e t Ct . Since these two methods of
A discount factor is the current price for a future (time

PV

of a cash ow

calculating the present value must be consistent,

P V a dt Ct a ert t Ct
and hence

dt a ert t
Note that this equation calculates terms of discount factors

dt

given

rt .

Rearranging this equation we nd the spot rate

rt

in

rt a

ln@dt A
t tI
and repaying it at a later date

An alternative concept that is very useful is a forward interest rate, the yield on borrowing at some future date

tP .

Let

today, at the current spot rate spot rate till period

tI

ft1 ;t2

be this interest rate. If we invest one dollar

and the forward rate for the period from

tI

to

tP

(which is what you would have to do to make an actual investment), you would get the following future value

F V a ert1 t1 eft1 ;t2 @t2 t1 A


The present value of this forward value using the time

tP discount factor has to equal one:

dt2 F V a I
These considerations are enough to calculate the relevant transforms. The forward rate for borrowing at time

tI for delivery at time tP is calculated as ft1 ;t2 a

ln

tP tI tP

dt2 dt1

ln

tP tI

dt1 dt2

The forward rate can also be calculated directly from yields as

ft1 ;t2 a rt2


C++ Code 5.1 Example

rt t tI t tP tI P I
1

shows the implementation of these transformations.

You are given the one period spot rate

rI a S7 and the two period discount factor dP a H:W.

Calculate the

two period spot rate and the forward rate from 1 to 2.

49

dt a ert t rt a

ln@dt A
t
ln

dt1 dt2

ft1 ;t2 a

tP tI t t ft1 ;t2 a rt2 P rt1 I tP tI tP tI

Notation: dt discount factor for payment at time t, rt : spot rate applying to cash ows at time t. ft1 ;t2 forward rate between time t1 and t2 , i.e. the interest rate you would agree on today on the future transactions.

#include <mth> using namespace std;


double term struture yield from disount ftor(const double& d t, const double& t) return ( log(d t)/t);

double term struture disount ftor from yield(const double& r, const double& t) return exp( r*t);

};

double term struture forwrd rte from disount ftors(const double& d tI, const double& d tP, const double& time) { return (log (d tI/d tP))/time;
};

double term struture forwrd rte from yields(const double& r tI, const double& r tP, const double& tI, const double& tP) { return r tP*tP/(tP tI) r tI*tI/(tP tI);

};

C++ Code 5.1:


C++ program:

Term structure transformations

out << " a " << tI << " period spot rate of " << r tI << " corresponds to a discount factor of " << d tI << endl; double tP=2; double d tP = 0.9; double r tP = term struture yield from disount ftor(d tP,tP); out << " a " << tP << " period discount factor of " << d tP << " corresponds to a spot rate of " << r tP << endl; out << " the forward rate between " << tI << " and " << tP << " is " << term struture forwrd rte from disount ftors(d tI,d tP,tPtI) << " using discount factors " << endl; out << " and is " << term struture forwrd rte from yields(r tI,r tP,tI,tP) << " using yields " << endl;
Output from C++ program:

double tI=1; double r tI=0.05; double d tI=term struture disount ftor from yield(r tI,tI);

I period spot rte of HFHS orresponds to disount ftor of HFWSIPPW P period disount ftor of HFW orresponds to spot rte of HFHSPTVHQ the forwrd rte etween I nd P is HFHSSQTHS using disount ftors nd is HFHSSQTHS using yields

50

5.2

The term structure as an object

From the previous we see that the term structure can be described in terms of discount factors, spot rates or forward rates, but that does not help us in getting round the dimensionality problem. If we think in terms of discount factors, for a complete specication of the current term structure one needs an innite number of discount factors factors as a

function d@tA, that, given a nonnegative time t, returns the discount factor.

fdt gtPR

+.

It is perhaps easier to think about this set of discount Since we have

established that there are three equivalent ways of dening a term structure, discount factors, spot rates and forward rates, we can therefore describe a term structure as a collection of three dierent functions that oer dierent views of the same underlying object. A term structure is an abstract object that to the user should provide

  

discount factors spot rates

d (prices of zero coupon bonds).

r (yields of zero coupon bonds). f t.


The user of a term structure will not need to know how the term structure is

forward rates

for any future maturity

implemented, all that is needed is an interface that species the above three functions. This is tailor made for being implemented as a C++

class.

A class in C++ terms is a collection of data In the present context it is a way of

structures and functions that operate on these data structures. specifying the three functions. r

@tA @tA

d f

@tA

5.2.1 Base class Header File 5.1


shows how we describe the generic term structure as a C++ class.

#ifndef iw gi gve r #dene iw gi gve r


class term struture lss { public: virtual double r(const double& t) const; GG yield on zero oupon ond virtual double d(const double& t) const; GG disount ftorGprie of zero oupon ond virtual double f (const double& tI, const double& tP) const; GG forwrd rte virtual term struture lss();
};

#endif

Header le 5.1:

Header le describing the

termstruture

base class

The code for these functions uses algorithms that are described earlier in this chapter for transforming between various views of the term structure. The term structure class merely provide a convenient

interface to these algorithms. The code is shown in

C++ Code 5.2

Note that the denitions of calculations are circular. Any given over-ride at least one of the functions We next consider two examples of

specic term structures.


51

(yield),

specic
f

type of term structure has to

(discount factor) or

(forward rate).

#include "fin_recipes.h"

term struture lssXXterm struture lss(){};


double term struture lssXXf (const double& tI, const double& tP) const{ double dI = d(tI); double dP = d(tP); return term struture forwrd rte from disount ftors(dI,dP,tP tI);

};

double term struture lssXXr(const double& t) const{ return term struture yield from disount ftor(d(t),t);
};

double term struture lssXXd(const double& t) const { return term struture disount ftor from yield(r(t),t);
};

C++ Code 5.2:

Default code for transformations between discount factors, spot rates and forward rates in

a term structure class

52

5.2.2 Flat term structure.


The at term structure overrides the

yield

member function of the base class.

The only piece of data this type of term structure needs is an interest rate.

#ifndef iw gi gve pve #dene iw gi gve pve #include "term_structure_class.h"


class term struture lss )t X public term struture lss private: double ; GG interest rte public: term struture lss )t(const double& r); virtual term struture lss )t(); virtual double r(const double& t) const; void set int rte(const double& r);
}; {

#endif

Header le 5.2:

Header le for term structure class using a at term structure

#include "fin_recipes.h"

term struture lss )tXXterm struture lss )t(const double& r){ term struture lss )tXXterm struture lss )t(){};
double term struture lss )tXXr(const double& ) const
{

r;

};

if (>=0) return
{

return

0; };

void term struture lss )tXXset int rte(const double& r)

r;

};

C++ Code 5.3: Example

Implementing term structure class using a at term structure

The term structure is at with rate between 1 and 2. C++ program:

r a S7.

Determine the discount factors for years 1 and 2 and the forward

term struture lss )t ts(0.05); double tI=1; out << "discount factor t1 = " << tI << ":" << ts.d(tI) << endl; double tP=2; out << "discount factor t2 = " << tP << ":" << ts.d(tP) << endl; out << "spot rate t = " << tI << ":" << ts.r(tI) << endl; out << "spot rate t = " << tP << ":" << ts.r(tP) << endl; out << "forward rate from t1= " << tI << " to t2= " << tP << ":" << ts.f (tI,tP) << endl;
Output from C++ program:

disount ftor tI a IXHFWSIPPW disount ftor tP a PXHFWHRVQU spot rte t a IXHFHS spot rte t a PXHFHS forwrd rte from tIa I to tPa PXHFHS
53

5.3

Using the currently observed term structure.

A rst step to a general term structure is to use market data on bond prices and interest rates to infer discount factors. The simplest way of presenting this problem is in terms of linear algebra. Suppose we have three bonds with cash ows at times 1, 2 and 3.

BI a dI CII C dP CIP C dP CIQ BP a dI CPI C dP CPP C dP CPQ BI a dI CQI C dP CQP C dP CQQ


Writing this in terms of matrices

P R

BI BP BQ dI dP dQ

Q S

aR

dI dP dQ

QP SR

CII CIP CIQ CPI CPP CPQ CQI CQP CQQ


QI P S R

Q S

Solving for the discount factors

P R

Q S

aR

CII CIP CIQ CPI CPP CPQ CQI CQP CQQ

BI BP BQ

Q S

or

d a CI B
using the obvious matrix denitions

BaR

BI BP BQ

Q S

daR

dI dP dQ

Q S

CaR

CII CIP CIQ CPI CPP CPQ CQI CQP CQQ

Q S

Example
The following set of bond and bond prices is observed: Time (in years) Bond Bond 1 2 2 3 4 5 Price 98 96 92 118 109 112 10 8 9 10 8 9 100 100 100 10 8 9 110 8 9 108 9 109 0 0.5 1 1.5 2 3 4

The bonds are treasury secrurities, which can be viewed as nominally riskless. 1. For what maturities is it possible to infer discount factors? 2. Determine the implicit discount factors in the market. 3. What is the interest rates implied in this set of discount rates? Here we can nd the discount factors for maturities of 0.5,1,1.5,2,3 and 4.

54

wtl

program:
0 0;0 0 100 0 0 0;10 10 10 110 0 0;8 8 8 8 108 0;9 9 9 9 9 109]

g=[100 0 0 0 0 0;0 100 0 0 f=[96 94 92 118 109 112] d=f*inv(g)' t=[0.5 1 1.5 2 3 4] r=d.^(1./t)1
Output from

wtl

program:

g a IHH H H H H H H IHH H H H H H H IHH H H H IH IH IH IIH H H V V V V IHV H W W W W W IHW f a WT WR WP IIV IHW IIP d a HFWTHHH HFWRHHH HFWPHHH HFVITQT HFUQWWH HFTTTIV t a HFSHHHH IFHHHHH IFSHHHH PFHHHHH QFHHHHH RFHHHHH r a HFHVSHTW HFHTQVQH HFHSUITP HFIHTUUP HFIHSTPV HFIHTVVR
To just use todays term structure, we need to take the observations of discount factors

dt

observed in

the market and use these to generate a term structure. The simplest possible way of doing this is to linearly interpolate the currently observable discount factors.

5.3.1 Linear Interpolation.


If we are given a set of discount factors (

dt )

for various maturities, the simplest way to construct a

term structure is by straightforward linear interpolation between the observations we have to nd an intermediate time. For many purposes this is good enough. This interpolation can be on either zero coupon yields, discount factors or forward rates, we illustrate the case of linear interpolation of spot (zero coupon) rates.

Computer algorithm, linear interpolation of yields.


in increasing order of time to maturity.

Note that the algorithm assumes the yields are ordered

Example
You observe the following term structure of spot rates Time 0.1 0.5 1 5 10

r
0.1 0.2 0.3 0.4 0.5

Interpolate spot rates (zero rates) at times 0.1, 0.5, 1, 3, 5 and 10.

55

#include <vetor> using namespace std; #include "fin_recipes.h"


double term struture yield linerly interpolted(const double& time, const vetor<double>& os times, const vetor<double>& os yields)

GG ssume the yields re in inresing time to mturity orderF int no os = os times.size(); if (no os<1) return 0; double t min = os times[0]; if (time <= t min) return os yields[0]; GG erlier thn lowest osF
double t mx = os times[no os 1]; if (time >= t mx) return os yields[no os

1]; GG lter thn ltest os 1]);

int t=1; GG (nd whih two oservtions we re etween while ( (t<no os) && (time>os times[t])) { ++t; }; double lmd = (os times[t] time)/(os times[t] os times[t

GG y ordering ssumptionD time is etween tEIDt double r = os yields[t1] * lmd + os yields[t] return r;
};

* (1.0

lmd);

C++ Code 5.4:


C++ program:

Interpolated term structure from spot rates

vetor<double> times; vetor<double> yields; times.push k(0.1); times.push k(0.5); times.push k(1); yields.push k(0.1); yields.push k(0.2); yields.push k(0.3); times.push k(5); times.push k(10); yields.push k(0.4); yields.push k(0.5); out << " yields at times: " << endl; out << " t=0.1 " << term struture yield linerly interpolted(0.1,times,yields) << endl; out << " t=0.5 " << term struture yield linerly interpolted(0.5,times,yields) << endl; out << " t=1 " << term struture yield linerly interpolted(1, times,yields) << endl; out << " t=3 " << term struture yield linerly interpolted(3, times,yields) << endl; out << " t=5 " << term struture yield linerly interpolted(5, times,yields) << endl; out << " t=10 " << term struture yield linerly interpolted(10, times,yields) << endl;
Output from C++ program:

yields t timesX taHFI HFI taHFS HFP taI HFQ taQ HFQS taS HFR taIH HFS

56

5.3.2 Interpolated term structure class.


The interpolated term structure implemented here uses a set of observations of yields as a basis, and for observations in between observations will interpolate between the two closest. The following only provides implementations of calculation of the yield, for the other two rely on the base class code. As shown in

Header File 5.3

and

C++ Code 5.5,

there is some more book-keeping involved here, need to

have code that stores observations of times and yields.

#ifndef iw gi gve sxiyveih #dene iw gi gve sxiyveih #include "term_structure_class.h" #include <vetor> using namespace std;
class term struture lss interpolted X public term struture lss private: vetor<double> times ; GG use to keep list of yields vetor<double> yields ; void ler(); public:
{

term struture lss interpolted(); term struture lss interpolted(const vetor<double>& times, const vetor<double>& yields); virtual term struture lss interpolted(); term struture lss interpolted(const term struture lss interpolted&); term struture lss interpolted operator= (const term struture lss interpolted&);

int no oservtions() const { return times .size(); }; virtual double r(const double& ) const; void set interpolted oservtions(vetor<double>& times, vetor<double>& yields);
};

#endif

Header le 5.3:

Header le describing a term structure class using linear interpolation between spot rates

57

#include "fin_recipes.h"
void term struture lss interpoltedXXler(){

times .erse(times .egin(), times .end()); yields .erse(yields .egin(), yields .end());

};

term struture lss interpoltedXXterm struture lss interpolted()Xterm struture lss(){ler();}; term struture lss interpoltedXXterm struture lss interpolted(const vetor<double>& in times, const vetor<double>& in yields) ler(); if (in times.size()!=in yields.size()) return; times = vetor<double>(in times.size()); yields = vetor<double>(in yields.size()); for (int i=0;i<in times.size();i++) { times [i]=in times[i]; yields [i]=in yields[i];
}; };

term struture lss interpoltedXXterm struture lss interpolted(){ ler();}; term struture lss interpoltedXXterm struture lss interpolted(const term struture lss interpolted& term) times = vetor<double> (term.no oservtions()); yields = vetor<double> (term.no oservtions()); for (int i=0;i<term.no oservtions();i++){ times [i] = term.times [i]; yields [i] = term.yields [i];
}; }; {

term struture lss interpolted term struture lss interpoltedXXopertor= (const term struture lss interpolted& term) = vetor<double> (term.no oservtions()); times yields = vetor<double> (term.no oservtions()); for (int i=0;i<term.no oservtions();i++){ = term.times [i]; times [i] yields [i] = term.yields [i];
};

return
};

(*this);

double term struture lss interpoltedXXr(const double& ) const { return term struture yield linerly interpolted(, times , yields
};

);

void

term struture lss interpoltedXXset interpolted oservtions(vetor<double>& in times, vetor<double>& in yields) ler(); if (in times.size()!=in yields.size()) return; times = vetor<double>(in times.size()); yields = vetor<double>(in yields.size()); for (int i=0;i<in times.size();i++) { times [i]=in times[i]; yields [i]=in yields[i];
}; };

C++ Code 5.5:

Term structure class using linear interpolation between spot rates

58

Example
Time 0.1 1 5

r
0.05 0.07 0.08

Determine discount factors and spot rates at times 1 and 2, and forward rate between 1 and 2. C++ program:

vetor<double> times; times.push k(0.1); vetor<double> spotrtes; spotrtes.push k(0.05); times.push k(5); times.push k(1); spotrtes.push k(0.07);spotrtes.push k(0.08); term struture lss interpolted ts(times,spotrtes); double tI=1; out << "discount factor t1 = " << tI << ":" << ts.d(tI) << endl; double tP=2; out << "discount factor t2 = " << tP << ":" << ts.d(tP) << endl; out << "spot rate t = " << tI << ":" << ts.r(tI) << endl; out << "spot rate t = " << tP << ":" << ts.r(tP) << endl; out << "forward rate from t1= " << tI << " to t2= " << tP << ":" << ts.f (tI,tP) << endl;
Output from C++ program:

disount ftor tI a IXHFWQPQWR disount ftor tP a PXHFVTSHPP spot rte t a IXHFHU spot rte t a PXHFHUPS forwrd rte from tIa I to tPa PXHFHUS

59

5.4

Bond calculations with a general term structure and continous compounding


Yield to maturity

Coupon bond paying coupons at dates t1 ; t2 ; : : ::


Bond Price

BH : BH a dti Cti a erti ti Cti

i i

y solves:

BH a
Convexity

Cti eyti

Duration

D:

Cx: BH BH BH
I I I

Da Da Da

BH BH BH
I I

ti dti Cti ti erti ti Cti ti eyti Cti

Cx a Cx a Cx a

tP dti Cti i tP erti ti Cti i tP eyti Cti i

Formula 5.1: C++ Code 5.6


and

Bond pricing with a continously compounded term structure illustrates how one would calculate bond prices and duration if one has a

C++ Code 5.7

term structure class.

#include "fin_recipes.h"
double onds prie(const vetor<double>& sh)ow times, const vetor<double>& sh)ows, const term struture lss& d) { double p = 0; for (unsigned i=0;i<sh)ow times.size();i++) {

+=

d.d(sh)ow times[i])*sh)ows[i];

};

return p;
};

C++ Code 5.6:

Pricing a bond with a term structure class

#include "fin_recipes.h"
double onds durtion(const vetor<double>& sh)ow times, const vetor<double>& sh)ow mounts, const term struture lss& d ) { double =0; double hI=0; for (unsigned i=0;i<sh)ow times.size();i++){

+= sh)ow mounts[i] * d.d(sh)ow times[i]); hI += sh)ow times[i] * sh)ow mounts[i] * d.d(sh)ow times[i]);

};

return hI/;
};

C++ Code 5.7:

Calculating a bonds duration with a term structure class

60

#include "fin_recipes.h" #include <mth>


double onds onvexity(const vetor<double>& sh)ow times, const vetor<double>& sh)ow mounts, const term struture lss& d ) { double f=0; double gx=0; for (unsigned i=0;i<sh)ow times.size();i++){

f += sh)ow mounts[i] * d.d(sh)ow times[i]); gx += pow(sh)ow times[i],2) * sh)ow mounts[i]

d.d(sh)ow times[i]);

};

return gx/f;
};

C++ Code 5.8:

Calculating a bonds convexity with a term structure class

61

Example
The term structure is at with

r a IH7

continously compunded interest.

Calculate price, duration, and

convexity of a 10%, 2 year bond. C++ program:

vetor <double> times; times.push k(1); times.push k(2); vetor <double> sh)ows; sh)ows.push k(10); sh)ows.push k(110); term struture lss )t ts)t(0.1); out << " price = " << onds prie (times, sh)ows, ts)t) << endl; out << " duration = " << onds durtion(times, sh)ows, ts)t) << endl; out << " convexity = " << onds onvexity(times, sh)ows, ts)t) << endl;
Output from C++ program:

prie a WWFIHVV durtion a IFWHVU onvexity a QFUPTII


References
Shiller (1990) is a good reference on the use of the term structure.

62

Chapter 6

The Mean Variance Frontier


Contents
6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The minimum variance frontier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Calculation of frontier portfolios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The global minimum variance portfolio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ecient portfolios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The zero beta portfolio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Allowing for a riskless asset. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ecient sets with risk free assets. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Short-sale constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 64 65 68 68 69 69 70 71 71 72

6.10 The Sharpe Ratio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.11 Equilibrium: CAPM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6.11.1 Treynor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.11.2 Jensen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .


6.12 Working with Mean Variance and CAPM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.13 Mean variance analysis using matrix libraries . . . . . . . . . . . . . . . . . . . . . . . . . . .

72 72
72 73

We now discuss a classical topic in nance, mean variance analysis. This leads to ways of accounting for the riskiness of cashows. Mean variance analysis concerns investors choices between portfolios of risky assets, and how an investor chooses portfolio weights. portfolios Let rp be a portfolio return. We assume that investors preferences over p satisfy a mean variance utility representation, u@pA a u@E rp ; @rp AA, with utility increasing in expected return @@u=@E rp > HA and decreasing in variance @@u=@ var@rp A < HA. In this part we consider the representation of the portfolio opportunity set of such decision makers. There are a number of useful properties of this opportunity set which follows purely from the mathematical formulation of the optimization problem. It is these properties we focus on here.

6.1

Setup

We assume there exists

n ! P risky securities, with expected returns e

eaT

T T R

E rI E rP E rn
. . .

Q U U U S

and covariance matrix

V:
Q U U U S

VaT

T T R

@rI ; rI A @rI ; rP A : : : @rP ; rI A @rP ; rP A : : : @rn ; rI A


. . .

:::
V

@rn ; rn A

The covariance matrix

is assumed to be invertible.

63

portfolio p is dened by a set of weights w invested in the risky assets.


P

waT

T T R

!I !P !n
. . .

Q U U U; S

where

wi

is the fraction of the investors wealth invested in asset

i.

Note that the weights sum to one.

The expected return on a portfolio is calculated as

E rp a wH e
and the variance of the portfolio is

P @rp A a wH Vw
Example
An investor can invest in three assets with expected returns and variances as specied in the following table.

Asset 1 2 3

E r
10% 11.5% 8%

 P @r A
0.20 0.10 0.15

The three assets are independent (uncorrelated). 1. Determine the expected return and standard deviation of an equally weighted portfolio of the three assets

wtl

program:

e=[0.1 0.11 0.08] =[ 0.2 0 0; 0 0.1 0 ; w=1/3*[1 1 1] er= e*w' sigm=sqrt(w**w')


Output from

0 0 0.15]

wtl

program:

e a HFIHHHHH HFIIHHHH HFHVHHHH a HFPHHHH HFHHHHH HFHHHHH HFHHHHH HFIHHHH HFHHHHH HFHHHHH HFHHHHH HFISHHH w a HFQQQQQ HFQQQQQ HFQQQQQ er a HFHWTTTU sigm a HFPPQTI

6.2

The minimum variance frontier

A portfolio is a frontier portfolio

frontier portfolio p solves

if it minimizes the variance for a given expected return, that is, a

wp

I a rg min wH Vw P w
64

subject to:

wH e a E ~p r wH 1 a I
The set of all frontier portfolios is called the

minimum variance frontier.

6.3

Calculation of frontier portfolios

Proposition 1 If the matrix V wp for a frontier portfolio p


wp

is full rank, and there are no restrictions on shortsales, the weights with mean E ~p can be found as r

a g C hE rp I @B 1H AeH A VI @C eH A1H A VI

where
ga ha

D D
I

A a 1H VI e B a eH VI e C a 1H VI 1
Aa

B A A C

D a BC AP a jAj
Proof

Any minimum variance portfolio solves the program


wp
= arg min
w

1 2

wH Vw

subject to
wH e = E [~p ] r wH 1 = 1

Set up the Lagrangian corresponding to this problem


1 L(w; ; je; V) = wH Vw  E [~p ] wH e (1 wH 1) r
2

Dierentiate

@L @w @L @

wH V eH 1H

=0

E [rp ] wH e = 0
65

@L @

=1

wH 1 = 0

Rewrite conditions above as (note that this requires the invertibility of V.


wH
=

eH V 1 1H V1

(6.1) (6.2) (6.3)

wH e = E [~p ] r wH 1 = 1

Post-multiply equation (6.1) with e and recognise the expression for E [rp ] in the second equation
wH e = E [rp ] = eH V1 e + 1H V1 e

Similarly post-multiply equation (6.1) with 1 and recognise the expression for
wH 1 = 1 = eH V1 1 + 1H V1 1

in the third equation

With the denitions of A, B , C and D above, this becomes the following system of equations
&

E [rp ]
1

= =

B + A A + C

'

Solving for  and , get

B AE [rp ] D CE [rp ] A D

=

Plug in expressions for  and into equation (6.1) above, and get
wH
= 1

H B 1 AeH V1 +

H C e A1H V1 E [rp ] = g + hE [rp ]


The portfolio dened by weights

The portfolio dened by weights

@g C hA is a portfolio with expected return 1.


Example

g is a portfolio with expected return 0.

This implies the useful property that

g1H

a I, and h1H a H.

An investor can invest in three assets with expected returns and variances as specied in the following table.

Asset 1 2 3

E r
10% 11.5% 8%

 P @r A
0.20 0.10 0.15

The three assets are independent (uncorrelated). 1. What are the weights of the minimum variance portfolio with mean 9%?

66

wtl

program:

e=[0.1 0.11 0.08]' =[ 0.2 0 0; 0 0.1 0 ; 0 0 0.15] r=0.09 n = length(e) = ones(1,n)*inv()*e = e'*inv(V)*e = ones(1,n)*inv()*ones(n,1) e = [ ; ] d = det(e) g = 1/d*(*ones(1,n) *e')*inv(V) h = h = 1/d*(*e' - a*ones(1,n))*inv(V) w=g+h*r
Output from

wtl

program:

e a HFIHHHHH HFIIHHHH HFHVHHHH a HFPHHHH HFHHHHH HFHHHHH HFHHHHH HFIHHHH HFHHHHH HFHHHHH HFHHHHH HFISHHH r a HFHWHHHH n a Q a PFIQQQ a HFPIQTU a PIFTTU e a HFPIQTU PFIQQQQ PFIQQQQ PIFTTTTU d a HFHUVQQQ g a HFHPIPUU EPFTVHVSI QFTSWSUR h a PFIPUU QIFWIRW EQRFHRPT w a HFPIPUU HFIWIRW HFSWSUR
This calculation is put into a

wtl

function in

wtl Code 6.1.

= e'*inv(V)*e; = ones(1,n)*inv()*ones(n,1); e = [ ; ]; d = det(e); g = 1/d*(*ones(1,n) *e')*inv(V); h = h = 1/d*(*e' - a*ones(1,n))*inv(V); w=g+h*r; end

function w = min vrine portfolio(e,,r) n = length(e); = ones(1,n)*inv()*e;

wtl Code 6.1:

Calculation of minimum variance portfolio for given return

67

Calculating the weights of the minimum variance portfolio given an interest rate

wp
where

a g C hE rp I @B 1H AeH A VI @C eH A1H A VI

ga ha

D D
I

A a 1H VI e B a eH VI e C a 1H VI 1 D a BC AP a
Notation: rp desired portfolio returns.V: covariance matrix of asset returns. e: vector of expected asset returns.

6.4

The global minimum variance portfolio

The portfolio that minimizes variance regardless of expected return is called the

ance portfolio.
H wmvp

Let

mvp be the global minimum variance portfolio.

global minimum vari-

Proposition 2 (Global Minimum Variance Portfolio)


I a 1H VI 1 I 1H VI a 1H VI ;
A C

The global minimum variance portfolio has weights

expected return E rmvp a

C I and variance var@rmvp A a C . E r


T

A C

 @r A

6.5

Ecient portfolios

Portfolios on the minimum variance frontier with expected returns higher than or equal to called

ecient

E rmvp are

portfolios.

E r
T
E [rmvp ]

E
 (rmvp )
68

 @r A

6.6

The zero beta portfolio

Proposition 3

For any portfolio p on the frontier, there is a frontier portfolio zc@pA satisfying

cov@rzc@pA ; rp A a H: This portfolio is called the zero beta portfolio relative to p. The zero beta portfolio zb@pA has return
E rzc@pA a
D A E r C2 A C p C

T s mvp
E [rzc(p) ]

p zc@pA
E

Note that if if

p is an ecient portfolio on the mean variance frontier then zc@pA is inecient. p is inecient zc@pA is ecient.
E [r] T

Conversely,

sp s mvp

s zc@pA

 (r)

6.7

Allowing for a riskless asset.

Suppose have

risky assets with weights

and one riskless assets with return

rf .

Intuitively, the return on a portfolio with a mix of risky and risky assets can be written as

E rp a weight in risky
which in vector form is:

return risky

C weight riskless

rf

E rp a wH e C @I wH 1Arf

An ecient portfolio in the presence of a riskless asset has the weights E rp rf wp a VI @e 1rf A H where H a @e 1rf AH VI @e 1rf A
Proposition 4
69

The variance of the ecient portfolio is @E rp rf AP P @rp A a H


Note that standard deviation is a linear function of deviation space.

E rp .

The ecient set is a line in mean-standard

6.8

Ecient sets with risk free assets.

Suppose

risky

rf <

A C.

Then the ecient set is the line from

@H; rf A through tangency on the ecient set of

assets.

E [r] T

se s A mvp C rf d d d d
pd
1

Cd

 (r)

Suppose

rf >

A C.

Then the ecient set is the two half-lines starting from

@H; rf A.

E [r] T

d d d d s de
p

rf Ad

s mvp

 (r)

If

rf a

A C,

the weight in the risk free asset is one. The risky portfolio is an zero investment portfolio.

The ecient set consists of two asymptotes toward the ecient set of risky assets.

70

E [r] T

d d d d
p

A C d

mvp

 (r)

6.9

Short-sale constraints

So far the analysis has put no restrictions on the set of weights frontier.

wp

that denes the minimum variance

For practical applications, existence of negative weights is problematic, since this involves

selling securities short. This has led to the investigation of to be non-negative.

restricted mean variance frontiers, where the weights are constrained

Denition 1
wp

A short sale resctricted minimum variance portfolio p solves

I a rg min wH Vw P w

subject to
wH e a E ~p r wH 1 a I wH

!0

Such short sale resctricted minimum variance portfolio portfolios are much harder to deal with analytically, since they do not admit a general solution, one rather has to investigate the Kuhn-Tucker conditions for corner solutions etc. To deal with this problem in practice one will use a subroutine for solving constrained optimization problems.

6.10

The Sharpe Ratio

The Sharpe ratio of a given portfolio

p is dened as

Sp a

E rp rf @rp A Sp of a portfolio p is the slope of the line in mean-standard deviations space from the p. Note that in the case with a risk free asset, the tangency portfolio has the

The Sharpe ratio

risk free rate through

maximal Sharpe Ratio on the ecient frontier.

71

6.11

Equilibrium: CAPM

Under certain additional assumptions, an economy of mean variance optimizers will aggregate to an economy where the Capital Asset Pricing Model (CAPM) holds. Under the CAPM, any asset returns will satisfy.

E ri a rf C i @E rm rf A
where

ri is the return on asset i, rf rp rf p

the return on the risk free asset,

6.11.1 Treynor

Tp a

6.11.2 Jensen

p a rp @rf C p @rm rf A
6.12 Working with Mean Variance and CAPM

The computational problems in mean variance optimization and the CAPM are not major, except for the case of short sales constrained portfolios (quadratic programming). The issues of more concern is estimation of parameters such as covariances and betas.

endfuntion

function s= shrpe(r,rf ) s=(mean(r) mean(rf ))/std(r rf );

wtl Code 6.2:

Sharpe Ratio

endfuntion

function t = treynor(r, rm, rf ) beta = cov(r,rm)/vr(rm); t = (mean(r rf ))/beta;

wtl Code 6.3:

Treynor Ratio

endfuntion

function lph = jensen(r, rm, rf ) beta = cov(r,rm)/vr(rm); lph = mean(r) (rf +beta*(mean(rm) rf ));

wtl Code 6.4:

Jensens alpha

Readings and Sources

The classical sources for this material are Merton (1972) and Roll (1977a). (Huang

and Litzenberger, 1988, Ch 3) has a good textbook discussion of it.

72

6.13

Mean variance analysis using matrix libraries


As shown using

Let us now consider how to implement mean variance analysis in C++.

wtl,

the

calculations are relatively simple matrix expressions. To implement the calculations in C++ the best way of doing it is to use a linear algebra class to deal with the calculations. For illustrative purposes we will show usage of two dierent matrix classes,

xewmt

and

sCC.

These classes are described in more detail

in an appendix, with some references to how to obtain and install them. In

C++ Code 6.1

and

C++ Code 6.2

we show how to do the basic mean variance calculations, calculating

means and standard deviations, using the two classes. Note the similarity to using

wtl

in the way

the matrix and vector multiplications are carried out. Note also an important dierence between the two classes. In element starts

sCC the indexing of elements start at zero, the usual C++ way. Hence, when adressing tmp@HDHA in the sCC example we are pulling the rst element. In Newmat the default indexing at one, the wtl way. Therefore, in adressing tmp@IDIA in the xewmt example we are also

pulling the rst element. This serves as a warning to read the documentation carefully, the o by one error is a very common occurrence when mixing libraries like this.

#include <mth> using namespace std; #include <itpp/itse.h> using namespace itpp;
double mv lulte men(const ve& e, const ve& w){

ve tmp = e.trnspose()*w; return tmp(0);

};

double mv lulte vrine(const mt& , const ve& w){

mt tmp = w.trnspose()**w; return tmp(0,0);

};

double mv lulte st dev(const mt& , const ve& w){ double vr = mv lulte vrine(,w); return sqrt(vr);
};

C++ Code 6.1: Example


Mean variance calculations.

Mean variance calculations using

sCC

ea Va

H:HS H :I

I :H H :H H :H I :H H :S H :S
!

Calculate mean, variance and stdev for portfolio

wa

73

#include <mth> using namespace std; #include "newmat.h" using namespace xiwe;
double mv lulte men(const wtrix& e, const wtrix& w){ return tmp(1,1);
};

wtrix tmp

e.t()*w;

double mv lulte vrine(const wtrix& , const wtrix& w){

wtrix tmp = w.t()**w; return tmp(1,1);

};

double mv lulte st dev(const wtrix& , const wtrix& w){ double vr = mv lulte vrine(,w); return sqrt(vr);
};

C++ Code 6.2:


C++ program:

Mean variance calculations using

xewmt

out << "Simple example of mean variance calculations " << endl; wtrix e(2,1); e(1,1)=0.05; e(2,1)=0.1; wtrix (2,2); (1,1)=1.0; (2,1)=0.0; (1,2)=0.0; (2,2)=1.0; wtrix w(2,1); w(1,1)=0.5; w(2,1)=0.5; out << " mean " << mv lulte men(e,w) << endl; out << " variance " << mv lulte vrine(,w) << endl; out << " stdev " << mv lulte st dev(,w) << endl;
Output from C++ program:

imple exmple of men vrine lultions men HFHUS vrine HFS stdev HFUHUIHU

74

In

C++ Code 6.4 and C++ Code 6.3 we show how to calculate the mean variance optimal portfolio for a given

required return. This is the case where there are no constraints on the weight, and we use the analytical solution directly.

#include "newmat.h" using namespace xiwe;

eturnwtrix mv lulte portfolio given men unonstrined(const wtrix& e, const wtrix& , const double& r){ int no ssets=e.xrows(); wtrix ones = wtrix(no ssets,1); for (int i=0;i<no ssets;++i){ ones.element(i,0) wtrix inv = .i(); GG inverse of wtrix e = (ones.t()*inv*e); double = e.element(0,0); wtrix f = e.t()*inv*e; double = f.element(0,0); wtrix g = ones.t()*inv*ones; double = g.element(0,0); double d = * *; wtrix invI=inv*ones; wtrix inve=inv*e; wtrix g = (invI* inve*)*(1.0/d); wtrix h = (inve* invI*)*(1.0/d); wtrix w = g + h*r; w.elese(); return w;
};

= 1; };

C++ Code 6.3:

Calculating the unconstrained frontier portfolio given an expected return using

xewmt

#include <itpp/itse.h> using namespace itpp;

mt mv lulte portfolio given men unonstrined(const ve& e, const mt& , const double& r){ int no ssets=e.size(); ve one = ones(no ssets); mt inv = inv(); GG inverse of mt e = one.trnspose()*inv*e; double = e(0,0); mt f = e.trnspose()*inv*e; double = f(0,0); mt g = one.trnspose()*inv*one; double = g(0,0); double d = **; mt invI=inv*one; mt inve=inv*e; mt g = (invI* inve*)*(1.0/d); mt h = (inve* invI*)*(1.0/d); mt w = g + h*r; return w;
};

C++ Code 6.4: Example

Calculating the unconstrained frontier portfolio given an expected return using

sCC

Mean variance calculations.

ea

H:HS H :I

75

Va

I :H H :H H :H I :H

Find the optmal minimum variance portfolio with return C++ program:

r a H:HUS.

out << "Testing portfolio calculation " << endl; wtrix e(2,1); e(1,1)=0.05; e(2,1)=0.1; wtrix (2,2); (1,1)=1.0; (2,1)=0.0; (1,2)=0.0; (2,2)=1.0; double r=0.075; wtrix w = mv lulte portfolio given men unonstrined(e,,r); out << " suggested portfolio: "; out << " w1 = " << w(1,1) << " w2 = " << w(2,1) << endl;
Output from C++ program:

esting portfolio lultion suggested portfolioX wI a HFS wP a HFS

76

Chapter 7

Futures algoritms.
Contents
7.1 Pricing of futures contract. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

In this we discuss algoritms used in valuing futures contracts.

7.1

Pricing of futures contract.

The futures price of an asset without payouts is the future value of the current price of the assset.

ft a er@T tA St
#include <mth> using namespace std;
double futures prie(const double& , GG urrent prie of underlying sset const double& r, GG risk free interest rte const double& time to mturity) { return exp(r*time to mturity)*;
};

C++ Code 7.1: Example


Let

Futures price

S a IHH and r a IH7.

What is the futures price for a contract with time to maturity of half a year?

C++ program:

double =100; double r=0.10;


Output from C++ program:

double time=0.5; out << " futures price = " << futures prie(,r, time) << endl;

futures prie a IHSFIPU

77

Chapter 8

Binomial option pricing


Contents
8.1 8.2 8.3 Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pricing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Multiperiod binomial pricing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 78 80

8.1

Options

Option and other derivative pricing is one of the prime success stories of modern nance. An option is a derivative security, the cash ows from the security is a function of the price of some typically called the underlying security.

other

security,

A call option is a right, but not obligation, to buy a given

quantity of the underlying security at a given price, called the exercise price interval. A put option is the right, but not obligation, to

K , within a certain time sell a given quantity of the underlying security

to an agreed excercise price within a given time interval. If an option can only be exercised (used) at a given date (the time interval is one day), the option is called an European Option. If the option can be used in a whole time period up to a given date, the option is called American. An option will only be used if it is valuable to the option holder. In the case of a call option, this is when the exercise price

is lower than the price one alternatively could buy the underlying security

for, which is the current price of the underlying security. Hence, options have never negative cash ows at maturity. Thus, for anybody to be willing to oer an option, they must have a cost when entered into. This cost, or price, is typically called an option a call option,

the price of a put option and

are indexed by time. We typically let

H be now

premium.

As notation, let

signify the price of

the price of the underlying security. All of these prices and

the nal maturity date of the option. From the

denition of the options, it is clear that at their last possible exercise date, the maturity date, they have cash ows.

CT a max@H; ST K A PT a max@H; K ST A
The challenge of option pricing is to determine the option premia

CH (call price) and PH (put price).

8.2

Pricing

All pricing uses that the cashows from the derivative is a direct function of the price of the underlying security. Pricing can therefore be done

relative

to the price of the underlying security. To price options

it is necessary to make assumptions about the probability distribution of movements of the underlying security. We start by considering this in a particularly simple framework, the binomial assumption. The price of the underlying is currently

SH .

The price can next period only take on two values,

Su and Sd .

78

SH r r r

Su

r j r

Sd

If one can nd all possible future states, an enumeration of all possibilities, one can value a security by constructing articial probabilities, called state price probabilities, which one use to nd an articial expected value of the underlying security, which is then discounted at the risk free interest rate. The binomial framework is particularly simple, since there are only two possible states.

nd the probability

of one state, we also nd the probability of the other as

@I q A.

If we

Equation 8.1

demonstrates this calculation for the underlying security.

SH a er @qSu C @I qASd A q.
The contribution of binomial option pricing is in actually calculating the number

(8.1)

Now, any derivative security based on this underlying security can be priced using the same probability

start by introducing constants

and

implicitly dened by

Su a uSH

and

q. To do valuation, Sd a dSH , and you get a

price process as illustrated in gure 8.1.

Figure 8.1

Binomial Tree

SH

rr

B r rr j

uSH dSH

and calculate the artical probability

q as

qa
in

er d ud
Formula 8.1
and implemented

The price of a one-period call option in a binomial framework is shown in

C++ Code 8.1.

Cu a mx@H; Su K A Cd a mx@H; Sd K A er d ud Su a uS0 and Sd a dS0 are the possible values for the underlying security next period, u and d are constants, r is the (continously qa
compounded) risk free interest rate and K is the call option exercise price.

CH a er @qCu C @I qACd A

Formula 8.1:
The state price probability

The single period binomal call option price

q is found by an assumption of no arbitrage opportunities.


79

If one has the

possibility of trading in the underlying security and a risk free bond, it is possible to create a portfolio of

#include <mth> #include <lgorithm> using namespace std;

GG stndrd mthemtil lirry GG de(ning the mx@A opertor


double& double& double& double& double&

double option prie ll europen inomil single period( const const const const const double p up = (exp(r) d)/(u d); double p down = 1.0 p up; double u = mx(0.0,(u* )); double d = mx(0.0,(d* )); double ll prie = exp( r)*(p up* u+p down* d); return ll prie;

, GG spot prie , GG exerie prie r, GG interest rte @per periodA u, GG up movement d){ GG down movement

};

C++ Code 8.1:

Binomial European, one period

these two assets that exactly duplicates the future payos of the derivative security. Since this portfolio has the same future payo as the derivative, the price of the derivative has to equal the cost of the duplicating portfolio. Working out the algebra of this, one can nd the expression for of the up and down movements

u and d.

q as the function

Exercise 8.1.
The price of the underlying security follows the binomial process

SH

B rr rr j

Su

Sd

A one period call option has payos

CH

B rr rr j

Cu a mx@H; Su K A Cd a mx@H; Sd K A

1. Show how one can combine a position in the underlying security with a position in risk free bonds to create a portfolio which exactly duplicates the payos from the call. 2. Use this result to show the one period pricing formula for a call option shown in formula 8.1.

8.3

Multiperiod binomial pricing

Of course, an assumption of only two possible future states next period is somewhat unrealistic, but if we iterate this assumption, and assume that every date, there are only two possible outcomes

next date,

but then, for each of these two outcomes, there is two new outcomes, as illustrated in the next gure:

80

St r r

uSt B rr r

B u(uSt ) = uuSt

r j r B d(uSt ) = u(dSt ) = udSt

r j r dSt r r r

r d(dS ) = ddS j r t t

Iterating this idea a few times more, the number of dierent

terminal

states increases markedly, and we

get closer to a realistic distribution of future prices of the underlying at the terminal date. Note that a crucial assumption to get a picture like this is that the factors

u and d are the same on each date.

rr r r r r rr rr rr r rr r rr r r rr rr r r rr rr r r rr r r rr rr r

Pricing in a setting like this is done by working backwards, starting at the terminal date. Here we know all the possible values of the underlying security. For each of these, we calculate the payos from the derivative, and nd what the set of possible derivative prices is

one period before.

Given these, we can

nd the option one period before this again, and so on. Working ones way down to the root of the tree, the option price is found as the derivative price in the rst node. For example, suppose we have two periods, and price a two period call option with exercise price

K.

81

S0 r r

uS0 B rr r

B uuS0

r j r B udS0

r j r dS0 r r r

r ddS j r 0

First step: Find terminal payos of derivative security:

r rr r

B rr r

B Cuu = max(0; Suu K )

rr

r j r C = max(0; duS K ) B du r

rr

r j r r

rr

rr

r C max(0; ddS K ) j r dd

Next step: Find the two possible call prices at time 1:

Cu a er @qCuu C @I qACud A Cd a er @qCud C @I qACdd A


B rr rr j

Cu

CH

Cd Cu and Cd , nd option value at time 0:

Final step: Using the two possible payos at time 1,

CH a er @qCu C @I qACd A
Thus, binomial pricing really concerns rolling backward in a binomial tree, and programming therefore concerns an ecient way of traversing such a tree. The obvious data structure for describing such a tree is shown in

C++ Code 8.2,

where the value in each node is calculated from nding out the number of up

and down steps are used to get to the particular node.

Exercise 8.2.

82

#include <vetor> #include <mth> using namespace std;

vetor< vetor<double> > inomil tree(const double& H, const double& u, const double& d, const int& no steps){ vetor< vetor<double> > tree; for (int i=1;i<=no steps;++i){ vetor<double> (i); for (int j=0;j<i;++j){ [j] = H*pow(u,j)*pow(d,ij1);
};

tree.push k();
};

return tree;
};

C++ Code 8.2:

Building a binomial tree

In terms of computational eciency the approcach of lot of calls to the

pow@A

C++ Code 8.2

will not be optimal, since it requires a

functional call. More ecient would be to carry out the tree building by doing the

multiplication from the previous node, for example the

one need to add one more node by multiplying the lowest element by 1. Implement such an alternative tree building procedure.

j 'th vector is the j I'th vector times u, and then d.

Basing the recursive calculation of a derivative price on a triangular array structure as shown in

C++ Code 8.2 is the most natural approach, but with some cleverness based on understanding the structure of the binomial tree, we can get away with the more ecienent algorithm that is shown in C++ Code 8.3. Note that here we only use one vetor<doule>, not a triangular array as built above. Example
Let

S a IHH:H, K a IHH:H, r a H:HPS, u a I:HS and d a I=u.

1. Price one and two period European Call options. C++ program:

double double u

= 100.0; = 1.05;

out << " one period european call = " << option prie ll europen inomil single period(,u,r,u,d) << endl; int no periods = 2; out << " two period european call = " << option prie ll europen inomil multi period given ud(,u,r,u,d,no periods) << endl;
Output from C++ program:

double u = 100.0; double r double d = 1/u;

= 0.025;

one period europen ll a two period europen ll a


Exercise 8.3.

QFTRQRP SFRRPSS

Implement pricing of single and multi period binomial put options.

Further reading

The derivation of the single period binomial is shown in for example Bossaerts and

degaard (2001), Hull (2006) or McDonald (2006).

83

#include <mth> #include <lgorithm> #include <vetor> using namespace std;

GG stndrd mthemtil lirry GG de(ning the mx@A opertor GG v vetor templtes

double option prie ll europen inomil multi period given ud(const double& , GG spot prie const double& u, GG exerie prie const double& r, GG interest rte @per periodA const double& u, GG up movement const double& d, GG down movement const int& no periods){ GG no steps in inomil tree double inv = exp( r); GG inverse of interest rte double uu = u*u; double p up = (exp(r) d)/(u d); double p down = 1.0 p up; vetor<double> pries(no periods+1); GG prie of underlying

pries[0] = *pow(d, no periods); GG (ll in the endnodesF for (int i=1; i<=no periods; ++i) pries[i] = uu*pries[i1]; vetor<double> ll vlues(no periods+1); GG vlue of orresponding ll for (int i=0; i<=no periods; ++i) ll vlues[i] = mx(0.0, (pries[i]u)); GG ll pyo's t mturity for (int step=no periods1; step>=0; step) { for (int i=0; i<=step; ++i) { ll vlues[i] = (p up*ll vlues[i+1]+p down*ll vlues[i])*inv;
};

};

return ll vlues[0];
};

C++ Code 8.3:

Binomial multiperiod pricing of European call option

84

Chapter 9

Basic Option Pricing, the Black Scholes formula


Contents
9.1 9.2 The formula . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Understanding the why's of the formula . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 87

9.2.1 9.2.2 9.2.3


9.3

The original Black Scholes analysis . . . . . . . . . . . . . . . . . . . . . . . . . The limit of a binomial case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The representative agent framework . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

88 88 88
88

Partial derivatives.

9.3.1 9.3.2 9.3.3


9.4

Delta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Other Derivatives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Implied Volatility. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .


. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

88 89 91
93

References

The pricing of options and related instruments has been a major breakthrough for the use of nancial theory in practical application. Since the original papers of Black and Scholes (1973) and Merton (1973), there has been a wealth of practical and theoretical applications. We will now consider the orginal Black Scholes formula for pricing options, how it is calculated and used. For the basic intuition about option pricing the reader should rst read the discussion of the binomial model in the previous chapter, as that is a much better environment for understanding what is actually calculated.

derivative security, its value depends on the value, or price, of some other underlying security, called the underlying security.. Let S denote the value, or price, of this underlying security. We need to keep track of what time this price is observed at, so let St denote that the price is observed at time t. A call (put) option gives the holder the right, but not the obligation, to buy (sell) some underlying asset at a given price K , called the exercise price, on or before some given date T . If the option is a so called European option, it can only be used (exercised) at the maturity date. If the option is of the so called American type, it can be used (exercised) at any date up to and including the maturity date T . If exercised at time T , a call option provides payo
An option is a

CT a mx@H; ST K A
and a put option provides payo

PT a mx@H; K ST A
The Black Scholes formulas provides analytical solutions for

European

put and call options, options

which can only be exercised at the options maturity date. Black and Scholes showed that the additional information needed to price the option is the (continously compounded) risk free interest rate variability of the underlying asset, measured by the standard deviation the time to maturity

@T tA of the option, measured in years.

r,

the

of (log) price changes, and

The original formula was derived under

the assumption that there are no payouts, such as stock dividends, coming from the underlying security during the life of the option. Such payouts will aection option values, as will become apparent later.

9.1

The formula
wtl Code 9.1.
85

Formula 9.1 gives the exact formula for a call option, and the calculation of the same call option is shown in

C++ Code 9.1

and

c a SN @dI A Ker@T tA N @dP A


where

dI a
and

ln

S K C @r C

I P p P  A@T tA  T t

dP a dI  T t
Alternatively one can calculate

dI a dP a

S ln K C r@T

S ln K C r@T

 T t  T t

p p

tA C I pT t
P P

dI and dP as

tA I pT t

S is the price of the underlying security, K the exercise price, r the (continously compounded) risk free interest rate,  the standard deviation of the underlying asset, t the current date, T the maturity date, T t the time to maturity for the option and N the cumulative normal distribution.

@A

Formula 9.1:

The Black Scholes formula

#include <mth> #include "normdist.h"

GG mthemtil g lirry GG the lultion of the umulrive norml distriution

double option prie ll lk sholes(const double& , GG spot @underlyingA prie const double& u, GG strike @exeriseA prieD const double& r, GG interest rte const double& sigm, GG voltility const double& time) { GG time to mturity double time sqrt = sqrt(time); double dI = (log(/u)+r*time)/(sigm*time sqrt)+0.5*sigm*time sqrt; double dP = dI (sigm*time sqrt); return *x(dI) u*exp( r*time)*x(dP);

};

C++ Code 9.1:

Price of European call option using the Black Scholes formula

function

= lk sholes ll(,u,r,sigm,time) time sqrt = sqrt(time); dI = (log(/u)+r*time)/(sigm*time sqrt)+0.5*sigm*time sqrt; dP = dI(sigm*time sqrt); = * norml df (dI) u * exp(r*time) * norml df (dP); endfuntion

wtl Code 9.1:

Price of European call option using the Black Scholes formula

86

Example
Stock in company XYZ is currently trading at 50. Consider a call option on XYZ stock with an exercise price of

K a SH and time to maturity of 6 months.


1. Determine the option price.

The volatility of XYZ stock has been estimated to be

 a QH7.

The current risk free interest rate (with continous compounding) for six month borrowing is 10%.

To calculate the price of this option we use the Black Scholes formula with inputs

 a H:Q and @T tA a H:S.


wtl
program:

S a SH, K a SH, r a H:IH,

= 100; u = 100; r = 0.1; sigm = 0.1; time = 1; = lk sholes ll(,u,r,sigm,time)


Output from

wtl

program:

a IHFQHV
C++ program:

double = 50; double u = 50; double r = double sigm = 0.30; double time=0.50;

0.10;

out << " Black Scholes call price = "; out << option prie ll lk sholes(, u
Output from C++ program:

r, sigm, time) << endl;

flk holes ll prie a SFRSQPS


Exercise 9.1.
The Black Scholes price for a put option is:

p a Ker@T tA N @dP A SN @dI A


where

dP a dI  T t; S
interest rate,

dI and dP are as for the call option: S ln X C @r C I  P A@T tA p P dI a  T t

 the standard deviation of the underlying asset, T t the time to maturity for the option and N @A the cumulative normal distribution.
1. Implement this formula.

is the price of the underlying secrutity,

the exercise price,

the (continously compounded) risk free

9.2

Understanding the why's of the formula

To get some understanding of the Black Scholes formula and why it works will need to delve in some detail into the mathematics underlying its derivation. It does not help that there are a number of ways to prove the Black Scholes formula, depending on the setup. As it turns out, two of these ways are

important to understand for computational purposes, the original Black Scholes continous time way, and the limit of a binomial process way of Cox, Ross, and Rubinstein (1979).

87

9.2.1 The original Black Scholes analysis


The primary assumption underlying the Black Scholes analyis concerns the stochastic process governing the price of the underlying asset. The price of the underlying asset,

S , is assumed to follow a geometric

Brownian Motion process, conveniently written in either of the shorthand forms

dS a Sdt C SdZ
or

dS a dt C dZ S where  and  are constants, and Z

is Brownian motion.

Using Ito's lemma, the assumption of no arbitrage, and the ability to trade continuously, Black and

dierential equation

Scholes showed that the price of (9.1).

any

contingent claim written on the underlying must solve the

partial

@f I @ P f P P @f rS C C  S a rf (9.1) @S @t P @S P For any particular contingent claim, the terms of the claim will give a number of boundary conditions
that determines the form of the pricing formula. The pde given in equation (9.1), with the boundary condition

cT a mx@H; ST K A was shown by Black

and Scholes to have an analytical solution of functional form shown in the Black Scoles formula 9.1.

9.2.2 The limit of a binomial case


Another is to use the limit of a binomial process (Cox et al., 1979). The latter is particularly interesting, as it allows us to link the Black Scholes formula to the binomial, allowing the binomial framework to be used as an approximation.

9.2.3 The representative agent framework


A nal way to show the BS formula to assume a representative agent and lognormality as was done in Rubinstein (1976).

9.3

Partial derivatives.

In trading of options, a number of partial derivatives of the option price formula is important.

9.3.1 Delta
The rst derivative of the option price with respect to the price of the underlying security is called the

delta

of the option price.

It is the derivative most people will run into, since it is important in hedging

of options.

@c a N @dI A @S
C++ Code 9.2
shows the calculation of the delta for a call option.

88

#include <mth> #include "normdist.h"


double option prie delt ll lk sholes(const double& , GG spot prie const double& u, GG trike @exeriseA prieD const double& r, GG interest rte const double& sigm, GG voltility const double& time){ GG time to mturity double time sqrt = sqrt(time); double dI = (log(/u)+r*time)/(sigm*time sqrt) + 0.5*sigm*time sqrt; double delt = x(dI); return delt;
};

C++ Code 9.2:


Delta (

Calculating the delta of the Black Scholes call option price

@c a N @dI A @S

Gamma ( )

@Pc n@dI A P a SpT t @S


Theta (

) (careful about which of these you want) @c I I a Sn@dI A  p C rKer@T tA N @dP A @ @T tA P T t

@c I I a Sn@dI A  p rKer@T tA N @dP A @t P T t

p @c a S T tn@dI A @ Rho () @c a K @T tAer@T tA N @dP A @r


S is the price of the underlying security, K the exercise price, r the (continously compounded) risk free interest rate,  the standard deviation of the underlying asset, t the current date, T the maturity date and T t the time to maturity for the option.     z 1 2 n@A is the normal distribution function n@z A a p1  e 2 z and N @A the cumulative normal distribution N @z A a I n@tAdt . 2

Vega

Formula 9.2: 9.3.2 Other Derivatives

Partial derivatives of the Black Scholes call option formula

The remaining derivatives are more seldom used, but all of them are relevant. All of them are listed in formula 9.3.2. The calculation of all of these partial derivatives for a call option is shown in

C++ Code 9.3.

Example
Consider again six month call options on XYZ stock. The option matures 6 months from now, at which time the holder of the option can recive one unit of the underlying security by paying the exercise price of

 a QH7.

The current price of the underlying security is

S a SH.

K a SH.

The volatility of the underlying security is given as

The current risk free interest rate (with continous compounding) for six month borrowing is 10%.

89

#include <mth> #include "normdist.h" using namespace std;


void option prie prtils ll lk sholes( const double& , GG spot prie const double& u, GG trike @exeriseA prieD const double& r, GG interest rte const double& sigm, GG voltility const double& time, GG time to mturity double& helt, GG prtil wrt double& qmm, GG seond prt wrt double& het, GG prtil wrt time double& eg, GG prtil wrt sigm double& ho){ GG prtil wrt r double time sqrt = sqrt(time); double dI = (log(/u)+r*time)/(sigm*time sqrt) + 0.5*sigm*time sqrt; double dP = dI (sigm*time sqrt);

helt = x(dI); qmm = n(dI)/(*sigm*time sqrt); het = (*sigm*n(dI))/(2*time sqrt) eg = * time sqrt*n(dI); ho = u*time*exp(r*time)*x(dP);

r*u*exp( r*time)*x(dP);

};

C++ Code 9.3:

Calculating the partial derivatives of a Black Scholes call option

1. Calculate the partial derivatives (Delta, Gamma, Theta, Vega and Rho) for this option. To calculate the partial derivatives we use inputs C++ program:

S a SH, K a SH, r a H:IH,  a H:Q and @T tA a H:S.

out << " Black Scholes call partial derivatives " << endl; double = 50; double u = 50; double r = 0.10; double sigm = 0.30; double time=0.50; double helt, qmm, het, eg, ho; option prie prtils ll lk sholes(,u,r,sigm, time, helt, qmm, het, eg, ho); out << " Delta = " << helt << endl; out << " Gamma = " << qmm << endl; out << " Theta = " << het << endl; out << " Vega = " << eg << endl; out << " Rho = " << ho << endl;
Output from C++ program:

flk holes ll prtil derivtives helt a HFTQQUQU qmm a HFHQSRUVW het a ETFTIRUQ eg a IQFQHRT ho a IQFIITV

90

9.3.3 Implied Volatility.


In calculation of the option pricing formulas, in particular the Black Scholes formula, the only unknown is the standard deviation of the underlying stock. A common problem in option pricing is to nd the implied volatility, given the observed price quoted in the market. For example, given call option, the following equation should be solved for the value of

:

cH , the price of a

cH a c@S; K; r; ; T tA
Unfortunately, this equation has no closed form solution, which means the equation must be numerically solved to nd

.

What is probably the algorithmic simplest way to solve this is to use a binomial search

algorithm, which is implemented in

C++ Code 9.4.

We start by bracketing the sigma by nding a high

sigma that makes the BS price higher than the observed price, and then, given the bracketing interval, we search for the volatility in a systematic way. shows such a calculation.

#include <mth> #include "fin_recipes.h"


double option prie implied voltility ll lk sholes isetions(const double& , const double& u, const double& r, const double& time, const double& option prie){ if (option prie<0.99*( u*exp( time*r))) { GG hek for ritrge violtionsF return 0.0; GG yption prie is too low if this hppens

};

GG simple inomil serh for the implied voltilityF GG relies on the vlue of the option inresing in voltility const double eggeg = 1.0e5; GG mke this smller for higher ury const int we siesyx = 100; const double rsqr evi = 1e10; const double iy = 1e40; GG wnt to rket sigmF (rst (nd mximum sigm y (nding sigm GG with estimted prie higher thn the tul prieF double sigm low=1e5; double sigm high=0.3; double prie = option prie ll lk sholes(,u,r,sigm high,time); while (prie < option prie) { sigm high = 2.0 * sigm high; GG keep doulingF prie = option prie ll lk sholes(,u,r,sigm high,time); if (sigm high>rsqr evi) return iy; GG pniD something wrongF
};

for (int i=0;i<we siesyx;i++){ double sigm = (sigm low+sigm high)*0.5;

prie = option prie ll lk sholes(,u,r,sigm,time); double test = (prieoption prie); if (fs(test)<eggeg) { return sigm; }; if (test < 0.0) { sigm low = sigm; } else { sigm high = sigm; }

};

return iy;
};

C++ Code 9.4:

Calculation of implied volatility of Black Scholes using bisections

Instead of this simple bracketing, which is actually pretty fast, and will (almost) always nd the solution, we can use the NewtonRaphson formula for nding the root of an equation in a single variable. The general description of this method starts with a function

f @A for which we want to nd a root.

f @xA a H:
91

The function

f @A needs to be dierentiable.

Given a rst guess

xH , iterate by

f @x A xiCI a xi H i f @xi A
until

jf @xi Aj < 
where

 is the desired accuracy.1

In our case

f @xA a cobs cBS @A


and, each new iteration will calculate

iCI a i C
C++ Code 9.5

cobs cBS @i A @cBS @A


@

shows the calculation of implied volatility using Newton-Raphson.

#include "fin_recipes.h" #include "normdist.h" #include <mth> #include <iostrem> double option prie implied voltility ll lk sholes newton(const double& , const double& u, const double& r, const double& time, const double& option prie) { if (option prie<0.99*(u*exp(time*r))) { GG hek for ritrge violtionsF yption prie is too low if this hppens return 0.0;
};

const int we siesyx = 100; const double eggeg = 1.0e 5; double t sqrt = sqrt(time);

double sigm = (option prie/)/(0.398*t sqrt); GG (nd initil vlue for (int i=0;i<we siesyx;i++){ double prie = option prie ll lk sholes(,u,r,sigm,time); double di' = option prie prie; if (fs(di' )<eggeg) return sigm; double dI = (log(/u)+r*time)/(sigm*t sqrt) + 0.5*sigm*t sqrt; double veg = * t sqrt * n(dI);

sigm

sigm

di' /veg;

};

return
};

99e10; GG something srewy hppenedD should throw exeption


C++ Code 9.5:
Calculation of implied volatility of Black Scholes using Newton-Raphson For the Black-Scholes

Note that to use Newton-Raphson we need the derivative of the option price.

formula this is known, and we can use this. But for pricing formulas like the binomial, where the partial derivatives are not that easy to calculate, simple bisection is the preferred algorithm.

Example
Consider again six month call options on XYZ stock. The option matures 6 months from now, at which time the holder of the option can recive one unit of the underlying security by paying the exercise price of

K a SH.

1 por further disussion of the xewtonEphson formul nd rketingD good soure is hpter W of ress et lF @IWWPA

92

The current price of the underlying security is compounding) for six month borrowing is 10%. 1. The current option price is The implied volatility is the an option price of

S a SH.

The current risk free interest rate (with continous

C a P:S.

Determine the volatility implicit in this price.

 which, input in the Black Scholes formula with these other inputs, will produce C a P:S. To calculate we use inputs S a SH, K a SH, r a H:IH and @T tA a H:S.
C++ program:

out out out out

double = 50; double u double g=2.5;

= 50;

double r

= 0.10;

double time=0.50;

<< << << <<

" Black Scholes implied volatility using Newton search = "; option prie implied voltility ll lk sholes newton(,u,r,time,g) << endl; " Black Scholes implied volatility using bisections = "; option prie implied voltility ll lk sholes isetions(,u,r,time,g) << endl;

Output from C++ program:

flk holes implied voltility using xewton serh a HFHSHHRPU flk holes implied voltility using isetions a HFHSHHRIW

9.4

References

Black and Scholes (1973) Merton (1973) Gray and Gray (2001) has a simple proof of the formula.

93

Chapter 10

Warrants
Contents
10.1 Warrant value in terms of assets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2 Valuing warrants when observing the stock value . . . . . . . . . . . . . . . . . . . . . . . . . 10.3 Readings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 94 96

A warrant is an option-like security on equity, but it is issued by the same company which has issued the equity, and when a warrant is exercised, a

new

stock is issued. This new stock is issued at a the

warrant strike price, which is lower than the current stock price (If it wasn't the warrant would not be

dilutes, the equity in a company.


10.1
Let

exercised.) Since the new stock is a a fractional right to all cashows, this stock issue

waters out,

or

The degree of dilution is a function of how many warrants are issued.

Warrant value in terms of assets


be the strike price,

Assume each warrant is for 1 new share, and let

n the number of shares outstanding and m the number of warrants issued. At be the current asset value of rm. Suppose all

warrants are exercised simultaneously. Then the assets of the rm increase by the number of warrants times the strike price of the warrant.

At C mK;
but this new asset value is spread over more shares, since each exercised warrant is now an equity. The assets of the rm is spread over all shares, hence each new share is worth:

At C mK mCn
making each exercised warrant worth:

At C mK K a m n n At K mCn C n

If we knew the current value of assets in the company, we could value the warrant in two steps: 1. Value the option using the Black Scholes formula and 2. Multiply the resulting call price with If we let

At n

as the current stock price.

n mCn .

Wt be the warrant value, the above arguments are summarized as:   n A Wt a C ; K; ; r; @T tA ; n C m BS n where CBS @A is the Black Scholes formula.
10.2 Valuing warrants when observing the stock value

However, one does not necessarily observe the asset value of the rm. Typically one only observes the equity value of the rm. If we let

St be the current stock price, the asset value is really:

At a nSt C mWt
94

Using the stock price, one would value the warrant as

Wt a
or

nCm n

CBS

nSt C mWt ; K; ; r; @T tA n
 m Wt ; K; ; r; @T tA n

Wt a
nd

nCm

CBS St C

Note that this gives the value of

Wt .

Wt as a function of Wt .

One need to solve this equation numerically to

The numerical solution for

Wt is done using the Newton-Rhapson method.   m n CBS St C Wt ; K; ; r; @T tA g@Wt A a Wt nCm n g@W iI A Wti a WtiI H tiI ; g @Wt A

Let

Starting with an initial guess for the warrant value as follows

Wto , the Newton-Rhapson method is that one iterates

where case

i signies iteration i, until the criterion function g@WtiI A is below some given accuracy . m N @d A mCn I


In this

gH @Wt A a I
where

dI a

ln

St C m Wt n K

 T t

C @r C I  P A@T tA P

An obvious starting value is to set calculate the Black Scholes value using the current stock price, and multiply it with

C++ Code 10.1 Example

m mCn .

implements this calculation.

A stock is currently priced at

S a RV.

Consider warrants on the same company with exercise price

time to maturity of six months. The company has

K a RH and n a IHHHH shares outstanding, and has issued m a IHHH

warrants. The current (continously compounded) risk free interest rate is 8%. Determine the current warrant price. C++ program:

double = 48; double u = 40; double r = 0.08; double sigm = 0.30; double time = 0.5; double m = 1000; double n = 10000; double w = wrrnt prie djusted lk sholes(,u,r,sigm, time, m, n);

out << " warrant price = " << w << endl;

Output from C++ program:

wrrnt prie a IHFIRP


Exercise 10.1.
The solution method assumes that all warrants are exercised simultanously. Can you see where this assumption is used?

95

#include "fin_recipes.h" #include "normdist.h" #include <mth>


const double isvyx=0.00001; double wrrnt prie djusted lk sholes(const double& , const double& u, const double& r, const double& sigm, const double& time, const double& m, GG numer of wrrnts outstnding const double& n){ GG numer of shres outstnding double time sqrt = sqrt(time); double w = (n/(n+m))*option prie ll lk sholes(,u,r,sigm,time); double g = w (n/(n+m))*option prie ll lk sholes(+(m/n)*w,u,r,sigm,time); while (fs(g)>isvyx) { double dI = (log((+(m/n))/u)+r*time)/(sigm*time sqrt)+0.5*sigm*time sqrt; double gprime = 1 (m/n)*x(dI);

w=wg/gprime; g = w(n/(n+m))*option prie ll lk sholes(+(m/n)*w,u,r,sigm,time);

};

return w;
};

C++ Code 10.1:

Adjusted Black Scholes value for a Warrant

10.3

Readings

McDonald (2006) and Hull (2006) are general references. A problem with warrants is that exercise of all warrants simultaneously is not necessarily optimal. Press et al. (1992) discusses the Newton-Rhapson method for root nding.

96

Chapter 11

Extending the Black Scholes formula


Contents
11.1 Adjusting for payouts of the underlying. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

11.1.1 Continous Payouts from underlying. . . . . . . . . . . . . . . . . . . . . . . . . 11.1.2 Dividends. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .


11.2 American options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

97 98
99

11.2.1 Exact american call formula when stock is paying one dividend. . . . . . . . .
11.3 Options on futures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.4 Foreign Currency Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.5 Perpetual puts and calls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.6 Readings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

99
102 103 104 105

11.3.1 Black's model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102

11.1

Adjusting for payouts of the underlying.

For options on other nancial instruments than stocks, we have to allow for the fact that the underlying may have payouts during the life of the option. For example, in working with commodity options, there is often some storage costs if one wanted to hedge the option by buying the underlying.

11.1.1 Continous Payouts from underlying.


The simplest case is when the payouts are done continuously. To value an European option, a simple adjustment to the Black Scholes formula is all that is needed. Let underlying commodity. Call and put prices for European options are then given by formula 11.1, which are implemented in

be the

continuous payout

of the

C++ Code 11.1.

c a Seq@T tA N @dI A Ker@T tA N @dP A


where

I q C P P A@T tA p  T t p dP a dI  T t
dI a
ln

S K C @r

S is the price of the underlying secrutity, K the exercise price, r the risk free interest rate, q the (continous) payout and  the standard deviation of the underlying asset, t the current date, T the maturity date, T t the time to maturity for the option and N @A the cumulative normal distribution.

Formula 11.1:

Analytical prices for European call option on underlying security having a payout of

Exercise 11.1.
The price of a put on an underlying security with a continous payout of

p a Ker@T tA N @dP A Seq@T tA N @dI A


1. Implement this formula.

q is:

97

#include <mth> #include "normdist.h" using namespace std;

GG mthemtil lirry GG this de(nes the norml distriution

double option prie europen ll pyout( const double& , GG spot prie const double& , GG trike @exeriseA prieD const double& r, GG interest rte const double& q, GG yield on underlying const double& sigm, GG voltility const double& time) { GG time to mturity double sigm sqr = pow(sigm,2); double time sqrt = sqrt(time); double dI = (log(/) + (r q + 0.5*sigm sqr)*time)/(sigm*time sqrt); double dP = dI (sigm*time sqrt); * exp( r*time) * x(dP); double ll prie = * exp( q*time)* x(dI) return ll prie;

};

C++ Code 11.1: 11.1.2 Dividends.

Option price, continous payout from underlying

A special case of payouts from the underlying security is stock options when the stock pays dividends. When the stock pays dividends, the pricing formula is adjusted, because the dividend changes the value of the underlying. The case of continuous dividends is easiest to deal with. It corresponds to the continuous payouts we have looked at previously. The problem is the fact that most dividends are paid at discrete dates.

European Options on dividend-paying stock.


To adjust the price of an European option for known dividends, we merely subtract the present value of the dividends from the current price of the underlying asset in calculating the Black Scholes value.

#include <mth> #include <vetor> #include "fin_recipes.h"

GG mthemtil lirry GG de(ne the lk sholes prie

double option prie europen ll dividends( const double& , const double& u, const double& r, const double& sigm, const double& time to mturity, const vetor<double>& dividend times, const vetor<double>& dividend mounts double djusted = ; for (int i=0;i<dividend times.size();i++) { if (dividend times[i]<=time to mturity){

) {

djusted

= dividend

mounts[i]

exp(r*dividend times[i]);

}; };

return option prie ll lk sholes(djusted ,u,r,sigm,time to mturity);


};

C++ Code 11.2: Example

European option price, dividend paying stock

Consider a stock option with the following data given:

is one year. dividend yield = 5%. Dividend payments at times

S a IHH, K a IHH, r a H:I,  a H:PS, time to maturity H:PS and H:US.

98

Determine the option price

C++ program:

= 100.0; double u = 100.0; r = 0.1; double sigm = 0.25; time=1.0; dividend yield=0.05; vetor<double> dividend times; vetor<double> dividend mounts; dividend times.push k(0.25); dividend mounts.push k(2.5); dividend times.push k(0.75); dividend mounts.push k(2.5); out << " european stock call option with contininous dividend = " << option prie europen ll pyout(,u,r,dividend yield,sigm,time) << endl; out << " european stock call option with discrete dividend = " << option prie europen ll dividends(,u,r,sigm,time,dividend times,dividend mounts) << endl;
double double double double
Output from C++ program:

europen stok ll option with ontininous dividend a IIFUQRR europen stok ll option with disrete dividend a IIFVHWR

11.2

American options

American options are much harder to deal with than European ones. The problem is that it may be optimal to use (exercise) the option before the nal expiry date. This optimal exercise policy will aect the value of the option, and the exercise policy needs to be known when solving the pde. However, the exercise policy is not known. There is therefore no general analytical solutions for American call and put options. There are some special cases. For American call options on assets that do not have any payouts, the American call price is the same as the European one, since the optimal exercise policy is to not exercise. For American puts this this not the case, it may pay to exercise them early. When

the underlying asset has payouts, it may also pay to exercise an American call option early. There is one known known analytical price for American call options, which is the case of a call on a stock that pays a known dividend

once

during the life of the option, which is discussed next. In all other cases

the American price has to be approximated using one of the techniques discussed in later chapters: Binomial approximation, numerical solution of the partial dierential equation, or another numerical approximation.

11.2.1 Exact american call formula when stock is paying one dividend.
When a stock pays dividend, a call option on the stock may be optimally exercised just before the stock goes ex-dividend. While the general dividend problem is usually approximated somehow, for the special case of one dividend payment during the life of an option an analytical solution is available, due to RollGeskeWhaley. If we let

be the stock price,

dividend payment,

the exercise price,

DI

the amount of dividend paid,

tI

the time of

the maturity date of option, we denote the time to dividend payment

and the time to maturity

 a T t.


I a T tI

A rst check of early exercise is:

DI

K I er@T t1 A

If this inequality is fullled, early exercise is not optimal, and the value of the option is

c@S er@t1 tA DI ; K; r; ; @T tAA


where

c@A is the regular Black Scholes formula.


99

If the inequality is not fullled, one performs the calculation shown in

C++ Code 11.3.

Formula 11.2

and implemented in

C a @S DI er@t1 tA A @N @bI A C N @aI ; bI ; AA C Ker@T tAA N @aP ; bP ; A @K DI Aer@t1 tA N @bP A


where

a aI a

@tI t

ln

T t

S D1 eq(1 K

aP a aI  T t bI a
ln


 

C @ r C I  P A P

 S D1 er(t1 t) C @r C " S p

bP a bI  T t
and

 @tI tA

I P A@tI tA P

" S solves " " c@S; tI A a S C DI K

S is the price of the underlying secrutity, K the exercise price, r the risk free interest rate, D1 is the dividend amount and  the standard deviation of the underlying asset, t the current date, T the maturity date, T t the time to maturity for the option and N @A the cumulative normal distribution. N @A with one argument is the univariate normal cumulative distribution. N @A with
three arguments is the bivariate normal distribution with the correlation between the two normals given as the third arguement.

Formula 11.2: Example

RollGeskeWhaley price of american call option paying one xed dividend

Consider an option on a stock paying one dividend. The relevant data is

 a I:H, I a H:S and DI a IH.


Price the option. C++ program:

S a IHH, K a IHH;r=0.1,  a H:PS,

= 100.0; double u = 100.0; r = 0.1; double sigm = 0.25; tu = 1.0; double tuI = 0.5; hI = 10.0; out << " american call price with one dividend = " << option prie merin ll one dividend(,u,r,sigm,tu,hI, tuI)<< endl;
double double double double
Output from C++ program:

merin ll prie with one dividend a IHFHITT


Exercise 11.2.
The Black approximation to the price of an call option paying a xed dividend is an approximation to the value of the call. Suppose the dividend is paid as some date

tI

before the maturity date of the option

T.

Blacks approximation calculates the value of two European options using the Black Scholes formula. One with expiry date equal to the ex dividend date of the options. Another with expiry date equal to the option expiry, but the current price of the underlying security is adjusted down by the amount of the dividend. 1. Implement Black's approximation.

100

#include <mth> #include "normdist.h" GG de(ne the norml distriution funtions #include "fin_recipes.h" GG the regulr lk sholes formul
double option prie merin ll one dividend(const double& , const double& u, const double& r, const double& sigm, const double& tu, const double& hI, const double& tuI){ if (hI <= u* (1.0 exp( r*(tu tuI)))) GG hek for no exerise return option prie ll lk sholes( exp( r*tuI)*hI,u,r,sigm,tu); const double eggeg = 1e 6; GG derese this for more ury double sigm sqr = sigm*sigm; double tu sqrt = sqrt(tu); double tuI sqrt = sqrt(tuI); double rho = sqrt(tuI/tu);

double r = 0; GG (rst (nd the r tht solves a rChIEu double low=0; GG the simplestX inomil serh double high=; GG strt y (nding very high ove r double = option prie ll lk sholes( high,u,r,sigm,tu tuI); double test = high hI+u; while ( (test>0.0) && ( high<=1e10) ) {

high *= 2.0; = option prie ll lk sholes( high,u,r,sigm,tutuI); test = highhI+u;

};

if ( high>1e10) { GG erly exerise never optimlD (nd f vlue return option prie ll lk sholes( hI*exp( r*tuI),u,r,sigm,tu);

};

r = 0.5 * high; GG now (nd r tht solves a rEhCu = option prie ll lk sholes( r,u,r,sigm,tutuI); test = rhI+u; while ( (fs(test)>eggeg) && (( high low)>eggeg) if (test<0.0) { high = r; } else { low = r; }; r = 0.5 * ( high + low); = option prie ll lk sholes( r,u,r,sigm,tutuI); test = rhI+u;
};

) {

double double double double double

I = (log((hI*exp(r*tuI))/u) +( r+0.5*sigm sqr)*tu) / (sigm*tu sqrt); P = I sigm*tu sqrt; I = (log((hI*exp(r*tuI))/ r)+(r+0.5*sigm sqr)*tuI)/(sigm*tuI sqrt); P = I sigm * tuI sqrt; g = (hI*exp(r*tuI)) * x(I) + (hI*exp(r*tuI)) * x(I,I,rho) (u*exp(r*tu))*x(P,P,rho) (uhI)*exp(r*tuI)*x(P); return g;

};

C++ Code 11.3:

Option price, RollGeskeWhaley call formula for dividend paying stock

101

11.3

Options on futures

11.3.1 Black's model


For an European option written on a futures contract, we use an adjustment of the Black Scholes solution, which was developed in Black (1976). Essentially we replace formula, and get the formula shown in 11.3 and implemented in C++

SH

with

Code 11.4.

er@T tAr F

in the Black Scholes

c a er@T tA @F N @dI A KN @dP AA


where

p P  @T tA  T t p dP a dI  T t
dI a
ln

F K C

I P

is the futures price,

price, and

Formula 11.3:

T t is the time to maturity of the option (in years).

K is the exercise price, r the risk free interest rate,  the volatility of the futures

Black's formula for the price of an European Call option with a futures contract as the

underlying security

#include <mth> #include "normdist.h" using namespace std;

GG mthemtis lirry GG norml distriution

double futures option prie ll europen lk( const double& p, GG futures prie const double& u, GG exerise prie const double& r, GG interest rte const double& sigm, GG voltility const double& time){ GG time to mturity double sigm sqr = sigm*sigm; double time sqrt = sqrt(time); double dI = (log (p/u) + 0.5 * sigm sqr * time) / (sigm * time sqrt); double dP = dI sigm * time sqrt; return exp( r*time)*(p * x(dI) u * x(dP));

};

C++ Code 11.4: Example

Price of European Call option on Futures contract

Price a futures option in the Black setting. Information: maturity is a half year. C++ program:

F a SH, K a RS, r a V7,  a H:P, and time to

double p = 50.0; double u = 45.0; double r = 0.08; double sigm = 0.2; double time=0.5;

out << " european futures call option = " << futures option prie put europen lk(p,u,r,sigm,time) << endl;
Output from C++ program:

europen futures ll option a HFVSIRUT


Exercise 11.3.
102

The Black formula for a put option on a futures contract is

p a er@T tA @KN @dP A F N @dI AA


where the varibles are as dened for the call option. 1. Implement the put option price.

11.4

Foreign Currency Options

Another relatively simple adjustment of the Black Scholes formula occurs when the underlying security is a currency exchange rate (spot rate). interest-rate dierential. In this case one adjusts the Black-Scholes equation for the

S be the spot exchange rate, and now let r be the domestic interest rate and rf the foreign interest rate.  is then the volatility of changes in the exchange rate. The calculation of the price of an European
Let call option is then shown in formula 11.4 and implented in

C++ Code 11.5.

c a Serf @T tA N @dI A Ker@T tA N @dP A


where

rf C I P @T tA p P dI a  T t p dP a dI  T t
ln
Formula 11.4:
European currency call

S K C r

S is the spot exchange rate and K the exercise price. r is the domestic interest rate and rf the foreign interest rate.  is the volatility of changes in the exchange rate. T t is the time to maturity for the option.

#include <mth> #include "normdist.h"

GG de(ne the norml distriution funtion

double urreny option prie ll europen( const double& , GG exhnge rteD const double& , GG exeriseD const double& r, GG r domestiD const double& r f, GG r foreignD const double& sigm, GG voltilityD const double& time){ GG time to mturity double sigm sqr = sigm*sigm; double time sqrt = sqrt(time); double dI = (log(/) + (r r f + (0.5*sigm sqr)) * time)/(sigm*time sqrt); double dP = dI sigm * time sqrt; return * exp( r f *time) * x(dI) * exp( r*time) * x(dP);

};

C++ Code 11.5: Example

European Futures Call option on currency

Price a European currency call given the following information and time to maturity = 0.5 years.

S a SH, K a SP, r a V7, rf a S7,  a PH7

103

C++ program:

double = 50.0; double u = 52.0; double r = 0.08; double rf =0.05; double sigm = 0.2; double time=0.5;

out << " european currency call option = " << urreny option prie ll europen(,u,r,rf,sigm,time) << endl;
Output from C++ program:

europen urreny ll option a PFPPSST


Exercise 11.4.
The price for an european put for a currency option is

p a Ker@T tA N @dP A Serf @T tA N @dI A


1. Implement this formula.

11.5
A

Perpetual puts and calls


Of course, only American perpetual

perpetal option is one with no maturity date, it is ininitely lived.

options make any sense, European perpetual options would probably be hard to sell.

1 For both puts

and calls analytical formulas has been developed. We consider the price of an American call, and discuss the put in an exercise. Formula 11.5 gives the analytical solution.

Cp
where

K hI I S a hI I hI K
s 

h1

I rq hI a P C P 

 r q I P Pr P C P P

S is the current price of the underlying security, K is the exercise price, r is the risk free interest rate, q is the dividend yield and  is the volatility of the underlying asset.

Formula 11.5:

Price for a perpetual call option

#include <mth> using namespace std;


double option prie merin perpetul ll(const const const const const double sigm sqr=pow(sigm,2); double hI = 0.5 ((r q)/sigm sqr); double& double& double& double& double&

, u, r, q, sigm){

hI += sqrt(pow(((rq)/sigm sqr0.5),2)+2.0*r/sigm sqr); double pri=(u/(hI1.0))*pow(((hI1.0)/hI)*(/u),hI); return pri;

};

C++ Code 11.6:

Price for an american perpetual call option

1 uh options would e like the lssil epril fools presentD perpetul zero oupon ondF F F

104

Example
Price a perpetual call, given the following informtation C++ program:

S a SH:H; K a RH:H; r a H:HS; q a H:HP;  a H:HS

double double double double

=50.0; double u=40.0; r=0.05; double q=0.02; sigm=0.05; prie = option prie merin perpetul ll(,u,r,q,sigm); out << " perpetual call price = " << prie << endl;

Output from C++ program:

perpetul ll prie a IWFRUTU


Exercise 11.5.
The price for a perpetual american put is

Pp a
where

hP I S K I hP hP K

h2

I rq hP a P P 

s 

 r q I P Pr P C P P

1. Implement the calculation of this formula.

11.6

Readings

Hull (2006) and McDonald (2006) are general references. A rst formulation of an analytical call price with dividends was in Roll (1977b). This had some errors, that were partially corrected in Geske (1979), before Whaley (1981) gave a nal, correct formula. See Hull (2006) for a textbook summary. Black

(1976) is the original development of the futures option. The original formulations of European foreign currency option prices are in Garman and Kohlhagen (1983) and Grabbe (1983). The price of a perpetual put was rst shown in Merton (1973). For a perpetual call see McDonald and Siegel (1986). The notation for perpetual puts and calls follows the summary in (McDonald, 2006, pg. 393).

105

Chapter 12

Option pricing with binomial approximations


Contents
12.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2 Pricing of options in the Black Scholes setting . . . . . . . . . . . . . . . . . . . . . . . . . . 106 107

12.2.1 European Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 12.2.2 American Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 12.2.3 Matlab implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
12.3 How good is the binomial approximation? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.4 Adjusting for payouts for the underlying . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 116 117

12.3.1 Estimating partials. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113


12.5 Pricing options on stocks paying dividends using a binomial approximation . . . . . . . . . . . .

12.5.1 Checking for early exercise in the binomial model. . . . . . . . . . . . . . . . . 117 12.5.2 Proportional dividends. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 12.5.3 Discrete dividends . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
12.6 Option on futures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.7 Foreign Currency options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.8 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 123 124

12.1

Introduction

We have shown binomial calculations given an up and down movement in chapter 8. However, binomial option pricing can also be viewed as an choice of the constants of

u and d. To do so one has to ask: u and d) of a binomial process

approximation

to a continuous time distribution by judicious Is it possible to nd a parametrization (choice

S r rr r

B r ruS rr

B uuS

rr

r j r B udS

rr

r j r dS r rr r

rr

r ddS j r

which has the same time series properties as a (continous time) process with the same mean and volatility? There is actually any number of ways of constructing this, hence one uses one degree of freedom on imposing that the nodes

I reconnect, by imposing u a d .

To value an option using this approach, we specify the number

@T tA into, and then calculate the option using a binomial tree with that number of steps.
106

n of periods to split the time to maturity

Given

S; X; r; ; T T t n

and the number of periods

n, calculate

t a

p d a e t
We also redene the risk neutral probabilities

p u a e t

R a e r t qa Rd ud t C I. t,
calculate the call price as a function of the For example, if there is one step,

To nd the option price, will roll backwards: At node two possible outcomes at time

CH rr rr rr

Cu a mx@H; Su X A

r j r

Cd a mx@H; Sd X A

nd the call price at time 0 as

CH a er @qCu C @I qACd A
With more periods one will roll backwards as discussed in chapter 8

12.2

Pricing of options in the Black Scholes setting

Consider options on underlying securities not paying dividend.

12.2.1 European Options


For European options, binomial trees are not that much used, since the Black Scholes model will give the correct answer, but it is useful to see the construction of the binomial tree without the checks for early exercise, which is the American case. The computer algorithm for a binomial in the following merits some comments. There is only one vector of call prices, and one may think one needs two, one at time

t and another at time t C I.

(Try to write

down the way you would solve it before looking at the algorithm below.) But by using the fact that the branches reconnect, it is possible to get away with the algorithm below, using one less array. You may want to check how this works. It is also a useful way to make sure one understands binomial option pricing.

107

#include <mth> #include <lgorithm> #include <vetor> using namespace std;

GG stndrd mthemtil lirry GG de(ning the mx@A opertor GG v vetor templtes

double option prie ll europen inomil( const double& , GG spot prie const double& u, GG exerie prie const double& r, GG interest rte const double& sigm, GG voltility const double& t, GG time to mturity const int& steps){ GG no steps in inomil tree double = exp(r*(t/steps)); GG interest rte for eh step double inv = 1.0/; GG inverse of interest rte double u = exp(sigm*sqrt(t/steps)); GG up movement double uu = u*u; double d = 1.0/u; double p up = ( d)/(u d); double p down = 1.0 p up; vetor<double> pries(steps+1); GG prie of underlying

for (int i=1; i<=steps; ++i) pries[i] = uu*pries[i 1]; vetor<double> ll vlues(steps+1); GG vlue of orresponding ll for (int i=0; i<=steps; ++i) ll vlues[i] = mx(0.0, (pries[i] u)); GG ll pyo's t mturity for (int step=steps 1; step>=0; step) { for (int i=0; i<=step; ++i) {

pries[0]

*pow(d, steps); GG (ll in the endnodesF

ll vlues[i]

= (p

up*ll vlues[i+1]+p down*ll vlues[i])*inv;

}; };

return ll vlues[0];
};

C++ Code 12.1: 12.2.2 American Options

Option price for binomial european

An American option diers from an European option by the exercise possibility. An American option can be exercised at any time up to the maturity date, unlike the European option, which can only be exercised at maturity. In general, there is unfortunately no analytical solution to the American option problem, but in some cases it can be found. For example, for an American call option on non-dividend paying stock, the American price is the same as the European call. It is in the case of American options, allowing for the possibility of early exercise, that binomial approximations are useful. At each node we calculate the value of the option as a function of the next periods prices, and then check for the value exercising of exercising the option now

C++ Code 12.2

illustrates the calculation of the price of an American call.

Actually, for this particular case, the american price will equal the european.

108

#include <mth> #include <vetor> using namespace std;


double option prie ll merin inomil( const const const const const const double = exp(r*(t/steps)); double inv = 1.0/; double u = exp(sigm*sqrt(t/steps)); double d = 1.0/u; double p up = ( d)/(u d); double p down = 1.0 p up; double& , double& u, double& r, double& sigm, double& t, int& steps) {

vetor<double> pries(steps+1); GG prie of underlying pries[0] = *pow(d, steps); GG (ll in the endnodesF double uu = u*u; for (int i=1; i<=steps; ++i) pries[i] = uu*pries[i1]; vetor<double> ll vlues(steps+1); GG vlue of orresponding ll for (int i=0; i<=steps; ++i) ll vlues[i] = mx(0.0, (pries[i] u)); GG ll pyo's t mturity

for (int step=steps 1; step>=0; for (int i=0; i<=step; ++i) {

step) {

ll vlues[i] = (p up*ll vlues[i+1]+p down*ll vlues[i])*inv; pries[i] = d*pries[i+1]; GG hek for exerise ll vlues[i] = mx(ll vlues[i],pries[i]u);

}; };

return ll vlues[0];
};

C++ Code 12.2:

Price of American call option using a binomial approximation

109

12.2.3 wtl implementation


To illustrate dierences between and

wtl Code 12.2.

wtl and C++, consider the two implementations in wtl Code 12.1

The calculation of a put is more compact, with less loops, by some judicious use

of array indexing.

function

= in m ll( , u, r, sigm,t,steps) = exp(r*(t/steps)); inv = 1.0/; u = exp(sigm*sqrt(t/steps)); d = 1.0/u; p up = (d)/(ud); p down = 1.0p up; pries = zeros(steps+1);

pries(1) = *(d^steps); uu = u*u; for i=2:steps pries(i) = uu*pries(i1); end ll vlues = max(0.0, (pries u)); for step=steps: 1:1 for i=1:step+1 ll vlues(i) = (p up*ll vlues(i+1)+p down*ll vlues(i))*inv; pries(i) = d*pries(i+1); ll vlues(i) = max(ll vlues(i),pries(i) u); end end

end

= ll vlues(1);

wtl Code 12.1:

Price of American call using a binomial approximation

function p = in m put( , u, r, sigm, t, steps) = exp(r*(t/steps));

inv = 1.0/; u = exp(sigm*sqrt(t/steps)); d = 1.0/u; p up = (d)/(ud); p down = 1.0p up;

pries = zeros(steps+1,1); pries(1) = *(d^steps); uu = u*u; for i=2:steps+1 pries(i) = uu*pries(i1); end vlues = max(0.0, (upries)); for step=steps:1:1 vlues = inv * ( p up*vlues(2:step+1) pries = u*pries(1:step); vlues = max(vlues,upries); end p=vlues(1); end

p down*vlues(1:step)

);

wtl Code 12.2:

Price of American put using a binomial approximation

110

Example
You are given the following information about an option:

S a IHH, K a IHH, r a H:I,  a H:PS and time to

maturity is 1 year. Price American calls and puts using binomial approximations with 100 steps. C++ program:

double = 100.0; double u = 100.0; double r = 0.1; double sigm = 0.25; double time=1.0; int no steps = 100;

out << " european call= " << option prie ll europen inomil(,u,r,sigm,time,no steps) << endl; out << " american call= " << option prie ll merin inomil(,u,r,sigm,time,no steps) << endl; out << " american put = " << option prie put merin inomil(,u,r,sigm,time,no steps) << endl;

Output from C++ program:

europen lla IRFWSHS merin lla IRFWSHS merin put a TFSRTWI wtl
program:

=100; u=100; r=0.1; sigm=0.25; time=1; no steps=100; g = in m ll(,u,r,sigm,time,no steps) = in m put(,u,r,sigm,time,no steps)
Output from

wtl

program:

g a IRFWSI a TFSRTW

111

12.3

How good is the binomial approximation?

To illustrate the behaviour of the binomial approximation gure 12.1 plots a comparison with the binomial approximation as a function of

n, the number of steps in the binomial approximation, and the true n, but rapidly moves towards the Black Scholes

(Black Scholes) value of the option. Note the sawtooth pattern, the binomial approximation jumps back and forth around the true value for small values of value as the

n increases.
17

Figure 12.1

Illustrating convergence of binomial to Black Scholes

16.5

16

15.5 c 15 14.5 14 13.5 0 10 20 30 40 50 n 60 70 80 90 100

binomial

Black Scholes

112

12.3.1 Estimating partials.


It is always necessary to calculate the partial derivatives as well as the option price. Let us start with Delta, the derivative of the option price with respect to the underlying. The binomial methods gives us ways to approximate these as well. How to nd them in the binomial case are described in Hull (2006). The implementation in

C++ Code 12.3

is for the nondividend case.

#include <mth> #include <lgorithm> #include <vetor> using namespace std;


double option prie delt merin ll inomil(const const const const const const double double double double double double double double& double& double& double& double& int& no

, u, r, sigm, t, steps){ GG steps in inomil

= exp(r*(t/no steps)); inv = 1.0/; u = exp(sigm*sqrt(t/no steps)); d = 1.0/u; uu= u*u; pp = (d)/(ud); phown = 1.0 pp;

vetor<double> pries (no steps+1); pries[0] = *pow(d, no steps); for (int i=1; i<=no steps; ++i) pries[i]

uu*pries[i1];
=

vetor<double> ll vlues (no steps+1); for (int i=0; i<=no steps; ++i) ll vlues[i]

mx(0.0, (pries[i]u));

for (int gurrtep=no steps 1 ; gurrtep>=1; for (int i=0; i<=gurrtep; ++i) {

gurrtep) {

pries[i] = d*pries[i+1]; ll vlues[i] = (phown*ll vlues[i]+pp*ll vlues[i+1])*inv; ll vlues[i] = mx(ll vlues[i], pries[i]u); GG hek for exerise
= (ll

}; };

double delt return delt;


};

vlues[1]ll vlues[0])/(*u*d);

C++ Code 12.3:


Calculation of all the derivatives are shown in

Delta

C++ Code 12.4

113

#include <mth> #include <lgorithm> #include "fin_recipes.h"


void option prie prtils merin ll inomil(const double& , GG spot prie const double& u, GG ixerise prieD const double& r, GG interest rte const double& sigm, GG voltility const double& time, GG time to mturity const int& no steps, GG steps in inomil double& delt, GG prtil wrt double& gmm, GG seond prt wrt double& thet, GG prtil wrt time double& veg, GG prtil wrt sigm double& rho){ GG prtil wrt r vetor<double> pries(no steps+1); vetor<double> ll vlues(no steps+1); double delt t =(time/no steps); double = exp(r*delt t); double inv = 1.0/; double u = exp(sigm*sqrt(delt t)); double d = 1.0/u; double uu= u*u; double pp = ( d)/(u d); double phown = 1.0 pp;

pries[0] = *pow(d, no steps); for (int i=1; i<=no steps; ++i) pries[i] = uu*pries[i1]; for (int i=0; i<=no steps; ++i) ll vlues[i] = mx(0.0, (pries[i]u)); for (int gurrtep=no steps1; gurrtep>=2; gurrtep) { for (int i=0; i<=gurrtep; ++i) { pries[i] = d*pries[i+1]; ll vlues[i] = (phown*ll vlues[i]+pp*ll vlues[i+1])*inv; ll vlues[i] = mx(ll vlues[i], pries[i]u); GG hek for exerise
}; };

double fPP = ll vlues[2]; double fPI = ll vlues[1]; double fPH = ll vlues[0]; for (int i=0;i<=1;i++) {

pries[i] = d*pries[i+1]; ll vlues[i] = (phown*ll vlues[i]+pp*ll vlues[i+1])*inv; ll vlues[i] = mx(ll vlues[i], pries[i]u); GG hek for exerise
= =

};

ll vlues[1]; ll vlues[0]; pries[0] = d*pries[1]; ll vlues[0] = (phown*ll vlues[0]+pp*ll vlues[1])*inv; ll vlues[0] = mx(ll vlues[0], u); GG hek for exerise on (rst dte double fHH = ll vlues[0]; delt = (fIIfIH)/(*u*d); double h = 0.5 * * ( uu d*d); gmm = ( (fPPfPI)/(*(uu1)) (fPIfPH)/(*(1d*d)) ) / h; thet = (fPIfHH) / (2*delt t); double di' = 0.02; double tmp sigm = sigm+di' ; double tmp pries = option prie ll merin inomil(,u,r,tmp sigm,time,no steps); veg = (tmp priesfHH)/di' ; di' = 0.05; double tmp r = r+di' ; tmp pries = option prie ll merin inomil(,u,tmp r,sigm,time,no steps); rho = (tmp priesfHH)/di' ;
};

double fII double fIH

C++ Code 12.4:

Hedge parameters

114

Example
Given the following information:

S a IHH, K a IHH, r a H:I,  a H:PS and time to maturity is 1 year, Use


), gamma, theta, vega and rho.

100 steps in the binomial approximation. 1. Estimate all the greeks for the option: delta( C++ program:

double double double double

= 100.0; double u = 100.0; r = 0.1; double sigm = 0.25; time=1.0; int no steps = 100; delt, gmm, thet, veg, rho; option prie prtils merin ll inomil(,u,r, sigm, time, no steps, delt, gmm, thet, veg, rho); out << " Call price partials " << endl; out << " delta = " << delt << endl; out << " gamma = " << gmm << endl; out << " theta = " << thet << endl; out << " vega = " << veg << endl; out << " rho = " << rho << endl;

Output from C++ program:

gll prie prtils delt a HFTWWUWP gmm a HFHIRHRHU thet a EWFVWHTU veg a QRFVSQT rho a STFWTSP
Exercise 12.1.

@T tA a I and r a H:I.

Consider an American call option on non-dividend paying stock, where

S a IHH, K a IHH,  a H:P,

1. Calculate the price of this option using Black Scholes 2. Calculate the price using a binomial approximation, using 10, 100 and 1000 steps in the approximation. 3. Discuss sources of dierences in the estimated prices.

115

12.4

Adjusting for payouts for the underlying

The simplest case of a payout is the similar one to the one we saw in the Black Scholes case, a continous payout of

y.

#include <mth> #include <lgorithm> #include <vetor> using namespace std;

GG stndrd mthemtil lirry GG de(nes the mx@A opertor GG v vetor templtes

double option prie ll merin inomil( const double& , GG spot prie const double& u, GG exerie prie const double& r, GG interest rte const double& y, GG ontinous pyout const double& sigm, GG voltility const double& t, GG time to mturity const int& steps) { GG no steps in inomil tree double = exp(r*(t/steps)); GG interest rte for eh step double inv = 1.0/; GG inverse of interest rte double u = exp(sigm*sqrt(t/steps)); GG up movement double uu = u*u; double d = 1.0/u; double p up = (exp((r y)*(t/steps)) d)/(u d); double p down = 1.0 p up; vetor<double> pries(steps+1); GG prie of underlying

pries[0] = *pow(d, steps); for (int i=1; i<=steps; ++i) pries[i]

uu*pries[i1]; GG (ll in the endnodesF

vetor<double> ll vlues(steps+1); GG vlue of orresponding ll for (int i=0; i<=steps; ++i) ll vlues[i] = mx(0.0, (pries[i] u)); GG ll pyo's t mturity

for (int step=steps 1; step>=0; for (int i=0; i<=step; ++i) {

step) {

ll vlues[i] = (p up*ll vlues[i+1]+p down*ll vlues[i])*inv; pries[i] = d*pries[i+1]; ll vlues[i] = mx(ll vlues[i],pries[i]u); GG hek for exerise

}; };

return ll vlues[0];
};

C++ Code 12.5:

Binomial option price with continous payout

116

12.5

Pricing options on stocks paying dividends using a binomial approximation

12.5.1 Checking for early exercise in the binomial model.


If the underlying asset is a stock paying dividends during the maturity of the option, the terms of the option is not adjusted to reect this cash payment, which means that the option value will reect the dividend payments. In the binomial model, the adjustment for dividends depend on whether the dividends are discrete or proportional.

12.5.2 Proportional dividends.


For proportional dividends, we simply multiply with an adjustment factor the stock prices at the ex dividend date, the nodes in the binomial tree will link up again, and we can use the same rolling back procedure.

117

#include #include #include #include #include

<mth> <lgorithm> <vetor>

"fin_recipes.h" <iostrem>

double option prie ll merin proportionl dividends inomil(const double& , const double& u, const double& r, const double& sigm, const double& time, const int& no steps, const vetor<double>& dividend times, const vetor<double>& dividend yields)

GG note tht the lst dividend dte should e efore the expiry dteD prolems if dividend t terminl node int no dividends=dividend times.size(); if (no dividends == 0) { return option prie ll merin inomil(,u,r,sigm,time,no steps); GG prie wGo dividends
};

double double double double double double double double

delt t = time/no steps; = exp(r*delt t); inv = 1.0/; u = exp(sigm*sqrt(delt t)); uu= u*u; d = 1.0/u; pp = (d)/(ud); phown = 1.0 pp; vetor<int> dividend steps(no dividends); GG when dividends re pid for (int i=0; i<no dividends; ++i) { dividend steps[i] = (int)(dividend times[i]/time*no steps);
};

vetor<double> pries(no steps+1); vetor<double> ll pries(no steps+1); pries[0] = *pow(d, no steps); GG djust downwrd terminl pries y dividends for (int i=0; i<no dividends; ++i) { pries[0]*=(1.0dividend yields[i]); }; for (int i=1; i<=no steps; ++i) { pries[i] = uu*pries[i1]; }; for (int i=0; i<=no steps; ++i) ll pries[i] = mx(0.0, (pries[i]u));
for (int step=no steps 1; step>=0; step) { for (int i=0;i<no dividends;++i) { GG hek whether dividend pid if (step==dividend steps[i]) { for (int j=0;j<=(step+1);++j) {

pries[j]*=(1.0/(1.0dividend yields[i]));

}; }; };

for (int i=0; i<=step;

++i) { ll pries[i] = (phown*ll pries[i]+pp*ll pries[i+1])*inv; pries[i] = d*pries[i+1]; GG hek for exerise ll pries[i] = mx(ll pries[i], pries[i]u);

}; };

return ll pries[0];
};

C++ Code 12.6:

Binomial option price of stock option where stock pays proportional dividends

118

12.5.3 Discrete dividends


The problem is when the dividends are constant dollar amounts. In that case the nodes of the binomial tree do not link up, and the number of branches increases dramatically, which means that the time to do the calculation is increased. The algorithm presented in

C++ Code 12.7

implements this case, with no linkup, by constructing a bi-

nomial tree up to the ex-dividend date, and then, at the terminal nodes of that tree, call itself with one less dividend payment, and time to maturity the time remaining at the ex-dividend date. Doing that calculates the value of the option at the ex-dividend date, which is then compared to the value of exercising just before the ex-dividend date. It is a instructive example of using recursion in simplifying calculations, but as with most recursive solutions, it has a cost in computing time. For large binomial trees and several dividends this procedure is costly in computing time.

119

#include <mth> #include <vetor> #include "fin_recipes.h" #include <iostrem> double option prie ll merin disrete dividends inomil(const double& , const double& u, const double& r, const double& sigm, const double& t, const int& steps, const vetor<double>& dividend times, const vetor<double>& dividend mounts) { int no dividends = dividend times.size(); if (no dividends==0) return option prie ll merin inomil(,u,r,sigm,t,steps);GG just do regulr int steps efore dividend = (int)(dividend times[0]/t*steps); const double = exp(r*(t/steps)); const double inv = 1.0/; const double u = exp(sigm*sqrt(t/steps)); const double d = 1.0/u; const double pp = (d)/(ud); const double phown = 1.0 pp; double dividend mount = dividend mounts[0]; vetor<double> tmp dividend times(no dividends1); GG temporries with vetor<double> tmp dividend mounts(no dividends1); GG one less dividend for (int i=0;i<(no dividends1);++i){ tmp dividend mounts[i] = dividend mounts[i+1]; tmp dividend times[i] = dividend times[i+1] dividend times[0];

vetor<double> pries(steps efore dividend+1); vetor<double> ll vlues(steps efore dividend+1); pries[0] = *pow(d, steps efore dividend); for (int i=1; i<=steps efore dividend; ++i) pries[i] = u*u*pries[i1]; for (int i=0; i<=steps efore dividend; ++i){ double vlue live = option prie ll merin disrete dividends inomil(pries[i]dividend mount,u, r, sigm, tdividend times[0],GG time fter (rst dividend stepssteps efore dividend, tmp dividend times, tmp dividend mounts); ll vlues[i] = mx(vlue live,(pries[i]u)); GG ompre to exerising now
};

};

for (int step=steps efore dividend for (int i=0; i<=step; ++i) {

1; step>=0; step) {

pries[i] = d*pries[i+1]; ll vlues[i] = (phown*ll vlues[i]+pp*ll vlues[i+1])*inv; ll vlues[i] = mx(ll vlues[i], pries[i]u);

}; };

return ll vlues[0];
};

C++ Code 12.7:

Binomial option price of stock option where stock pays discrete dividends

120

Example
Given the following information

S a IHH, K a IHH, r a H:I,  a H:PS

and time to maturity is 1 year,

Calculate option price with two dierent assumptions about dividends: 1. Continuous payout 2. Discrete payout, C++ program:

d a H:HP.

d a H:HPS at times H:PS and H:US.

= 100.0; double u = 100.0; r = 0.10; double sigm = 0.25; time=1.0; steps = 100; d=0.02; out << " call price with continuous dividend payout = " << option prie ll merin inomil(,u,r,d,sigm,time,no steps) << endl; vetor<double> dividend times; vetor<double> dividend yields; dividend times.push k(0.25); dividend yields.push k(0.025); dividend times.push k(0.75); dividend yields.push k(0.025); out << " call price with proportial dividend yields at discrete dates = " << option prie ll merin proportionl dividends inomil(,u,r,sigm,time,no steps, dividend times, dividend yields) << endl; vetor<double> dividend mounts; dividend mounts.push k(2.5); dividend mounts.push k(2.5); out << " call price with proportial dividend amounts at discrete dates = " << option prie ll merin disrete dividends inomil(,u,r,sigm,time,no steps, dividend times, dividend mounts) << endl;
double double double int no double
Output from C++ program:

ll prie with ontinuous dividend pyout a IQFSWPT ll prie with proportil dividend yields t disrete dtes a IIFVTHR ll prie with proportil dividend mounts t disrete dtes a IPFHPQQ

12.6

Option on futures

For American options, because of the feasibility of early exercise, the binomial model is used to approximate the option value for both puts and calls.

Example

F a SH:H; K a RS:H; r a H:HV; sigma a H:P, time=0.5, no steps=100; Price the futures option
C++ program:

double double double int no

p = 50.0; double u = 45.0; r = 0.08; double sigm = 0.2; time=0.5; steps=100; out << " european futures call option = " << futures option prie ll merin inomil(p,u,r,sigm,time,no steps) << endl;

Output from C++ program:

europen futures ll option a SFURPSR

121

#include <mth> #include <lgorithm> #include <vetor> using namespace std;


double futures option prie ll merin inomil(const double& p, GG prie futures ontrt const double& u, GG exerise prie const double& r, GG interest rte const double& sigm, GG voltility const double& time, GG time to mturity const int& no steps) { GG numer of steps vetor<double> futures pries(no steps+1); vetor<double> ll vlues (no steps+1); double t delt= time/no steps; double inv = exp( r*(t delt)); double u = exp(sigm*sqrt(t delt)); double d = 1.0/u; double uu= u*u; double pp = (1 d)/(u d); GG note how proility is lulted double phown = 1.0 pp;

futures pries[0] = p*pow(d, no steps); int i; for (i=1; i<=no steps; ++i) futures pries[i] = uu*futures pries[i1]; GG terminl tree nodes for (i=0; i<=no steps; ++i) ll vlues[i] = mx(0.0, (futures pries[i]u)); for (int step=no steps1; step>=0; step) { for (i=0; i<=step; ++i) { futures pries[i] = d*futures pries[i+1]; ll vlues[i] = (phown*ll vlues[i]+pp*ll vlues[i+1])*inv; ll vlues[i] = mx(ll vlues[i], futures pries[i]u); GG hek for exerise
};

};

return ll vlues[0];
};

C++ Code 12.8:

Pricing an american call on an option on futures using a binomial approximation

122

12.7

Foreign Currency options

For American options, the usual method is approximation using binomial trees, checking for early exercise due to the interest rate dierential.

#include <mth> #include <lgorithm> #include <vetor> using namespace std;


double urreny option prie ll merin inomil(const double& , const double& u, const double& r, const double& r f, const double& sigm, const double& time, const int& no steps) { vetor<double> exhnge rtes(no steps+1); vetor<double> ll vlues(no steps+1); double t delt= time/no steps; double inv = exp( r*(t delt)); double u = exp(sigm*sqrt(t delt)); double d = 1.0/u; double uu= u*u; double pp = (exp((r r f )*t delt) d)/(u d); GG djust for foreign intFrte double phown = 1.0 pp;

exhnge rtes[0] = *pow(d, no steps); int i; for (i=1; i<=no steps; ++i) { exhnge rtes[i] = uu*exhnge rtes[i1]; GG terminl tree nodes
}

for (i=0; i<=no steps; for (int step=no steps for (i=0; i<=step;

++i) { exhnge rtes[i] = d*exhnge rtes[i+1]; ll vlues[i] = (phown*ll vlues[i]+pp*ll vlues[i+1])*inv; ll vlues[i] = mx(ll vlues[i], exhnge rtes[i]u); GG hek for exerise

1; step>=0; step) {

++i)

ll vlues[i]

mx(0.0, (exhnge rtes[i]u));

}; };

return ll vlues[0];
};

C++ Code 12.9: Example

Pricing an american call on an option on currency using a binomial approximation

Price a futures currency option with the following information: time=0.5, number of steps = 100. C++ program:

S a SH; K a SP; r a H:HV; rf a H:HS;  a H:P,

= 50.0; double u = 52.0; r = 0.08; double rf =0.05; sigm = 0.2; double time=0.5; steps = 100; out << " european currency option call = " << urreny option prie ll merin inomil(,u,r,rf,sigm,time,no steps) << endl;
double double double int no
Output from C++ program:

europen urreny option ll a PFPQIPW

123

12.8

References

The original source for binomial option pricing was the paper by Cox et al. (1979). Textbook discussions are in Cox and Rubinstein (1985), Bossaerts and degaard (2001) and Hull (2006).

124

Chapter 13

Finite Dierences
Contents
13.1 Explicit Finite dierences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.2 European Options. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.3 American Options. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.4 Implicit nite dierences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.5 An example matrix class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.6 Finite Dierences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.7 American Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.8 European Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.9 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 125 127 130 130 130 130 133 134

13.1

Explicit Finite dierences

The method of choice for any engineer given a dierential equation to solve is to numerically approximate it using a nite dierence scheme, which is to approximate the continous dierential equation with a discrete

dierence

equation, and solve this dierence equation.

13.2

European Options.

For European options we do not need to use the nite dierence scheme, but we show how one would nd the european price for comparison purposes. We show the case of an explicit nite dierence scheme in

C++ Code 13.1.


of inputs.

A problem with the explicit version is that it may not converge for certain combinations

125

#include <mth> #include <vetor> using namespace std;


double option prie put europen (nite di' expliit(const double& , const double& , const double& r, const double& sigm, const double& time, const int& no steps, const int& no t steps) { double sigm sqr = pow(sigm,2); int w=no steps; if ((no steps%2)==1) { ++w; } GG need no steps to e evenX double delt = 2.0*/w; vetor<double> vlues(w+1); for (unsigned m=0;m<=w;m++) { vlues[m] = m*delt ; }; int x=no t steps; double delt t = time/x;

vetor<double> (w); vetor<double> (w); vetor<double> (w); double rI=1.0/(1.0+r*delt t); double rP=delt t/(1.0+r*delt t); for (unsigned int j=1;j<w;j++){ [j] = rP*0.5*j*(r+sigm sqr*j); [j] = rI*(1.0sigm sqr*j*j*delt t); [j] = rP*0.5*j*(r+sigm sqr*j);
};

vetor<double> f next(w+1); for (unsigned m=0;m<=w;++m) { f next[m]=mx(0.0, vlues[m]); double f [w+1]; for (int t=x1;t>=0;t) { f [0]=; for (unsigned m=1;m<w;++m) { f [m]=[m]*f next[m1]+[m]*f next[m]+[m]*f next[m+1];
};

};

f [w] = 0; for (unsigned m=0;m<=w;++m)


};

f next[m]

f [m];

};

return f [w/2];
};

C++ Code 13.1:

Explicit nite dierences calculation of european put option

126

13.3

American Options.
C++ Code 13.2 shows the C++ code for an american put option and wtl Code 13.1 implemented in wtl.

We now compare the American versions of the same algoritms, the only dierence being the check for exercise at each point. shows the same

#include <mth> #include <lgorithm> #include <vetor> using namespace std;


double option prie put merin (nite di' expliit( const double& , const double& u, const double& r, const double& sigm, const double& time, const int& no steps, const int& no t steps) double sigm sqr = sigm*sigm; int w=no steps+(no steps%2); GG need no steps to e evenX double delt = 2.0*/w; vetor<double> vlues(w+1); for (int m=0;m<=w;m++) { vlues[m] = m*delt ; }; int x=no t steps; double delt t = time/x;

vetor<double> (w); vetor<double> (w); vetor<double> (w); double rI=1.0/(1.0+r*delt t); double rP=delt t/(1.0+r*delt t); for (int j=1;j<w;j++){ [j] = rP*0.5*j*(r+sigm sqr*j); [j] = rI*(1.0sigm sqr*j*j*delt t); [j] = rP*0.5*j*(r+sigm sqr*j); vetor<double> f next(w+1); for (int m=0;m<=w;++m) { f next[m]=mx(0.0,u vlues[m]); }; vetor<double> f (w+1); for (int t=x1;t>=0;t) { f [0]=u; for (int m=1;m<w;++m) { f [m]=[m]*f next[m1]+[m]*f next[m]+[m]*f next[m+1]; f [m] = mx(f [m],u vlues[m]); GG hek for exerise
}; };

f [w] = 0; for (int m=0;m<=w;++m)


};

f next[m]

f [m];

};

return f [w/2];
};

C++ Code 13.2:

Explicit nite dierences calculation of american put option

127

function

= (ndi' exp m put(,u,r,sigm,time,no steps,no t steps) sigm sqr = sigm^2; w=no steps + rem(no steps,2); # need no steps to e even: delt = 2*/w; vlues = delt * (0:w)'; x=no t steps; delt t = time/x;

rI=1/(1+r*delt t); rP=delt t/(1+r*delt t); =zeros(w1,1); =zeros(w1,1); =zeros(w1,1); for j=1:w1 (j) = rP*0.5*j*(r+sigm sqr*j); (j) = rI*(1.0sigm sqr*j*j*delt t); (j) = rP*0.5*j*(r+sigm sqr*j); endfor f next = max(0,u vlues); for t=x1:1:0 f = [ u; .*f next(1:w1)+.*f next(2:w)+.*f next(3:w+1); f = max(f,u vlues); f next=f ; endfor =f (1+w/2); endfuntion

0];

wtl Code 13.1:

Explicit nite dierences calculation of American put option

128

Example
Given the following parameters:

S a SH, K a SH, r a IH7 and  a H:R.

The time to maturity is 0.4167.

Price European and American put option prices using nite dierences with 20 steps in the 11 steps in the time dimenstion. C++ program:

S dimension and

= 50.0; u = 50.0; r = 0.1; sigm = 0.4; time=0.4167; steps=20; t steps=11; out << " explicit finite differences, european put price = "; out << option prie put europen (nite di' expliit(,u,r,sigm,time,no steps,no t steps) << endl; out << " explicit finite differences, american put price = "; out << option prie put merin (nite di' expliit(,u,r,sigm,time,no steps,no t steps) << endl;
double double double double double int no int no
Output from C++ program:

expliit finite differenesD europen put prie a RFHQTTU expliit finite differenesD merin put prie a RFPSHVS
Readings
Brennan and Schwartz (1978) is one of the rst nance applications of nite dierences.

Section 14.7 of Hull (1993) has a short introduction to nite dierences. Wilmott, Dewynne, and Howison (1994) is an exhaustive source on option pricing from the perspective of solving partial dierential equations.

129

13.4

Implicit nite dierences


g
is the ability to

What really distinguishes C++ from standard

extend

the language by creating classes

and collecting these classes into libraries. A library is a collection of classes and routines for one particular purpose. We have already seen this idea when creating the

dte and termstruture classes.

However,

one should not necessarily always go ahead and create such classes from scratch. It is just as well to use somebody else's class, as long as it is correct and well documented and fullls a particular purpose.

13.5
Use

An example matrix class


as an example matrix class.

xewmt

13.6

Finite Dierences

We use the case of implicit nite dierence calculations to illustrate matrix calculations in action. The method of choice for any engineer given a dierential equation to solve is to numerically approximate it using a nite dierence scheme, which is to approximate the continous dierential equation with a discrete

dierence

equation, and solve this dierence equation.

In the following we implement

implicit nite dierences.

Explicit nite dierences was discussed earlier,

we postponed the implicit case to now because it is much simplied by a matrix library.

13.7

American Options
wtl. wtl Code 13.2 shows the implementaC++ Code 13.3 using the xewmt library and C++ Code 13.4

Let us rst look at how this pricing is implemented in tion. Implementation of the same calculation in using IT++.

function

= (ndi' imp m put(,u,r,sigm,time,no steps,no t steps) sigm sqr = sigm^2; w=no steps + rem(no steps,2); # need no steps to e even: delt = 2.0*/doule(w); vlues = delt * (1:w+1)'; x=no t steps; delt t = time/x; e = zeros(w+1,w+1); e(1,1)=1.0; for j=2:w e(j,j1) = 0.5*j*delt t*(rsigm sqr*j); e(j,j) = 1.0 + delt t*(r+sigm sqr*j*j); e(j,j+1) = 0.5*j*delt t*(rsigm sqr*j); endfor e(w+1,w+1)=1.0; f = max(0,u vlues); p = inv(e)*f; for t=x1:1:1 f = p; p = inv(e)*f; p=max(p,u vlues); endfor = p(w/2); endfuntion

wtl Code 13.2:

Calculation of price of American put using implicit nite dierences

130

#include <mth> #include "newmat.h" GG de(nitions for newmt mtrix lirry using namespace xiwe; #include <vetor> #include <lgorithm> using namespace std;
double option prie put merin (nite di' impliit(const double& , const double& u, const double& r, const double& sigm, const double& time, const int& no steps, const int& no t steps) double sigm sqr = sigm*sigm; int w=no steps + (no steps%2); GG need no steps to e evenX double delt = 2.0*/double(w); double vlues[w+1]; for (int m=0;m<=w;m++) { vlues[m] int x=no t steps; double delt t = time/x;

GG

int wano stepsY if @@no steps7PAaaIA { CCwY }Y GG need no steps to e evenX


=

m*delt ;

};

fndwtrix e(w+1,1,1); e=0.0; e.element(0,0) = 1.0; for (int j=1;j<w;++j) { e.element(j,j1) = 0.5*j*delt t*(rsigm sqr*j); GG j e.element(j,j) = 1.0 + delt t*(r+sigm sqr*j*j); GG jY e.element(j,j+1) = 0.5*j*delt t*(rsigm sqr*j); GG jY
};

e.element(w,w)=1.0; golumnetor f(w+1); for (int m=0;m<=w;++m){ f.element(m) = mx(0.0,u vlues[m]); golumnetor p=e.i()*f; for(int t=x1;t>0;t) { f = p; p = e.i()*f; for (int m=1;m<w;++m) { GG now hek for exerise p.element(m) = mx(p.element(m), u vlues[m]);
}; };

};

return p.element(w/2);
};

C++ Code 13.3:


matrix library

Calculation of price of American put using implicit nite dierences with the

xewmt

131

#include <mth> GG#inlude <vetor> GG#inlude <lgorithm> using namespace std; #include <itpp/itse.h> using namespace itpp;
double option prie put merin (nite di' impliit itpp(const double& , const double& u, const double& r, const double& sigm, const double& time, const int& no steps, const int& no t steps) double sigm sqr = sigm*sigm; int w=no steps + (no steps%2); GG need no steps to e evenX double delt = 2.0*/double(w); double vlues[w+1]; for (int m=0;m<=w;m++) { vlues[m] int x=no t steps; double delt t = time/x;

m*delt ;

};

mt e = zeros(w+1,w+1); e(0,0) = 1.0; for (int j=1;j<w;++j) { e(j,j1) = 0.5*j*delt t*(rsigm sqr*j); GG j e(j,j) = 1.0 + delt t*(r+sigm sqr*j*j); GG jY e(j,j+1) = 0.5*j*delt t*(rsigm sqr*j); GG jY
};

e(w,w)=1.0; ve f(w+1); for (int m=0;m<=w;++m){ f(m) = mx(0.0,u vlues[m]); mt snve = inv(e); ve p=snve*f; for(int t=x1;t>0;t) { f = p; p = snve*f; for (int m=1;m<w;++m) { GG now hek for exerise p(m) = mx(p(m), u vlues[m]);
}; };

};

return p(w/2);
};

C++ Code 13.4:


library

Calculation of price of American put using implicit nite dierences with the IT++ matrix

132

13.8

European Options

For European options we do not need to use the nite dierence scheme, but for comparison purposes

C++ Code 13.5

show how one would nd the European price.

#include <mth> #include "newmat.h" GG de(nitions for newmt mtrix lirry using namespace xiwe; #include <vetor> GG stndrd v vetor templte #include <lgorithm> using namespace std;
double option prie put europen (nite di' impliit(const double& , const double& u, const double& r, const double& sigm, const double& time, const int& no steps, const int& no t steps) double sigm sqr = sigm*sigm; int w=no steps + (no steps%2); GG need no steps to e evenX double delt = 2.0*/w; vetor<double> vlues(w+1); for (int m=0;m<=w;m++) { vlues[m] int x=no t steps; double delt t = time/x;

GG

int wano stepsY if @@no steps7PAaaIA { CCwY }Y GG need no steps to e evenX


=

m*delt ;

};

fndwtrix e(w+1,1,1); e=0.0; e.element(0,0) = 1.0; for (int j=1;j<w;++j) { e.element(j,j1) = 0.5*j*delt t*(rsigm sqr*j); GG j e.element(j,j) = 1.0 + delt t*(r+sigm sqr*j*j); GG jY e.element(j,j+1) = 0.5*j*delt t*(rsigm sqr*j); GG jY
};

e.element(w,w)=1.0; golumnetor f(w+1); for (int m=0;m<=w;++m){ f.element(m) golumnetor p=e.i()*f; for(int t=x1;t>0;t) { f = p; p = e.i()*f;
};

mx(0.0,u vlues[m]);

};

return p.element(w/2);
};

C++ Code 13.5:

Calculation of price of European put using implicit nite dierences

133

Exercise 13.1.
The routines above uses direct multiplication with the inverse of stable ways of doing it?

A.

Are there alternative, numerically more

Example
Given the parameters

S a SH, K a SH, r a H:I,  a H:R, time=0.5, no S steps=200; no t steps=200;

1. Price European put options using both Black Scholes and implicit nite dierences. 2. Price the American put option using implicit nite dierences. C++ program:

out out out out out

double = 50.0; double u = 50.0; double r = 0.1; double sigm = 0.4; double time=0.5; int no steps=200; int no t steps=200;

<< << << << <<

" black scholes put price = " << option prie put lk sholes(,u,r,sigm,time)<< endl; " implicit Euro put price = "; option prie put europen (nite di' impliit(,u,r,sigm,time,no steps,no t steps) << endl; " implicit American put price = "; option prie put merin (nite di' impliit(,u,r,sigm,time,no steps,no t steps) << endl;

Output from C++ program:

wtl

program:

= 50.0; u = 50.0; r = 0.1; sigm = 0.4; time=0.5; no steps=200; no t steps=200; = (ndi' imp m put(,u,r,sigm,time,no steps,no t steps)
Output from

wtl

program:

Exercise 13.2.
The

xewmt

library is only one of a large number of available matrix libraries, both public domain and

commercial oerings. Look into alternative libraries and replace What needs changing in the option price formulas?

xewmt with one of these alternative libraries.

13.9

References

Hull (2006). See the natbib documentation.

134

Chapter 14

Option pricing by simulation


Contents
14.1 Simulating lognormally distributed random variables . . . . . . . . . . . . . . . . . . . . . . . . 14.2 Pricing of European Call options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.3 Hedge parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.4 More general payos. Function prototypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.5 Improving the eciency in simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 136 137 139 140

14.5.1 Control variates. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 14.5.2 Antithetic variates. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141


14.6 More exotic options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.7 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 145

We now consider using Monte Carlo methods to estimate the price of an European option, and let us rst consider the case of the usual European Call, which can priced by the Black Scholes equation. Since there is already a closed form solution for this case, it is not really necessary to use simulations, but we use the case of the standard call for illustrative purposes. At maturity, a call option is worth

cT a mx@H; ST X A
At an earlier date

t, the option value will be the expected present value of this.

ct a E P V @mx@H; ST X A
Now, an important simplifying feature of option pricing is the risk neutral result, which implies that we can treat the (suitably transformed) problem as the decision of a risk neutral decision maker, if we also modify the expected return of the underlying asset such that this earns the risk free rate.

ct a er@T tA E mx@H; ST X A; E is a transformation of the original expectation. One way to estimate the value of the call is to simulate a large number of sample values of ST according to the assumed price process, and nd the
where estimated call price as the average of the simulated values. By appealing to a law of large numbers, this average will converge to the actual call value, where the rate of convergence will depend on how many simulations we perform.

14.1

Simulating lognormally distributed random variables

Lognormal variables are simulated as follows. Let one. If

x be normally distributed with mean zero and variance ~ St follows a lognormal distribution, then the one-period-later price StCI is simulated as 1 2 ~ StCI a St e@r 2  ACx ;
p ~ 1 2 ST a St e@r 2  A@T tAC T tx

or more generally, if the current time is

t and terminal date is T , with a time between t and T


C++ Code 14.1.

of

@T tA,

Simulation of lognormal random variables is illustrated by

135

#include <mth> using namespace std; #include "normdist.h"


double simulte lognorml rndom vrile(const double& , GG urrent vlue of vrile const double& r, GG interest rte const double& sigm, GG voltitily const double& time) { GG time to (nl dte double = (r 0.5 * pow(sigm,2) )*time; double h = sigm * sqrt(time); return * exp( + h * rndom norml());

};

C++ Code 14.1:

Simulating a lognormally distributed random variable

14.2

Pricing of European Call options

For the purposes of doing the Monte Carlo estimation of the price of an European call

ct a er@T tA E mx@H; ST X A;
note that here one merely need to simulate the terminal price of the underlying, underlying at any time between

distributed random variables, which gives us a set of observations of the terminal price

ST . If we let ST;I ; ST;P ; ST;Q ; : : : ST;n denote the n simulated values, we will estimate E mx@H; ST X A as the average ct a er@T tA
C++ Code 14.2
2 n
iaI

t and T is not relevant for pricing.

ST ,

the price of the

We proceed by simulating lognormally

of option payos at maturity, discounted at the risk free rate.

mx @H; ST;i X A

shows the implementation of a Monte Carlo estimation of an European call option.

#include <mth> GG stndrd mthemtil funtions #include <lgorithm> GG de(ne the mx@A funtion using namespace std; #include "normdist.h" GG de(nition of rndom numer genertor
double option prie ll europen simulted( const double& , const double& u, const double& r, const double& sigm, const double& time, const int& no sims){ double = (r 0.5 * pow(sigm,2))*time; double h = sigm * sqrt(time); double sum pyo's = 0.0; for (int n=1; n<=no sims; n++) { double = * exp( + h * rndom norml());

sum pyo's

+=

mx(0.0, u);

}; };

return exp( r*time)

* (sum

pyo's/double(no sims));

C++ Code 14.2: Example


Given

European Call option priced by simulation

S a IHH, K a IHH, r a H:I,  a H:PS, time=1.

Use 5000 simulations. Price put and call option using

Black Scholes and simulation.

136

C++ program:

out << " call: black scholes price = " << option prie ll lk sholes(,u,r,sigm,time) << endl; out << " simulated price = " << option prie ll europen simulted(,u,r,sigm,time,no sims) << endl; out << " put: black scholes price = " << option prie put lk sholes(,u,r,sigm,time) << endl; out << " simulated price = " << option prie put europen simulted(,u,r,sigm,time, no sims) << endl;
Output from C++ program:

double =100.0; double u=100.0; double r=0.1; double sigm=0.25; double time=1.0; int no sims=5000;

lk sholes prie a IRFWUSV simulted prie a IRFVRHR putX lk sholes prie a SFRSWSR simulted prie a SFURSVV

llX

14.3

Hedge parameters

It is of course, just as in the standard case, desirable to estimate hedge parameters as well as option prices. We will show how one can nd an estimate of the option price with respect to the underlying security:

@ct . @S

delta,

the rst derivative of the call

this, let us recall that the rst derivative of a function

f H @xA a h3H lim


Thinking of

option price at two dierent values of the underlying, estimate the option delta as

f @S A as the option price formula ct a f @S Y X; r; ; @T tAA, we see that we can evaluate the S and S C q, where q is a small quantity, and

f @x C hA f @xA h

To understand how one goes about estimating is dened as the limit

f @ S C q A f @S A q S
and

In the case of Monte Carlo estimation, it is very important that this is done by using the same sequence of random variables to estimate the two option prices with prices of the underlying

C++

Code 14.3

S C q.

implements this estimation of the option delta.

One can estimate other hedge parameters in a simular way.

Example
Given

S a IHH, K a IHH, r a H:I,  a H:PS, time=1.

Use 5000 simulations. Calculate deltas of put and call

option using Black Scholes and simulation. C++ program:

out << " call: bs delta = " << option prie delt ll lk sholes(,u,r,sigm,time) << " sim delta = " << option prie delt ll europen simulted(,u,r,sigm,time,no sims) << endl; out << " put: bs delta = " << option prie delt put lk sholes(,u,r,sigm,time) << " sim delta = " << option prie delt put europen simulted(,u,r,sigm,time,no sims) << endl;
Output from C++ program:

double =100.0; double u=100.0; double r=0.1; double sigm=0.25; double time=1.0; int no sims=5000;

llX s delt a HFUHHPHV putX s delt a EHFPWWUWP

sim delt a HFUHIRVR sim delt a EHFQHUPII

137

#include <mth> GG stndrd mthemtil funtions #include <lgorithm> GG de(ne the mx@A funtion using namespace std; #include "normdist.h" GG de(nition of rndom numer genertor
double option prie delt ll europen simulted(const const const const const const double = (r 0.5 * pow(sigm,2))*time; double h = sigm * sqrt(time); double sum pyo's = 0.0; double sum pyo's q = 0.0; double q = *0.01; for (int n=1; n<=no sims; n++) { double = rndom norml(); double = * exp( + h * ); double& double& double& double& double& int& no

, u, r, sigm, time, sims){

sum pyo's += mx(0.0, u); double q = (+q)* exp( + h * ); sum pyo's q += mx(0.0, qu);

};

double = exp( r*time) * (sum pyo's/no sims); double q = exp( r*time) * (sum pyo's q/no sims); return ( q )/q;

};

C++ Code 14.3:

Estimate Delta of European Call option priced by Monte Carlo

138

14.4

More general payos. Function prototypes

The above shows the case for a call option. If we want to price other types of options, with dierent payos we could write similar routines for every possible case. But this would be wasteful, instead

a bit of thought allows us to write option valuations for any kind of option whose payo depend on the value of the underlying at maturity, only. Let us now move toward a generic routine for pricing derivatives with Monte Carlo. This relies on the ability of C++ to write subroutines which one call with

function prototypes, i.e. that in the call to to the subroutine/function one provides a function instead
of a variable. Consider pricing of standard European put and call options. At maturity each option only depend on the value of the underlying

ST

and the exercise price

through the relations

CT a mx@ST X; HA PT a mx@X ST ; HA
C++ Code 14.4
shows two C++ functions which calculates this.

#include <lgorithm> using namespace std;


double pyo' ll(const double& , const double& u){ return mx(0.0, u);

};

double pyo' put (const double& , const double& u) return mx(0.0,u );

};

C++ Code 14.4:

Payo call and put options

The interesting part comes when one realises one can write a generic simulation routine to which one provide one of these functions, or some other function describing a payo which only depends on the price of the underlying and some constant.

C++ Code 14.5

shows how this is done.

#include <mth> using namespace std; #include "fin_recipes.h"


double derivtive prie simulte europen option generi(const double& , const double& u, const double& r, const double& sigm, const double& time, double pyo' (const double& prie, const double& ), const int& no sims) { double sum pyo's=0; for (int n=0; n<no sims; n++) { double = simulte lognorml rndom vrile(,r,sigm,time);

sum pyo's

+=

pyo' ( ,u);
* (sum

}; };

return exp( r*time)

pyo's/no sims);

C++ Code 14.5:


Note the presence of the line

Generic simulation pricing

139

doule pyoff@onst doule8 D onst doule8 uAD


in the subroutine call. When this function is called, the calling program will need to provide a function to put there, such as the Black Scholes example above. The next example shows a complete example of how this is done.

Example
Given

S a IHH, K a IHH, r a H:I,  a H:PS, time=1, no sims=5000.


double = 100; double u = 100; double r = 0.1; double sigm = 0.25; double time = 1.0; int no sims

C++ program:

out << "Black Scholes call option price = " << option prie ll lk sholes(,u,r,sigm,time) << endl; out << "Simulated call option price = " << derivtive prie simulte europen option generi(,u,r,sigm,time,pyo' ll,no sims) << endl; out << "Black Scholes put option price = " << option prie put lk sholes(,u,r,sigm,time) << endl; out << "Simulated put option price = " << derivtive prie simulte europen option generi(,u,r,sigm,time,pyo' put,no sims) << endl;
Output from C++ program:

= 50000;

flk holes ll option prie imulted ll option prie flk holes put option prie imulted put option prie

a a a a

IRFWUSV IRFWWS SFRSWSR SFSSWW

As we see, even with as many as 50,000 simuations, the option prices estimated using Monte Carlo still diers substantially from the true values.

14.5

Improving the eciency in simulation

There are a number of ways of improving the implementation of Monte Carlo estimation such that the estimate is closer to the true value.

14.5.1 Control variates.


One is the method of control variates. The idea is simple. When one generates the set of terminal values of the underlying security, one can value several derivatives using the same set of terminal values. What if one of the derivatives we value using the terminal values is one which we have an analytical solution to? For example, suppose we calculate the value of an at the money European call option using both the (analytical) Black Scholes formula and Monte Carlo simulation. If it turns out that the Monte Carlo estimate overvalues the option price, we think that this will also be the case for other derivatives valued using the same set of simulated terminal values. derivative of interest downwards. Thus, suppose we want to value an European put and we use the price of an at the money European call as the control variate. Using the same set of simulated terminal values options using Monte Carlo as: We therefore move the estimate of the price of the

ST;i ,

we estimate the two

pt a er@T tA ct a er@T tA

2 n
iaI

mx @H; X ST;i A mx @H; ST;i X A

2 n
iaI

140

We calculate the Black Scholes value of the call a control variate adjustment, as follows

cbs , and calculate pcv , the estimate of the put price with t t

pcv a pt C @cbs ct A t t
One can use other derivatives than the at-the-money call as the control variate, the only limitation being that it has a tractable analytical solution.

C++ Code 14.6

shows the implementation of a Monte Carlo estimation using an at-the-money European

call as the control variate.

#include <mth> using namespace std; #include "fin_recipes.h"


double

derivtive prie simulte europen option generi with ontrol vrite(const double& , const double& , const double& r, const double& sigm, const double& time, double pyo' (const double& , const double& ), const int& no sims) { double s = option prie ll lk sholes(,,r,sigm,time);GG prie n t the money flk holes ll double sum pyo's=0; double sum pyo's s=0; for (int n=0; n<no sims; n++) { double = simulte lognorml rndom vrile(,r,sigm,time); sum pyo's += pyo' ( ,); sum pyo's s += pyo' ll( ,); GG simulte t the money flk holes prie
};

double sim = exp( r*time) * (sum pyo's/no sims); double s sim = exp( r*time) * (sum pyo's s/no sims);

sim += ( s s sim); return sim;


};

C++ Code 14.6:

Generic with control variate

14.5.2 Antithetic variates.


An alternative to using control variates is to consider the method of

antithetic variates.

The idea behind

this is that Monte Carlo works best if the simulated variables are spread out as closely as possible to the true distribution. Here we are simulating unit normal random variables. One property of the normal is that it is symmetric around zero, and the median value is zero. Why don't we enforce this in the

simulated terminal values? An easy way to do this is to rst simulate a unit random normal variable

Z , and then use both Z

and

Z to generate the lognormal random variables.

C++ Code 14.7

shows the

implementation of this idea. Boyle (1977) shows that the eciency gain with antithetic variates is not particularly large. There are other ways of ensuring that the simulated values really span the whole sample space, sometimes called pseudo Monte Carlo.

141

#include "fin_recipes.h" #include "normdist.h" #include <mth> using namespace std;


double

derivtive prie simulte europen option generi with ntitheti vrite(const double& , const double& u, const double& r, const double& sigm, const double& time, double pyo' (const double& , const double& ), const int& no sims) { double = (r 0.5 * pow(sigm,2) )*time; double h = sigm * sqrt(time); double sum pyo's=0; for (int n=0; n<no sims; n++) { double x=rndom norml(); double I = * exp( + h * x); sum pyo's += pyo' (I,u); double P = * exp( + h * (x)); sum pyo's += pyo' (P,u);
}; };

return exp( r*time)

* (sum

pyo's/(2*no sims));

C++ Code 14.7:

Generic with antithetic variates

142

Example
Given

S a IHH, K a IHH, r a H:I,  a H:PS, time=1, no sims=50000.

Price put and call option using Black

Scholes and simulation. The simulation is to use both control variates and anthitetic methods. C++ program:

out << "Black Scholes call option price = " << option prie ll lk sholes(,u,r,sigm,time) << endl; out << "Simulated call option price = " << derivtive prie simulte europen option generi(,u,r,sigm,time, pyo' ll,no sims) << endl; out << "Simulated call option price, CV = " << derivtive prie simulte europen option generi with ontrol vrite(,u,r,sigm,time, pyo' ll,no sims) << endl; out << "Simulated call option price, AV = " << derivtive prie simulte europen option generi with ntitheti vrite(,u,r,sigm,time, pyo' ll,no sims) << endl; out << "Black Scholes put option price = " << option prie put lk sholes(,u,r,sigm,time) << endl; out << "Simulated put option price = " << derivtive prie simulte europen option generi(,u,r,sigm,time,pyo' put,no sims) << endl; out << "Simulated put option price, CV = " << derivtive prie simulte europen option generi with ontrol vrite(,u,r,sigm,time, pyo' put,no sims) << endl; out << "Simulated put option price, AV = " << derivtive prie simulte europen option generi with ntitheti vrite(,u,r,sigm,time, pyo' put,no sims) << endl;
Output from C++ program:

double = 100; double u = 100; double r = 0.1; double sigm = 0.25; double time = 1; int no sims

= 50000;

flk holes ll option prie imulted ll option prie imulted ll option prieD g imulted ll option prieD e flk holes put option prie imulted put option prie imulted put option prieD g imulted put option prieD e

a a a a a a a a

IRFWUSV IRFWWS IRFWUSV IRFWWIW SFRSWSR SFRIVTI SFRPSRI SFRTHRQ

143

14.6

More exotic options

These generic routines can also be used to price other options. Any European option that only depends on the terminal value of the price of the underlying security can be valued. Consider the discussed by e.g. Hull (2006). An

cash or nothing call

pays a xed amount

above the exercise price at maturity, otherwise nothing.

binary options Q if the price of the asset is An asset or nothing call pays the price of the

asset if the price is above the exercise price at maturity, otherwise nothing. Both of these options are easy to implement using the generic routines above, all that is necesary is to provide the payo functions as shown in

C++ Code 14.8.

double pyo' sh or nothing ll(const double& , const double& u){ if (>=u) return 1; return 0;
};

double pyo' sset or nothing ll(const double& , const double& u){ if (>=u) return ; return 0;
};

C++ Code 14.8:

Payo binary options

Now, many exotic options are not simply functions of the terminal price of the underlying security, but depend on the evolution of the price from now till the terminal date of the option. For example options that depend on the average of the price of the underlying (Asian options). For such cases one will have to simulate the whole path. We will return to these cases in the chapter on pricing of exotic options.

Example
Given with

S a IHH, K a IHH, r a H:I,  a H:PS, time=1. Q a I.

Use 5000 simulations. Price cash or nothing option

Price asset or nothing option. In both cases compare results using control variate and anthitetic methods.

144

C++ program:

out << " cash or nothing, Q=1: " << derivtive prie simulte europen option generi(,u,r,sigm,time, pyo' sh or nothing ll, no sims) << endl; out << " control variate " << derivtive prie simulte europen option generi with ontrol vrite(,u,r,sigm,time, pyo' sh or nothing ll, no sims) << endl; out << " antithetic variate " << derivtive prie simulte europen option generi with ntitheti vrite(,u,r,sigm,time, pyo' sh or nothing ll, no sims) << endl; out << " asset or nothing: " << derivtive prie simulte europen option generi(,u,r,sigm,time, pyo' sset or nothing ll, no sims) << endl; out << " control variate " << derivtive prie simulte europen option generi with ontrol vrite(,u,r,sigm,time, pyo' sset or nothing ll, no sims) << endl; out << " antithetic variate " << derivtive prie simulte europen option generi with ntitheti vrite(,u,r,sigm,time, pyo' sset or nothing ll, no sims) << endl;
Output from C++ program:

double =100.0; double u=100.0; double r=0.1; double sigm=0.25; double time=1.0; int no sims=5000;

sh or nothingD aIX HFSRURPU ontrol vrite IFHPSSP ntitheti vrite HFSRWSWV sset or nothingX UHFSPWP ontrol vrite TWFVRSI ntitheti vrite UHFPPHS
Exercise 14.1.
Consider the pricing of an European Call option as implemented in code 14.2, and the generic formula for pricing with Monte Carlo for European options that only depend on the terminal value of the underlying security, as implemented in code 14.5. Note the dierence in the implementation of the lognormal simulation of terminal values. Why can one argue that the rst implementation is more ecient than the other?

14.7

References

Boyle (1977) is a good early source on the use of the Monte Carlo technique for pricing derivatives. Simulation is also covered in Hull (2006).

145

Chapter 15

Approximations
Contents
15.1 The Johnson (1983) approximation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.2 An approximation to the American Put due to Geske and Johnson (1984) . . . . . . . . . . . . 15.3 A quadratic approximation to American prices due to BaroneAdesi and Whaley. . . . . . . . . . 15.4 An alternative approximation to american options due to Bjerksund and Stensland (1993) . . . . 15.5 Readings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
There has been developed some useful

146 148 151 154 156

approximations to various specic options.

It is of course Amer-

ican options that are approximated. We will look at a number of approximations, both for their intrinsic usefulness, but also as examples of dierent approaches to generating an approximated value. The rst we will look at is the Johnson (1983) approximation to an American put. This is a purely empirical

approach to estimating the functional forms, with parameters estimated using regressions. The Geske and Johnson (1984) approach is to view the American option as a the limit of a sequence of Bermudan options with increasing number of exercise dates. The American value is found by interpolating forward the Bermudan values. The Barone-Adesi and Whaley (1987) approximation decomposes the American option into two, the European value, and the early exercise premium. The early exercise premium is relatively small, and is easier to approximate. Finally, the Bjerksund and Stensland (1993) is an example of bounding the option value by nding a lower bound on its value. A typical approach to doing so is to specify some (suboptimal) exercise strategy. As soon as the exercise strategy is known, the option is easily valued. Approximations are useful, but they should be used with caution. Typically, an approximation works well within a range of parameter values, but can go seriously wrong for some unfortunate combination of parameters. The user is well advised to to consider alternative approximations, and at a minimum use the price of the corresponding European option as a sanity check in the calculations. (In fact, in several of the following routines values are checked against Black Scholes values.)

15.1

The Johnson (1983) approximation


Formula 15.1 C++ Code 15.1

An early attempt at an analytical approximation to the price of an American put is provided by Johnson (1983). provides the details, and provides the implementation.

Example
Using the parameters

r a H:IPS, S a I:I, X a I,  a H:S and time to maturity of one year, calculate the

price of an american call using the Johnson (1983) approximation. C++ program:

out << " American put price using Johnson approximation = " << option prie merin put pproximted johnson(, , r, sigm, time) << endl;
Output from C++ program:

double r=0.125; double =1.1; double =1; double sigm=0.5; double time = 1;

emerin put prie using tohnson pproximtion a HFIISVP


146

P @X A a p Xer@T tA C @I Ap @X A r@T tA a aH r@T tA C aI Sc a X


  l

where

la

ln@S=Sc A ln@X=Sc A

IC

m

where

ma

P @T tA a Pr=P bH P @T tA C bI
Their parameter values are estimated as

The constants

aH , aI , bI and bP are constants. aH a Q:WTRW aI a H:HQPQPS

bH a I:HRHVHQ bI a H:HHWTQ
S : Current value of underlying security. X : Exercise price of american put. : Volatility of underlying. r: risk freee interest rate. @T tA: Time to maturity for option.

Formula 15.1:

The functional form of the Johnson (1983) approximation to the value of an American put

#include <mth> #include "fin_recipes.h"


double option prie merin put pproximted johnson( const double& , const double& , const double& r, const double& sigm, const double& time ){ double sigm sqr=pow(sigm,2); double H= 3.9649 ; double I = 0.032325; double H = 1.040803; double I = 0.00963; double gmm = 2*r/sigm sqr; double m = (sigm sqr*time)/(H*sigm sqr*time+I); double = * pow (((gmm)/(1+gmm)),m); double l = (log(/))/(log(/) ); double lph = pow( ( (r*time)/(H*r*time+I) ), l ); double = lph*option prie put lk sholes(,*exp(r*time),r,sigm,time) double p=option prie put lk sholes(,,r,sigm,time); GG for sfety use the flk holes s lower ound return mx(p,);
}; + (1

lph)*option

prie put lk sholes(,,r,sigm,time);

C++ Code 15.1:

The Johnson (1983) approximation to an american put price

Barone-Adesi (2005) notes that this approximation is inaccurate outside of the parameter range considered in the paper.

147

15.2

An approximation to the American Put due to Geske and Johnson (1984)


The solution

Geske and Johnson (1984) develop an approximation for the American put problem.

technique is to view the American put as an sequence of Bermudan options, with the number of exercise dates increasing. The correct value is the limit of this sequence. Dene

Pi

to be the price of the put option with

dates of exercise left.

european option, with the one exercise date the expiry date.

PP

PI

is then the price of an

is the price of an option that can be

exercised twice, once halfway between now and expiry, the other at expiry. Geske-Johnson shows how these options may be priced, and then develops a sequence of approximate prices that converges to the correct price. An approximation involving 3 option evaluations is

P a PQ C @PQ PP A @PP PI A
To calculate these, rst dene

U P

I P

dI @q;  A a
and

ln

  S C rC q

p  

I P  P

;
r

dP @q;  A a dI  
P Q

I IP a p ; P
In this notation,

I IQ a p ; Q

PQ a

PI a XerT NI @dP @X; T AA SNI @dI @X; T AA


To calculate

PI is the ordinary (european) Black Scholes value:

T T SNI dI S T ; T PP a Xer 2 NI dP S T ; 2 2 P P         T T ; dP @X; T AY IP SNP dI S T ; ; dI @X; T A Y IP C XerT NP dP S T ; 2 2

PP :





and

ST 2

solves

T S a X p S; X; ; r;  a S T 2
P
To calculate

PQ :

T PQ a Xer 3 NI

2T T PT C Xer 3 NP dP S T ; ; dP S 23T ; Y IP 3 Q Q       T SNP dI S T ; T ; dI S 23T ; PQ Y IP 3 Q       rT NQ dI S T ; T ; dI S 2T ; PT ; dI @X; T AY IP ; IQ ; PQ C Xe 3 3 Q Q       T PT SNQ dP S T ; Q ; dP S 23T ; Q ; dP @X; T AY IP ; IQ ; PQ 3

dP S ; Q
T



SNI dI S ; Q
T



where the critical stock prices solves

S a X PP S; X;

PT ; r;  a S T=Q Q
148

T S a X p S; X; ; r;  a S PT=Q Q
The main issue in implementation of this formula (besides keeping the notation straight) is the evalutation of of

PQ , since it involves the evaluation of a trivariate normal cumulative distribution. The evaluation NQ @A is described later, since it involves calls to external routines for numerical intergration. S a X p S; X; ; r;  a S T 2
P


To solve for

involves Newton steps. Dene

g@S A a S X C p S; X; ; r; 
P
Iterate on

g Si a Si H g
until

g is equal to zero with some given tolerance.

149

#include #include #include #include

<mth>

"normdist.h" "fin_recipes.h" <iostrem>

const double eggeg=1e

6;

inline double dI(const double& ,const double& , const double& r, const double& sigm, const double& tu){ return (log(/) + (r+0.5*pow(sigm,2))*tu)/(sigm*sqrt(tu));
};

inline double dP(const double& , const double& , const double& r, const double& sigm, const double& tu){ return dI(,,r,sigm,tu) sigm*sqrt(tu);

};

inline double lP(const double& , const double& , const double& r, const double& sigm, const double& time, const double& tP, const double& P r, const double& rhoIP){ double P = *exp( r*tP)*x( dP(,P r,r,sigm,tP));

P = *x(dI(,P r,r,sigm,tP)); P += *exp(r*time)*x(dP(,P r,r,sigm,tP),dP(,,r,sigm,time),rhoIP); P = *x(dI(,P r,r,sigm,tP),dI(,,r,sigm,time),rhoIP); return P;

};

double option prie merin put pproximted geske johnson( const double& , const double& , const double& r, const double& sigm, const double& time ){ double I = option prie put lk sholes(,,r,sigm,time); double rhoIP=1.0/sqrt(2.0); double rhoIQ=1.0/sqrt(3.0); double rhoPQ=sqrt(2.0/3.0); double tP = time/2.0; double tPQ = time*2.0/3.0; double tQ = time/3.0; double i=; double P r=; double g=1; double gprime=1; while (fs(g)>eggeg){

g=i+option prie put lk sholes(i,,r,sigm,tP); gprime=1.0+option prie delt put lk sholes(i,,r,sigm,tP); P r=i; i=ig/gprime;

};

double P

= lP(,,r,sigm,time,tP,P r,rhoIP); P=mx(I,P); GG for sfetyD use one less step s lower ound double PQ r=P r; g=1; while (fs(g)>eggeg){ g=i+option prie put lk sholes(i,,r,sigm,tPQ); gprime=1.0+option prie delt put lk sholes(i,,r,sigm,tPQ); PQ r=i; i=ig/gprime;

};

double Q r=PQ r;

g=1; while (fs(g)>eggeg){ g=i+option prie put lk sholes(i,,r,sigm,tQ); gprime=1.0+option prie delt put lk sholes(i,,r,sigm,tQ); Q r=i; i=ig/gprime;

};

double Q

= * exp(r*tQ) * x(dP(,Q r,r,sigm,tQ)); Q = * x(dI(,Q r,r,sigm,tQ)); Q += *exp(r*time)*x(dP(,Q r,r,sigm,tQ),dP(,PQ r,r,sigm,tPQ),rhoIP); Q = *x(dI(,Q r,r,sigm,tQ),dI(,PQ r,r,sigm,tPQ),rhoIP); Q += *exp(r*tPQ)*xQ(dI(,Q r,r,sigm,tQ),dI(,PQ r,r,sigm,tPQ),dI(,,r,sigm,time),rhoIP,rhoIQ,rhoPQ); Q = *xQ(dP(,Q r,r,sigm,tQ),dP(,PQ r,r,sigm,tPQ),dP(,,r,sigm,time),rhoIP,rhoIQ,rhoPQ); Q=mx(P,Q); GG for sfetyD use one less step s lower ound return Q+3.5*(QP)0.5*(PI);

};

C++ Code 15.2:

Geske Johnson approximation of American put

150

15.3

A quadratic approximation to American prices due to BaroneAdesi and Whaley.


1 The commodity is assumed to have a continuous payout

We now discuss an approximation to the option price of an American option on a commodity, described in Barone-Adesi and Whaley (1987) (BAW).

b.

The starting point for the approximation is the (Black-Scholes) stochastic dierential equation valid

for the value of any derivative with price

V.

Here

I P P  S VS S C bSVS rV C Vt a H P

(15.1)

is the (unknown) formula that determines the price of the contingent claim. For an European

option the value of

has a known solution, the adjusted Black Scholes formula. For American options,

which may be exercised early, there is no known analytical solution. To do their approximation, BAW decomposes the American price into the European price and the early exercise premium

C @S; T A a c@S; T A C "C @S; T A


Here

"C

is the early exercise premium. The insight used by BAW is that

"C

must

also satisfy the same

partial dierential equation. To come up with an approximation BAW transformed equation (15.1) into one where the terms involving

Vt

are neglible, removed these, and ended up with a standard linear

homeogenous second order equation, which has a known solution. The functional form of the approximation is shown in formula 15.2.

C @S; T A a
where

&

c@S; T A C AP SX
r

S q2 S

if if

S < S S ! S
3

I qP a P

M @N IA C @N IAP C RK

and

S solves

 S  I e@brA@T tA N @dI @S AA AP a qP Pr Pb M a P ; N a P ; K @T A a I er@T tA  

S X a c @S ; T A C
Formula 15.2:
call

 S  I e@brA@T tA N @dI @S AA qP

Notation: S Stock price. X : Exercise price.


The functional form of the Barone Adesi Whaley approximation to the value of an American

In implementing this formula, the only problem is nding the critical value problem of nding a root of the equation

S.

This is the classical

g @ S A a S X c@ S A
The next estimate of

 S  I e@brA@T tA N @dI @S AA a H qP

This is solved using Newton's algorithm for nding the root. We start by nding a rst seed value

Si is found by:

SH .

g@A SiCI a Si H g
1 he pproximtion is lso disussed in rull @PHHTAF

151

At each step we need to evaluate

g@A and its derivative gH @A.


 

g @ S A a S X c@ S A gH @S A a @I
where

qP

S I e@brA@T tA N @dI A


qP

A I e@brA@T tA N @dI A C

qP

I @brA@T tA @e n@dI AA

 T t

pI

c@ S A

is the Black Scholes value for commodities.

Code 15.3 shows the implementation of this

formula for the price of a call option.

Example
Consider the following set of parameters, used as an example in the Barone-Adesi and Whaley (1987) paper:

S a IHH, X a IHH,  a H:PH, r a H:HV, b a H:HR.

1. Price a call option with time to maturity of 3 months. C++ program:

double = 100; double = double r = 0.08; double =

out << " Call price using Barone-Adesi Whaley approximation = " << option prie merin ll pproximted w(,,r,,sigm,time) << endl;

0.04; double time = 0.25;

100;

double sigm

= 0.20;

Output from C++ program:

gll prie using froneEedesi hley pproximtion a SFURQQW


Exercise 15.1.
The Barone-Adesi  Whaley insight can also be used to value a put option, by approximating the value of the early exercise premium. For a put option the approximation is

P @S A a p@S; T A C AI X S

S q1 S

if if

S > S S S

S AI a @I e@brA@T tA N @dI @S AA qI
One again solves iteratively for

S , for example by Newton's procedure, where now one would use


 S I e@brA@T tA N @dI A qI 

g @S A a X S p@ S A C g H @S A a @
I


IA I e@brA@T tA N @dI A qI

qI

I @brA@T tA e

 T t

pI

n@dI A

1. Implement the calculation of the price of an American put option using the BAW approach.

152

#include <mth> #include <lgorithm> using namespace std; #include "normdist.h" #include "fin_recipes.h"

GG norml distriution GG de(ne other option priing formuls

const double eggeg=1.0e

6;

double option prie merin ll pproximted w( const double& , const double& , const double& r, const double& , const double& sigm, const double& time) { double sigm sqr = sigm*sigm; double time sqrt = sqrt(time); double nn = 2.0*/sigm sqr; double m = 2.0*r/sigm sqr; double u = 1.0 exp( r*time); double qP = ( (nn 1)+sqrt(pow((nn 1),2.0)+(4*m/u)))*0.5;

double double double double

qP inf = 0.5 * ( (nn1) + sqrt(pow((nn1),2.0)+4.0*m)); GG seed vlue from pper str inf = / (1.0 1.0/qP inf ); hP = (*time+2.0*sigm*time sqrt)*(/( str inf )); seed = + ( str inf )*(1.0exp(hP));

int no itertions=0; GG iterte on to (nd strD using xewton steps double i= seed; double g=1; double gprime=1.0; while ((fs(g) > eggeg)
&& (fs(gprime) && (

>eggeg) GG to void exploding xewton9s no itertions++<500) && (i>0.0)) { double = option prie europen ll pyout(i,,r,,sigm,time); double dI = (log(i/)+(+0.5*sigm sqr)*time)/(sigm*time sqrt); g=(1.01.0/qP)*i+(1.0/qP)*i*exp((r)*time)*x(dI); gprime=( 1.01.0/qP)*(1.0exp((r)*time)*x(dI)) +(1.0/qP)*exp((r)*time)*n(dI)*(1.0/(sigm*time sqrt)); i=i(g/gprime);

};

double str = 0; if (fs(g)>eggeg) { str = seed; } GG did not onverge else { str = i; }; double g=0; double = option prie europen ll pyout(,,r,,sigm,time); if (>= str) {

g=;

else

double dI = (log( str/)+(+0.5*sigm sqr)*time)/(sigm*time sqrt); double eP = (1.0 exp(( r)*time)*x(dI))* ( str/qP);

g=+eP*pow((/ str),qP);

}; };

return mx(g,); GG know vlue will never e less thn f vlue

C++ Code 15.3:

Barone Adesi quadratic approximation to the price of a call option

153

15.4

An alternative approximation to american options due to Bjerksund and Stensland (1993)

Bjerksund and Stensland (1993) provides an alternative approximation to the price of American options. Their approximation is an example of calculating a lower bound for the option value. Their valua-

tion relies on using an exercise strategy that is known, and although suboptimal, close enough to the (unknown) exercise strategy that the approximated value is The call option is found as

C @S; K; T; r; b; Y X A a @X AS @X A'@S; T j ; X; X A C '@S; T jI; X; X A

'@S; T jI; K; X A X'@S; T jH; X; X A C X'@S; T jH; K; X A


where

@X A a @X K AX
I b a C P P
  s   r b I P CP P P P 

'@S; T j ; H; X A a


e S

X N @dI A S




N @dP A

I  a r C b C @ IAP T P

dI a dP a

I ln@S=H A C b C @ P A P T
ln@X P =SH A C b C @ I A P T P

 T

 T

Pb  a P C @P IA 

XT a BH C BI BH A@I eh@T A h@T A a bT C P T


 

 



BI BH KP


BH

or (suggested in a later paper Bjerksund and Stensland (2002))

h@T A a bT C P T BI a K I




BI BH

r BH a mx K; K rb
Formula 15.3:
ican Call

S : Price of underlying security. K : Exercise price.


The Bjerksund and Stensland (1993) lower bound approximation to the value of an Amer-

154

The corresponding put option can be estimated as

P @S; X; T; r; b; A a C @X; S; T; r b; b; A
#include "fin_recipes.h" #include <mth> #include "normdist.h"
inline double phi(double , double , double gmm, double r, double , double r, double , double sigm){ double sigm sqr=pow(sigm,2); double kpp = 2.0*/sigm sqr + 2.0*gmm 1.0; double lmd = ( r + gmm * + 0.5*gmm*(gmm 1.0)*sigm sqr)*; GG hek thisD sys lmd in text double dI= (log(/r)+(+(gmm 0.5)*sigm sqr)*)/(sigm*sqrt()); double dP= (log((*)/(*r))+(+(gmm 0.5)*sigm sqr)*)/(sigm*sqrt()); double phi = exp(lmd) * pow(,gmm) * (x(dI) pow((/),kpp) * x(dP)); return phi;

};

double option prie merin ll pproximted jerksund stenslnd( const double& , const double& u, const double& r, const double& , const double& sigm, const double& ){ double sigm sqr=pow(sigm,2); double fH=mx(u,(r/(r )*u)); double et = (0.5 /sigm sqr) + sqrt( pow((/sigm sqr 0.5),2) + 2.0 * r/sigm sqr); double finf = et/(et 1.0)*u; double h= (* + 2.0*sigm*sqrt())*((u*u)/(finf fH)); double = fH+(finf fH)*(1.0 exp(h)); double lph = ( u)*pow(, et); double g=lph*pow(,et);

g = lph*phi(,,et,,,r,,sigm); g += phi(,,1,,,r,,sigm); g = phi(,,1,u,,r,,sigm) ; g = u*phi(,,0,,,r,,sigm); g += u*phi(,,0,u,,r,,sigm); double =option prie europen ll pyout(,u,r,,sigm,); GG for sfety use the flk holes s lower ound return mx(,g);

};

C++ Code 15.4:

Approximation of American Call due to Bjerksund and Stensland (1993)

#include "fin_recipes.h"
double option prie merin put pproximted jerksund stenslnd( const double& , const double& , const double& r, const double& q, const double& sigm, const double& ){ return option prie merin ll pproximted jerksund stenslnd(,,r (r q),r q,sigm,);

};

C++ Code 15.5:

Approximation of American put due to Bjerksund and Stensland (1993)

155

Exercise 15.2.
An option is At the Money Forward if the forward price

equals the exercise price.

1. Show that a reasonable approximation to the Black Scholes value of a call option on a non-dividend paying asset that is At the Money Forward is

C a H:R T tP V @F A
where and

 is the volatility.

is the forward price,

P V @A signies the present value operator, T t is the time to maturity

15.5

Readings

Barone-Adesi (2005) summarizes the history of approximating the American put.

156

Chapter 16

Average, lookback and other exotic options


Contents
16.1 Bermudan options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.2 Asian options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.3 Lookback options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.4 Monte Carlo Pricing of options whose payo depend on the whole price path . . . . . . . . . . . 16.5 Control variate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.6 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 159 160 162 165 166

16.4.1 Generating a series of lognormally distributed variables . . . . . . . . . . . . . 162

We now look at a type of options that has received a lot of attention in later years. The distinguishing factor of these options is that they depend on the today and the option maturity.

whole price path

of the underlying security between

16.1

Bermudan options
1 a mix of an European and American option.
It is a

A Bermudan option is, as the name implies,

standard put or call option which can only be exercised at discrete dates throughout the life of the option. The simplest way to do the pricing of this is again the binomial approximation, but now, instead of checking at every node whether it is optimal to exercise early, only check at the nodes corresponding to the potential exercise times.

C++ Code 16.1 shows the calculation of the Bermudan price using binomial

approximations. The times as which exercise can happen is passed as a vector argument to the routine, and in the binomial a list of which nodes exercise can happen is calculated and checked at every step.

Example
steps = 500,

Price a Bermudan put. The following informaton is given

S a VH, K a IHH r = 0.20; time = 1;  a H:PS, q a H:H, Potential exercise times = 0,25, 0.5 and 0.75.

C++ program:

potentil exerise times.push k(0.5); potentil exerise times.push k(0.75); out << " Bermudan put price = " << option prie put ermudn inomil(,u,r,q,sigm,time,potentil exerise times,steps) << endl;
Output from C++ program:

double =80; double u=100; double r = 0.20; double time = 1.0; double sigm = 0.25; int steps = 500; double q=0.0; vetor<double> potentil exerise times; potentil exerise times.push k(0.25);

fermudn put prie a ISFWHUW

1 ine fermud is somewhere etween emeri nd iuropeFFF

157

#include <mth> #include <lgorithm> #include <vetor> using namespace std;

GG stndrd g mthemtil lirry GG de(nes the mx@A opertor GG v vetor templtes

double option prie put ermudn inomil( const double& , const double& , const double& r, const double& q, const double& sigm, const double& time, const vetor<double>& potentil exerise times, const int& steps) { double delt t=time/steps; double = exp(r*delt t); double inv = 1.0/; double u = exp(sigm*sqrt(delt t)); double uu = u*u; double d = 1.0/u; double p up = (exp((r q)*delt t) d)/(u d); double p down = 1.0 p up; vetor<double> pries(steps+1); vetor<double> put vlues(steps+1);

vetor<int> potentil exerise steps; GG rete list of steps t whih exerise my hppen for (int i=0;i<potentil exerise times.size();++i){ double t = potentil exerise times[i]; if ( (t>0.0)&&(t<time) ) { potentil exerise steps.push k(int(t/delt t));
}; };

for (int i=1; i<=steps; ++i) pries[i] = uu*pries[i 1]; for (int i=0; i<=steps; ++i) put vlues[i] = mx(0.0, ( pries[i])); GG put pyo's t mturity for (int step=steps 1; step>=0; step) { bool hek exerise this step=false; for (int j=0;j<potentil exerise steps.size();++j){ if (step==potentil exerise steps[j]) { hek exerise this step=true; };

pries[0]

*pow(d, steps); GG (ll in the endnodesF

};

for (int i=0; i<=step;

++i) { put vlues[i] = (p up*put vlues[i+1]+p down*put vlues[i])*inv; pries[i] = d*pries[i+1]; if (hek exerise this step) put vlues[i] = mx(put vlues[i],pries[i]);

}; };

return put vlues[0];


};

C++ Code 16.1:

Binomial approximation to Bermudan put option

158

16.2

Asian options

The payo depends on the average of the underlying price. An

average price call

has payo

" CT a mx@H; S X A; " S is the average of the underlying in the period between t and T . Another Asian is the average strike call
where

" CT a mx@H; ST S A
There are dierent types of Asians depending on how the average

" S is calculated. For the case of S being " being a geometric average, there is an analytic formula due to Kemna and lognormal and the average S
Vorst (1990). Hull (2006) also discusses this case. It turns out that one can calculate this option using the regular Black Scholes formula adjusting the volatility to

I I r C q C P P T
C++ Code 16.2

= Q and the dividend yield to

in the case of continous sampling of the underlying price distribution. shows the calculation of the analytical price of an Asian geometric average price call.

#include <mth> using namespace std; #include "normdist.h" GG norml distriution de(nitions
double

option prie sin geometri verge prie ll(const double& , const double& u, const double& r, const double& q, const double& sigm, const double& time){ double sigm sqr = pow(sigm,2); double dj div yield=0.5*(r+q+sigm sqr/6.0); double dj sigm=sigm/sqrt(3.0); double dj sigm sqr = pow(dj sigm,2); double time sqrt = sqrt(time); double dI = (log(/u) + (rdj div yield + 0.5*dj sigm sqr)*time)/(dj sigm*time sqrt); double dP = dI(dj sigm*time sqrt); double ll prie = * exp(dj div yield*time)* x(dI) u * exp(r*time) * x(dP); return ll prie;
};

C++ Code 16.2: Example


Relevant parameters:

Analytical price of an Asian geometric average price call

S a IHH, K a IHH, q a H, r a H:HT,  a H:PS and time to maturity is one year.

Price

an Asian geometric average price call. C++ program:

double =100; double u=100; double q=0; double r=0.06; double sigm=0.25; double time=1.0;

out << " Analytical geometric average = " << option prie sin geometri verge prie ll(,u,r,q,sigm,time) << endl;

Output from C++ program:

enlytil geometri verge a TFURVUT


159

16.3

Lookback options

The payo from lookback options depend on the maximum or minimum of the underlying achieved through the period. The payo from the lookback call is the terminal price of the undelying less the minimum value

CT a mx@H; ST min S A  Pt;T


For this particular option an analytical solution has been found, due to Goldman, Sosin, and Gatto (1979), which is shown in

Formula 16.1

and implemented in

C++ Code 16.3.

C a Seq@T tA N @aI A Seq@T tA aI a


ln

S Smin

  P  P Y1 N @aI A Smin er@T tA N @aP A e N @aQA P@r q A P@r q A

C @r q C I  P A@T tA P

aP a aI  T t aQ a YI a
ln

S Smin

 T t

r C q C I P @T tA P p  T t

Smin S

I P r q P  P ln
P

Formula 16.1:

Analytical formula for a lookback call

#include <mth> using namespace std; #include "normdist.h"


double option prie europen lookk ll(const double& , const double& min, const double& r, const double& q, const double& sigm, const double& time){ if (r==q) return 0; double sigm sqr=sigm*sigm; double time sqrt = sqrt(time); double I = (log(/min) + (r q+sigm sqr/2.0)*time)/(sigm*time sqrt); double P = I sigm*time sqrt; double Q = (log(/min) + ( r+q+sigm sqr/2.0)*time)/(sigm*time sqrt); double I = 2.0 * (r q sigm sqr/2.0)*log(/min)/sigm sqr; return * exp( q*time)*x(I) *exp( q*time)*(sigm sqr/(2.0*(r q)))*x( I)

min * exp(r*time)*(x(P)(sigm

sqr/(2*(rq)))*exp(I)*x(Q));

};

C++ Code 16.3: Example


Parameters

Price of lookback call option

S a IHH, Smin a S q a H, r a H:HT,  a H:QRT, time = 1.0, Price an European lookback call.

160

C++ program:

double =100; double min=; double q = double sigm = 0.346; double time = 1.0;

0;

double r

= 0.06;

out << " Lookback call price = " << option prie europen lookk ll(,min,r,q,sigm,time) << endl;

Output from C++ program:

vookk ll prie a PUFHUIQ

161

16.4

Monte Carlo Pricing of options whose payo depend on the whole price path

Monte Carlo simulation can be used to price a lot of dierent options. The limitation is that the options should be European. American options can not be priced by simulation methods. There is (at least) two reasons for this. First, the optimal exercise policy would have to be known. But if the exercise policy was known there would be an analytical solution. Second, approximations using Monte Carlo relies on a law of large numbers. But if some of the sample paths were removed, the LLN would be invalidated. In chapter 14 we looked at a general simulation case where we wrote a generic routine which we passed a payo function to, and the payo function was all that was necessary to dene an option value. The payo function in that case was a function of the

terminal

price of the underlying security. The only

dierence to the previous case is that we now have to generate a price

sequence

and write the terminal

payo of the derivative in terms of that, instead of just generating the terminal value of the underlying security from the lognormal assumption.

16.4.1 Generating a series of lognormally distributed variables


Recall that one will generate lognormally distributed variables as

p ~ 1 2 ST a St e@r 2  A@T tAC T tx


where the current time is into say

t and terminal date is T .

To simulate a price sequence one splits this period

periods, each of length

t a

T t N t t C t t C Pt t C Qt T
E
Time

Each step in the simulated price sequence is

p ~ 1 2 StCt a St e@r 2  AC tx


C++ Code 16.4
shows how one would simulate a sequence of lognormally distributed variables. This code is then used in the generic routine to do calculations, as shown in

C++ Code 16.5.

To price an option we are then only in need of a denition of a payo function. We consider a couple of examples. One is the case of an Asian option, shown in Another is the payo for a lookback, shown in

C++ Code 16.6.2

C++ Code 16.7.3

2 xote the use of the accumulate() funtionD whih is prt of the g++ stndrdF 3 xote the use of the min_element() nd max_element funtionsD whih re prt of the g++ stndrdF

162

#include <mth> #include <vetor> using namespace std; #include "normdist.h"

vetor<double> simulte lognormlly distriuted sequene(const double& , const double& r, const double& sigm, const double& time, GG time to (nl dte const int& no steps){ GG numer of steps vetor<double> pries(no steps); double delt t = time/no steps; double = (r0.5*pow(sigm,2))*delt t; double h = sigm * sqrt(delt t); double t = ; GG initilize t urrent prie for (int i=0; i<no steps; ++i) { t = t * exp( + h * rndom norml()); pries[i]= t;
};

return pries;
};

C++ Code 16.4:

Simulating a sequence of lognormally distributed variables

#include <mth> using namespace std; #include "fin_recipes.h"


double

derivtive prie simulte europen option generi(const double& , const double& u, const double& r, const double& sigm, const double& time, double pyo' (const vetor<double>& pries, const double& ), const int& no steps, const int& no sims) { double sum pyo's=0; for (int n=0; n<no sims; n++) { vetor<double>pries = simulte lognormlly distriuted sequene(,r,sigm,time,no steps); sum pyo's += pyo' (pries,u);
}; };

return exp( r*time)

* (sum

pyo's/no sims);

C++ Code 16.5:

Generic routine for pricing European options

163

#include <mth> #include <numeri> #include <vetor> using namespace std;


double pyo' rithmetri verge ll(const vetor<double>& pries, const double& u) double sum=umulte(pries.egin(), pries.end(),0.0); double vg = sum/pries.size(); return mx(0.0,vg u);
{

};

double pyo' geometri verge ll(const vetor<double>& pries, const double& u) double logsum=log(pries[0]); for (unsigned i=1;i<pries.size();++i){ logsum+=log(pries[i]); }; double vg = exp(logsum/pries.size()); return mx(0.0,vg u);

};

C++ Code 16.6:

Payo function for Asian call option

#include <vetor> #include <lgorithm> using namespace std;


double pyo' lookk ll(const vetor<double>& pries, const double& unused vrile) double m = *min element(pries.egin(),pries.end()); return pries.k() m; GG lwys positive or zero
{

};

double pyo' lookk put(const vetor<double>& pries, const double& unused vrile) double m = *mx element(pries.egin(),pries.end()); return m pries.k(); GG mx is lwys lrger or equlF

};

C++ Code 16.7:

Payo function for lookback option

164

16.5

Control variate

As discussed in chapter 14, a control variate is a price which we both have an analytical solution of and nd the Monte Carlo price of. The dierences between these two prices is a measure of the bias in the Monte Carlo estimate, and is used to adjust the Monte Carlo estimate of other derivatives priced using the same random sequence.

C++ Code 16.8

shows the Black Scholes price used as a control variate. An alternative could have been

the analytical lookback price, or the analytical solution for a geometric average price call shown earlier.

#include "fin_recipes.h" #include <mth> using namespace std;


double

derivtive prie simulte europen option generi with ontrol vrite(const double& , const double& u, const double& r, const double& sigm, const double& time, double pyo' (const vetor<double>& pries, const double& ), const int& no steps, const int& no sims) { double s = option prie ll lk sholes(,,r,sigm,time);GG prie n t the money flk holes ll double sum pyo's=0; double sum pyo's s=0; for (int n=0; n<no sims; n++) { vetor<double> pries = simulte lognormlly distriuted sequene(,r,sigm,time, no steps); double I= pries.k(); sum pyo's += pyo' (pries,u); sum pyo's s += pyo' ll(I,); GG simulte t the money flk holes prie
};

double sim = exp( r*time) * (sum pyo's/no sims); double s sim = exp( r*time) * (sum pyo's s/no sims);

sim += ( s s sim); return sim;


};

C++ Code 16.8: Example

Control Variate

Using the parameters

S a IHH, K a IPH, r a H:IH, time = 1.0  a H:PS, no sims = 10000, no steps = 250, q a H, price arithmetric and geometric average calls by generic simulation.

165

C++ program:

out << "Testing general simulation of European options " << endl; double =100; double u=120; double r = 0.10; double time = 1.0; double sigm = 0.25; int no sims = 10000; int no steps = 250; double q=0; out << " simulated arithmetric average " << " S= " << << " r= " << r << " price=" << derivtive prie simulte europen option generi(,u,r,sigm,time, pyo' rithmetri verge ll, no steps,no sims) << endl; out << " simulated geometric average = " << derivtive prie simulte europen option generi(,u,r,sigm,time, pyo' geometri verge ll, no steps,no sims) << endl; out << " analytical lookback put = " << option prie europen lookk put(,,r,q,sigm,time) << endl; out << " simulated lookback put = " << derivtive prie simulte europen option generi(,0,r,sigm,time, pyo' lookk put, no steps,no sims) << endl; out << " analytical lookback call = " << option prie europen lookk ll(,,r,q,sigm,time) << endl; out << " simulated lookback call = " << derivtive prie simulte europen option generi(,0,r,sigm,time, pyo' lookk ll, no steps,no sims) << endl; out << " simulated lookback call using control variates = " << derivtive prie simulte europen option generi with ontrol vrite(,0,r,sigm,time, pyo' lookk ll, no steps,no sims) << endl;
Output from C++ program:

esting generl simultion of iuropen options simulted rithmetri verge a IHH ra HFI prieaIFRWTWT simulted geometri verge a IFQVHIU nlytil lookk put a ITFPTTS simulted lookk put a IRFWVRT nlytil lookk ll a PPFVHVW simulted lookk ll a PIFWQQT simulted lookk ll using ontrol vrites a PPFHTVS

16.6

References

Exotic options are covered in Hull (2006). Rubinstein (1993) has an extensive discussion of analytical solutions to various exotic options. Gray and Gray (2001) also looks at some analytical solutions.

166

Chapter 17

Generic binomial pricing


Contents
17.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17.2 Delta calculation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 171

17.1

Introduction

In earlier chapters we have seen a large number of dierent versions of the binomial pricing formula. In this chapter we see how we can build a framework for binomial pricing that lets us write a single generic routine that can be used for a binomial approximation of all sorts of derivatives. The important feature that lets us write such a generic routine is that the only place the terms of the derivative appears in the calculation is the calculation of the value at each node. Consider the binomial approximation of an American call in Chapter 12's

C++ Code 12.2,

repeated below as

C++ Code 17.1

for convenience.

#include <mth> #include <lgorithm> #include <vetor> using namespace std;

GG stndrd mthemtil lirry GG de(nes the mx@A opertor GG v vetor templtes

double option prie ll merin inomil( const double& , GG spot prie const double& , GG exerie prie const double& r, GG interest rte const double& sigm, GG voltility const double& t, GG time to mturity const int& steps) { GG no steps in inomil tree double = exp(r*(t/steps)); GG interest rte for eh step double inv = 1.0/; GG inverse of interest rte double u = exp(sigm*sqrt(t/steps)); GG up movement double d = 1.0/u; double p up = ( d)/(u d); double p down = 1.0 p up;

vetor<double> pries(steps+1); GG prie of underlying pries[0] = *pow(d, steps); GG (ll in the endnodesF double uu = u*u; for (int i=1; i<=steps; ++i) pries[i] = uu*pries[i1]; vetor<double> ll vlues(steps+1); GG vlue of orresponding ll for (int i=0; i<=steps; ++i) ll vlues[i] = mx(0.0, (pries[i] )); GG ll pyo's t mturity

for (int step=steps 1; step>=0; for (int i=0; i<=step; ++i)

step) {
{

ll vlues[i] = (p up*ll vlues[i+1]+p down*ll vlues[i])*inv; pries[i] = d*pries[i+1]; ll vlues[i] = mx(ll vlues[i],pries[i]); GG hek for exerise

}; };

return ll vlues[0];
};

C++ Code 17.1:

Binomial price of American Call

167

The terms of the derivative only appears when calculating the value at the nodes, where the calculation

mx@priesEuDHA

appears.

The key to building a generic binomial routine lies in replacing this

calculation with a generic routine.

C++ Code 17.2

shows how the generic ruotine is implemented.

#include <mth> #include <lgorithm> #include <vetor> using namespace std;

GG stndrd mthemtil lirry GG de(nes the mx@A opertor GG v vetor templtes

double option prie generi inomil( const double& , const double& u, double generi pyo' (const double& , const double& u), const double& r, const double& sigm, const double& t, const int& steps) { double = exp(r*(t/steps)); GG interest rte for eh step double inv = 1.0/; GG inverse of interest rte double u = exp(sigm*sqrt(t/steps)); GG up movement double d = 1.0/u; double p up = ( d)/(u d); double p down = 1.0 p up;

vetor<double> pries(steps+1); GG prie of underlying pries[0] = *pow(d, steps); GG (ll in the endnodesF double uu = u*u; for (int i=1; i<=steps; ++i) pries[i] = uu*pries[i1]; vetor<double> vlues(steps+1); GG vlue of orresponding ll for (int i=0; i<=steps; ++i) vlues[i] = generi pyo' (pries[i],u); GG pyo's t mturity
for (int step=steps 1; step>=0; for (int i=0; i<=step; ++i)

step) {
{

vlues[i] = (p up*vlues[i+1]+p down*vlues[i])*inv; GG vlue y not exerising pries[i] = d*pries[i+1]; vlues[i] = mx(vlues[i],generi pyo' (pries[i],u)); GG hek for exerise

}; };

return vlues[0];
};

C++ Code 17.2:

Generic binomial calculation

168

Using this routine is then merely a matter of providing a denition of the derivative payo. shows how the payos are dened for standard put and call options.

C++ Code 17.3

Pricing American put and call

options is then merely a matter of supplying these payo denitions to the generic binomial routine.

#include <lgorithm> using namespace std;


double pyo' ll(const double& , const double& u){ return mx(0.0, u);

};

double pyo' put (const double& , const double& u) return mx(0.0,u );

};

C++ Code 17.3: Example

Payo denitions for put and call options

@T tA a I and r a H:I.

Consider American call and put option on non-dividend paying stock, where

S a IHH, K a IHH,  a H:P,

1. Price the options using binomial approximations with 100 steps. C++ program:

out << " american call price = " << option prie generi inomil(,u,pyo' ll, r, sigm, time to mturity, steps) << endl; out << " american put price = " << option prie generi inomil(,u,pyo' put, r, sigm, time to mturity, steps) << endl;
Output from C++ program:

double = 100.0; double u = 100.0; double r = 0.1; double sigm = 0.25; double time to mturity=1.0; int steps = 100;

merin ll prie a IRFWSHS merin put prie a TFSRTWI


More exotic options can also be calculated using the same approach. For example,

C++ Code 17.4

shows

payo denitions for two binary options, options that pay o one dollar if the price of the underlying is above

K (call) or below K (put).

The typical such option is European, the check for whether the option

is in the money happens at maturity, but one can also think of cases where the binary option pays o one dollar as soon as

S , the price of the underlying, hits the barrier K . S S a IHH.

Example
Consider binary options that pays one dollar if the price

of the underlying increases to Using

some time period. Suppose the current price of the underlying is

r a H:I, price such a binary option when K a IPH.

K or above during  a H:P, @T tA a I and

169

double pyo' inry ll(const double& , const double& u){ if (>=u) return 1; return 0;
};

double pyo' inry put(const double& , const double& u){ if (<=u) return 1; return 0;
};

C++ Code 17.4:


C++ program:

Payo denitions for binomial options

out << " binary option price = " << option prie generi inomil(,u,pyo' inry ll, r, sigm, time to mturity, steps) << endl;
Output from C++ program:

double = 100.0; double u = 120.0; double r = 0.1; double sigm = 0.25; double time to mturity=1.0; int steps = 100;

inry option prie a HFRWVVSV

170

17.2

Delta calculation
C++ Code 17.5
shows how

Deltas and other greeks are calculated using the same style of generic routine. to calculate delta using the same generic approach.

#include <mth> #include <lgorithm> #include <vetor> using namespace std;


double option prie delt generi inomil(const double& , const double& u, double generi pyo' (const double& , const double& u), const double& r, const double& sigm, const double& t, const int& no steps){ double = exp(r*(t/no steps)); double inv = 1.0/; double u = exp(sigm*sqrt(t/no steps)); double d = 1.0/u; double uu= u*u; double pp = ( d)/(u d); double phown = 1.0 pp;

vetor<double> pries (no steps+1); pries[0] = *pow(d, no steps); for (int i=1; i<=no steps; ++i) pries[i] vetor<double> vlues (no steps+1); for (int i=0; i<=no steps; ++i) vlues[i]

uu*pries[i1]; generi pyo' (pries[i],u);

for (int gurrtep=no steps 1 ; gurrtep>=1; for (int i=0; i<=gurrtep; ++i) {

gurrtep) {

pries[i] = d*pries[i+1]; vlues[i] = (phown*vlues[i]+pp*vlues[i+1])*inv; vlues[i] = mx(vlues[i], generi pyo' (pries[i],u));


= (vlues[1]

}; };

double delt return delt;


};

vlues[0])/(*u*d);
C++ Code 17.5:

Generic binomial calculation of delta

Exercise 17.1.
The generic routines discussed in this chapter have been for American options. How would you modify them to account for European options?

171

Chapter 18

Trinomial trees
Contents
18.1 Intro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 172 175 18.2 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18.3 Further reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

18.1

Intro

A trinomial tree is similar to a binomial tree, just with one more branch. At each point of time there are three possible future values of the underlying

S.

SH

rr r

B E

Su a uSH Sm a SH Sd a dSH

rr

rr j r

18.2

Implementation

A trinomial tree can be implemented with various parameterizations. We will show the calulation using the following parameterization:

p u a e Qt

ea

u
r

pu a pm a pu a

P I t rq C P IP P T
 

P Q
r

t P I rq C IP P P T
 

We calculate the option price using the usual roll back procedure with the continuation value

ert @pu fu C pm fm C pd fd A
Example
You are given the following information about an option:

S a IHH, K a IHH, r a H:I,  a H:PS and time to

maturity is 1 year. Price an American put using a trinomial approximation with 100 steps.

172

#include <vetor> #include <mth> using namespace std;


double option prie put merin trinomil( const double& , const double& u, const double& r, const double& q, const double& sigm, const double& t, const int& steps) { double delt t = t/steps; double inv = exp( r*(delt t)); double sigm sqr=pow(sigm,2);

double double double double double

u = exp(sigm*sqrt(3.0*delt t)); d = 1.0/u; p u = 1.0/6.0 + sqrt(delt t/(12.0*sigm sqr)) p m = 2.0/3.0; p d = 1.0/6.0 sqrt(delt t/(12.0*sigm sqr))

* (r

q0.5*sigm q0.5*sigm

sqr); sqr);

* (r

vetor< vetor<double> > tree; GG prie of underlying in tree vetor<double> ve; ve.push k(); for (int step=1;step<=steps;++step){ tree.push k(ve); ve.insert(ve.egin(),ve[0]*d); GG use the ft tht only the extreme vlues hngeF ve.push k(ve[ve.size()1]*u);
}; = ve.size(); vetor<double> vlues next = vetor<double>(m); GG vlue of option next step for (int i=0; i<m; ++i) vlues next[i] = mx(0.0, uve[i]); GG ll pyo's t mturity vetor<double> vlues; for (int step=steps1; step>=0; step) { m = tree[step].size(); vlues = vetor<double> (m); GG vlue of option for (int i=0; i<m; ++i) { vlues[i] = (p u*vlues next[i+2]+p m*vlues next[i+1] + p d*vlues next[i])*inv; vlues[i] = mx(vlues[i],utree[step][i]); GG hek for exerise };

int m

vlues next=vlues;
};

return vlues[0];
};

C++ Code 18.1:


C++ program:

Price of american put using a trinomial tree

out << " american put = " << option prie put merin trinomil(,u,r,q,sigm,time,no steps) << endl;
Output from C++ program:

double = 100.0; double u = 100.0; double r = 0.1; double q = 0; double sigm double time=1.0; int no steps = 100;

= 0.25;

merin put a TFSPUIW

173

function

= opt prie trinom m put(, u, r, q, sigm, t, steps) delt t = t/steps; sigm sqr=sigm^2; inv = exp(r*delt t); u = exp(sigm*sqrt(3.0*delt t)); d = 1.0/u; p u = 1/6 + sqrt(delt t/(12*sigm sqr)) * (rq0.5*sigm sqr); p m = 2/3; p d = 1/6 sqrt(delt t/(12*sigm sqr)) * (rq0.5*sigm sqr);

ve = [ ]; tree = [ ve ]; u = ; d = ; for step=1:steps+1 u = u*u; d = d*d; ve = [ d; ve; u ]; tree=[ [tree; zeros(2,step)] ve ]; end vlues next = max(0,uve); for step = steps:1:0 m = 2*step+1; vlues = inv*(p u*vlues next(3:m+2)+p m*vlues next(2:m+1)+p d*vlues next(1:m)); vlues = max(vlues, utree(1:m,step+1)); vlues next = vlues; end end = vlues; end

wtl Code 18.1: wtl


program:

Price of american put using a trinomial tree

=100; u=100; r=0.1; q=0; sigm=0.25; time=1; no steps=100; = opt prie trinom m put(,u,r,q,sigm,time,no steps)
Output from

wtl

program:

a TFSRTV
Exercise 18.1.
In the code for the trinomial tree the price of the underlying is put into a triangular data structure. This can be collapsed into a single array, since the only changes when you add one step is to add one price at the top and at the bottom. If you keep track of the top and bottom of the current array you can access the prices of the underlying through some clever indexing into the single vector of prices of the underlying.

Exercise 18.2.
Similarly to the binomial case, one can build a generic trinomial tree where the payo function is passed as a parameter to the routine. Implement such a generic trinomial tree.

174

18.3

Further reading

Hull (2006)

175

Chapter 19

Alternatives to the Black Scholes type option formula


Contents
19.1 Merton's Jump diusion model. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.2 Hestons pricing formula for a stochastic volatility model . . . . . . . . . . . . . . . . . . . . . 176 178
Few of

A large number of alternative formulations to the Black Scholes analysis has been proposed. them have seen any widespread use, but we will look at some of these alternatives.

19.1

Merton's Jump diusion model.

Merton (1976) has proposed a model where in addition to a Brownian Motion term, the price process of the underlying is allowed to have

jumps.

The risk of these jumps is assumed to not be priced.

In the following we look at an implementation of a special case of Merton's model, described in (Hull, 1993, pg 454), where the size of the jump has a normal distribution. jump distribution. The price of an European call option is given in

C++ Code 19.1

Formula 19.1

and

are parameters of the and implemented in

ca
where

I eH  @H  An
naH

n3

P CBS @S; X; rn ; n ; T tA

 aT t H a @I C A CBS @A is the Black Scholes formula, and n P P n a P C  n ln@I C A rn a r  C 


Formula 19.1:
The option pricing formula of the Merton (1976) model

In implementing this formula, we need to terminate the innite sum at some point.

But since the

factorial function is growing at a much higher rate than any other, that is no problem, terminating at nabout

n a SH
H

should be on the conservative side.

To avoid numerical diculties, use the following

method for calculation of

e   @ H  A n e   @ H  A n a exp ln n3 n3
Example

33

a exp H  C n ln@H  A ln i
iaI

Price an option using Merton's jump diusion formula, using the parameters

S a IHH, K a IHH, r a H:HS,  a H:Q,  a H:S,  a H:S,  a H:S.


176

#include <mth> #include "fin_recipes.h"


double option prie ll merton jump di'usion( const double& , const double& , const double& r, const double& sigm, const double& time to mturity, const double& lmd, const double& kpp, const double& delt) { const int wex=50; double tu=time to mturity; double sigm sqr = sigm*sigm; double delt sqr = delt*delt; double lmdprime = lmd * (1+kpp); double gmm = log(1+kpp); double = exp( lmdprime*tu)*option prie ll lk sholes(,,r lmd*kpp,sigm,tu); double log n = 0; for (int n=1;n<=wex; ++n) { log n += log(double(n)); double sigm n = sqrt( sigm sqr+n*delt sqr/tu ); double r n = r lmd*kpp+n*gmm/tu;

+=

exp(lmdprime*tu+n*log(lmdprime*tu)log n)* option prie ll lk sholes(,,r n,sigm n,tu);

};

return ;
};

C++ Code 19.1:


time to maturity=1. C++ program:

Mertons jump diusion formula

out << " Merton Jump diffusion call = " << option prie ll merton jump di'usion(,u,r,sigm,time to mturity,lmd,kpp,delt) << endl;
Output from C++ program:

double =100; double u=100; double r=0.05; double sigm=0.3; double time to mturity=1; double lmd=0.5; double kpp=0.5; double delt=0.5;

werton tump diffusion ll a PQFPHUR

177

19.2

Hestons pricing formula for a stochastic volatility model

Heston (1993) relaxes the Black-Scholes assumption of a constant volatility by introducing a stochastic volatility. He nds exact solutions for European options. Let

S be the stock price and v the volatility. dS @tA a Sdt p v@tASdzI @tA C p d v@tA a v@tAdt C v@tASdzP @tA
p

These two variables are assumed to follow joint stochastic

processes.

The two processes

zI and zP have correlation .


p

Rewrite the process for the volatility as

dv@tA a  @ v@tAA dt C  v@tAdzP


Let

@S; v; tA be the price of volatility risk. P @t; T A a er@T tA K.

Under a constant interest rate

Consider a call option with strike price

Its price is given by

Formula 19.2.

Price of Call option using Hestons formula The option price is

C @s; v; tA a SPI KP @t; T APP


where

I I I ei ln@K A fj @x; v; T; A Pj @x; v; T; ln@K AA a C Re d P  H i

fj @x; v; T; A a eC @;ACD@;AvCix
&

a I ged C @; A a ri C P @bj i C dA P ln  Ig D@; A a uI a ; a a  bI a  C   bP a  C  x a ln@S A ga bj i C d bj i d
q

!'

bj i C d I ed P I ged uP a


I P

I P

d a @i bj AP P @Puj i P A
Notation: S : price of undelying security. K : exercise price.
The implementation of this pricing formula has some instructive C++ features. First, it illustrates calculations of of complex variables. Complex numbers is part of the C++ standard, and are accessed by including the

5inlude `omplexb
178

statement. Complex numbers are templated, it is necessary to specify what type of oating point type to use, such as

omplex`douleb

or

omplex`doule douleb.
1

To evaluate the price it is also necessary to do a numerical integration. In the calculation this is solved by a call to an external routine. We use a routine provided by the Gnu GSL project.

Example
Given the following set of parameters:

 a H:HI and  a H:HI, price a call option using the Heston formula
C++ program:

S a IHH, K a IHH, r a H:HI, v a H:HI,  a H:S,  a H,  a P,  a H,

double =100; double u=100; double r=0.01; double v=0.01; double tu=0.5; double rho=0; double kpp=2; double lmd=0.0; double thet=0.01; double sigm=0.01;

out << "heston call price " << heston ll option prie( , u, r, v, tu, rho, kpp, lmd, thet, sigm) << endl;

Output from C++ program:

heston ll prie QFHTWRR

1 en exmple lterntives would hve een xumeril eipes in gCC9s qudrtureF

179

#include <iostrem> #include <mth> #include <omplex> using namespace std; #include "gsl/gsl_integration.h"
struct heston prms {double u; double x; double r; double v; double tu; double kpp; double thet; double rho; double sigm; double lmd; int j;}; extern "C"{ double heston integrnd j(double phi, void *p){ struct heston prms* prms = (struct heston prms*)p; double u = (prms >u); double x = (prms >x); double v = (prms >v); double r = (prms >r); double kpp = (prms >kpp); double thet = (prms >thet); double rho = (prms >rho); double sigm = (prms >sigm); double lmd = (prms >lmd); double tu = (prms >tu); double j = (prms >j); double sigm sqr = pow(sigm,2); double uj; double j; if (j==1){ uj=0.5; j=kpp+lmd rho*sigm; } else { uj= 0.5; j=kpp+lmd; }; omplex <double> i(0,1); double = kpp*thet; omplex<double> d = sqrt( pow(rho*sigm*phi*i j,2) sigm sqr*(2*uj*phi*i pow(phi,2)) ); omplex<double> g = (j rho*sigm*phi*i+d)/(j rho*sigm*phi*i d); omplex<double> g = r*phi*i*tu+(/sigm sqr)*((j rho*sigm*phi*i+d)*tu 2.0*log((1.0 g*exp(d*tu))/(1.0 g))); omplex<double> h = (j rho*sigm*phi*i+d)/sigm sqr * ( (1.0 exp(d*tu))/(1.0 g*exp(d*tu)) ); omplex<double> fI = exp(g+h*v+i*phi*x); omplex<double> p = exp( phi*i*log(u))*fI/(i*phi); return rel(p);

};};

inline double heston j(double , double u, double r, double v, double tu, double sigm, double kpp, double lmd, double rho, double thet, int j){ double x=log(); struct heston prms prms = { u, x, r, v, tu, kpp, thet, rho, sigm, lmd, j};

size t n=10000; gsl integrtion workspe* w = gsl integrtion workspe llo(n); gsl funtion p; p.funtion = &heston integrnd j; p.prms=&prms; double result, error; gsl integrtion qgiu(&p,0,1e7,1e7,n,w,&result,&error); GG integrl to in(nity strting t zero return 0.5 + result/w s;

};

double heston ll option prie(const double& , const double& u, const double& r, const double& v, const double& tu, const double& rho, const double& kpp, const double& lmd, const double& thet, const double& sigm){ double I = heston j(,u,r,v,tu,sigm,kpp,lmd,rho,thet,1); double P = heston j(,u,r,v,tu,sigm,kpp,lmd,rho,thet,2); double g=*I u*exp( r*tu)*P; return g;

};

C++ Code 19.2:

Hestons pricing formula for a stochastic volatility model

180

Chapter 20

Pricing of bond options, basic models


Contents
20.1 Black Scholes bond option pricing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.2 Binomial bond option pricing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181 183

The area of xed income securities is one where a lot of work is being done in creating advanced mathematical models for pricing of nancial securities, in particular xed income derivatives. The focus of the modelling in this area is on modelling the term structure of interest rates and its evolution over time, which is then used to price both bonds and xed income derivatives. However, in some cases one does not need the machinery of term structure modelling which we'll look at in later chapters, and price derivatives by modelling the evolution of the bond price directly. Specically, suppose that the price of a Bond follows a Geometric Brownian Motion process, just like the case we have studied before. This is not a particularly realistic assumption for the long term behaviour of bond prices, since any bond price converges to the bond face value at the maturity of the bond. The Geometric Brownian motion may be OK for the case of short term options on long term bonds.

20.1

Black Scholes bond option pricing


C++ Code 20.1 C++ Code 20.2

Given the assumed Brownian Motion process, prices of European Bond Options can be found using the usual Black Scholes formula, as shown in case of an option on a coupon bond. for a zero coupon bond and for the

#include <mth> #include "normdist.h"


double ond option prie put zero lk sholes(const double& f, const double& , const double& r, const double& sigm, const double& time){ double time sqrt = sqrt(time); double dI = (log(f/)+r*time)/(sigm*time sqrt) + 0.5*sigm*time sqrt; double dP = dI (sigm*time sqrt); double p = * exp( r*time) * x( dP) f * x( dI); return p;

};

C++ Code 20.1:

Black scholes price for European put option on zero coupon bond

181

#include <mth> #include <vetor> using namespace std; #include "normdist.h" #include "fin_recipes.h"
double ond option prie put oupon ond lk sholes( const double& f, const double& , const double& r, const double& sigm, const double& time, const vetor<double> oupon times, const vetor<double> oupon mounts){ double djusted f=f; for (unsigned int i=0;i<oupon times.size();i++) { if (oupon times[i]<=time) {

djusted f

= oupon

mounts[i]

exp(r*oupon times[i]);

}; };

return ond option prie put zero lk sholes(djusted f,,r,sigm,time);


};

C++ Code 20.2:

Black scholes price for European put option on coupon bond

182

20.2

Binomial bond option pricing


C++ Code 20.3

Since we are in the case of geometric Brownian motion, the usual binomial approximation can be used to price American options, where the bond is the underlying security. of a put price shows the calculation

#include <mth> #include <lgorithm> #include <vetor> using namespace std;

GG stndrd mthemtil lirry GG de(ning the mx@A opertor GG v vetor templtes

double ond option prie put merin inomil( const double& f, GG fond prie const double& u, GG exerise prie const double& r, GG interest rte const double& sigm, GG voltility const double& t, GG time to mturity const int& steps){ GG no steps in inomil tree double = exp(r*(t/steps)); GG interest rte for eh step double inv = 1.0/; GG inverse of interest rte double u = exp(sigm*sqrt(t/steps)); GG up movement double uu = u*u; double d = 1.0/u; double p up = ( d)/(u d); double p down = 1.0 p up; vetor<double> pries(steps+1); GG prie of underlying vetor<double> put vlues(steps+1); GG vlue of orresponding put

pries[0] = f*pow(d, steps); GG (ll in the endnodesF for (int i=1; i<=steps; ++i) pries[i] = uu*pries[i1]; for (int i=0; i<=steps; ++i) put vlues[i] = mx(0.0, (upries[i])); GG put pyo's t mturity for (int step=steps1; step>=0; step) { for (int i=0; i<=step; ++i) { put vlues[i] = (p up*put vlues[i+1]+p down*put vlues[i])*inv; pries[i] = d*pries[i+1]; put vlues[i] = mx(put vlues[i],(upries[i])); GG hek for exerise
}; };

return put vlues[0];


};

C++ Code 20.3:

Binomial approximation to american put bond option price

183

Example
Parameters:

B a IHH, K a IHH, r a H:HS,  a H:I, time=1.

There is also a coupon bond with the the same bond price, but paying coupon of

H:S at date 1.

1. Price a an European put option on the zero coupon bond using Black Scholes. 2. Price a an European put option on the coupon coupon bond using Black Scholes. 3. Price a an European put option on the zero coupon bond using binomial approximation with 100 steps. C++ program:

double double double double double

f=100; u=100; r=0.05; sigm=0.1; time=1; out << " zero coupon put option price = " << ond option prie put zero lk sholes(f,u,r,sigm,time) << endl;

vetor<double> oupon times; oupon times.push k(0.5); vetor<double> oupons; oupons.push k(1); out << " coupon bond put option price = " << ond option prie put oupon ond lk sholes(f,u,r,sigm,time,oupon times,oupons); out << endl;
int steps=100;

out << " zero coupon american put option price, binomial = " << ond option prie put merin inomil(f,u,r,sigm,time,steps) << endl;
Output from C++ program:

zero oupon put option prie a IFWPUWI oupon ond put option prie a PFPPVSP zero oupon merin put option prieD inomil a PFRQPVP

184

Chapter 21

Credit risk
Contents
21.1 The Merton Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.2 Issues in implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Option pricing has obvious applications to the pricing of risky bonds.

185 186

21.1

The Merton Model

This builds on the Black and Scholes (1973) and Merton (1973) framework to nd the value of the debt issued by the rm. The ideas were already in Black and Scholes, who discussed the view of the rm as a call option. Assume debt structure: There is a single debt issue. Debt is issued as a zero coupon bond. The bond is due on a given date

T.

Assuming the rm value

follows the usual Brownian motion proces, debt is found as a closed form

solution, similar in structure to the Black Scholes equation for a call option. Easiest seen from the interpretation of rm debt as the price of risk free debt, minus the value of a put option. Price debt by the price Scholes formula. The Black Scholes formula for a call option is

of risk free debt, and then subtract the price of the put, using the Black

c a S N @dI A K er@T tA N @dP A


where

dI a

ln

S K C @r C

dP a dI  T t N @ A a
The cumulative normal distribution

I p P A@T tA  T t

p a Ker@T tA N @dP A SN @dI A


In the context here, reinterpret

S as V , rm value.

The put is priced as

p a Ker@T tA N @dP A Vt N @dI A


where

dI a

ln

V t K C @r C

I p P A@T tA  T t

Note on interpretation: The spread between risky and risk free debt determined solely by the price of the put option.

185

Example
The current value of the rm

V a IHH.

The rm has issued one bond with face value 90, which is due to

be paid one year from now. The risk free interest rate is 5% and the volatility of the rms value is 25%. Determine the value of the debt. C++ program:

out << " Debt value = " << exp(r*)*p


Output from C++ program:

double =100; double p=90; double r=0.05; double =1; double sigm=0.25; double p = option prie put lk sholes(,p,r,sigm,);

out << " Credit Risk Calculation " << endl;

p << endl;

gredit isk glultion het vlue a VIFVSWP

21.2

Issues in implementation
Firm value and rm volatility is unobservable. The model assumes a simple debt structure, most debt structures tend to be more complex.

 

186

Chapter 22

Term Structure Models


Contents
22.1 The Nelson Siegel term structure approximation . . . . . . . . . . . . . . . . . . . . . . . . . 22.2 Extended Nelson Siegel models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22.3 Cubic spline. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22.4 Cox Ingersoll Ross. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22.5 Vasicek . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22.6 Readings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 190 192 195 198 199

We now expand on the analysis of the term structure in chapter 5. As shown there, the term structure is best viewed as an abstract class providing, as functions of term to maturity, the prices of zero coupon bonds (discount factors), yield on zero coupon bonds (spot rates) or forward rates. In the earlier case we considered two particular implementations of the term structure: A at term structure or a term structure estimated by linear interpolations of spot rates. We now consider a number of alternative term structure models. The focus of this chapter is empirical, we consider ways in which on one can specify a term structure in a lower dimensional way. Essentially we are looking at ways of doing curve-tting, of estimating a nonlinear relationship between time and discount factors, or between time and spot rates. Since the relationship is nonlinear, this is a nontrivial problem. One has to choose a functional form to estimate, which allows enough exibility to t the term structure, but not so exible that it violates the economic restrictions on the term structure. Here are some considerations.

    

Discount factors must be positive. ( for abritrage.

dt > H).

This is because they are prices, negative prices allow

Discount factors must be a nonincreasing function of time. ( avoid arbitrage. Nominal interest rates can not be negative. ( of arbitrage opportunities.

dt ! dtCk V k > H).

Again, this is to

rt ! H V tA This is another implication of the absence

Both discount factors and interest rates must be smooth functions of time. The value of a payment today is the payment today.

dH a I.
Of

A number of alternative ways of estimating the term structure has been considered. Some are purely used as interpolation functions, while others are fully specied, dynamic term structure models.

the models that follow, the approximating function proposed in Nelson and Siegel (1987) and the cubic spline used by e.g. McCulloch (1971) are examples of the rst kind, and the term structure models of Cox, Ingersoll, and Ross (1985) and Vasicek (1977) are examples of the second kind. What is the typical use of the functions we consider here? One starts with a set of xed income securities, typically a set of treasury bonds. Observing the prices of these bonds, one asks: What set of discount factors is most likely to have generated the observed prices. Or: What term structure approximations provides the best t to this set of observed bond prices.

22.1

The Nelson Siegel term structure approximation

Nelson and Siegel (1987) proposes the parameterization shown in FormulaRefns

187

r@tA a H C @ I C P A
Formula 22.1:
#include <mth> using namespace std;

I e 
t

t 

t C P e 

Notation: t: Time to maturity. r spot interest rate, 0 ; 1 ; 2 and : constants.


Nelson and Siegel (1987) parameterization of term structure

double term struture yield nelson siegel(const double& t, const double& etH, const double& etI, const double& etP, const double& lmd) { if (t==0.0) return etH; double tl = t/lmd; double r = etH + (etI+etP) * ((1 exp( tl))/tl) + etP return r;

exp(tl);

};

C++ Code 22.1:

Calculation of the Nelson and Siegel (1987) term structure model

The implementation of this calculation is shown in This is wrapped in a term structure

class

C++ Code 22.1. Header File 22.1


{

as shown in

and

C++ Code 22.2.

class term struture lss nelson siegel X public term struture lss private: double etH , etI , etP , lmd ; public: term struture lss nelson siegel(const double& etH, const double& etI, const double& etP, const double& lmd); virtual double yield(const double& ) const;
};

Header le 22.1:

Header le dening a term structure class wrapper for the Nelson Siegel approximation

188

#include "fin_recipes.h"

term struture lss nelson siegelXXterm struture lss nelson siegel( const double& H, const double& I, const double& P, const double& l) { etH =H; etI =I; etP =P; lmd =l;
};

double term struture lss nelson siegelXXr(const double& t) const { if (t<=0.0) return etH ; return term struture yield nelson siegel(t,etH ,etI ,etP ,lmd
};

);

C++ Code 22.2:

Dening a term structure class wrapper for the Nelson Siegel approximation

189

Example
Using the parameters

H a H:HI, I a H:HI, P a H:HI,  a S:H and t a I in the Nelson Siegel approximation,

nd the 1 year discount factor and spot rate, and the forward rate between years 1 and 2. C++ program:

out << "Example calculations using the Nelson Siegel term structure approximation" << endl; out << " direct calculation, yield = " << term struture yield nelson siegel(t,etH,etI,etP,lmd) << endl; term struture lss nelson siegel ns(etH,etI,etP,lmd); out << " using a term structure class" << endl; out << " yield (t=1) = " << ns.r(t) << endl; out << " discount factor (t=1) = " << ns.d(t) << endl; out << " forward rate (t1=1, t2=2) = " << ns.f (1,2) << endl;
Output from C++ program:

double etH=0.01; double etI=0.01; double etP=0.01; double lmd=5.0; double t=1.0;

ixmple lultions using the xelson iegel term struture pproximtion diret lultionD yield a HFHQTQIRP using term struture lss yield @taIA a HFHQTQIRP disount ftor @taIA a HFWTRQQU forwrd rte @tIaID tPaPA a HFHQHHTHP

22.2

Extended Nelson Siegel models

The Nelson and Siegel (1987) model is simple, with parameters with clear obvious economic interpretations. It does have the problem that the term structure shapes that it allows is limited. To allow

for more complex shapes, such as humped shapes, it has been extended in various ways. approximation was introduced by Lars Svensson, parameterized as shown in

A popular

Formula 22.2

r@tA a H C I
Formula 22.2:

I e 1
t

t 

C P

I e 1
t

t 1

e t1

C Q

I e 2
t

t 2

e t2

Notation: t: Time to maturity. r spot interest rate, 0 ; 1 ; 2 and : constants.


Svensson's extension of the Nelson and Siegel (1987) parameterization of term structure

This is wrapped in a term structure class as shown in

Header File 22.2

and

C++ Code 22.4.

190

#include <mth> using namespace std;


double term struture yield svensson(const double& t, const double& etH, const double& etI, const double& etP, const double& etQ, const double& tuI, const double& tuP){ if (t==0.0) return etH; double r = etH;

r += r += r += return

etI* ((1exp(t/tuI))/(t/tuI)) ; etP * ( ((1exp(t/tuI))/(t/tuI)) etQ * ( ((1exp(t/tuP))/(t/tuP)) r;

exp(t/tuI) ); exp(t/tuP) );

};

C++ Code 22.3:

Calculation of Svensson's extended Nelson and Siegel (1987) term structure model

class term struture lss svenssonXpuli term private: double etH , etI , etP , etQ , tuI public: term struture lss svensson(const double& const double& const double& const double& const double& const double& virtual double yield(const double& ) const;
};

struture lss
,

tuP

etH, etI, etP, etQ, tuI, tuP);

Header le 22.2:

Header le dening a term structure class wrapper for the Svensson model

#include "fin_recipes.h"

term struture lss svenssonXXterm struture lss svensson( const double& H, const double& I, const double& P, const double& Q, const double& tuI, const double& tuP) { etH =H; etI =I; etP =P; etQ =Q; tuI =tuI; tuP =tuP;
};

double term struture lss svenssonXXr(const double& t) const { if (t<=0.0) return etH ; return term struture yield svensson(t,etH ,etI ,etP ,etQ ,tuI ,tuP
};

);

C++ Code 22.4:

Dening a term structure class wrapper for the Svensson model

191

22.3

Cubic spline.

Cubic splines are well known for their good interpolation behaviour. The cubic spline parameterization was rst used by McCulloch (1971) to estimate the nominal term structure. He later added taxes in

McCulloch (1975). The cubic spline was also used by Litzenberger and Rolfo (1984). In this case the qubic spline is used to approximate the

discount factor, not the yields.

d@tA a I C bI t C cI tP C dI tQ C Fj @t tj AQ Ift<tj g j aI
Here

IfAg

is the indicator function for an event

To estimate this we need to nd the

QCK

A, and we have K knots .

parameters:

fbI ; cI ; dI ; FI ; ; FK g
If the spline

knots are known, this is a simple linear regression.

C++ Code 22.5 shows the calculation using

this approximation.

#include <mth> #include <vetor> using namespace std;


double term struture disount ftor ui spline(const double& t, const double& I, const double& I, const double& dI, const vetor<double>& f, const vetor<double>& knots){ double d = 1.0 + I*t + I*(pow(t,2)) + dI*(pow(t,3)); for (int i=0;i<knots.size();i++) { if (t >= knots[i]) { d += f [i] * (pow((t knots[i]),3)); } else { break; };

};

return d;
};

C++ Code 22.5: Header File 22.3


and

Approximating a discount function using a cubic spline wraps this calculations into a term structure class.

C++ Code 22.6

#include "fin_recipes.h" #include <vetor> using namespace std;


class term struture lss ui spline X public term struture lss { private: double ; double ; double d ; vetor<double> f ; vetor<double> knots ; public: term struture lss ui spline(const double& , const double& , const double& d, const vetor<double>& f, const vetor<double> & knots); virtual term struture lss ui spline(); virtual double d(const double& ) const;
};

Header le 22.3:

Term structure class wrapping the cubic spline approximation

192

#include "fin_recipes.h"

term struture lss ui splineXX term struture lss ui spline ( const double& , const double& , const double& d, const vetor<double>& f, const vetor<double>& knots) = ; = ; d = d; f .ler(); knots .ler(); if (f.size()!=knots.size()){ return; }; for (int i=0;i<f.size();++i) { f .push k(f [i]); knots .push k(knots[i]);
}; };

double term struture lss ui splineXXd(const double& ) const { return term struture disount ftor ui spline(, , ,d ,f ,knots
};

);

C++ Code 22.6:

Term structure class wrapping the cubic spline approximation

193

Example
Using the parameters

b a H:I c a H:I, d a H:I,

aR

H:HI H:HI H:HI


P

Q S

knots a R

P U IP

Q S

Find short rates and discount factors for 1 year, and the forward rate between 1 and 2 years. C++ program:

out << "Example term structure calculations using a cubic spline " << endl; double =0.1; double =0.1; double d=0.1; vetor<double> f ; f.push k(0.01); f.push k(0.01); f.push k(0.01); vetor<double> knots; knots.push k(2); knots.push k(7); knots.push k(12); out << " direct calculation, discount factor (t=1) " << term struture disount ftor ui spline(1,,,d,f,knots) << endl; out << " Using a term structure class " << endl; term struture lss ui spline s(,,d,f,knots); out << " yield (t=1) = " << s.r(1) << endl; out << " discount factor (t=1) = " << s.d(1) << endl; out << " forward (t1=1, t2=2) = " << s.f (1,2) << endl;
Output from C++ program:

ixmple term struture lultions using ui spline diret lultionD disount ftor @taIA IFI sing term struture lss yield @taIA a EHFHWSQIHP disount ftor @taIA a IFI forwrd @tIaID tPaPA a HFQIVRSR

194

22.4

Cox Ingersoll Ross.

The Cox et al. (1985) model is the best known example of a continuous time, general equilibrium model of the term structure. It is commonly used in academic work because it is a general equilibrium model that still is simple enough to let us nd closed form expressions for derivative securities. The short interest rate.

dr@tA a @ r@tAAdt C  r@tAdW


The discount factor for a payment at time T.

d@t; T A a A@t; T AeB@t;T Ar@tA


where

a @  C A P C P  P
P e 2 @CC A@T tA A@t; T A a @ C  C A@e@T tA IA C P
1

5 2 2


and

B @t; T A a
parameter,

Pe @T tA I @ C  C A@e@T tA IA C P
risk

Five parameters:

r, the short term interest rate, , the mean reversion parameter, , the market  the longrun mean of the process and , the variance rate of the process.

#include <mth> using namespace std;


double term struture disount ftor ir(const double& t, const double& r, const double& kpp, const double& lmd, const double& thet, const double& sigm){ double sigm sqr=pow(sigm,2); double gmm = sqrt(pow((kpp+lmd),2)+2.0*sigm sqr); double denum = (gmm+kpp+lmd)*(exp(gmm*t) 1)+2*gmm; double p=2*kpp*thet/sigm sqr; double enumI= 2*gmm*exp(0.5*(kpp+lmd+gmm)*t); double e = pow((enumI/denum),p); double f = (2*(exp(gmm*t) 1))/denum; double dft=e*exp( f*r); return dft;

};

C++ Code 22.7:

Calculation of the discount factor using the Cox et al. (1985) model

195

#include "fin_recipes.h"
class term struture lss ir X public term struture lss { private: double r ; GG interest rte double kpp ; GG men reversion prmeter double lmd ; GG risk version double thet ; GG long run men double sigm ; GG voltility public:

term struture lss ir(); term struture lss ir(const double& r, const double& k, const double& l, const double& th, const double& sigm); virtual double d(const double& ) const;

};

Header le 22.4:

Class denition, Cox et al. (1985) model, header le

#include "fin_recipes.h"

GGterm struture lss irXXterm struture lss ir@A{Y}Y


term struture lss irXXterm struture lss ir(const double& r, const double& k, const double& l, const double& th, const double& sigm) { r =r; kpp =k; lmd =l; thet =th; sigm =sigm;
};

double term struture lss irXXd(const double& ) const{ return term struture disount ftor ir(,r ,kpp ,lmd ,thet ,sigm
};

);

C++ Code 22.8:

Class denition, Cox et al. (1985) model

196

Example
Parameters:

short rate and discount factor for C++ program:

r a H:HS,  a H:HI,  a H:I,  a H:HV and  a H:H. Use the CIR term structure model. t a I, and forward rate between years 1 and 2.

Find

out << "Example calculations using the Cox Ingersoll Ross term structure model " << endl; = 0.05; double kpp=0.01; double sigm=0.1; double thet=0.08; double lmd=0.0; out << " direct calculation, discount factor (t=1): " << term struture disount ftor ir(1, r, kpp, lmd, thet, sigm) << endl; out << " using a class " << endl; term struture lss ir ir(r,kpp,lmd,thet,sigm); out << " yield (t=1) = " << ir.r(1) << endl; out << " discount factor (t=1) = " << ir.d(1) << endl; out << " forward (t1=1, t2=2) = " << ir.f (1,2) << endl;
double r
Output from C++ program:

ixmple lultions using the gox sngersoll oss term struture model diret lultionD disount ftor @taIAX HFWSIITT using lss yield @taIA a HFHSHHTTV disount ftor @taIA a HFWSIITT forwrd @tIaID tPaPA a HFHRWVUST

197

22.5

Vasicek

#include <mth> using namespace std;


double term struture disount ftor vsiek(const const const const const double e,f; double sigm sqr = sigm*sigm; double = *; if (==0.0){ double& double& double& double& double&

time, r, , , sigm){

f e

= =

time; exp(sigm sqr*pow(time,3))/6.0;

else

f e

= (1.0 =

exp(
=

exp(*time))/; ((ftime)*(*0.5*sigm
e*exp(f*r);

sqr))/

((sigm

sqr*f*f)/(4*)));

};

double dft return dft;


}

C++ Code 22.9:

Calculating a discount factor using the Vasicek functional form

#include "fin_recipes.h"
class term struture lss vsiek X public term struture lss { private: double r ; double ; double ; double sigm ; public: term struture lss vsiek(const double& r, const double& , const double& , const double& sigm); virtual double disount ftor(const double& ) const;
};

Header le 22.5:

Class denition, Vasicek (1977) model

#include "fin_recipes.h"

term struture lss vsiekXXterm struture lss vsiek(const double& r, const double& , const double& , const double& sigm) r =r; =; =; sigm =sigm;
};

double term struture lss vsiekXXd(const double& ) const{ return term struture disount ftor vsiek(,r , , ,sigm
};

);

C++ Code 22.10:

Class denition, Vasicek (1977) model

198

Example
Parameters

discount factor for C++ program:

r a H:HS, a a H:I, b a H:I,  a H:I Use the Vasicek term structure model. t a I, and forward rate between years 1 and 2.

Find short rate and

out << "Example term structure calculation using the Vasicek term structure model" << endl; double r=0.05; double =0.1; double =0.1; double sigm=0.1; out << " direct calculation, discount factor (t=1): " << term struture disount ftor vsiek(1, r, , , sigm) << endl; term struture lss vsiek v(r,,,sigm); out << " using a term structure class " << endl; out << " yield (t=1) = " << v.r(1) << endl; out << " discount factor (t=1) = " << v.d(1) << endl; out << " forward rate (t1=1, t2=2) = " << v.f (1,2) << endl;
Output from C++ program:

ixmple term struture lultion using the siek term struture model diret lultionD disount ftor @taIAX HFWSSRHV using term struture lss yield @taIA a HFHRSTITV disount ftor @taIA a HFWSSRHV forwrd rte @tIaID tPaPA a HFHPVIRUT

22.6

Readings

The methods in this chapter I rst studied in my dissertation at Carnegie Mellon University in 1992, which lead to the paper published as Green and degaard (1997). A textbook treatment of estimation and tting of term structure models can be found in (Martinelli, Priaulet, and Priaulet, 2003, Ch 4)

199

Chapter 23

Binomial Term Structure models


Contents
23.1 The Rendleman and Bartter model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23.2 Readings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 202

Pricing bond options with the Black Scholes model, or its binomial approximation, as done in chapter 20, does not always get it right. For example, it ignores the fact that at the maturity of the bond, the bond volatility is zero. The bond volatility decreases as one gets closer to the bond maturity. This behaviour is not captured by the assumptions underlying the Black Scholes assumption. We therefore look at more complicated term structure models, the unifying theme of which is that they are built by building of the interest rate.

trees

23.1

The Rendleman and Bartter model

The Rendleman and Bartter approach to valuation of interest rate contingent claims (see Rendleman and Bartter (1979) and Rendleman and Bartter (1980)) is a particular simple one. Essentially, it is

to apply the same binomial approach that is used to approximate options in the Black Scholes world, but the random variable is now the interest rate. This has implications for multiperiod discounting:

Taking the present value is now a matter of choosing the correct sequence of spot rates, and it may be necessary to keep track of the whole tree of interest rates. Such a tree can then be used to price various xed income securities. In the next chapter we illustrate this more generally, here we show a direct implementation of the original model.

C++ Code 23.1

implements the original algorithm for a call

option on a (long maturity) zero coupon bond.

200

#include <mth> #include <lgorithm> #include <vetor> using namespace std;


double ond option prie ll zero merin rendlemn rtter(const double& , const double& option mturity, const double& , const double& w, GG term struture prmters const double& interest, GG urrent short interest rte const double& ond mturity, GG time to mturity for underlying ond const double& mturity pyment, const int& no steps) { double delt t = ond mturity/no steps; double double double double

u=exp(*sqrt(delt t)); d=1/u; p up = (exp(w*delt t)d)/(ud); p down = 1.0p up;

vetor<double> r(no steps+1); r[0]=interest*pow(d,no steps); double uu=u*u; for (int i=1;i<=no steps;++i){ r[i]=r[i1]*uu;}; vetor<double> (no steps+1); for (int i=0;i<=no steps;++i){ [i] = mturity pyment; }; int no ll steps=int(no steps*option mturity/ond mturity); for (int urr step=no steps;urr step>no ll steps;urr step) for (int i=0;i<urr step;i++) { r[i] = r[i]*u; [i] = exp(r[i]*delt t)*(p down*[i]+p up*[i+1]);
}; };

vetor<double> g(no ll steps+1); for (int i=0;i<=no ll steps;++i){ g[i]=mx(0.0,[i]); }; for (int urr step=no ll steps;urr step>=0;urr step) { for (int i=0;i<urr step;i++) { r[i] = r[i]*u; [i] = exp(r[i]*delt t)*(p down*[i]+p up*[i+1]); g[i]=mx([i], exp(r[i]*delt t)*(p up*g[i+1]+p down*g[i]));
}; };

return g[0];
};

C++ Code 23.1:

RB binomial model for European call on zero coupon bond

201

Example

Parameters:

K a WSH, S a H:IS and M a H:HS The interest rate is 10%, The option matures in 4 years, the

bond matures in year 5, with a bond maturity payment of 1000. Price the option on the zero coupon bond using a RandlemanBartter approximation with 100 steps. C++ program:

double u=950; double =0.15; double w=0.05; double interest=0.10; double option mturity=4; double ond mturity=5; double ond mturity pyment=1000; int no steps=100;

out << " Rendleman Bartter price of option on zero coupon bond: "; out << ond option prie ll zero merin rendlemn rtter( u, option mturity, , w, interest, ond mturity, ond mturity pyment, no steps);

Output from C++ program:

endlemn frtter prie of option on zero oupon ondX HFHHUIQTTI

23.2

Readings

General references include Sundaresan (2001). Rendleman and Bartter (1979) and Rendleman and Bartter (1980) are the original references for building standard binomial interest rate trees.

202

Chapter 24

Interest rate trees


Contents
24.1 The movement of interest rates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24.2 Discount factors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24.3 Pricing bonds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24.4 Callable bond . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24.5 Readings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203 204 205 207 209

In this chapter we show a way of building interest rate trees and apply it to the pricing of various xed income securities. The rst need in such a procedure is to specify the future evolution of interest rates.

24.1

The movement of interest rates

We will assume that interest rates follow a Geometric Brownian Motion process

dr a rdt C rdZ
This is the same assumption which was used for stock prices in the Black Scholes case. This leads to the same binomial approximation, for one period:

rH

B ru rr rr j rd

or several periods:

rH

r rr

u Br rr

ruu

r rrd j r

rr

rr j B

rud

rr j

rdd

When using this approach it turns out to be useful to keep the whole tree around, we therefore separate the building of the tree in one routine, as shown in

C++ Code 24.1.

Example
Parameters:

rH IH7, u a I:HP, d a H:WW.

Build a 2 period interest rate tree.

203

#include <vetor> #include <mth> using namespace std;

vetor<vetor<double> > interest rte trees gm uild(const double& rH, const double& u, const double& d, const int& n){ vetor< vetor<double> > tree; vetor<double> r(1); r[0]=rH; tree.push k(r); for (int i=1;i<=n;++i) { double rtop=r[r.size()1]*u; for (int j=0;j<i;++j){ r[j] = d*r[j];
};

r.push k(rtop); tree.push k(r);


};

return tree;
};

C++ Code 24.1:


function tree

Building interest rate tree

= interest rte trees gm uild(rH,u,d,n) r=[rH]; tree=[r]; rtop=rH; for i=1:n rtop = u * rtop; r = [rtop;d*r]; tree=[ [zeros(1,i);tree] r ]; endfor endfuntion

wtl Code 24.1:


C++ program:

Building interest rate tree

vetor< vetor<double> > tree = interest rte trees gm uild(0.1,1.02,0.99,3); out << " Interest rate tree: " << endl; out << " Time 0: " << tree[0][0] << endl; out << " Time 1: " << tree[1][0] << " " << tree[1][1] << endl; out << " Time 2: " << tree[2][0] << " " << tree[2][1] << " " << tree[2][2] << endl;
Output from C++ program:

snterest rte treeX ime HX HFI ime IX HFHWW HFIHP ime PX HFHWVHI HFIHHWV

HFIHRHR

24.2

Discount factors

We want to price bonds and other xed income securities, which contains sets of future cash ows. Instead of interest rates we need prices, not interest rates, i.e. discount factors. The interest rate tree therefore needs to be used to generate discount factors, which needs to be specied at every point of the tree, and for all relevant maturities. Let

d@t; T A be the discount factor at time t for a time T


204

payment.

If we at time 0 want to price cash ows at time 2, we need the following set of discount factors

d@H; PA r r r r

du @I; PA

r j r

dd @I; PA q, which are used as follows:

In constructing trees of discount we need one additional piece of information,

d@H; PA a er0 @qdu @I; PA C @I C qAdd @I; PAA


The parameter

q serves the same purpose as the state price probability, but it is found dierently. q?

Exercise 24.1.
Given the prices of two discount bonds, with maturities 1 and 2, how would you back out

Exercise 24.2.
Suppose you have

q and the tree of short interest rates.

How would you calculate the

t-period spot rate?

24.3

Pricing bonds

Pricing straight bonds is then just a matter of the usual recursive valuation

#include <vetor> #include <mth> using namespace std;


double interest rte trees gm vlue of sh)ows(const vetor<double>& )ow, const vetor< vetor<double> const double& q){ int n=)ow.size(); vetor< vetor<double> > vlues(n); vetor<double> vlue(n); for (int i=0;i<n;i++){ vlue[i]=)ow[n 1]; };

>& r tree,

vlues[n1]=vlue; for (int t=n1;t>0;t){ vetor<double> vlue(t,0.0); for (int i=0;i<t;++i){ vlue[i]=)ow[t1]+exp(r tree[t1][i])*(q*vlues[t][i]+(1q)*vlues[t][i+1]);
};

vlues[t1]=vlue;
};

return vlues[0][0];
};

C++ Code 24.2: Example


Parameters:

Valuing cash ows

rH IH7, u a I:HP, d a H:WW.

Let

q a H:S.

Determine the price of a 3 period coupon bond

with coupon of 10 and face value of 100.

205

C++ program:

double rH=0.1; double u=1.02; double d=0.99; int n=3; double q=0.5; vetor< vetor<double> > tree vetor<double> sh)ows;

interest rte trees gm uild(rH,u,d,n);

sh)ows.push k(0); sh)ows.push k(10); sh)ows.push k(10); sh)ows.push k(110); out << "Bond price B = " << interest rte trees gm vlue of sh)ows(sh)ows,tree,q);

Output from C++ program:

fond prie f a WVFSWWU


Exercise 24.3.
The example just presented assumes cash ows dates matches the dates of interest rate changes. How would you modify the code to allow for dierences in timing of interest rate changes and cashows. Or can you do this alternatively, by adjusting the inputs to the routine?

206

24.4

Callable bond

A slightly more involved example is a callable bond.

#include <vetor> #include <mth> using namespace std;


double interest rte trees gm vlue of llle ond(const const const const const int n=)ows.size(); vetor< vetor<double> > vlues(n); vetor<double> vlue(n); for (int i=0;i<n;i++){ vlue[i]=)ows[n 1]; };

vetor<double>& )ows, vetor< vetor<double> >& r tree, double& q, int& (rst ll time, double& ll prie){

vlues[n1]=vlue; for (int t=n1;t>0;t){ vetor<double> vlue(t,0.0); for (int i=0;i<t;++i){ vlue[i]=)ows[t1]+exp(r tree[t1][i])*(q*vlues[t][i]+(1q)*vlues[t][i+1]); if (t>=(rst ll time){ vlue[i]=min(vlue[i],ll prie); };
}; };

vlues[t1]=vlue;
return vlues[0][0];
};

C++ Code 24.3: Example

Valuing callable bond

Construct a short rate lattice for periods (years) 0 through 9 with an initial rate of rates determined by a multiplicative factors

u a I:P or d a H:W.

Assign

q a H:S.

rH a T7 and with successive

1. Using this lattice, nd the value of a 10-year 6% bond. 2. Suppose this bond can be called by the issuing party at any time after 5 years. (When the bond is

called, the face value plus the currently due coupon are paid at that time and the bond is canceled.) What is the fair value of this bond? The interest rate lattice: step: nodes: 25.8 21.5 17.9 14.9 12.4 10.4 8.6 7.2 6.0 5.4 6.5 4.9 7.8 5.8 4.4 9.3 7.0 5.2 3.9 11.2 8.4 6.3 4.7 3.5 13.4 10.1 7.6 5.7 4.3 3.2 16.1 12.1 9.1 6.8 5.1 3.8 2.9 19.3 14.5 10.9 8.2 6.1 4.6 3.4 2.6 0 1 2 3 4 5 6 7 8 9 31.0 23.2 17.4 13.1 9.8 7.3 5.5 4.1 3.1 2.3

1. Valuing the noncallable bond The cash ow lattice

207

step: nodes:

10 106

6 6 6 6 6 6 6 6 6 0 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6

106 106 106 106 106 106 106 106 106 106

The value lattice: step: nodes: 83.78 73.14 68.67 67.84 69.38 72.59 77.07 82.57 88.89 89.90 102.03 95.59 107.13 89.88 101.29 111.05 85.09 96.24 105.79 113.70 81.45 92.19 101.37 108.96 115.09 79.32 89.45 98.04 105.10 110.78 115.26 79.28 88.46 96.14 102.39 107.37 111.29 114.32 82.27 89.93 96.19 101.20 105.15 108.21 110.57 112.38 90.04 95.06 99.02 102.11 104.49 106.32 107.71 108.77 109.56 0 1 2 3 4 5 6 7 8 9 10 106.00 106.00 106.00 106.00 106.00 106.00 106.00 106.00 106.00 106.00 106.00

The value of the bond is

B a VW:WH.

2. The callable will be called when the value of the bond is above par, because the issuing company can issue a bond at a lower interest rate. The following set of values is calculated step: nodes: 83.78 73.14 68.67 67.84 69.38 72.59 77.07 82.53 88.70 89.35 101.05 95.21 105.44 89.80 100.56 108.22 85.08 96.08 104.39 109.19 81.45 92.18 101.03 106.36 108.31 79.32 89.45 98.01 104.42 106.00 106.00 79.28 88.46 96.14 102.32 106.00 106.00 106.00 82.27 89.93 96.19 101.20 105.00 106.00 106.00 106.00 90.04 95.06 99.02 102.11 104.49 106.00 106.00 106.00 106.00 0 1 2 3 4 5 6 7 8 9 10 106.00 106.00 106.00 106.00 106.00 106.00 106.00 106.00 106.00 106.00 106.00

The value of the bond is

B a VW:QS.

208

C++ program:

sh)ows.push k(0); for (int t=1;t<=9;++t){ sh)ows.push k(6); }; sh)ows.push k(106); out << "Straight bond price = " << interest rte trees gm vlue of sh)ows(sh)ows,tree,q) << endl; int (rst ll time = 6; double ll prie = 106; out << "Callable bond price = " << interest rte trees gm vlue of llle ond(sh)ows,tree,q, (rst ll time, ll prie) << endl;
Output from C++ program:

double rH=0.06; double u=1.2; double d=0.9; int n=10; double q=0.5; vetor< vetor<double> > tree vetor<double> sh)ows;

interest rte trees gm uild(rH,u,d,n);

tright ond prie a VWFWHIU gllle ond prie a VWFPRVQ


Exercise 24.4.
How would you price a call option on a coupon bond in this setting?

24.5

Readings

General references include Sundaresan (2001). Rendleman and Bartter (1979) and Rendleman and Bartter (1980) are the original references for building standard binomial interest rate trees.

209

Chapter 25

Building term structure trees using the Ho and Lee (1986) approach
25.1 Intro

In this section we build interest rate trees following the orgiginal paper of Ho and Lee (1986). We will follow the analysis in the paper, and use it to illustrate how yu can build trees of more complex term structures than the simple binomial trees of the interest rate. The selling point of the original paper was that one could t an initial term structure and then specify an evolution of the term structure consistent with this initial term structure.

25.2 25.3

Building trees of term structures Ho Lee term structure class

#include "fin_recipes.h"
class term struture lss ho lee X public term struture lss private: int n ; int i ; double delt double pi ; public:
{

term struture lss* initil term

term struture lss ho lee(term const const const const double d(const double& ) const;

struture lss* (tted term, int & n, int & i, double& lmd, double& pi);

};

vetor< vetor<term struture lss ho lee> > term struture ho lee uild term struture tree(term struture lss* initil, const int& no steps, const double& delt, const double& pi);
double prie europen ll option on ond using ho lee(term struture lss* initil, const double& delt, const double& pi, const vetor<double>& underlying ond )ow times, const vetor<double>& underlying ond )ows, const double& u, const double& option time to mturity);

Header le 25.1:

Term structure class for Ho-Lee

210

#include "term_structure_class_ho_lee.h"

term struture lss ho leeXXterm struture lss ho lee(term struture lss* (tted term, const int & n, const int & i, const double& delt, const double& pi){ initil term =(tted term; n =n; i =i; delt =delt; pi =pi;
};

C++ Code 25.1:

Term structure class for Ho-Lee

#include "fin_recipes.h" #include "term_structure_class_ho_lee.h"


inline double h(const double& , const double& delt, const double& pi){ return (1.0/(pi+(1 pi)*pow(delt,)));

};

double term struture lss ho leeXXd(const double& ) const{ double d=(*initil term ).d(+n )/(*initil term ).d(n ); for (int j=1;j<n ;++j){

*=

h(+(n

j),delt

,pi ) /

h(n

j,delt
));

,pi ) ;

};

d *= h(,delt ,pi return d;


};

)*pow(delt ,*(n

C++ Code 25.2:

Term structure class for Ho-Lee, calculation of discount function

#include "term_structure_class_ho_lee.h"

vetor< vetor<term struture lss ho lee> > term struture ho lee uild term struture tree(term struture lss* initil, const int& no steps, const double& delt, const double& pi){ vetor< vetor<term struture lss ho lee> > hl tree; for (int t=0;t<5;++t){ hl tree.push k(vetor<term struture lss ho lee>()); for (int j=0;j<=t;++j){ term struture lss ho lee hl(initil,t,j,delt,pi); hl tree[t].push k(hl);
}; };

return hl tree;
};

C++ Code 25.3:

Building a term structure tree

211

25.4

Pricing things

We now have access to what we need to do pricing through the recursive relationship

C @n; iA a C @n C I; i C IA C @I AC @n C i; iA Pi@nA @IA


where

C @n; iA is the value of a security at time n at node i.

What we are pricing are typically state and time-contingent claims to cash ows. Let us illustrate pricing of an (European) call option on some underlying bond. Suppose this bond is risk free. Its cash ows at each future date does not depend on the state, but the timing of cash ows changes as you move in the tree. It is therefore necessary to some way gure out at date when you want to price the underlying bond at that date.

t:

What are the future cash ows

We build a small class that contains this

information, and use it, together with the term structures in the individual nodes, to nd the bond price at each node. The value of the bond at the dierent nodes change because the term structure you use for discounting is changing. This bond price is then used to nd the option value at each node.

212

#include "term_structure_class_ho_lee.h"
class time ontingent sh )ows{ public: vetor<double> times; vetor<double> sh )ows; time ontingent sh )ows(const vetor<double>& in times, const vetor<double>& in )ows){

times=in times; sh )ows=in )ows;


};

};

int no )ows(){ return times.size();


};

vetor<time ontingent sh )ows> uild time series of ond time ontingent sh )ows(const vetor<double>& initil times, const vetor<double>& initil )ows){ vetor<time ontingent sh )ows> ve f ; vetor<double> times = initil times; vetor<double> )ows = initil )ows; while (times.size()>0){ ve f.push k(time ontingent sh )ows(times,)ows)); vetor<double> tmp times; vetor<double> tmp )ows; for (int i=0;i<times.size();++i){ if (times[i]1.0>=0.0) { tmp times.push k(times[i]1); tmp )ows.push k()ows[i]);
}; };

times
};

tmp times; )ows

tmp )ows;

return ve f ;
};

double prie europen ll option on ond using ho lee(term struture lss* initil, const double& delt, const double& pi, const vetor<double>& underlying ond )ow times, const vetor<double>& underlying ond )ows, const double& u, const double& time to mturity){ int = int(time to mturity+0.0001);

vetor<vetor<term struture lss ho lee> > hl tree = term struture ho lee uild term struture tree(initil,+1,delt,pi); vetor<time ontingent sh )ows> ve f = uild time series of ond time ontingent sh )ows(underlying ond )ow times, underlying ond )ows);

vetor<double> vlues(+1); for (int i=0;i<=;++i){


};

vlues[i]=mx(0.0,onds prie(ve f [+1].times, ve f [+1].sh )ows, hl tree[+1][i])

u);
};

for (int t=;t>=0; t){ vetor<double> vlues this(t+1); for (int i=0;i<=t;++i){ vlues this[i]=(pi*vlues[i+1]+(1.0 pi)*vlues[i])*hl tree[t][i].d(1);

vlues=vlues this;

};

return vlues[0];
};

C++ Code 25.4:

Pricing of European call option on straight bond using Ho-Lee

213

Example
You are pricing options on a 5 year zero coupon risk free bond. The options are European calls with a time to maturity of 3 years. You will price the options using a Ho-Lee approach with parameters

 a H:S and  a H:WV.

Price the option using two dierent assumptions about the current term structure: 1. The term structure is at with an interest rate of 10% (continously compounded). 2. The current term structure has been estimated using a Nelson Siegel parameterization with parameters

H a H:HW, I a H:HI, P a H:HI and  a S:H.

C++ program:

term struture lss* initil=new term struture lss )t(r); vetor<double> times; times.push k(5.0); vetor<double> )ows; )ows.push k(100); double u=80; double time to mturity=3; out << " Flat term structure " << endl; out << " c= " << prie europen ll option on ond using ho lee(initil,delt, pi, times,)ows,u,time to mturity); out << endl; delete (initil); double etH=0.09; double etI=0.01; double etP=0.01; double lmd=5.0; initil = new term struture lss nelson siegel(etH,etI,etP,lmd); out << " Nelson Siegel term structure " << endl; out << " c= " << prie europen ll option on ond using ho lee(initil,delt, pi, times,)ows,u,time to mturity); out << endl;
Output from C++ program:

double delt=0.98; double pi=0.5; double r=0.1;

plt term struture a TFRTQPQ xelson iegel term struture a TFQQPQV


Exercise 25.1.
What changes do you need to make to call?

C++ Code 25.4 to price an American call option instead of an European

Exercise 25.2.
If you for example want to price a bond, you need to keep track of intermediate payments of coupon. Implement such a procedure. To see that it is correct us it to price a (straight) bond and then compare the value calculated in the tree with the value using the current term structure. Then modify the code to build in a callable bond feature. What additional informaiton must be kept track of ?

Exercise 25.3.
In the Ho and Lee (1986) paper there is a typo in equation (22). Can you see what it is?

25.5

References

The discussion in this chapter follows closely the original paper Ho and Lee (1986)

214

Chapter 26

Term Structure Derivatives


Contents
26.1 Vasicek bond option pricing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215

26.1

Vasicek bond option pricing

If the term structure model is Vasicek's model there is a solution for the price of an option on a zero coupon bond, due to Jamshidan (1989). Under Vacisek's model the process for the short rate is assumed to follow.

dr a a@b rAdt C dZ


where

a, b and 

are constants. We have seen earlier how to calculate the discount factor in this case.

We now want to consider an European Call option in this setting.

P @t; sA be the time t price of a zero coupon bond with a payment of $1 at time s (the discount factor). t of a European call option maturing at time T on on a discount bond maturing at time s is (See Jamshidan (1989) and Hull (1993))
Let The price at time

P @t; sAN @hA XP @t; T AN @h P A


where

P @t; sA I C P P P @t; T AX P P a v@t; T AB @T; sA I ea@T tA B @t; T A a a P @I ea@T tA A v@t; T AP a Pa In the case of a a H, ha
I ln

v@t; T A a  T t P a @s T A T t
Example
Parameters:

a a H:I, b a H:I,  a H:HP, r a H:HS, X a H:W.

Price a Vacicek call on a zero.

C++ program:

double

= 0.1; double = 0.1; double sigm = 0.02; double r = 0.05; double =0.9; out << " Vasicek call option price " << ond option prie ll zero vsiek(,r,1,5,,,sigm) << endl;

Output from C++ program:

siek ll option prie HFHHHPPTVQQ

215

#include "normdist.h" #include "fin_recipes.h" #include <mth> using namespace std;


double ond option prie ll zero vsiek(const double& , GG exerise prie const double& r, GG urrent interest rte const double& option time to mturity, const double& ond time to mturity, const double& , GG prmeters const double& , const double& sigm){ double t = option time to mturity; double s t = ond time to mturity; double s = s t t; double v t ; double sigm ; if (==0.0) {

v t = sigm * sqrt ( t ) ; sigm = sigm* s*sqrt( t); v t

else

double f s
};

sqrt (sigm*sigm*(1exp(2** t))/(2*)); = (1exp(* s))/; sigm = v t *f s;


= = (1.0/sigm

) * log (term struture disount ftor vsiek(s t,r,,,sigm)/ struture disount ftor vsiek( t,r,,,sigm)*) ) + sigm /2.0; double = term struture disount ftor vsiek(s t,r,,,sigm)*x(h) *term struture disount ftor vsiek( t,r,,,sigm)*x(hsigm ); return ;
(term };

double h

C++ Code 26.1:

Bond option pricing using the Vasicek model

216

Appendix A

Normal Distribution approximations.


Contents
A.1 The normal distribution function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.2 The cumulative normal distribution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.3 Multivariate normal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.4 Calculating cumulative bivariate normal probabilities . . . . . . . . . . . . . . . . . . . . . . . A.5 Simulating random normal numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.6 Cumulative probabilities for general multivariate distributions . . . . . . . . . . . . . . . . . . . A.7 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217 217 218 218 221 222 222

We will in general not go into detail about more standard numerical problems not connected to nance, there are a number of well known sources for such, but we show the example of calculations involving the normal distribution.

A.1

The normal distribution function

The nurmal distribution function

n@xA a e 2
is calculated as

x2

#include <mth> GG lirry of mth funtions using namespace std; GG whih is prt of the stndrd nmespe

GG most g ompilers de(ne sD ut just in se it doesn9t #ifndef s #dene s 3.141592653589793238462643 #endif


double n(const double& z) { GG norml distriution funtion return (1.0/sqrt(2.0*s))*exp( 0.5*z*z);

};

C++ Code A.1:

The normal distribution function

A.2

The cumulative normal distribution

The solution of a large number of option pricing formulas are written in terms of the cumulative normal distribution. For a random variable is lower than a given value with mean

H and unit variance is less than z , N @z A, one have to evaluate the integral

z.

the cumulative probability is the probability that the outcome

To calculate the probability that a normally distubuted random variable

ro@x

z A a N @z A a

n@xAdx a

e 2 dx
x2

217

There is no explicit closed form solution for calculation of this integral, but a large number of well known approximations exists. Abramowiz and Stegun (1964) is a good source for these approximations. The following is probably the most used such approximation, it being pretty accurate and relatively fast. The arguments to the function are assumed normalized to a (0,1) distribution.

#include <mth> GG mth funtionsF using namespace std;


double x(const double& z) { if (z > 6.0) { return 1.0; }; GG this gurds ginst over)ow if (z < 6.0) { return 0.0; };

double double double double double double double double double double double

I = 0.31938153; P = 0.356563782; Q = 1.781477937; R = 1.821255978; S = 1.330274429; p = 0.2316419; P = 0.3989423;

=fs(z); t = 1.0/(1.0+*p); = P*exp((z)*(z/2.0)); n = ((((S*t+R)*t+Q)*t+P)*t+I)*t; n = 1.0*n; if ( z < 0.0 ) n = 1.0 n; return n;


};

C++ Code A.2:

The cumulative normal

A.3

Multivariate normal

The normal distribution is also dened for several random variables. We then characterise the random variables

vector

of

XaT

T T R

xI xP xn
. . .

Q U U U S

A probability statement about this vector is a joint statement about all elements of the vector.

A.4

Calculating cumulative bivariate normal probabilities

The most used multivariate normal calculation is the bivariate case, where we let

x and y

be bivariate

normally distributed, each with mean 0 and variance 1, and assume the two variables have correlation of

.

By the denition of correlation

 P I; I.
p

The cumulative probability distribution

P @x < a; y < bA a N @a; b; A


a
a b

I exp I I P I P

P xy P  I x IP PC y dxdy P

There are several approximations to this integral. We pick one such, discussed in (Hull, 1993, Ch 10), shown in

C++ Code A.3.


218

#include <mth> GG inlude the stndrd lirry mthemtis funtions using namespace std; GG whih re in the stndrd nmespe
double x(const double&); GG de(ne the univrite umultive norml distriution s seprte funtion

#ifndef s const double s=3.141592653589793238462643; #endif


inline double f (const double& x, const double& y, const double& prime, const double& prime, const double& rho) { double r = prime*(2*x prime) + prime*(2*y prime) return exp(r);

+ 2*rho*(x

prime)*(yprime);

};

inline double sgn(const double& x) if (x>=0.0) return 1.0; return 1.0;

GG sign funtion

};

double x(const double& , const double& , const double& rho) { if ( (<=0.0) && (<=0.0) && (rho<=0.0) ) { double prime = /sqrt(2.0*(1.0 rho*rho)); double prime = /sqrt(2.0*(1.0 rho*rho)); double e[4]={0.3253030, 0.4211071, 0.1334425, 0.006374323}; double f[4]={0.1337764, 0.6243247, 1.3425378, 2.2626645 }; double sum = 0; for (int i=0;i<4;i++) { for (int j=0; j<4; j++) {

sum

+=

e[i]*e[j]* f (f[i],f[j],prime,prime,rho);

}; };

sum = sum return sum;


}

* (

sqrt(1.0rho*rho)/s);

else

if ( * * rho <= 0.0 ) { if ( ( <=0.0 ) && ( >=0.0 ) && (rho>=0.0) return x() x(, , rho);

) {

else if ( (>=0.0) && (<=0.0) && (rho>=0.0) return x() x( , , rho);

) {

else if ( (>=0.0) && (>=0.0) && (rho<=0.0) return x() + x() 1.0 + x( , , rho);

) {

}; }

else

if ( * * rho >= 0.0 ) { double denum = sqrt(* 2*rho** + *); double rhoI = ((rho * ) * sgn())/denum; double rhoP = ((rho * ) * sgn())/denum; double delt=(1.0 sgn()*sgn())/4.0; return x(,0.0,rhoI) + x(,0.0,rhoP) delt;

};

return
};

99.9; GG should never get hereD lterntively throw exeption


C++ Code A.3:
Approximation to the cumulative bivariate normal

If one has more than two correlated variables, the calculation of cumulative probabilites is a nontrivial problem. One common method involves Monte Carlo estimation of the denite integral. We will consider this, but then it is necessary to rst consider simulation of random normal variables.

Example
219

Calculate N(0) and N(0,0,0) C++ program:

out << " N(0) = " << x(0) << endl; out << " N(0,0,0) = " << x(0,0,0) << endl;
Output from C++ program:

x@HA a HFS x@HDHDHA a HFPS

220

A.5

Simulating random normal numbers

Generation of random numbers is a large topic and is treated at length in such sources as Knuth (1997). The generated numbers can never be truly random, only pseudo-random, they will be generated according to some reproducible algorithm and after a (large) number of random number generations the sequence will start repeating itself. The number of iterations before replication starts is a measure of the quality of a random number generator. For anybody requiring high-quality random number generators the

rnd@A

function provided by the standard C++ library should be avoided, but for not getting into

involved discussion of random number generations we use this function as a basis for the generation of uniformly distributed numbers in the interval

H; IA, as shown in C++ Code A.4.

#include <stdli> using namespace std;


double rndom uniform H I(void){ return double(rnd())/double(exh we); GG this uses the g lirry rndom numer genertorF
};

C++ Code A.4: Exercise A.1.


Replace the

Pseudorandom numbers from an uniform

H; IA distribution

rndomuniform function here by an alternative of higher quality, by looking into what numerical mthli
or

libraries is available on your computing platform, or by downloading a high quality random number generator from such places as

sttli.
C++ Code A.5.

These uniformly distributed distributed random variates are used as a basis for the polar method for normal densities discussed in Knuth (1997) and inplemented as shown in

#include <mth> #include <stdli> using namespace std;


double rndom uniform H I(void); double rndom norml(void){ double I, P, I, P; double =2; while (>=1) {

I = rndom uniform H I(); P = rndom uniform H I(); I = 2.0*I1.0; P = 2.0*P1.0; = pow(I,2)+pow(P,2);

};

double I=I*sqrt(( return I;


};

2.0*log())/);
@H; IA distribution

C++ Code A.5: Example

Pseudorandom numbers from a normal

1. Generate 5 random uniform numbers (0,1) 2. Generate 5 random N(0,1) numbers.

221

C++ program:

out << " 5 random uniform numbers between 0 and 1: " << endl; out << " "; for (int i=0;i<5;++i){ out << " " << rndom uniform H I(); }; out << endl; out << " 5 random normal(0,1) numbers: " << endl; out << " "; for (int i=0;i<5;++i){ out << " " << rndom norml() ; }; out << endl;
Output from C++ program:

S rndom uniform numers etween H nd IX HFVRHIVV HFQWRQVQ HFUVQHWW HFUWVRR HFWIITRU S rndom norml@HDIA numersX EIFHUPPR HFWPSWRT PFUHPHP IFQTWIV HFHIVUQIQ

A.6

Cumulative probabilities for general multivariate distributions

When moving beyond the bivariate case calculation of probability integrals become more of an exercise in general numerical integration. possibility. A typical tool is Monte Carlo integration, but that is not the only

A.7

References

Tong (1990) discusses the multivariate normal distribution, and is a good reference.

222

Appendix B

C++ concepts
This chapter contains a listing of various

g/C++

concepts and some notes on each of them.

umulte@A ool

Function accumulating the elements of a sequence.

Boolean variable, taking on the two values use the values zero and one for

flse

and

true true.

and

flse.

For historical reasons one can also

lss onst

(C++ keyword). (qualifyer to variable in C++ function call). (basic type). A oating point number with high accuracy. (C function). Dened in

doule exp@xA fs flot for

<cmath>.

Returns the natural exponent

e to the given power x, ex .

(basic type). A oating point number with limited accuracy.

Loop

heder file if
Indexation (in vectors and matrices). known trap for people coming to reasons. Arrays in To access element number

in an array

from other languages.

Present in

e,

use

eiEI.

Well

for historical eciency

were implemented using pointers.

Indexing was done by nding the rst

element of the array, and then adding pointers to nd the indexed element. The rst element is of course found by adding nothing to the rst elment, hence the rst element was indexed by zero.

inlude inline
(qualifyer to C++ function name). implemented by

inlining

Hint to the optimizer that this function is most eciently

it, or putting the full code of the function into each instance of its

calling. Has the side eect of making the function local to the le in which it is dened.

int

(basic type). An integer with a limited number of signicant digits. (C function). Dened in

log@xA long

<cmath>.

Calculates the natural logarithm

ln@xA of its argument.

(basic type). An integer that can contain a large number. (C++ function)

minelement@A mxelement nmespe return

(C++ function)

(C++ concept)

stndrd nmespe string

(C++ concept)

(C++ basic type)

223

using

(C++ concept) (C++ container class). Dened in

vetor while

<vetor>

224

Appendix C

Interfacing to external libraries


Contents
C.1 Newmat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C.2 IT++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C.3 GSL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C.4 Internet links . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 225 225 225

C.3.1 The evaluation of N3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225

In various places we have used routines from other public domain packages. In this appendix there are some notes about the libraries which are referenced, and some comments about linking to them.

C.1 C.2 C.3

Newmat IT++ GSL

C.3.1 The evaluation of

NQ

In the calculation of the American Put approximation of Geske and Johnson (1984), a trivariate normal needs to be evaluated. Following the discussion in the paper, this is evaluated as

 IQ  k z h z NQ @h; k; j Y IP ; IQ ; PQ A a n@z ANP p PQP ; p IQP ; p IP P p PQ P I PQ I IQ I IQ I PQ I
This is an univariate integral, and can be evaluated using quadrature.

C.4

Internet links

Some useful internet links

httpXGGwwwFroertnzFnet:

Homepage for

xewmt,

the matrix class used as an example.

225

#include <mth> #include <iostrem> using namespace std; #include "gsl/gsl_integration.h" #include "normdist.h"
struct nQ prms {double h; double k; double rhoIP; double rhoIQ; double rhoPQ; extern "C"{ double fQ(double z, void *p){ struct nQ prms* prms = (struct nQ prms*)p; double h = (prms >h); double k = (prms >k);; double rhoIP = (prms >rhoIP); double rhoIQ = (prms >rhoIQ); double rhoPQ = (prms >rhoPQ); double f = n(z);
};

f *=x( (krhoPQ*z)/sqrt(1.0rhoPQ*rhoPQ), (hrhoIQ*z)/(sqrt(1.0rhoIQ*rhoIQ)), (rhoIPrhoIQ*rhoPQ)/(sqrt(1.0rhoIQ*rhoIQ)*sqrt(1.0rhoPQ*rhoPQ))); return f ;

}; };

double xQ(const double& h, const double& k, const double& j, const double& rhoIP, const double& rhoIQ, const double& rhoPQ){ struct nQ prms prms = { h, k, rhoIP, rhoIQ, rhoPQ};

size t n=1000; gsl integrtion workspe* w = gsl integrtion workspe llo(n); gsl funtion p; p.funtion = &fQ; p.prms=&prms; double result, error; gsl integrtion qgs(&p,20.0,j,1e7,1e7,n,w,&result,&error); return result;

};

C++ Code C.1:

Approximating

NQ @A using the method of Geske and Johnson (1984)

226

Appendix D

Summarizing routine names


In many of the algorithms use is made of other routines. To simplify the matter all routines are summarised in one header le, fin_recipes.h. This appendix shows this le.

GG (leX (n reipesFh GG uthorX fernt erne yedegrd GG de(nes ll routines in the (nnil numeril reipes ook
#ifndef psx igsi r #dene psx igsi r #include <vetor> #include <mth> using namespace std;

GGGGGGGGG present vlue GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GG disrete oumpounding GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GG disreteD nnul ompounding
const vetor<double>& )ow times, const vetor<double>& )ow mounts, const double& r); double sh )ow irr disrete(const vetor<double>& )ow times, const vetor<double>& )ow mounts); bool sh )ow unique irr(const vetor<double>& )ow times, const vetor<double>& )ow mounts); double onds prie disrete(const vetor<double>& sh)ow times, const vetor<double>& sh)ows, const double& r); double onds yield to mturity disrete(const vetor<double>& times, const vetor<double>& mounts, const double& ondprie); double onds durtion disrete(const vetor<double>& times, const vetor<double>& sh)ows, const double& r); double onds durtion muly disrete(const vetor<double>& sh)ow times, const vetor<double>& sh)ows, const double& ond prie); double onds durtion modi(ed disrete (const vetor<double>& times, const vetor<double>& mounts, const double& ond prie); double onds onvexity disrete(const vetor<double>& )ow times, const vetor<double>& )ow mounts, const double& r); double sh )ow pv disrete
(

GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GG ontinous ompoundingF double sh )ow pv(const vetor<double>& )ow times,const vetor<double>& )ow mounts,const double& r); double sh )ow irr(const vetor<double>& )ow times, const vetor<double>& )ow mounts); double onds prie(const vetor<double>& sh)ow times, const vetor<double>& sh)ows, const double& r); double onds prie(const vetor<double>& oupon times, const vetor<double>& oupon mounts, const vetor<double>& prinipl times, const vetor<double>& prinipl mounts, const double& r); double onds durtion(const vetor<double>& sh)ow times, const vetor<double>& sh)ows, const double& r); double onds yield to mturity(const vetor<double>& sh)ow times,const vetor<double>& sh)ow mounts, const double& ondprie); double onds durtion muly(const vetor<double>& sh)ow times, const vetor<double>& sh)ows, const double& ond prie); double onds onvexity(const vetor<double>& sh)ow times, const vetor<double>& sh)ow mounts, const double& y ); GGG term struture sis

227

double term struture yield from disount ftor(const double& dft, const double& t); double term struture disount ftor from yield(const double& r, const double& t); double term struture forwrd rte from disount ftors(const double& d tI, const double& d tP, const double& time); double term struture forwrd rte from yields(const double& r tI, const double& r tP, const double& tI, const double& tP); double term struture yield linerly interpolted(const double& time, const vetor<double>& os times, const vetor<double>& os yields);

GG term struture lss

class term struture lss { public: virtual term struture lss(); virtual double r(const double& t) const; GG short rteD yield on zero oupon ond virtual double d(const double& t) const; GG disount ftor virtual double f (const double& tI, const double& tP) const; GG forwrd rte
};

class term struture lss )t X public term struture lss private: GG interest rte double ; public: term struture lss )t(const double& r); virtual term struture lss )t(); virtual double r(const double& t) const; void set int rte(const double& r);
};

class term struture lss interpolted X public term struture lss private: vetor<double> times ; GG use to keep list of yields vetor<double> yields ; void ler(); public:

term struture lss interpolted(); term struture lss interpolted(const vetor<double>& times, const vetor<double>& yields); virtual term struture lss interpolted(); term struture lss interpolted(const term struture lss interpolted&); term struture lss interpolted operator= (const term struture lss interpolted&);

int no oservtions() const { return times .size(); }; virtual double r(const double& ) const; void set interpolted oservtions(vetor<double>& times, vetor<double>& yields);
};

GG using the term struture lsses


double onds prie(const vetor<double>& sh)ow times, const vetor<double>& sh)ows, const term struture lss& d); double onds durtion(const vetor<double>& sh)ow times, const vetor<double>& sh)ow mounts, const term struture lss& d); double onds onvexity(const vetor<double>& sh)ow times, const vetor<double>& sh)ow mounts, const term struture lss& d);

GGGG putures priing double futures prie(const double& , const double& r, const double& time to mturity); GGG finomil option priing
double option prie ll europen inomil single period( const double& , const double& u, const double& r,

GG one periode inomil

228

GG multiple periode inomil

const double& u, const double& d);

double option prie ll europen inomil multi period given ud( const double& , const double& u, const double& r, const double& u, const double& d, const int& no periods);

GG multiple periode inomil vetor< vetor<double> > inomil tree(const double& H, const double& u,const double& d, const int& no steps); GGG flk holes formul GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
double option prie ll lk sholes(const double& , const double& u, const double& r, const double& sigm, const double& time) ; double option prie put lk sholes (const double& , const double& u, const double& r, const double& sigm, const double& time) ; double

option prie implied voltility ll lk sholes newton( const double& , const double& u, const double& r, const double& time, const double& option prie);
double option prie implied voltility ll lk sholes isetions( const double& , const double& u, const double& r, const double& time, const double& option prie); double option prie delt ll lk sholes(const double& , const double& u, const double& r, const double& sigm, const double& time); double option prie delt put lk sholes (const double& , const double& u, const double& r, const double& sigm, const double& time); void option prie prtils ll lk sholes(const double& , const double& u, const double& r, const double& sigm, const double& time, double& helt, double& qmm, double& het, double& eg, double& ho); void option prie prtils put lk sholes(const double& , const double& u, const double& r, const double& sigm, const double& time, double& helt, double& qmm, double& het, double& eg, double& ho);

GGG wrrnt prie double wrrnt prie djusted lk sholes(const double& , const double& u, const double& r, const double& sigm, const double& time, const double& no wrrnts outstnding, const double& no shres outstnding);
double wrrnt prie djusted lk sholes(const const const const const double& double& double& double& double&

, const double& u, r, const double& q, sigm, const double& time, no wrrnts outstnding, no shres outstnding);

GGG ixtensions of the flk holes model GGGGGGGGGGGGGG


double option prie europen ll pyout(const double& , const double& u, const double& r, const double& , const double& sigm, const double& time); double option prie europen put pyout (const double& , const double& u, const double& r, const double& , const double& sigm, const double& time); double option prie europen ll dividends(const double& , const double& u, const double& r, const double& sigm, const double& time, const vetor<double>& dividend times, const vetor<double>& dividend mounts ); double option prie europen put dividends( const double& , const double& u, const double& r, const double& sigm,const double& time, const vetor<double>& dividend times, const vetor<double>& dividend mounts); double option prie merin ll one dividend(const double& , const double& u, const double& r, const double& sigm,

229

const double& tu, const double& hI, const double& tuI); double futures option prie ll europen lk(const double& p, const double& u, const double& r, const double& sigm, const double& time); double futures option prie put europen lk(const double& p, const double& u, const double& r, const double& sigm, const double& time); double urreny option prie ll europen(const double& , const double& u, const double& r, const double& r f, const double& sigm, const double& time); double urreny option prie put europen(const double& , const double& u, const double& r, const double& r f, const double& sigm, const double& time); double option prie merin perpetul ll(const double& , const double& u, const double& r, const double& q, const double& sigm); double option prie merin perpetul put(const double& , const double& u, const double& r, const double& q, const double& sigm);

GG inomil option pproximtion GGGGGGGGGGGGGGGG


double option prie ll europen inomil(const double& , const double& u, const double& r, const double& sigm, const double& t, const int& steps); double option prie put europen inomil (const double& , const double& u, const double& r, const double& sigm, const double& t, const int& steps); double option prie ll merin inomil(const double& , const double& u, const double& r, const double& sigm, const double& t, const int& steps); double option prie put merin inomil (const double& , const double& u, const double& r, const double& sigm, const double& t, const int& steps); double option prie ll merin inomil(const double& , const double& u, const double& r, const double& y, const double& sigm, const double& t, const int& steps); double option prie put merin inomil (const double& , const double& u, const double& r, const double& y, const double& sigm, const double& t, const int& steps); double option prie ll merin disrete dividends inomil( const double& , const double& u, const double& r, const double& sigm, const double& t, const int& steps, const vetor<double>& dividend times, const vetor<double>& dividend mounts); double option prie put merin disrete dividends inomil(const double& , const double& u, const double& r, const double& sigm, const double& t, const int& steps, const vetor<double>& dividend times, const vetor<double>& dividend mounts); double option prie ll merin proportionl dividends inomil(const double& , const double& u, const double& r, const double& sigm, const double& time, const int& no steps, const vetor<double>& dividend times, const vetor<double>& dividend yields); double option prie put merin proportionl dividends inomil( const double& , const double& u, const double& r, const double& sigm, const double& time, const int& no steps, const vetor<double>& dividend times, const vetor<double>& dividend yields); double option prie delt merin ll inomil(const double& , const double& u, const double& r, const double& sigm, const double& t, const int& no steps); double option prie delt merin put inomil(const double& , const double& u, const double& r, const double& sigm, const double& t, const int& no steps); void option prie prtils merin ll inomil(const double& , const double& u, const double& r, const double& sigm, const double& time, const int& no steps, double& delt, double& gmm, double& thet, double& veg, double& rho); void option prie prtils merin put inomil(const double& , const double& u, const double& r, const double& sigm, const double& time, const int& no steps,

230

double& delt, double& gmm, double& thet, double& veg, double& rho); double futures option prie ll merin inomil(const double& p, const double& u, const double& r, const double& sigm, const double& time, const int& no steps); double futures option prie put merin inomil( const double& p, const double& u, const double& r, const double& sigm, const double& time, const int& no steps); double urreny option prie ll merin inomil( const double& , const double& u, const double& r, const double& r f, const double& sigm, const double& t, const int& n); double urreny option prie put merin inomil( const double& , const double& u, const double& r, const double& r f, const double& sigm, const double& t, const int& n);

GGGGGGGGGGGGGGGGGGGG (nite di'erenes GGGGGGGGGGGGGGGGGG


double option prie ll merin (nite di' expliit( const double& , const double& u, const double& r, const double& sigm, const double& time, const int& no steps, const int& no t steps); double option prie put merin (nite di' expliit( const double& , const double& u, const double& r, const double& sigm, const double& time, const int& no steps, const int& no t steps); double option prie ll europen (nite di' expliit( const double& , const double& u, const double& r, const double& sigm, const double& time, const int& no steps, const int& no t steps); double option prie put europen (nite di' expliit( const double& , const double& u, const double& r, const double& sigm, const double& time, const int& no steps, const int& no t steps); double option prie ll merin (nite di' impliit( const double& , const double& u, const double& r, const double& sigm, const double& time, const int& no steps, const int& no t steps); double option prie put merin (nite di' impliit( const double& , const double& u, const double& r, const double& sigm, const double& time, const int& no steps, const int& no t steps); double option prie ll europen (nite di' impliit( const double& , const double& u, const double& r, const double& sigm, const double& time, const int& no steps, const int& no t steps); double option prie put europen (nite di' impliit( const double& , const double& u, const double& r, const double& sigm, const double& time, const int& no steps, const int& no t steps);

GGGGGGGGGGGGGGGGGGGGGGGGG simulted option pries GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GG yo' only funtion of terminl prie double option prie ll europen simulted(const double& , const double& u, const double& r, const double& sigm, const double& time to mturity, const int& no sims); double option prie put europen simulted(const double& , const double& u, const double& r, const double& sigm, const double& time to mturity, const int& no sims); double option prie delt ll europen simulted(const double& , const double& u, const double& r, const double& sigm, const double& time to mturity, const int& no sims); double option prie delt put europen simulted(const double& , const double& u, const double& r, const double& sigm, const double& time to mturity, const int& no sims); double simulte lognorml rndom vrile(const double& , const double& r, const double& sigm, const double& time);
double

231

derivtive prie simulte europen option generi( const double& , const double& u, const double& r, const double& sigm, const double& time, double pyo' (const double& , const double& u), const int& no sims); double derivtive prie simulte europen option generi with ontrol vrite(const double& , const double& u, const double& r,const double& sigm, const double& time, double pyo' (const double& , const double& u), const int& no sims); derivtive prie simulte europen option generi with ntitheti vrite(const double& , const double& u, const double& r, const double& sigm, const double& time, double pyo' (const double& , const double& u), const int& no sims); GGGGGGGGGGGGGGGGGGGGGGGGGGGGG GG pyo's of vrious optionsD to e used s funtion rguments in ove simultions double pyo' ll(const double& , const double& u); double pyo' put (const double& , const double& u); double pyo' sh or nothing ll(const double& , const double& u); double pyo' sset or nothing ll(const double& , const double& u);
double

GGGGGGGGGGG pproximted option pries GGGGGGGGGGGGGGGGGGGGGGGG double option prie merin put pproximted johnson( const double& , const double& , const double& r, const double& sigm, const double& time );
double option prie merin ll pproximted w(const double& , const double& u, const double& r, const double& , const double& sigm, const double& time); double option prie merin put pproximted w(const double& , const double& u, const double& r, const double& , const double& sigm, const double& time); double option prie merin put pproximted geske johnson( const double& , const double& , const double& r, const double& sigm, const double& time ); double option prie merin ll pproximted jerksund stenslnd( const double& , const double& , const double& r, const double& q, const double& sigm, const double& time ); double option prie merin put pproximted jerksund stenslnd( const double& , const double& , const double& r, const double& q, const double& sigm, const double& );

GGGGGGGGGGGGGG pth dependent nd other exoti options GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG


double option prie ll ermudn inomil(const double& , const double& u, const double& r, const double& q, const double& sigm, const double& time, const vetor<double>& potentil exerise times, const int& steps); double option prie put ermudn inomil( const double& , const double& u, const double& r, const double& q, const double& sigm, const double& time, const vetor<double>& potentil exerise times,

232

const int& steps); double option prie europen lookk ll(const double& , const double& min, const double& r, const double& q, const double& sigm, const double& time); double option prie europen lookk put(const double& , const double& min, const double& r, const double& q, const double& sigm, const double& time); double

option prie sin geometri verge prie ll(const double& , const double& u, const double& r, const double& q, const double& sigm, const double& time); vetor<double> simulte lognormlly distriuted sequene(const double& , const double& r, const double& sigm, const double& time, const int& no steps); double derivtive prie simulte europen option generi( const double& , const double& u, const double& r, const double& sigm, const double& time, double pyo' (const vetor<double>& , const double& u), const int& no steps, const int& no sims);
double

derivtive prie simulte europen option generi with ontrol vrite(const double& , const double& u, const double& r, const double& sigm, const double& time, double pyo' (const vetor<double>& , const double& u), const int& nosteps, const int& nosims);

GGGGGGGGGGGGGGGGGGGGGGGGGGGGG GG pyo's of vrious optionsD to e used s funtion rguments in ove simultions


double double double double

pyo' pyo' pyo' pyo'

rithmetri verge ll(const vetor<double>& pries, const double& u); geometri verge ll(const vetor<double>& pries, const double& u); lookk ll(const vetor<double>& pries, const double& unused vrile); lookk put(const vetor<double>& pries, const double& unused vrile);

GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GG generi inomil trees


double option prie generi inomil( const double& , const double& u, double generi pyo' (const double& , const double& u), const double& r, const double& sigm, const double& t, const int& steps); double pyo' inry ll(const double& , const double& u); double pyo' inry put(const double& , const double& u);

GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GG trinomil trees


double option prie ll merin trinomil( const double& , const double& u, const double& r, const double& q, const double& sigm, const double& t, const int& steps) ; double option prie put merin trinomil( const double& , const double& u, const double& r, const double& q, const double& sigm, const double& t, const int& steps) ;

GGGGGGGGGGGGGGGGGGG lterntive stohsti proesses GGGGGGGGGGGGGGGG


double option prie ll merton jump di'usion( const double& , const double& u, const double& r, const double& sigm, const double& time to mturity, const double& lmd, const double& kpp, const double& delt); double heston ll option prie(const double& , const double& u, const double& r, const double& v, const double& tu,

233

const double& rho, const double& kpp, const double& lmd, const double& thet, const double& sigm);

GG (xed inome derivtivesD qfw ssumption on ond prie


double ond option prie ll zero lk sholes(const double& f, const double& u, const double& r, const double& sigm, const double& time); double ond option prie put zero lk sholes(const double& f, const double& u, const double& r, const double& sigm, const double& time); double ond option prie ll oupon ond lk sholes(const double& f, const double& u, const double& r, const double& sigm, const double& time, const vetor<double> oupon times, const vetor<double> oupon mounts); double ond option prie put oupon ond lk sholes(const double& f, const double& u, const double& r, const double& sigm, const double& time, const vetor<double> oupon times, const vetor<double> oupon mounts); double ond option prie ll merin inomil( const double& f, const double& u, const double& r, const double& sigm, const double& t, const int& steps); double ond option prie put merin inomil( const double& f, const double& u, const double& r, const double& sigm, const double& t, const int& steps);

GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GG term struture models GGG formuls for lultion


double term struture yield nelson siegel(const double& t, const double& etH, const double& etI, const double& etP, const double& lmd ); double term struture yield svensson(const double& t, const double& etH, const double& etI, const double& etP, const double& etQ, const double& tuI, const double& tuP ); double term struture disount ftor ui spline(const double& t, const double& I, const double& I, const double& dI, const vetor<double>& f, const vetor<double>& knots); double term struture disount ftor ir(const double& t, const double& r, const double& kpp, const double& lmd, const double& thet, const double& sigm); double term struture disount ftor vsiek(const double& time, const double& r, const double& ,const double& , const double& sigm);

GGG de(ning lsses wrpping the ove term struture pproximtions


class term struture lss nelson siegel X public term struture lss { private: double etH , etI , etP , lmd ; public: term struture lss nelson siegel(const double& etH, const double& etI, const double& etP, const double& lmd); virtual double r(const double& t) const;
};

class term struture lss svenssonXpuli term struture lss { private: double etH , etI , etP , etQ , tuI , tuP ; public: term struture lss svensson(const double& etH, const double& etI, const double& etP, const double& etQ,

234

const double& tuI, const double& tuP); virtual double r(const double& ) const;
};

class term struture lss ui spline X public term struture lss { private: double ; double ; double d ; vetor<double> f ; vetor<double> knots ; public: term struture lss ui spline(const double& , const double& , const double& d, const vetor<double>& f, const vetor<double> & knots); virtual double d(const double& t) const; GG disount ftor
};

class term struture lss ir X public term struture lss { private: double r ; double kpp ; double lmd ; double thet ; double sigm ; public: term struture lss ir(const double& r, const double& k, const double& l, const double& th,const double& sigm); virtual double d(const double& t) const; GG disount ftor
};

class term struture lss vsiek X public term struture lss { private: double r ; double ; double ; double sigm ; public: term struture lss vsiek(const double& r, const double& , const double& , const double& sigm); virtual double d(const double& ) const;
};

GGGGGGGGGGGGGGGGG GGG inomil term struture models GGG ond optionD rendlemnn rtter @inomilA
double

ond option prie ll zero merin rendlemn rtter(const double& u, const double& option mturity, const double& , const double& w, const double& interest, const double& ond mturity, const double& mturity pyment, const int& no steps); vetor< vetor<double> > interest rte trees gm uild(const double& rH, const double& u, const double& d, const int& n);
double interest rte trees gm vlue of sh)ows(const vetor<double>& )ow, const vetor< vetor<double> const double& q); double interest rte trees gm vlue of llle ond(const const const const const

>& r tree,

vetor<double>& )ows, vetor< vetor<double> >& r tree, double& q, int& (rst ll time, double& ll prie);

double prie europen ll option on ond using ho lee(term struture lss* initil, const double& delt, const double& pi, const vetor<double>& underlying ond )ow times, const vetor<double>& underlying ond )ows, const double& u, const double& option time to mturity);

GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GG term struture derivtivesD nlytil solutions

235

double ond option prie ll zero vsiek(const double& , const double& r, const double& option time to mturity, const double& ond time to mturity, const double& , const double& , const double& sigm); double ond option prie put zero vsiek(const double& , const double& r, const double& option time to mturity, const double& ond time to mturity, const double& , const double& , const double& sigm); #endif

236

Appendix E

Installation
The routines discussed in the book are available for download.

E.1

Source availability

The algorithms are available from my home page as a ZIP le containing the source code. These have been tested with the latest version of the GNU C++ compiler. As the algorithms in places uses code from the Standard Template Library, other compilers may not be able to compile all the les directly. If your compiler complains about missing header les you may want to check if the STL header les have dierent names on your system. The algorithm les comply with the current ANSI standard for C++ libraries. If the compiler is more than a couple of years old, it will not have STL. Alternatively, the GNU compiler

is available for free on the internet, for most current operating systems.

237

List of C++ Codes


1.1 1.2 1.3 1.4 3.1 3.2 3.3 3.4 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 6.1 6.2 6.3 6.4 7.1 8.1 8.2 8.3 9.1 9.2 9.3 9.4 9.5 10.1 11.1 11.2 11.3 11.4 11.5 11.6 12.1 12.2 12.3 12.4 12.5 12.6 A complete program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Basic operations for the date class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Comparison operators for the date class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Iterative operators for the date class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Present value with discrete compounding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Estimation of the internal rate of return . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Test for uniqueness of IRR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Present value calculation with continously compounded interest . . . . . . . . . . . . . . . . . . . Bond price calculation with discrete, annual compounding. . . . . . . . . . . . . . . . . . . . . . Bond yield calculation with discrete, annual compounding . . . . . . . . . . . . . . . . . . . . . . Bond duration using discrete, annual compounding and a at term structure . . . . . . . . . . . Calculating the Macaulay duration of a bond . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Modied duration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Bond convexity with a at term structure and annual compounding . . . . . . . . . . . . . . . . Bond price calculation with continously compounded interest and a at term structure . . . . . Bond duration calculation with continously compounded interest and a at term structure . . . Calculating the Macaulay duration of a bond with continously compounded interest and a at term structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Bond convexity calculation with continously compounded interest and a at term structure . . . Term structure transformations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Default code for transformations between discount factors, spot rates and forward rates in a term structure class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Implementing term structure class using a at term structure . . . . . . . . . . . . . . . . . . . . Interpolated term structure from spot rates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Term structure class using linear interpolation between spot rates . . . . . . . . . . . . . . . . . Pricing a bond with a term structure class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Calculating a bonds duration with a term structure class . . . . . . . . . . . . . . . . . . . . . . Calculating a bonds convexity with a term structure class . . . . . . . . . . . . . . . . . . . . . . Mean variance calculations using IT++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mean variance calculations using Newmat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Calculating the unconstrained frontier portfolio given an expected return using Newmat . . . . . . Calculating the unconstrained frontier portfolio given an expected return using IT++ . . . . . . . Futures price . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Binomial European, one period . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Building a binomial tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Binomial multiperiod pricing of European call option . . . . . . . . . . . . . . . . . . . . . . . . . Price of European call option using the Black Scholes formula . . . . . . . . . . . . . . . . . . . . Calculating the delta of the Black Scholes call option price . . . . . . . . . . . . . . . . . . . . . Calculating the partial derivatives of a Black Scholes call option . . . . . . . . . . . . . . . . . . Calculation of implied volatility of Black Scholes using bisections . . . . . . . . . . . . . . . . . . Calculation of implied volatility of Black Scholes using Newton-Raphson . . . . . . . . . . . . . . Adjusted Black Scholes value for a Warrant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Option price, continous payout from underlying . . . . . . . . . . . . . . . . . . . . . . . . . . . . European option price, dividend paying stock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Option price, RollGeskeWhaley call formula for dividend paying stock . . . . . . . . . . . . . . Price of European Call option on Futures contract . . . . . . . . . . . . . . . . . . . . . . . . . . European Futures Call option on currency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Price for an american perpetual call option . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Option price for binomial european . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Price of American call option using a binomial approximation . . . . . . . . . . . . . . . . . . . . Delta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Hedge parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Binomial option price with continous payout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Binomial option price of stock option where stock pays proportional dividends . . . . . . . . . . 9 11 12 13 25 29 31 33 36 36 38 39 40 41 44 45 45 45 50 52 53 56 58 60 60 61 73 74 75 75 77 80 83 84 86 89 90 91 92 96 98 98 101 102 103 104 108 109 113 114 116 118

238

12.7 Binomial option price of stock option where stock pays discrete dividends . . . . . . . . . . . . . 120 12.8 Pricing an american call on an option on futures using a binomial approximation . . . . . . . . . 122 12.9 Pricing an american call on an option on currency using a binomial approximation . . . . . . . . 123 13.1 Explicit nite dierences calculation of european put option . . . . . . . . . . . . . . . . . . . . . 126 13.2 Explicit nite dierences calculation of american put option . . . . . . . . . . . . . . . . . . . . . 127 13.3 Calculation of price of American put using implicit nite dierences with the Newmat matrix library131 13.4 Calculation of price of American put using implicit nite dierences with the IT++ matrix library 132 13.5 Calculation of price of European put using implicit nite dierences . . . . . . . . . . . . . . . . 133 14.1 Simulating a lognormally distributed random variable . . . . . . . . . . . . . . . . . . . . . . . . 136 14.2 European Call option priced by simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 14.3 Estimate Delta of European Call option priced by Monte Carlo . . . . . . . . . . . . . . . . . . . 138 14.4 Payo call and put options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 14.5 Generic simulation pricing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 14.6 Generic with control variate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 14.7 Generic with antithetic variates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 14.8 Payo binary options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 15.1 The Johnson (1983) approximation to an american put price . . . . . . . . . . . . . . . . . . . . 147 15.2 Geske Johnson approximation of American put . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 15.3 Barone Adesi quadratic approximation to the price of a call option . . . . . . . . . . . . . . . . . 153 15.4 Approximation of American Call due to Bjerksund and Stensland (1993) . . . . . . . . . . . . . . 155 15.5 Approximation of American put due to Bjerksund and Stensland (1993) . . . . . . . . . . . . . . 155 16.1 Binomial approximation to Bermudan put option . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 16.2 Analytical price of an Asian geometric average price call . . . . . . . . . . . . . . . . . . . . . . . 159 16.3 Price of lookback call option . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 16.4 Simulating a sequence of lognormally distributed variables . . . . . . . . . . . . . . . . . . . . . . 163 16.5 Generic routine for pricing European options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 16.6 Payo function for Asian call option . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164 16.7 Payo function for lookback option . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164 16.8 Control Variate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 17.1 Binomial price of American Call . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 17.2 Generic binomial calculation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 17.3 Payo denitions for put and call options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 17.4 Payo denitions for binomial options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170 17.5 Generic binomial calculation of delta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 18.1 Price of american put using a trinomial tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 19.1 Mertons jump diusion formula . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177 19.2 Hestons pricing formula for a stochastic volatility model . . . . . . . . . . . . . . . . . . . . . . . 180 20.1 Black scholes price for European put option on zero coupon bond . . . . . . . . . . . . . . . . . . 181 20.2 Black scholes price for European put option on coupon bond . . . . . . . . . . . . . . . . . . . . 182 20.3 Binomial approximation to american put bond option price . . . . . . . . . . . . . . . . . . . . . 183 22.1 Calculation of the Nelson and Siegel (1987) term structure model . . . . . . . . . . . . . . . . . . 188 22.2 Dening a term structure class wrapper for the Nelson Siegel approximation . . . . . . . . . . . . 189 22.3 Calculation of Svensson's extended Nelson and Siegel (1987) term structure model . . . . . . . . 191 22.4 Dening a term structure class wrapper for the Svensson model . . . . . . . . . . . . . . . . . . . 191 22.5 Approximating a discount function using a cubic spline . . . . . . . . . . . . . . . . . . . . . . . 192 22.6 Term structure class wrapping the cubic spline approximation . . . . . . . . . . . . . . . . . . . . 193 22.7 Calculation of the discount factor using the Cox et al. (1985) model . . . . . . . . . . . . . . . . 195 22.8 Class denition, Cox et al. (1985) model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196 22.9 Calculating a discount factor using the Vasicek functional form . . . . . . . . . . . . . . . . . . . 198 22.10Class denition, Vasicek (1977) model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198 23.1 RB binomial model for European call on zero coupon bond . . . . . . . . . . . . . . . . . . . . . 201 24.1 Building interest rate tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204 24.2 Valuing cash ows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 24.3 Valuing callable bond . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207 25.1 Term structure class for Ho-Lee . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 25.2 Term structure class for Ho-Lee, calculation of discount function . . . . . . . . . . . . . . . . . . 211 25.3 Building a term structure tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 25.4 Pricing of European call option on straight bond using Ho-Lee . . . . . . . . . . . . . . . . . . . 213

239

26.1 A.1 A.2 A.3 A.4 A.5 C.1

Bond option pricing using the Vasicek model . . . . . . . . . . . . . The normal distribution function . . . . . . . . . . . . . . . . . . . . The cumulative normal . . . . . . . . . . . . . . . . . . . . . . . . . Approximation to the cumulative bivariate normal . . . . . . . . . . Pseudorandom numbers from an uniform [0; 1) distribution . . . . . Pseudorandom numbers from a normal (0; 1) distribution . . . . . . Approximating N3 () using the method of Geske and Johnson (1984)

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

216 217 218 219 221 221 226

240

List of Matlab Codes


6.1 6.2 6.3 6.4 9.1 12.1 12.2 13.1 13.2 18.1 24.1 Calculation of minimum variance portfolio for given return . . . . . Sharpe Ratio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Treynor Ratio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Jensens alpha . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Price of European call option using the Black Scholes formula . . . . Price of American call using a binomial approximation . . . . . . . . Price of American put using a binomial approximation . . . . . . . . Explicit nite dierences calculation of American put option . . . . Calculation of price of American put using implicit nite dierences Price of american put using a trinomial tree . . . . . . . . . . . . . . Building interest rate tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 72 72 72 86 110 110 128 130 174 204

241

Appendix F

Acknowledgements.
After this paper was put up on the net, I've had quite a few emails about them. pointed out bugs and other inaccuracies. Among the ones I want to say thanks to for making improving suggestions and pointing out bugs are Ariel Almedal Andrei Bejenari Steve Bellantoni Jean-Paul Beveraggi Lars Gregori Daniel Herlemont Lorenzo Isella Jens Larsson Garrick Lau Steven Leadbeater Michael L Locher Lotti Luca, Milano, Italy Tuan Nguyen Michael R Wayne Some of them has

242

Index
, 89 , 89 , 89
A, 130 a, 128 antithetic variates, 141 asset or nothing call, 144 cash_ow_pv, 33 cash_ow_pv_discrete, 25, 26, 30, 227 cash_ow_unique_irr, 31 class, 9 cmath, 7 Complex numbers in C++, 179 control variates, 140 convexity of bond, 41 Cox Ingersoll Ross term structure model, 195 currency option, 103 currency option American, 123 European, 103 currency_option_price_call_american_binomial, 123 currency_option_price_call_european, 103, 104

BaroneAdesi and Whaley, 151 binary option, 144 binomial option price, 78, 106 binomial term structure models, 200 binomial_tree, 83 Black futures option, 102 Black Scholes option pricing formula, 85 Bond Price Flat term structure, 34 d, 53, 59, 235 Promised payments, 34 d1, 150 bond d2, 150 duration, 38 date::date, 11 price, 35 date::day, 11 yield to maturity, 35 date::month, 11 bond convexity, 41 date::valid, 11 bond option date::year, 11 basic binomial, 183 delta, 88 Black Scholes, 181 binomial, 113 Vasicek, 215 Black Scholes, 88 bond_option_price_call_zero_american_rendleman_bartter, derivative_price_simulate_european_option_generic, 201, 202, 235 139, 145, 163, 166 bond_option_price_call_zero_vasicek, 215, 216 derivative_price_simulate_european_option_generic_with_antithetic_ bond_option_price_put_american_binomial, 183 142 bond_option_price_put_coupon_bond_black_scholes,derivative_price_simulate_european_option_generic_with_control_va 182 141, 165 bond_option_price_put_zero_black_scholes, 181, 184 Discount factor, 34 bonds_convexity, 45, 61 discount factor, 24 bonds_convexity_discrete, 41 discount_factor, 198 bonds_duration, 45, 46, 60 double (C++ type), 5 bonds_duration_discrete, 38, 39, 42 duration, 38 bonds_duration_macaulay, 45 Macaulay, 38 bonds_duration_macaulay_discrete, 39 modied, 40 bonds_duration_modied_discrete, 40 e, 74, 76 bonds_price, 44, 60, 62, 228 early exercise premium, 151 bonds_price_discrete, 35, 36 exp, 186 bonds_yield_to_maturity_discrete, 36, 37 exp() (C++ statement), 7 bool (C++ type), 5 explicit nite dierences, 125 build_time_series_of_bond_time_contingent_cash_ows, 213 f, 219 f3, 226 calcP2, 150 nite dierences, 125, 130 call option, 78 explicit, 125 cash ow, 24 for (C++ statement), 8 cash or nothing call, 144 function prototypes (C++ concept), 139 cash_ow_irr_discrete, 29

243

normal distribution futures approximations, 217 option, 102 futures_option_price_call_american_binomial, 121, 122 option futures_option_price_call_european_black, 102 call, 78 futures_option_price_put_european_black, 102 currency, 103 futures_price, 77 futures, 102 lookback, 160 gamma, 89 put, 78 geometric Brownian motion, 88 Option price Geske and Johnson, 148 Black Scholes, 85 hedging parameters option price Black Scholes, 88 binomial, 106 heston_call_option_price, 179, 180 simulated, 135 heston_integrand_j, 180 option_price_american_call_approximated_baw, 152, heston_Pj, 180 153 hT, 211 option_price_american_call_approximated_bjerksund_stensland, 155 if, 12 option_price_american_call_one_dividend, 100, 101 implied volatility option_price_american_perpetual_call, 104 calculation, 91 option_price_american_put_approximated_bjerksund_stensland, include (C++ statement), 6 155 int (C++ type), 5 option_price_american_put_approximated_geske_johnson, interest_rate_trees_gbm_build, 204 150 interest_rate_trees_gbm_value_of_callable_bond, 207 option_price_american_put_approximated_johnson, interest_rate_trees_gbm_value_of_cashows, 205, 209 146, 147 internal rate of return, 28 option_price_asian_geometric_average_price_call, 159 Internet links, 225 option_price_call_american_binomial, 109, 116, 121, irr, 28 167 iteration operator option_price_call_american_discrete_dividends_binomial, denition of (C++ concept), 13 120 option_price_call_american_proportional_dividends_binomial, Jump Diusion, 176 118 option_price_call_black_scholes, 86, 87, 137, 140, 143 Links option_price_call_european_binomial, 108, 111 Internet, 225 option_price_call_european_binomial_multi_period_given_ud, long (C++ type), 5 84 lookback option, 160 option_price_call_european_binomial_single_period, 80, 83 main, 9 option_price_call_european_simulated, 136 Merton option_price_call_merton_jump_diusion, 177 Jump Diusion, 176 option_price_delta_american_call_binomial, 113 modied duration, 40 option_price_delta_call_black_scholes, 89, 137 Monte Carlo option_price_delta_call_european_simulated, 138 antithetic variates, 141 option_price_delta_generic_binomial, 171 monte carlo option_price_european_call_dividends, 98 control variates, 140 option_price_european_call_payout, 98, 99 mv_calculate_mean, 73, 74 mv_calculate_portfolio_given_mean_unconstrained, 75option_price_european_lookback_call, 160, 161 option_price_generic_binomial, 168170 mv_calculate_st_dev, 73, 74 option_price_implied_volatility_call_black_scholes_bisections, mv_calculate_variance, 73, 74 91 option_price_implied_volatility_call_black_scholes_newton, N, 218220 92, 93 n, 217 option_price_partials_american_call_binomial, 114, N3, 226 115 next_date, 13 option_price_partials_call_black_scholes, 90 no_observations, 57, 228 option_price_put_american_nite_di_explicit, 127 Normal distribution option_price_put_american_nite_di_implicit, 131 Simulation, 221

244

option_price_put_american_nite_di_implicit_itpp, term structure models binomial, 200 132 term_structure_class::d, 52 option_price_put_american_trinomial, 173 term_structure_class::f, 52 option_price_put_bermudan_binomial, 157, 158 term_structure_class::r, 52 option_price_put_black_scholes, 134 option_price_put_european_nite_di_explicit, 126, term_structure_class_cir, 196, 235 term_structure_class_cir::d, 196 129 option_price_put_european_nite_di_implicit, 133 term_structure_class_cir::term_structure_class_cir, 196 term_structure_class_cubic_spline, 192, 193, 235 partial derivatives term_structure_class_cubic_spline::d, 193 binomial, 113 term_structure_class_at::r, 53 Black Scholes, 88 term_structure_class_ho_lee, 210 partials term_structure_class_ho_lee::d, 211 Black Scholes, 88 term_structure_class_ho_lee::term_structure_class_ho_lee, payo_arithmetric_average_call, 164 211 payo_asset_or_nothing_call, 144 term_structure_class_interpolated::clear, 58 payo_binary_call, 170 term_structure_class_interpolated::r, 58 payo_binary_put, 170 term_structure_class_interpolated::set_interpolated_observations, payo_call, 139, 169 58 payo_cash_or_nothing_call, 144 term_structure_class_interpolated::term_structure_class_interpolated payo_geometric_average_call, 164 58 payo_lookback_call, 164 term_structure_class_nelson_siegel, 188 payo_lookback_put, 164 term_structure_class_nelson_siegel::r, 189 payo_put, 139, 169 term_structure_class_nelson_siegel::term_structure_class_nelson_sie phi, 155 189 pow() (C++ statement), 7 term_structure_class_svensson, 191, 234 power, 9 term_structure_class_svensson::r, 191 present value, 24 term_structure_class_svensson::term_structure_class_svensson, previous_date, 13 191 price_european_call_option_on_bond_using_ho_lee, term_structure_class_vasicek::d, 198 213 term_structure_class_vasicek::term_structure_class_vasicek, prices, 110 198 pricing term_structure_discount_factor_cir, 195, 197 relative, 78 term_structure_discount_factor_cubic_spline, 192, 194 put option, 78 term_structure_discount_factor_from_yield, 50 term_structure_discount_factor_vasicek, 198, 199 quadratic approximation, 151 term_structure_forward_rate_from_discount_factors, 50 r, 51, 53, 57, 228 term_structure_forward_rate_from_yields, 50 random_normal, 221 term_structure_ho_lee_build_term_structure_tree, 210, random_uniform_0_1, 221 211 relative pricing, 78 term_structure_yield_from_discount_factor, 50 Rendleman and Bartter model, 200 term_structure_yield_linearly_interpolated, 56 return term_structure_yield_nelson_siegel, 188, 190 internal rate of, 28 term_structure_yield_svensson, 191 rho, 89 theta, 89 time sgn, 219 value of, 24 Sharpe Ratio, 71 time_contingent_cash_ows, 213 simulate_lognormal_random_variable, 136 simulate_lognormally_distributed_sequence, 163 underlying security, 85 Simulation valid, 10 Random normal numbers, 221 Vasicek, 198 simulation, 135 vega, 89 string (C++ type), 5 volatility term structure derivatives, 215 implied, 91 Term structure model warrant_price_adjusted_black_scholes, 96 Cox Ingersoll Ross, 195
245

Bibliography
wilton ermowiz nd srene e tegunF rndook of wthE emtil puntionsF xtionl fureu of tndrdsD IWTRF qiovnni froneEedesiF he sg of the emerin putF tourE nl of fnking nd pinneD PWXPWHW!PWIVD PHHSF qiovnni froneEedesi nd oert i hleyF i0ient nE lyti pproximtion of emerin option vluesF tournl of pinneD RP@PAXQHI!PHD tune IWVUF etter fjerksund nd qunnr tenslndF glosed form pE proximtions of merin optionsF ndinvin tournl of wngementD PH@SAXUTI!UTRD IWWQF etter fjerksund nd qunnr tenslndF glosed form vluE tion of merin optionsF orking perD xrrD ytoer PHHPF pisher flkF he priing of ommodity ontrtsF tournl of pinnil ionomisD QXITU!UWD IWUTF pisher flk nd wyron holesF he priing of options nd orporte liilitiesF tournl of olitil ionomyD UXTQU!SRD IWUQF vi fodieD elex uneD nd eln t wrusF snvestmentsF wqrw rillD T editionD PHHSF eter v fosserts nd fernt erne degrdF vetures on gorporte pinneF orld ienti( ressD ingporeD PHHIF helim foyleF yptionsX e wonte grlo pprohF tournl of pinnil ionomisD RXQPQ!QVD IWUUF ihrd e freley nd tewrt g wyersF riniples of gorE porte pinneF wqrw!rillD seventh editionD PHHPF wihel frennn nd idurdo hwrtzF pinite di'erene methods nd jump proesses rising in the priing of onE tingent limsX e synthesisF tournl of pinnil nd untittive enlysisD IQXRTI!URD IWUVF tohn gox nd wrk uinsteinF yptions mrketsF rentie! rllD IWVSF tohn g goxD tephen e ossD nd wrk uinsteinF ypE tion priingX e simpli(ed pprohF tournl of pinnil ionomisD UXPPW!PTQD IWUWF tohn g goxD tonthn i sngersollD nd tephen e ossF e theory of the term struture of interest rtesF ionometE riD SQXQVS!RHVD IWVSF w f qrmn nd uohlhgenF poreign urreny option vluesF tournl of snterntionl woney nd pinneD PX PQI!QUD IWVQF oert qeskeF he vlution of ompound optionsF tournl of pinnil ionomisD UXTQ!VID wrh IWUWF oert qeske nd r i tohnsonF he merin put vlued nlytillyF tournl of pinneD s@SAD heemer IWVRF

w frry qoldmnD rowrd f osinD nd wry enn qttoF th!dependent optionsX fuy t the lowD sell t the highF tournl of pinneD QRD heemer IWUWF t y qreF he priing of ll nd put options on foreign exhngeF tournl of snterntionl woney nd pinneD PXPQW!SQD IWVQF hilip qry nd tephen p qryF e frmework for vluing derivtive seuritiesF pinnil wrketsD snstitutions nd snstrumentsD IH@SAXPSQ!PUTD heemer PHHIF ihrd g qreen nd fernt erne degrdF ere there tx e'ets in the reltive priing of FF qovernment ondsc tournl of pinneD SPXTHW!TQQD tune IWWUF oert e rugenF wodern snvestment heoryF rentie! rllD (fth editionD PHHIF teven v restonF e losedEform solution fo option with stohstik voltility with pplitions to ond nd urE reny optionsF eview of pinnil tudiesD T@PAXQPU!QRQD IWWQF ro nd veeF erm struture movement nd priing interest rte ontingent limsF tournl of pinneD RQX IHII!PWD IWVTF ghiEfu rung nd oert r vitzenergerF poundtions for (nnil eonomisF xorth!rollndD IWVVF tohn rullF yptionsD putures nd other herivtivesF rentie!rllD sixth editionD PHHTF tohn rullF yptionsD putures nd other herivtive euritiesF rentie!rllD seond editionD IWWQF p tmshidnF en ext ond option priing formulF tourE nl of pinneD RRXPHS!WD wrh IWVWF r i tohnsonF en nlyti pproximtion of the merin put prieF tournl of pinnil nd untittive enlyE sisD IV@IAXIRI!RVD IWVQF e uemn nd e orstF e priing method for options sed on verge sset vluesF tournl of fnking nd pinneD IRXIIQ!PWD wrh IWWHF honld i unuthF he ert of gomputer rogrmming olume PD eminumeril elgotithmsF eddison!esleyD third editionD IWWUF tnley f vippmnF gCC primerF eddison!esleyD P ediE tionD IWWPF tnley f vippmn nd tos9ee vjoieF eddison!esleyD third editionD IWWVF

gCC primerF

oert r vitzenerger nd tques olfoF en interntionl study of tx e'ets on government ondsF tournl of pinneD QWXI!PPD IWVRF rrry wrkowitzF ortfolio seletionF tournl of pinneD UXUU!WID IWSPF vionel wrtinelliD hilippe riuletD nd tphne riuletF pixed snome euritiesF lutionD isk wngement nd ortfolio trtegiesF iley pinneD PHHQF t rouston wgullohF wesuring the term struture of inE terest rtesF tournl of fusinessD RRXIW!QID IWUIF t rouston wgullohF he tx djusted yield urveF tournl of pinneD QHXVII!VPWD IWUSF

246

oert whonld nd hniel iegelF he vlue of witing to investF urterly tournl of ionomisD pges UHU!UPUD xovemer IWVTF oert v whonldF herivtives wrketsF ersonD seond editionD PHHTF oert g wertonF en nlyti derivtion of the e0ient portfolio frontierF tournl of pinnil nd untittive enlysisD UXIVSI!UPD eptemer IWUPF oert g wertonF he theory of rtionl option priingF fell tournlD RXIRI!IVQD IWUQF oert g wertonF yption priing when underlying stok reE turns re disontinousF tournl of pinnil ionomisD QXIPS!RRD IWUTF prno wodiglini nd werton w willerF he ost of pE itlD orportion (nne nd the theory of investmentF emerin ionomi eviewD RVXPTI!WUD IWSVF ghrles xelson nd endrew p iegelF rsimonious modE elling of yield urvesF tournl of fusinessD TH@RAXRUQ!VWD IWVUF grl t xorstromF e su0ient onditions for unique nonE negtive internl rte of returnF tournl of pinnil nd untittive enlysisD U@QAXIVQS!QWD IWUPF illim ressD ul e eukolskyD illim etterlingD nd frin plnneryF xumeril eipes in gF gmridge niversity ressD seond editionD IWWPF ihrd t endlemn nd frit t frtterF wo!stte option priingF tournl of pinneD QR@SAXIHWQ!IIIHD heemer IWUWF ihrd t endlemn nd frit t frtterF he priing of opE tions on det seuritiesF tournl of pinnil nd unE tittive enlysisD IS@IAXII!PRD wrh IWVHF ihrd ollF e ritique of the sset priing theory9s tests! rt sX yn pst nd potentil testility of the theoryF tournl of pinnil ionomisD RXIPW!IUTD IWUUF

ihrd ollF en nlytil formul for unproteted emeriE n ll options on stoks with known dividendsF tournl of pinnil ionomisD SXPSI!SVD IWUUF tephen e ossD ndolph ester(eldD nd te'rey p t'eF gorporte pinneF wqrsErillD seventh editionD PHHSF wrk uinsteinF he vlution of unertin inome strems nd the vlution of optionsF fell tournlD UX RHU!PSD IWUTF wrk uinsteinF ixoti optionsF niversity of gliforniD ferkeleyD working pperD IWWQF illim p hrpeD qordon t elexnderD nd te'ery fiE leyF snvestmentsF rentie rllD sixth editionD IWWWF oert tF hillerF he term struture of interest rtesF sn f w priedmn nd p r rhnD editorsD rndook of wonE etry ionomisD volume PD hpter IQD pges TPU!UPPF ilsevierD IWWHF fjrne troustrupF he gCC rogrmming lngugeF eddison!esleyD third editionD IWWUF uresh undresnF pixed snome wrkets nd their herivE tivesF outhEesternD P editionD PHHIF v ongF he wultivrite xorml histriutionF pringerD IWWHF y siekF en equilirium hrteriztion of the term strutureF tournl of pinnil ionomisD SXIUU!VVD IWUUF oert i hleyF yn the vlution of emerin ll options on stoks with known dividendsF tournl of pinnil ionomisD WXPHU!ID IWVIF ul ilmottD te' hewynneD nd m rowisonF yption riingD wthemtil models nd omputtionF yxford pinnil ressD IWWRF sfx H WSPPHVP HPF

247

Das könnte Ihnen auch gefallen