ńņš. 1 |

C++ DESIGN PATTERNS AND DERIVATIVES PRICING

2nd edition

Design patterns are the cutting-edge paradigm for programming in object-oriented lan-

guages. Here they are discussed in the context of implementing ļ¬nancial models in C++.

Assuming only a basic knowledge of C++ and mathematical ļ¬nance, the reader is taught

how to produce well-designed, structured, reusable code via concrete examples.

This new edition includes several new chapters describing how to increase robustness

in the presence of exceptions, how to design a generic factory, how to interface C++

with EXCEL, and how to improve code design using the idea of decoupling. Complete

ANSI/ISO compatible C++ source code is hosted on an accompanying website for the

reader to study in detail, and reuse as they see ļ¬t.

A good understanding of C++ design is a necessity for working ļ¬nancial mathemati-

cian; this book provides a thorough introduction to the topic.

Mathematics, Finance and Risk

Editorial Board

Mark Broadie, Graduate School of Business, Columbia University

Sam Howison, Mathematical Institute, University of Oxford

Neil Johnson, Centre for Computational Finance, University of Oxford

George Papanicolaou, Department of Mathematics, Stanford University

C++ DESIGN PATTERNS AND

D E R I VA T I V E S P R I C I N G

M. S. J O S H I

University of Melbourne

CAMBRIDGE UNIVERSITY PRESS

Cambridge, New York, Melbourne, Madrid, Cape Town, Singapore, SĆ£o Paulo

Cambridge University Press

The Edinburgh Building, Cambridge CB2 8RU, UK

Published in the United States of America by Cambridge University Press, New York

www.cambridge.org

Information on this title: www.cambridge.org/9780521721622

Ā© M. S. Joshi 2008

This publication is in copyright. Subject to statutory exception and to the provision of

relevant collective licensing agreements, no reproduction of any part may take place

without the written permission of Cambridge University Press.

First published in print format 2008

ISBN-13 978-0-511-39693-9 eBook (NetLibrary)

ISBN-13 978-0-521-72162-2 paperback

Cambridge University Press has no responsibility for the persistence or accuracy of urls

for external or third-party internet websites referred to in this publication, and does not

guarantee that any content on such websites is, or will remain, accurate or appropriate.

To Jane

Contents

Preface page xiii

Acknowledgements xvi

1 A simple Monte Carlo model 1

1.1 Introduction 1

1.2 The theory 1

1.3 A simple implementation of a Monte Carlo call

option pricer 2

1.4 Critiquing the simple Monte Carlo routine 7

1.5 Identifying the classes 9

1.6 What will the classes buy us? 10

1.7 Why object-oriented programming? 11

1.8 Key points 11

1.9 Exercises 12

2 Encapsulation 13

2.1 Implementing the pay-off class 13

2.2 Privacy 15

2.3 Using the pay-off class 16

2.4 Further extensibility defects 19

2.5 The openā“closed principle 20

2.6 Key points 21

2.7 Exercises 22

3 Inheritance and virtual functions 23

3.1 ā˜is aā™ 23

3.2 Coding inheritance 24

3.3 Virtual functions 24

3.4 Why we must pass the inherited object by reference 29

3.5 Not knowing the type and virtual destruction 30

3.6 Adding extra pay-offs without changing ļ¬les 34

vii

viii Contents

3.7 Key points 37

3.8 Exercises 37

4 Bridging with a virtual constructor 38

4.1 The problem 38

4.2 A ļ¬rst solution 39

4.3 Virtual construction 43

4.4 The rule of three 51

4.5 The bridge 53

4.6 Beware of new 57

4.7 A parameters class 58

4.8 Key points 65

4.9 Exercises 65

5 Strategies, decoration, and statistics 66

5.1 Differing outputs 66

5.2 Designing a statistics gatherer 66

5.3 Using the statistics gatherer 69

5.4 Templates and wrappers 73

5.5 A convergence table 77

5.6 Decoration 80

5.7 Key points 81

5.8 Exercises 81

6 A random numbers class 83

6.1 Why? 83

6.2 Design considerations 84

6.3 The base class 86

6.4 A linear congruential generator and the adapter pattern 88

6.5 Anti-thetic sampling via decoration 93

6.6 Using the random number generator class 97

6.7 Key points 102

6.8 Exercises 102

7 An exotics engine and the template pattern 103

103

7.1 Introduction

7.2 Identifying components 104

105

7.3 Communication between the components

7.4 The base classes 106

7.5 A Blackā“Scholes path generation engine 111

7.6 An arithmetic Asian option 115

117

7.7 Putting it all together

7.8 Key points 120

7.9 Exercises 120

Contents ix

8 Trees 121

8.1 Introduction 121

8.2 The design 123

8.3 The TreeProduct class 125

8.4 A tree class 129

8.5 Pricing on the tree 135

8.6 Key points 139

8.7 Exercises 139

9 Solvers, templates, and implied volatilities 141

141

9.1 The problem

9.2 Function objects 142

9.3 Bisecting with a template 145

9.4 Newtonā“Raphson and function template

arguments 149

9.5 Using Newtonā“Raphson to do implied

volatilities 151

9.6 The pros and cons of templatization 154

9.7 Key points 156

9.8 Exercises 156

10 The factory 157

10.1 The problem 157

10.2 The basic idea 157

10.3 The singleton pattern 158

10.4 Coding the factory 159

10.5 Automatic registration 162

165

10.6 Using the factory

10.7 Key points 166

10.8 Exercises 167

11 Design patterns revisited 168

11.1 Introduction 168

11.2 Creational patterns 168

11.3 Structural patterns 169

11.4 Behavioural patterns 170

11.5 Why design patterns? 171

11.6 Further reading 172

11.7 Key points 172

11.8 Exercise 173

12 The situation in 2007 174

12.1 Introduction 174

12.2 Compilers and the standard library 174

12.3 Boost 176

x Contents

12.4 QuantLib 177

12.5 xlw 177

12.6 Key points 178

12.7 Exercises 178

13 Exceptions 179

13.1 Introduction 179

13.2 Safety guarantees 180

13.3 The use of smart pointers 180

13.4 The rule of almost zero 183

13.5 Commands to never use 184

13.6 Making the wrapper class exception safe 185

13.7 Throwing in special functions 186

13.8 Floating point exceptions 187

13.9 Key points 192

14 Templatizing the factory 197

14.1 Introduction 197

14.2 Using inheritance to add structure 197

14.3 The curiously recurring template pattern 199

14.4 Using argument lists 200

14.5 The private part of the ArgumentList class 206

14.6 The implementation of the ArgumentList 208

14.7 Cell matrices 220

14.8 Cells and the ArgumentLists 224

14.9 The template factory 232

14.10 Using the templatized factory 237

14.11 Key points 242

14.12 Exercises 243

15 Interfacing with EXCEL 244

15.1 Introduction 244

15.2 Usage 245

15.3 Basic data types 247

15.4 Extended data types 248

15.5 xlw commands 250

15.6 The interface ļ¬le 250

15.7 The interface generator 253

15.8 Troubleshooting 254

15.9 Debugging with xlls 254

15.10 Key points 255

15.11 Exercises 255

Contents xi

16 Decoupling 256

16.1 Introduction 256

16.2 Header ļ¬les 256

16.3 Splitting ļ¬les 259

16.4 Direction of information ļ¬‚ow and levelization 260

16.5 Classes as insulators 262

16.6 inlining 262

16.7 Template code 263

16.8 Functional interfaces 264

16.9 Pimpls 264

16.10 Key points 265

16.11 Exercises 265

Appendix A Blackā“Scholes formulas 266

Appendix B Distribution functions 270

Appendix C A simple array class 274

C.1 Choosing an array class 274

C.2 A simple array class 275

C.3 A simple array class 278

Appendix D The code 285

D.1 Using the code 285

D.2 Compilers 285

D.3 License 285

Appendix E Glossary 286

Bibliography 287

Index 289

Preface

This book is aimed at a reader who has studied an introductory book on mathemat-

ical ļ¬nance and an introductory book on C++ but does not know how to put the

two together. My objective is to teach the reader not just how to implement models

in C++ but more importantly how to think in an object-oriented way. There are

already many books on object-oriented programming; however, the examples tend

not to feel real to the ļ¬nancial mathematician so in this book we work exclusively

with examples from derivatives pricing.

We do not attempt to cover all sorts of ļ¬nancial models but instead examine a

few in depth with the objective at all times of using them to illustrate certain OO

ideas. We proceed largely by example, rewriting, our designs as new concepts are

introduced, instead of working out a great design at the start. Whilst this approach

is not optimal from a design standpoint, it is more pedagogically accessible. An

aspect of this is that our examples are designed to emphasize design principles

rather than to illustrate other features of coding, such as numerical efļ¬ciency or

exception safety.

We commence by introducing a simple Monte Carlo model which does not use

OO techniques but rather is the simplest procedural model for pricing a call option

one could write. We examine its shortcomings and discuss how classes naturally

arise from the concepts involved in its construction.

In Chapter 2, we move on to the concept of encapsulation ā“ the idea that a class

allows to express a real-world analogue and its behaviours precisely. In order to

illustrate encapsulation, we look at how a class can be deļ¬ned for the pay-off of a

vanilla option. We also see that the class we have deļ¬ned has certain defects, and

this naturally leads on to the openā“closed principle.

In Chapter 3, we see how a better pay-off class can be deļ¬ned by using inheri-

tance and virtual functions. This raises technical issues involving destruction and

passing arguments, which we address. We also see how this approach is compatible

with the openā“closed principle.

xiii

xiv Preface

Using virtual functions causes problems regarding the copying of objects of un-

known type, and in Chapter 4 we address these problems. We do so by introducing

virtual constructors and the bridge pattern. We digress to discuss the ā˜rule of threeā™

and the slowness of new. The ideas are illustrated via a vanilla options class and a

parameters class.

With these new techniques at our disposal, we move on to looking at more com-

plicated design patterns in Chapter 5. We ļ¬rst introduce the strategy pattern that

expresses the idea that decisions on part of an algorithm can be deferred by dele-

gating responsibilities to an auxiliary class. We then look at how templates can be

used to write a wrapper class that removes a lot of our difļ¬culties with memory

handling. As an application of these techniques, we develop a convergence table

using the decorator pattern.

In Chapter 6, we look at how to develop a random numbers class. We ļ¬rst exam-

ine why we need a class and then develop a simple implementation which provides

a reusable interface and an adequate random number generator. We use the imple-

mentation to introduce and illustrate the adapter pattern, and to examine further the

decorator pattern.

We move on to our ļ¬rst non-trivial application in Chapter 7, where we use the

classes developed so far in the implementation of a Monte Carlo pricer for path-

dependent exotic derivatives. As part of this design, we introduce and use the tem-

plate pattern. We ļ¬nish with the pricing of Asian options.

We shift from Monte Carlo to trees in Chapter 8. We see the similarities and

differences between the two techniques, and implement a reusable design. As part

of the design, we reuse some of the classes developed earlier for Monte Carlo.

We return to the topic of templates in Chapter 9. We illustrate their use by design-

ing reusable solver classes. These classes are then used to deļ¬ne implied volatility

functions. En route, we look at function objects and pointers to member functions.

We ļ¬nish with a discussion of the pros and cons of templatization.

In Chapter 10, we look at our most advanced topic: the factory pattern. This

patterns allows the addition of new functionality to a program without changing

any existing ļ¬les. As part of the design, we introduce the singleton pattern.

We pause in Chapter 11 to classify, summarize, and discuss the design patterns

we have introduced. In particular, we see how they can be divided into creational,

structural, and behavioural patterns. We also review the literature on design patterns

to give the reader a guide for further study.

The ļ¬nal four chapters are new for the second edition. In these our focus is

different: rather than focussing exclusively on design patterns, we look at some

other important aspects of good coding that neophytes to C++ tend to be unaware

of.

Preface xv

In Chapter 12, we take a historical look at the situation in 2007 and at what has

changed in recent years both in C++ and the ļ¬nancial engineering communityā™s

use of it.

The study of exception safety is the topic of Chapter 13. We see how making the

requirement that code functions well in the presence of exceptions places a large

number of constraints on style. We introduce some easy techniques to deal with

these constraints.

In Chapter 14, we return to the factory pattern. The original factory pattern re-

quired us to write similar code every time we introduced a new class hierarchy; we

now see how, by using argument lists and templates, a fully general factory class

can be coded and reused forever.

In Chapter 15, we look at something rather different that is very important in

day-to-day work for a quant: interfacing with EXCEL. In particular, we examine

the xlw package for building xlls. This package contains all the code necessary to

expose a C++ function to EXCEL, and even contains a parser to write the new

code required for each function.

The concept of physical design is introduced in Chapter 16. We see how the

objective of reducing compile times can affect our code organization and design.

The code for the examples in the ļ¬rst 11 chapters of this book can be freely

downloaded from www.markjoshi.com/design, and any bugļ¬xes will be posted

there. The code for the remaining chapters is taken from the xlw project and can

be downloaded from xlw.sourceforge.net. All example code is taken from

release 2.1.

Acknowledgements

I am grateful to the Royal Bank of Scotland for providing a stimulating environ-

ment in which to learn, study and do mathematical ļ¬nance. Most of my views on

coding C++ and ļ¬nancial modelling have been developed during my time work-

ing there. My understanding of the topic has been formed through daily discussions

with current and former colleagues including Chris Hunter, Peter JĀØ ckel, Dhermin-

a

der Kainth, Sukhdeep Mahal, Robin Nicholson and Jochen Theis. I am also grate-

ful to a host of people for their many comments on the manuscript, including Alex

Barnard, Dherminder Kainth, Rob Kitching, Sukhdeep Mahal, Nadim Mahassen,

Hugh McBride, Alan Stacey and Patrik Sundberg. I would also like to thank David

Tranah and the rest of the team at Cambridge University Press for their careful

work and attention to detail. Finally my wife has been very supportive.

I am grateful to a number of people for their comments on the second edi-

tion, with particular thanks to Chris Beveridge, Narinder Claire, Nick Denson and

Lorenzo Liesch.

xvi

1

A simple Monte Carlo model

1.1 Introduction

In the ļ¬rst part of this book, we shall study the pricing of derivatives using Monte

Carlo simulation. We do this not to study the intricacies of Monte Carlo but because

it provides many convenient examples of concepts that can be abstracted. We pro-

ceed by example, that is we ļ¬rst give a simple program, discuss its good points, its

shortcomings, various ways round them and then move on to a new example. We

carry out this procedure repeatedly and eventually end up with a fancy program.

We begin with a routine to price vanilla call options by Monte Carlo.

1.2 The theory

We commence by discussing the theory. The model for stock price evolution is

d St = ĀµSt dt + Ļ St dWt , (1.1)

and a riskless bond, B, grows at a continuously compounding rate r . The Blackā“

Scholes pricing theory then tells us that the price of a vanilla option, with expiry T

and pay-off f , is equal to

eā’r T E( f (ST )),

where the expectation is taken under the associated risk-neutral process,

d St = r St dt + Ļ St dWt . (1.2)

We solve equation (1.2) by passing to the log and using Itoā™s lemma; we compute

1

d log St = r ā’ Ļ 2 dt + Ļ dWt . (1.3)

2

As this process is constant-coefļ¬cient, it has the solution

1

log St = log S0 + r ā’ Ļ 2 t + Ļ Wt . (1.4)

2

1

2 A simple Monte Carlo model

Since Wt is a Brownian motion, WT is distributed as a Gaussian with mean zero

and variance T , so we can write

ā

WT = T N (0, 1), (1.5)

and hence

ā

1

log ST = log S0 + r ā’ Ļ 2 T + Ļ T N (0, 1), (1.6)

2

or equivalently,

ā

(r ā’ 1 Ļ 2 )T +Ļ T N (0,1)

ST = S0 e . (1.7)

2

The price of a vanilla option is therefore equal to

ā

ā’r T (r ā’ 1 Ļ 2 )T +Ļ T N (0,1)

E f S0 e .

e 2

The objective of our Monte Carlo simulation is to approximate this expectation by

using the law of large numbers, which tells us that if Y j are a sequence of identically

distributed independent random variables, then with probability 1 the sequence

N

1

Yj

N j=1

converges to E(Y1 ).

So the algorithm to price a call option by Monte Carlo is clear. We draw a random

variable, x, from an N (0, 1) distribution and compute

ā

(r ā’ 1 Ļ 2 )T +Ļ T x

,

f S0 e 2

where f (S) = (S ā’ K )+ . We do this many times and take the average. We then

multiply this average by eā’r T and we are done.

1.3 A simple implementation of a Monte Carlo call option pricer

A ļ¬rst implementation is given in the program SimpleMCMain1.cpp.

Listing 1.1 (SimpleMCMain1.cpp)

// requires Random1.cpp

#include <Random1.h>

#include <iostream>

#include <cmath>

using namespace std;

1.3 A simple implementation of a Monte Carlo call option pricer 3

double SimpleMonteCarlo1(double Expiry,

double Strike,

double Spot,

double Vol,

double r,

unsigned long NumberOfPaths)

{

double variance = Vol*Vol*Expiry;

double rootVariance = sqrt(variance);

double itoCorrection = -0.5*variance;

double movedSpot = Spot*exp(r*Expiry +itoCorrection);

double thisSpot;

double runningSum=0;

for (unsigned long i=0; i < NumberOfPaths; i++)

{

double thisGaussian = GetOneGaussianByBoxMuller();

thisSpot = movedSpot*exp( rootVariance*thisGaussian);

double thisPayoff = thisSpot - Strike;

thisPayoff = thisPayoff >0 ? thisPayoff : 0;

runningSum += thisPayoff;

}

double mean = runningSum / NumberOfPaths;

mean *= exp(-r*Expiry);

return mean;

}

int main()

{

double Expiry;

double Strike;

double Spot;

double Vol;

double r;

unsigned long NumberOfPaths;

cout << "\nEnter expiry\n";

cin >> Expiry;

4 A simple Monte Carlo model

cout << "\nEnter strike\n";

cin >> Strike;

cout << "\nEnter spot\n";

cin >> Spot;

cout << "\nEnter vol\n";

cin >> Vol;

cout << "\nr\n";

cin >> r;

cout << "\nNumber of paths\n";

cin >> NumberOfPaths;

double result = SimpleMonteCarlo1(Expiry,

Strike,

Spot,

Vol,

r,

NumberOfPaths);

cout <<"the price is " << result << "\n";

double tmp;

cin >> tmp;

return 0;

}

Our program uses the auxiliary ļ¬les Random1.h and Random1.cpp.

Listing 1.2 (Random1.h)

#ifndef RANDOM1_H

#define RANDOM1_H

double GetOneGaussianBySummation();

double GetOneGaussianByBoxMuller();

#endif

1.3 A simple implementation of a Monte Carlo call option pricer 5

Listing 1.3 (Random1.cpp)

#include <Random1.h>

#include <cstdlib>

#include <cmath>

// the basic math functions should be in namespace

// std but arenā™t in VCPP6

#if !defined(_MSC_VER)

using namespace std;

#endif

double GetOneGaussianBySummation()

{

double result=0;

for (unsigned long j=0; j < 12; j++)

result += rand()/static_cast<double>(RAND_MAX);

result -= 6.0;

return result;

}

double GetOneGaussianByBoxMuller()

{

double result;

double x;

double y;

double sizeSquared;

do

{

x = 2.0*rand()/static_cast<double>(RAND_MAX)-1;

y = 2.0*rand()/static_cast<double>(RAND_MAX)-1;

sizeSquared = x*x + y*y;

}

while

( sizeSquared >= 1.0);

6 A simple Monte Carlo model

result = x*sqrt(-2*log(sizeSquared)/sizeSquared);

return result;

}

We ļ¬rst include the header ļ¬le Random1.h. Note that the program has

<Random1.h> rather than "Random1.h". This means that we have set our com-

piler settings to look for header ļ¬les in the directory where Random1.h is. In this

case, this is in the directory C/include. (In Visual C++, the directories for in-

clude ļ¬les can be changed via the menus tools, options, directories.)

Random1.h tells the main ļ¬le that the functions

double GetOneGaussianBySummation()

and

double GetOneGaussianByBoxMuller()

exist. We include the system ļ¬le iostream as we want to use cin and cout for

the user interface. The system ļ¬le cmath is included as it contains the basic math-

ematical functions exp and sqrt.

We have the command using namespace std because all the standard

library commands are contained in the namespace std. If we did not give the

using directive, then we would have to preļ¬x all their uses by std::, so then

it would be std::cout rather than cout.

The function SimpleMonteCarlo1 does all the work. It takes in all the standard

inputs for the Blackā“Scholes model, the expiry and strike of the option, and in

addition the number of paths to be used in the Monte Carlo.

Before starting the Monte Carlo we precompute as much as possible. Thus we

compute the variance of the log of the stock over the optionā™s life, the adjustment

term ā’ 1 Ļ 2 T for the drift of the log, and the square root of the variance. Whilst we

2

cannot precompute the ļ¬nal value of spot, we precompute what we can and put it

in the variable movedSpot.

We initialize the variable, runningSum, to zero as it will store the sum so far of

the option pay-offs at all times.

We now loop over all the paths. For each path, we ļ¬rst draw the random number

from the N (0, 1) distribution using the Boxā“Muller algorithm and put it in the

variable thisGaussian.

The spot at the end of the path is then computed and placed in thisSpot. Note

that although our derivation of the SDE involved working with the log of the spot,

we have carefully avoided using log in this routine. The reason is that log and exp

1.4 Critiquing the simple Monte Carlo routine 7

are slow to compute in comparison to addition and multiplication, we therefore

want to make as few calls to them as possible.

We then compute the call optionā™s pay-off by subtracting the strike and taking

the maximum with zero. The pay-off is then added to runningSum and the loop

continues.

Once the loop is complete, we divide by the number of paths to get the expecta-

tion. Finally, we discount to get our estimate of the price which we return.

The main program takes in the inputs from the user, calls the Monte Carlo func-

tion, and displays the results. It asks for a ļ¬nal input to stop the routine from re-

turning before the user has had a chance to read the results.

1.4 Critiquing the simple Monte Carlo routine

The routine we have written runs quickly and does what it was intended to do. It is

a simple straightforward procedural program that performs as required. However,

if we worked with this program we would swiftly run into annoyances. The essence

of good coding is reusability. What does this mean? One simple deļ¬nition is that

code is reusable if someone has reused it. Thus reusability is as much a social

concept as a technical one. What will make it easy for someone to reuse your

code? Ultimately, the important attributes are clarity and elegance of design. If

another coder decides that it would take as much effort to recode your routines as

to understand them, then he will recode, and his inclination will be to recode in any

case, as it is more fun than poring over someone elseā™s implementation.

The second issue of elegance is equally important. If the code is clear but difļ¬cult

to adapt then another coder will simply abandon it, rather than put lots of effort

into forcing it to work in a way that is unnatural for how it was built.

The demands of reusability therefore mean we should strive for clarity and ele-

gance. In addition, we should keep in mind when considering our original design

the possibility that in future our code might need to be extended.

We return to our simple Monte Carlo program. Suppose we have a boss and

each day he comes by and asks for our program to do something more. If we have

designed it well then we will simply have to add features; if we have designed

poorly then we will have to rewrite existing code.

So what might the evil boss demand?

āDo puts as well as calls!ā

āI canā™t see how accurate the price is, put in the standard error.ā

āThe convergence is too slow, put in anti-thetic sampling.ā

āI want the most accurate price possible by 9am tomorrow so set it running for

14 hours.ā

8 A simple Monte Carlo model

āItā™s crucial that the standard error is less than 0.0001, so run it until thatā™s

achieved. Weā™re in a hurry though so donā™t run it any longer than strictly necessary.ā

āI read about low-discrepancy numbers at the weekend. Just plug them in and

see how good they are.ā

āApparently, standard error is a poor measure of error for low-discrepancy sim-

ulations. Put in a convergence table instead.ā

āHmm, I miss the standard error can we see that too.ā

āWe need a digital call pricer now!ā

āWhat about geometric average Asian calls?ā

āHow about arithmetic average Asian puts?ā

āTake care of variable parameters for the volatility and interest rates.ā

āUse the geometric Asian option as a control variate for the arithmetic one.ā

āThese low-discrepancy numbers apparently only work well if you Brownian

bridge. Put that in as well.ā

āPut in a double digital geometric Asian option.ā

āWhat about jump risk? Put in a jump-diffusion model.ā

To adapt the routine as written would require a rewrite to do any of these. We

have written the simplest routine we could think of, without considering design

issues. This means that each change is not particularly natural and requires extra

work.

For example, with this style of programming how would we would do the put

option?

Option one: copy the function, change the name by adding put at the end, and

rewrite the two lines where the pay-off is computed.

Option two: pass in an extra parameter, possibly as an enum and compute the

pay-off via a switch statement in each loop of the Monte Carlo. The problem

with the ļ¬rst option is that when we come to the next task, we have to adapt both

the functions in the same way and do the same thing twice. If we then need more

pay-offs this will rapidly become a maintenance nightmare.

The issues with the other option are more subtle. One problem is that a switch

statement is an additional overhead so that the routine will now run a little slower.

A deeper problem is that when we come to do a different routine which also uses a

pay-off, we will have to copy the code from inside the ļ¬rst routine or rewrite it as

necessary. This once again becomes a maintenance problem; every time we want to

add a new sort of pay-off we would have to go through every place where pay-offs

are used and add it on.

A C style approach to this problem would be to use a function pointer, we pass

a pointer to a function as an argument to the Monte Carlo. The function pointed to

is then called via the pointer in each loop to specify the price. Note that the call

to the function would have to specify the strike as well as spot since the function

1.5 Identifying the classes 9

could not know its value. Note also that if we wanted to do a double-digital option

we would have problems as the double digital pays if and only if spot is between

two levels, and we only have one argument, the strike, to play with.

The C++ approach to this problem is to use a class. The class would encapsulate

the behaviour of the pay-off of a vanilla option. A pay-off object would then be

passed into the function as an argument and in each loop a method expressing its

value would be called to output the price for that pay-off. We look at the imple-

mentation of such a class in the next chapter.

1.5 Identifying the classes

In the previous section, we saw that the problem of wanting to add different sorts

of vanilla options led naturally to the use of a class to encapsulate the notion of

a pay-off. In this section, we look at identifying other natural classes which arise

from the bossā™s demands.

Some of the demands were linked to differing forms that the boss wanted the

information in. We could therefore abstract this notion by creating a statistics gath-

erer class.

We also had differing ways of terminating the Monte Carlo. We could termi-

nate on time, on standard error or simply after a ļ¬xed number of paths. We could

abstract this by writing a terminator class.

There were many different issues with the method of random number genera-

tion. The routine as it stands relies on the inbuilt generator which we do not know

much about. We therefore want to be able to use other random number generators.

We also want the ļ¬‚exibility of using low-discrepancy numbers which means an-

other form of generation. (In addition, Boxā“Muller does not work well with low-

discrepancy numbers so we will need ļ¬‚exibility in the inputs.) Another natural

abstraction is therefore a random number generator class.

As long as our option is vanilla then specifying its parameters via pay-off and

strike is fairly natural and easy; however, it would be neater to have one class

that contains both pieces of information. More generally, when we pass to path-

dependent exotic options, it becomes natural to have a class that expresses the

optionā™s properties. What would we expect such a class to do? Ultimately, an easy

way to decide what the class should and should not know is to think of whether a

piece of information would be contained in the term-sheet. Thus the class would

know the pay-off of the option. It would know the expiry time. If it was an Asian

it would know the averaging dates. It would also know whether the averaging

was geometric or arithmetic. It would not know anything about interest rates, nor

the value of spot nor the volatility of the spot rate as none these facts are con-

tained in the term-sheet. The point here is that by choosing a real-world concept to

10 A simple Monte Carlo model

encapsulate, it is easy to decide what to include or not to include. It is also easy

for another user to understand how you have decided what to include or not to

include.

What other concepts can we identify? The concept of a variable parameter could

be made into a class. The process from which spot is drawn is another concept. The

variable interest rates could be encapsulated via a class that expresses the notion of

a discount curve.

1.6 What will the classes buy us?

Suppose that having identiļ¬ed all these classes, we implement them. What do we

gain?

The ļ¬rst gain is that because these classes encapsulate natural ļ¬nancial concepts,

we will need them when doing other pieces of coding. For example, if we have a

class that does yield curves then we will use it time and time again, as to price any

derivative using any reasonable method involves knowledge of the discount curve.

Not only will we save time on the writing of code but we will also save time on

the debugging. A class that has been tested thoroughly once has been tested forever

and in addition, any little quirks that evade the testing regime will be found through

repeated reuse. The more times and ways something has been reused the fewer the

bugs that will be left. So using reusable classes leads to more reliable code as well

as saving us coding time. Debugging often takes at least as much time as coding in

any case, so saving time on debugging is a big beneļ¬t.

A second gain is that our code becomes clearer. We have written the code in

terms of natural concepts, so another coder can identify the natural concepts and

pick up our code much more easily.

A third gain is that the classes will allow us to separate interface from implemen-

tation. All the user needs to know about a pay-off class or discount curve class are

what inputs yield what outputs? How the class works internally does not matter.

This has multiple advantages. The ļ¬rst is that the class can be reused without the

coder having to study its internal workings. The second advantage is that because

the deļ¬ning characteristic of the class is what it does but not how it does it, we can

change how it does it at will. And crucially, we can do this without rewriting the rest

of our program. One aspect of this is that we can ļ¬rst quickly write a suboptimal

implementation and improve it later at no cost. This allows us to provide enough

functionality to test the rest of the code before devoting a lot of time to the class.

A third advantage of separating interface from implementation is that we can write

multiple classes that implement the same interface and use them without rewriting

all the interface routines. This is one of the biggest advantages of object-oriented

design.

1.8 Key points 11

In the next chapter, we look at some of these concepts in the concrete case of a

pay-off class.

1.7 Why object-oriented programming?

This is a book about implementing pricing models using object-oriented C++ pro-

grams. The reader may ask why this is worth learning. A short answer is that this is

the skill you need if you want a job working as a quantitative analyst or quantitative

developer. But this begs the question of why this is the required skill.

Object-oriented programming has become popular as computer projects have be-

come larger and larger. A single project may now involve millions of lines of code.

No single programmer will ever be able to hold all of that code in his mind at once.

Object-oriented programming provides us with a way of coding that corresponds

to natural mental maps. We know what each class of objects does, and more impor-

tantly we tightly deļ¬ne how they can interact with each other. This allows a clear

map in the coderā™s mind of how the code ļ¬ts together. And equally importantly,

this allows easy communication of the codeā™s structure to other programmers in

the team.

When the coder needs to focus in on a particular part of the code, he need only

look at the interior of the particular object involved and its interface with other ob-

jects. As long as the interface is not broken, and the new object lives up to the same

responsibilities as the old one then there is no danger of unexpected ramiļ¬cations

(i.e. bugs) in distant parts of the code. Thus object-oriented programming leads to

more robust code that is easier for teams to work on.

1.8 Key points

In this chapter, we have looked at how to implement a simple Monte Carlo rou-

tine on a procedural program. We then criticized it from the point of view of easy

extensibility and reuse.

ā¢ Options can be priced by risk-neutral expectation.

ā¢ Monte Carlo uses the Law of Large Numbers to approximate this risk-neutral

expectation.

ā¢ Reuse is as much a social issue as a technical one.

ā¢ Procedural programs can be hard to extend and reuse.

ā¢ Classes allow us to encapsulate concepts which makes reuse and extensibility a

lot easier.

ā¢ Making classes closely model real-world concepts makes them easier to design

and to explain.

12 A simple Monte Carlo model

ā¢ Classes allow us to separate the design of the interface from the coding of the

implementation.

1.9 Exercises

Exercise 1.1 Modify the program given to price puts.

Exercise 1.2 Modify the program given to price double digitals.

Exercise 1.3 Change the program so that the user inputs a string which speciļ¬es

the option pay-off.

Exercise 1.4 Identify as many classes as you can in the evil bossā™s list of demands.

2

Encapsulation

2.1 Implementing the pay-off class

In the last chapter, we looked at a simple Monte Carlo pricer and concluded that

the program would be improved if we used a class to encapsulate the notion of the

pay-off of a vanilla option. In this section, we look at how such a pay-off might be

implemented. In the ļ¬les PayOff1.h and Payoff1.cpp, we develop such a class.

Before looking at the source ļ¬le, PayOff1.cpp, we examine the more important

header ļ¬le. The header ļ¬le is much more important because it is all that other ļ¬les

will see, and ideally it is all that the other ļ¬les need to see.

Listing 2.1 (PayOff1.h)

#ifndef PAYOFF_H

#define PAYOFF_H

class PayOff

{

public:

enum OptionType {call, put};

PayOff(double Strike_, OptionType TheOptionsType_);

double operator()(double Spot) const;

private:

double Strike;

OptionType TheOptionsType;

};

#endif

We use an enum to distinguish between different sorts of pay-offs. If we ever

want more than put and call, we would add them to the list. We will discuss

13

14 Encapsulation

more sophisticated approaches in Chapter 3 but this approach is enough to get us

started.

The constructor

PayOff(double Strike_, OptionType TheOptionsType_)

takes in the strike of the option and the type of the option pay-off.

The main method of the class is

double PayOff::operator()(double spot) const

The purpose of this method is that given a value of spot, it returns the value of the

pay-off.

Note the slightly odd syntax: we have overloaded operator(). To call this

method for an object thePayoff with spot given by S we would write

thePayoff(S). Thus when use the object it appears more like a function than

an object; such objects are often called function objects or functors. (Note that the

C++ concept of functor is quite different from the pure mathematical one.)

We have deļ¬ned operator() to be const. This means that the method does not

modify the state of the object. This is as we would expect: computing the pay-off

does not change the strike or the type of an option.

Suppose we did not specify that operator() was const; what would happen?

The same functionality would be provided and the code would still compile. How-

ever, if a pay-off object was declared const at some point by a user then the com-

piler would complain if we tried to call operator(), and give us a complicated

message to the effect that we cannot call non const methods of const objects.

Thus if we want a method to be usable in const objects we must declare the

method const.

An alternative approach, adopted by some programmers, is not to use const

anywhere. The argument goes along the lines of āIf we use const in some places,

we must use it everywhere, and all it does is cause trouble and stop me doing what

I want so why bother? Life will be much easier if we just do not use it.ā

Yet I use const as much as possible. The reason is that it is a safety enforce-

ment mechanism. Thinking about const forces me to consider the context of

an object and whether or not I wish it to change when doing certain things. If

I am woolly in my thinking then the compiler will generally squeal when I at-

tempt to compile, and thus errors are picked up at compile time instead of at run

time.

A second beneļ¬t is that by giving the compiler the extra information that objects

are const, we allow it to make extra optimizations. Code on a good compiler can

therefore run faster when const is used. Now we are ready for PayOff1.cpp.

2.2 Privacy 15

Listing 2.2 (PayOff1.cpp)

#include <PayOff1.h>

#include <MinMax.h>

PayOff::PayOff(double Strike_, OptionType TheOptionsType_)

:

Strike(Strike_), TheOptionsType(TheOptionsType_)

{

}

double PayOff::operator ()(double spot) const

{

switch (TheOptionsType)

{

case call :

return max(spot-Strike,0.0);

case put:

return max(Strike-spot,0.0);

default:

throw("unknown option type found.");

}

}

2.2 Privacy

We have declared the data in the pay-off class to be private. This means that the

data cannot be accessed by code outside the class. The only code that can see, let

alone change, their values are the constructor and the method operator(). What

does this buy us? After all, for some reason the user might want to know the strike

of an option and we have denied him the possibility of ļ¬nding it out.

The reason is that as soon we let the user access the data directly, it is much

harder for us to change how the class works. We can think of the class as a contract

between coder and user. We, the coder, have provided the user with an interface:

if he gives us spot we will give him the value of the pay-off. This is all we have

contracted to provide. The user therefore expects and receives precisely that and

no more.

For example, if the user could see the strike directly and accessed it, and if we

changed the class so that the strike was no longer stored directly (which we shall

16 Encapsulation

do in the next chapter), then we would get compile errors from everywhere the

strike was accessed. If the class had been used a lot in many ļ¬les, in many different

projects (which is after all the objective of reuse), then to ļ¬nd every place where

strike had been accessed would be a daunting task. In fact, if this were the case

we would probably consider ļ¬nding them all a considerable waste of time, and we

would probably give up reforming the internal workings.

Thus by making the data private, we can enforce the contract between coder

and user in such a way that the contract does not say anything about the inte-

rior workings of the class. If for some reason, we wanted the user to be able

to know the strike of the pay-off then we could add in an extra method double

GetStrike() const. Whilst this would seem to undo all the beneļ¬ts of using pri-

vate data, this is not so since it still allows us the possibility of storing the data in a

totally different way.

To conclude, by using private data we can rework the interior workings of a class

as and when we need to without worrying about the impact on other code. That is,

private data helps us to separate interface and implementation.

2.3 Using the pay-off class

Having designed a pay-off class, we want to use it in our Monte Carlo routines. We

do this in the function SimpleMonteCarlo2 which is declared in SimpleMC.h

and deļ¬ned in SimpleMC.cpp.

Listing 2.3 (SimpleMC.h)

#ifndef SIMPLEMC_H

#define SIMPLEMC_H

#include <PayOff1.h>

double SimpleMonteCarlo2(const PayOff& thePayOff,

double Expiry,

double Spot,

double Vol,

double r,

unsigned long NumberOfPaths);

#endif

Listing 2.4 (SimpleMC.cpp)

#include <SimpleMC.h>

#include <Random1.h>

#include <cmath>

2.3 Using the pay-off class 17

// the basic math functions should be in

// namespace std but arenā™t in VCPP6

#if !defined(_MSC_VER)

using namespace std;

#endif

double SimpleMonteCarlo2(const PayOff& thePayOff,

double Expiry,

double Spot,

double Vol,

double r,

unsigned long NumberOfPaths)

{

double variance = Vol*Vol*Expiry;

double rootVariance = sqrt(variance);

double itoCorrection = -0.5*variance;

double movedSpot = Spot*exp(r*Expiry +itoCorrection);

double thisSpot;

double runningSum=0;

for (unsigned long i=0; i < NumberOfPaths; i++)

{

double thisGaussian = GetOneGaussianByBoxMuller();

thisSpot = movedSpot*exp( rootVariance*thisGaussian);

double thisPayOff = thePayOff(thisSpot);

runningSum += thisPayOff;

}

double mean = runningSum / NumberOfPaths;

mean *= exp(-r*Expiry);

return mean;

}

The main change from our original Monte Carlo routine is that we now input a

PayOff object instead of a strike. The strike is, of course, now hidden inside the

inputted object. We pass the object by reference and make it const as we have no

need to change it inside our routine. Note that the only line of our algorithm that is

new is

double thisPayOff = thePayOff(thisSpot);

18 Encapsulation

We illustrate how the routine might be called in SimpleMCMain2.cpp. Here we

deļ¬ne both call and put objects and this shows that the routine can now be used

without change to prices both types of options.

Listing 2.5 (SimpleMCMain2.cpp)

/*

requires

PayOff1.cpp

Random1.cpp,

SimpleMC.cpp,

*/

#include<SimpleMC.h>

#include<iostream>

using namespace std;

int main()

{

double Expiry;

double Strike;

double Spot;

double Vol;

double r;

unsigned long NumberOfPaths;

cout << "\nEnter expiry\n";

cin >> Expiry;

cout << "\nEnter strike\n";

cin >> Strike;

cout << "\nEnter spot\n";

cin >> Spot;

cout << "\nEnter vol\n";

cin >> Vol;

cout << "\nr\n";

cin >> r;

2.4 Further extensibility defects 19

cout << "\nNumber of paths\n";

cin >> NumberOfPaths;

PayOff callPayOff(Strike, PayOff::call);

PayOff putPayOff(Strike, PayOff::put);

double resultCall = SimpleMonteCarlo2(callPayOff,

Expiry,

Spot,

Vol,

r,

NumberOfPaths);

double resultPut = SimpleMonteCarlo2(putPayOff,

Expiry,

Spot,

Vol,

r,

NumberOfPaths);

cout <<"the prices are " << resultCall

<< " for the call and "

<< resultPut

<< " for the put\n";

double tmp;

cin >> tmp;

return 0;

}

2.4 Further extensibility defects

We have now set-up a pay-off class. One of our original objectives was to be able

to extend the code easily without needing to rewrite other code when we add new

pay-offs. Have we achieved this? Yes.

Suppose we now want to add in the digital call pay-off. What do we need to do?

We add in an extra type, digitalcall, in the enum. We also change the switch

statement in the operator() to include the extra case of a digital call and in that

case return 1 if spot is above strike and 0 otherwise.

20 Encapsulation

Everywhere the PayOff class has been used, in our case the Monte Carlo routine

but possibly in many places, the digital call is now available just by passing in a

PayOff object in an appropriate state.

Do this change for yourself and hit ā˜buildā™. One slightly non-obvious effect is

that all the ļ¬les which involve pay-offs are now recompiled. So although there is

no obvious difference in those ļ¬les, we see something slightly unexpected: as they

include the ļ¬le PayOff1.h, and it has changed, they must be recompiled too.

This is a warning sign that the code is not as independent as we would like. In an

extreme case, we might not have access to source code for purchased libraries; any

programming model that required us to recompile those libraries would be useless

to us. In addition even if we could recompile, it might be a time-consuming process

which we would prefer to avoid.

We would therefore like a way of programming that allows us not just to add

functionality without modifying dependent ļ¬les, but also to be able to do so without

having to recompile existing ļ¬les.

In fact, any solution that allowed us to do so would have to allow us to add an

extra sort of pay-off without changing the pay-off class that the ļ¬les using pay-offs

see. For if the part that they see changes in any way, the compiler will insist on

recompiling them even if the changes do not appear to be material.

2.5 The openā“closed principle

The previous sectionā™s discussion leads naturally to a programming idea known as

the open-closed principle. The ā˜openā™ refers to the idea that code should always

be open for extension. So in this particular case, we should always be able to add

extra pay-offs.

The ā˜closedā™ means that the ļ¬le is ā˜closed for modiļ¬cationā™. This refers to the

idea that we should be able to do the extension without modifying any existing

code, and we should be able to do so without even changing anything in any of the

existing ļ¬les.

This may seem a little counterintuitive; how can one possibly make new

forms of pay-offs without changing the pay-off class? To illustrate the idea be-

fore presenting the C++ solution, we consider how we might do this using C style

techniques.

Suppose instead of making the class contain an enum that deļ¬nes the option type,

we instead use a function pointer. Thus we replace OptionType with

double (*FunctionPtr)(double,double).

The constructor for the pay-off would then take in the strike and a function

pointer. It would store both and when operator() was called it would dereference

2.6 Key points 21

the pointer and call the function pointed to with spot and strike as its argu-

ments.

This code achieves a lot of our objectives. We can put the function pointed to in

a new ļ¬le, so the existing ļ¬le for the pay-off class does not change each time we

add a new form of pay-off. This means that neither the pay-off ļ¬le nor the Monte

Carlo ļ¬le which includes the header ļ¬le for pay-off need to be recompiled let alone

changed.

However, there is still a ļ¬‚y in the ointment. What do we do when the boss comes

by and demands a double-digital pay-off? The double digital requires two strikes

(or barrier levels) and we only have one slot, the strike. Now this was also a problem

with our original pay-off class; it too had only one slot for the strike.

One solution would be to use an array to specify and store parameters. The strike

would be replaced by an array in both constructor and class members. The function

pointer would take the array and spot as it arguments. This could be made to work.

However, the code is now starting to lose the properties of clarity and elegance

which were a large part of our original objectives.

So although the function pointer gets us a long way it does not get us far enough

and we need a more sophisticated approach. The issue is that we need a way of

specifying an object for the pay-off which is not of a predetermined type. This

object will contain all the data it needs know and no more. So for a vanilla call or

put the object would contain the strike, but for a double digital it would contain

both of the two barrier levels.

Fortunately, C++ was designed with just this sort of problem in mind, and in

the next chapter we shall study how to use inheritance and virtual functions to

overcome these problems. We have used the openā“closed principle as a way of

motivating the introduction of these concepts, and we shall repeatedly return to it

as a paradigm for evaluating programming approaches.

2.6 Key points

In this chapter, we looked at one way of using a class to encapsulate the notion of

a pay-off. We then saw some of the advantages of using such a class. We also saw

that the class had not achieved all of our objectives.

ā¢ Using a pay-off class allows us to add extra forms of pay-offs without modifying

our Monte Carlo routine.

ā¢ By overloading operator() we can make an object look like a function.

ā¢ const enforces extra discipline by forcing the coder to be aware of which code

is allowed to change things and which code cannot.

ā¢ const code can run faster.

22 Encapsulation

ā¢ The open-closed principle says that code should be open for extension but closed

for modiļ¬cation.

ā¢ Private data helps us to separate interface from implementation.

2.7 Exercises

Exercise 2.1 Modify the pay-off class so that it can handle digital options.

Exercise 2.2 Modify the pay-off class so that it can handle double-digital options.

Exercise 2.3 Test whether on your compiler using const speeds code up.

3

Inheritance and virtual functions

3.1 ā˜is aā™

We reconsider our PayOff class. At the end of the last chapter, we concluded

that we would like to be able to use differing sorts of objects as pay-offs without

changing any of the code that takes in pay-off objects. In other words, we would

like to be able to say that a call option pay-off ā˜is aā™ pay-off, and express this idea

in code.

The mechanism for expressing the ā˜is aā™ relationship in C++ is inheritance.

There are plenty of examples we have already seen where such ā˜is aā™ relationships

are natural. For example, a call option is a vanilla option. The compilerā™s built-in

random number generator is a random number generator. Boxā“Muller is a method

of turning uniform random variables into Gaussian random variables. An Asian

option is a path-dependent exotic option. An arithmetic Asian call option is an

Asian option, as is a geometric Asian put option. Returning the mean is a way

of gathering statistics for a Monte Carlo simulation. Specifying the continuously

compounding rate is a way to specify the discount curve. The BlackScholes model

is a model of stock price evolution.

Thus ā˜is aā™ relationships are very natural in mathematical ļ¬nance (as well as in

coding and life in general.) We shall use inheritance to express such relationships.

We shall refer to the class we inherit from as the base class and the class which

does the inheriting will be called the inherited class. The base class will always

express a more general concept than the inherited class.

Note that there is nothing to stop us inheriting several times. For example,

our base might be PathDependentExoticOption. An inherited class might

be AsianOption. We might then further inherit AsianPutOption and

AsianCallOption from AsianOption.

The key point is that each inherited class reļ¬nes the class above it in the hierar-

chy to something more speciļ¬c.

23

24 Inheritance and virtual functions

3.2 Coding inheritance

To indicate that a class, PayOffCall, is inherited from a class PayOff, we use the

key word public. Thus when declaring the inherited class, we write

class PayOffCall : public PayOff

What effect does this have? PayOffCall inherits all the data members and meth-

ods of PayOff. And most importantly, the compiler will accept a PayOffCall

object wherever it expects a PayOff object. Thus we can write all our code to

work off PayOff objects but then use inherited class objects to specify the precise

properties. (There are some issues, however; see Section 3.4.)

We can also add data members and methods at will. The rules of public in-

heritance say that we can access protected data and methods of the base class

inside the methods of the inherited class but we cannot access the private data. It

is generally recommended to use private data for this reason; if we did otherwise

then any changes in the design of the base class might require that any inherited

classes be rewritten and at the very least all inherited classes would have to be

checked. By using private data, we encapsulate what the base class does, and

allow ourselves to reimplement it in future. It is, however, safe to use protected

methods, as these, similarly to public methods, deļ¬ne part of the objectā™s in-

terface. As long as the implicit (or ideally explicit) contract which expresses the

methodā™s functionality does not change, it does not matter what interior changes are

made.

3.3 Virtual functions

Returning to our example of the PayOff class, we redeļ¬ne the class to work using

inheritance. Our base class is still called PayOff but whereas previously it did a

lot, it now does almost nothing. In fact, it does one thing; it speciļ¬es an interface.

We give the code in PayOff2.h and PayOff2.cpp.

Listing 3.1 (PayOff2.h)

#ifndef PAYOFF2_H

#define PAYOFF2_H

class PayOff

{

public:

PayOff(){};

virtual double operator()(double Spot) const=0;

virtual ˜PayOff(){}

private:

3.3 Virtual functions 25

};

class PayOffCall : public PayOff

{

public:

PayOffCall(double Strike_);

virtual double operator()(double Spot) const;

virtual ˜PayOffCall(){}

private:

double Strike;

};

class PayOffPut : public PayOff

{

public:

PayOffPut(double Strike_);

virtual double operator()(double Spot) const;

virtual ˜PayOffPut(){}

private:

double Strike;

};

#endif

Listing 3.2 (PayOff2.cpp)

#include <PayOff2.h>

#include <minmax.h>

PayOffCall::PayOffCall(double Strike_) : Strike(Strike_)

{

}

double PayOffCall::operator () (double Spot) const

{

return max(Spot-Strike,0.0);

}

double PayOffPut::operator () (double Spot) const

{

return max(Strike-Spot,0.0);

}

26 Inheritance and virtual functions

PayOffPut::PayOffPut(double Strike_) : Strike(Strike_)

{

}

The main changes to the pay-off class are that we have added the keyword

virtual to operator() and we placed an =0, at the end of operator(). We

have added in a destructor which is also virtual. We have also abolished all the

data from both the constructor and the class deļ¬nition.

We also have two new classes PayOffCall and PayOffPut. Each of these have

been inherited from the class PayOff. These classes will now do all the work. The

call pay-off ā˜is aā™ pay-off, and we will use PayOffCall instead of the pay-off class

where we need a call pay-off. Similarly for the put pay-off.

The crucial point is that the main method, operator() is now virtual. What

is a virtual function? In technical terms, it is a function whose address is bound

at runtime instead of at compile time. What does that mean? In the code, where a

PayOff object has been speciļ¬ed, for example in our simple Monte Carlo routine,

the code when running will encounter an object of a class that has been inherited

from PayOff. It will then decide what function to call on the basis of what type

that object is. So if the object is of type PayOffCall, it calls the operator()

method of PayOffCall, and if it is of type PayOffPut, it uses the method from

ńņš. 1 |