<<

. 2
( 9)



>>

the PayOffPut class and so on.
It™s worth understanding how the compiler implements this. Rather than saying,
“hmm, what type is this object? Ah, it™s a call so I™ll use the call pay-off function,”
it adds extra data to each object of the class which speci¬es what function to use. In
fact, essentially what it stores is a function pointer. So virtual functions are really a
fancy way of using function pointers. Indeed, if you run a program involving virtual
function pointers through a debugger, and examine through the watch window an
object from a class with virtual functions, you will ¬nd an extra data member,
the virtual function table. This virtual function table is a list of addresses to be
called for the virtual functions associated with the class. So if when running a
program, a virtual function is encountered, the table is looked up and execution
jumps into the function pointed to. Note that this operation takes a small amount of
time so ef¬ciency fanatics dislike virtual functions as they cause a small decrease in
execution speed. Note also that the amount of memory per object has also increased
1
as the object now contains a lot of extra data.


1
It is a curious fact that the C++ standard says nothing about how virtual functions are implemented so the
effects are compiler dependent: However, modern compilers typically store one copy of the virtual table for
each class, and each object contains a pointer to the relevant table.
3.3 Virtual functions 27

If virtual functions are just function pointers, why bother with them? The ¬rst
reason is that they are syntactically a lot simpler. The structure of our program is
much clearer: if we can say this is a pay-off call object and this is a pay-off put
object rather than having to say that we have a pay-off object but it contains a
pointer to a function de¬ning a call pay-off, we have a gain in clarity.
A second and important reason is that we get extra functionality. Depending
on the complexity of the pay-off we may need extra data which cannot be ex-
pressed by a single number. With inheritance, we simply require the inherited class
to contain all the data necessary. Thus for a double-digital pay-off we simply have
two doubles expressing the upper and lower barriers. For a power option, we
have a double for the strike and an unsigned long for the power. We could
even have some complicated object stored as an extra argument. Indeed, if we
wanted to do a complicated pay-off as a linear combination of call options, the ex-
tra data could be further call options whose pay-offs would be evaluated inside the
operator() method and added together.
As well as being a virtual function, the operator() method has an =0 after
it. This means that it is a pure virtual function. A pure virtual function has the
property that it need not be de¬ned in the base class and must be de¬ned in an
inherited class. Thus by putting =0 we are saying that the class is incomplete, and
that certain aspects of its interface must be programmed in an inherited class.
In SimpleMCMain3.cpp we give an example of how to use the new pay-off
class. Note that it uses SimpleMC2.h which only differs from SimpleMC.h in the
replacement of PayOff.h with PayOff2.h. So we omit it.

Listing 3.3 (SimpleMCMain3.cpp)

/*
requires
PayOff2.cpp
Random1.cpp
SimpleMC2.cpp
*/
#include<SimpleMC2.h>
#include<iostream>
using namespace std;

int main()
{
double Expiry;
double Strike;
double Spot;
28 Inheritance and virtual functions

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;

cout << "\nNumber of paths\n";
cin >> NumberOfPaths;

PayOffCall callPayOff(Strike);
PayOffPut putPayOff(Strike);

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 "
3.4 Why we must pass the inherited object by reference 29

<< resultPut <<
" for the put\n";

double tmp;
cin >> tmp;

return 0;
}



3.4 Why we must pass the inherited object by reference
In our Monte Carlo routine, we have a parameter of type const PayOff& called
thePayOff. This means that the parameter is being passed by reference rather
than by value. The routine therefore works off the original object passed in. If we
had not used the ˜&™ it would copy the object: it would be passed by value not by
reference. Suppose we change the parameter to type PayOff with or without the
const, what happens? The code will not compile.
Why not? When the argument Payoff is encountered, the compiler refuses to
create an object of type PayOff because it has a pure virtual method. The method
operator() has not been de¬ned, and the rules of C++ say that you cannot create
an object of a type with a pure virtual method.
How could we get round this? Suppose we decide to make operator() an
ordinary virtual function by de¬ning it. For example, we could just make it return
0 and still override in the inherited clases as before. The code with the ˜&™ would
compile and run as before, giving the same results. The code without the ˜&™ would
now compile and run. However, the price of every option would be zero, which is
certainly not what we want.
This happens because when the compiler encounters the argument of type
PayOff, the input parameter is copied into a variable of type PayOff. This
occurs because the compiler will call the copy constructor of PayOff. Like all copy
constructors, it takes in an object of type const PayOff&. As the compiler happily
accepts references to inherited objects instead of references to base-class objects
this is legal and the compiler does not complain. However, the copy constructor
of PayOff is not interested in all the extra data and information contained in the
inherited object: it just looks down the data coming from the base class and copies
it into the new object. As the new object is truly a base class object rather than an
inherited class object pretending to be a base class object, its virtual functions will
be those of the base class.
This all means that the new variable has the size and data of a PayOff object
regardless of the type of the inputted object. The compiler therefore truncates all
30 Inheritance and virtual functions

the additional data members which have been added, and the virtual function table
is that of the base class object not the inherited class. In fact, disastrous things
would occur if the new object inherited the virtual function table of the inherited
object, as the virtual methods would try to access non-existent data members with
possibly dangerous consequences.
Making the base class method concrete instead of pure virtual was therefore a
mistake, and, in fact, the compiler™s rejection of the argument without the ˜&™ was
saving us from a dangerous error.
It™s worth thinking a little about what actually happens when the object is passed
by reference. All that happens is that the function is passed the address of the
object in memory, no copying occurs and the object™s state is precisely as it was
outside. However, if the object™s state does change inside the routine it will also
change outside which may not be what we want. We therefore include the const
to indicate that the routine cannot do anything which may change the state of the
object. The function can ˜look but not touch.™


3.5 Not knowing the type and virtual destruction
Generally, one cannot pass an object of one type where another type is expected; a
big feature of C++ is that it enforces type security. This means that the compiler
picks up many errors at compile time instead of at run time. We cannot even run
our program until we have made sure that all objects are of the types expected. This
reduces the number of bugs that need to be found while the program is running by
enforcing some discipline.
However, the rules of inheritance say that we can always pass a reference to
an object of an inherited class instead of a reference to a base class object. This
means that at times we do not know the type of object. For example, inside the
Monte Carlo routine, SimpleMC2, we appear to be using a base class object not an
inherited one.
There are two ways to forget the type of the object. The ¬rst, which we have
already used, is to refer to it via a reference to the base class type instead of the
inherited class type. The second, related, method is via a pointer.
If we have a pointer to an inherited object we can always cast it into a base
class object without any trouble. We give an example of this in SimpleMC-
Main4.cpp.

Listing 3.4 (SimpleMCMain4.cpp)
/*
requires
PayOff2.cpp
3.5 Not knowing the type and virtual destruction 31

Random1.cpp
SimpleMC2.cpp
*/
#include<SimpleMC2.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;

cout << "\nNumber of paths\n";
cin >> NumberOfPaths;

unsigned long optionType;

cout << "\nenter 0 for call, otherwise put ";
cin >> optionType;

PayOff* thePayOffPtr;
32 Inheritance and virtual functions

if (optionType== 0)
thePayOffPtr = new PayOffCall(Strike);
else
thePayOffPtr = new PayOffPut(Strike);

double result = SimpleMonteCarlo2(*thePayOffPtr,
Expiry,
Spot,
Vol,
r,
NumberOfPaths);

cout <<"\nthe price is " << result << "\n";
double tmp;
cin >> tmp;

delete thePayOffPtr;

return 0;
}

The user of our unsophisticated interface enters a zero for a call option and a non-
zero number for a put option. We use an if statement to create the pay-off object.
Note the important point here is that we use new. Whilst we would like to simply
write

if (optionType== 0)
PayOffCall thePayOff(Strike);
else
PayOffPut thePayOff(Strike);

this will not give us what we want. The reason is that whilst the object
thePayOff will happily be created, it will be an automatic variable, which is one
that automatically disappears whenever the scope is left. In this case, the scope is
the dependent clause of the if statement, so as soon we leave the if statement
the object no longer exists and any attempts to reference thePayOff will result
in compiler errors.
On the other hand, when we use new we are instructing the compiler that we
wish to take some memory whilst the code is running, and that memory should not
be released until we explicitly say so. The object created will therefore continue to
exist outside the if statement as desired. The operator new ¬nds enough memory
3.5 Not knowing the type and virtual destruction 33

to put the object into and calls the constructor, placing the object at the memory
that has been allocated. It returns a pointer to the object created.
Thus the code new PayOffCall(Strike) creates the PayOffCall object and
it returns a pointer to the object so we can access it. The returned pointer will
be of type PayOffCall*. Fortunately, we can always cast a pointer from an in-
herited class pointer into a base class pointer. We therefore assign payOffPtr
to the result of new and we have the desired result. Note that we declare
payOffPtr outside the if to ensure that it persists after the if statement is com-
plete.
When we reach the call to the Monte Carlo routine, we can now pass in either a
call or a put, depending on what the pointer points to. We dereference the pointer
in order to pass in the object rather than the pointer by putting *payOffPtr.
The ¬nal thing we must do is get rid of the object. By using new, we told the
compiler that it must not destroy the object nor deallocate the memory until we
say so. If we never tell it to do so then the memory will never be freed up, and
our memory will slowly leak away until program crashes. The way we instruct the
compiler to destroy the object and deallocate the memory is to use the operator
delete. When we call delete, it ¬rst calls the destructor of the object. At this
point we must be careful: we have a pointer to a base object, so which destructor
will it call? If the destructor is not virtual then it will call the base class destruc-
tor. If the object is of an inherited class this may cause problems as the object will
not be destroyed properly. For example, if the inherited class object had an array as
a data member then the memory allocated for that array will never be deallocated.
In our case, the base class is abstract and there cannot be any objects of its type.
This means that calling the base class destructor must be an error. For this reason,
we declare the destructor virtual. The compiler then uses the virtual function
table to correctly decide which destructor to call. In fact, many compilers issue
a warning if you declare a method pure virtual and do not declare the destructor
virtual.
In fact, when calling and executing the destructor of an inherited class, the com-
piler always calls the base class destructor; this ensures that all the data members
of the object which arise from the base class are correctly destroyed.
In this section, we looked at one case where we did not know the type of an
object and this caused us a little trouble, but it was also very useful. By treating
the inherited class object as a base class object, we were able to make the same
code work regardless of the precise type of the object. The important fact was that
whatever the type of the object, it had to implement all the methods de¬ned in the
base class and this was enough to ensure that the code ran smoothly. One way of
summarizing this situation is to say that the inherited class implements the interface
de¬ned by the base class.
34 Inheritance and virtual functions

In the next chapter, we will look at some additional problems caused by not
knowing types, such as the problem of copying an object of unknown type, and
examine their solutions.


3.6 Adding extra pay-offs without changing ¬les
One of our objectives when rewriting the PayOff class was to create a class that
could be extended without changing any of the existing code. In addition, we
wished to be able to add extra pay-offs without having to recompile either the
¬le containing the PayOff class or any ¬les which included the ¬le de¬ning the
PayOff class. In this section, we see how to do this with our class de¬nition.
Suppose the new pay-off we wish to add is the double digital pay-off. This pay-
off pays 1 if spot is between two values and 0 otherwise. We de¬ne the new pay-off
class in a new ¬le, DoubleDigital.h with the associated code in
DoubleDigital.cpp.

Listing 3.5 (DoubleDigital.h)
#ifndef DOUBLEDIGITAL_H
#define DOUBLEDIGITAL_H
#include <Payoff2.h>

class PayOffDoubleDigital : public PayOff
{
public:
PayOffDoubleDigital(double LowerLevel_,
double UpperLevel_);

virtual double operator()(double Spot) const;
virtual ˜PayOffDoubleDigital(){}

private:
double LowerLevel;
double UpperLevel;
};
#endif
and the source code is

Listing 3.6 (DoubleDigital.cpp)
#include <DoubleDigital.h>
3.6 Adding extra pay-offs without changing ¬les 35

PayOffDoubleDigital::PayOffDoubleDigital(double LowerLevel_,
double UpperLevel_)
: LowerLevel(LowerLevel_),
UpperLevel(UpperLevel_)
{
}

double PayOffDoubleDigital::operator()(double Spot) const
{
if (Spot <= LowerLevel)
return 0;
if (Spot >= UpperLevel)
return 0;

return 1;
}

The crucial point is that whilst we must include the ¬le DoubleDigital.h in
our interface we do not include it in either the Monte Carlo ¬le, SimpleMC2, or
the pay-off ¬le, PayOff2. The changes to the interface ¬le are minimal and we
have

Listing 3.7 (SimpleMCMain5.cpp)

/*
requires DoubleDigital.cpp
PayOff2.cpp
Random1.cpp
SimpleMC2.cpp
*/
#include<SimpleMC2.h>
#include<DoubleDigital.h>
#include<iostream>
using namespace std;

int main()
{
double Expiry;
double Low,Up;
double Spot;
36 Inheritance and virtual functions

double Vol;
double r;
unsigned long NumberOfPaths;

cout << "\nEnter expiry\n";
cin >> Expiry;

cout << "\nEnter low barrier\n";
cin >> Low;

cout << "\nEnter up barrier\n";
cin >> Up;

cout << "\nEnter spot\n";
cin >> Spot;

cout << "\nEnter vol\n";
cin >> Vol;

cout << "\nr\n";
cin >> r;

cout << "\nNumber of paths\n";
cin >> NumberOfPaths;

PayOffDoubleDigital thePayOff(Low,Up);

double result = SimpleMonteCarlo2(thePayOff,
Expiry,
Spot,
Vol,
r,
NumberOfPaths);

cout <<"\nthe price is " << result << "\n";
double tmp;
cin >> tmp;

return 0;
}
3.8 Exercises 37

Thus adding the new pay-off only required recompilation of one ¬le rather than
many and this achieves one objective: the PayOff class is open for extension but
closed for modi¬cation. In particular, we could have added the new pay-off even if
we did not have access to the source code of the PayOff class.
What we would really like is to be able to add new pay-offs without changing
any ¬les. That is we would like to be able to add new pay-offs without changing the
interfacing ¬le. In the interface, the user would simply type the name of the pay-
off and this would be translated into the relevant pay-off. Rather surprisingly it is
possible to do this. The solution is to use a design known as the Factory pattern.
We shall discuss how to do this in Chapter 10.


3.7 Key points
In this chapter, we looked at how inheritance could be used to implement a
PayOff class that is closed for modi¬cation but open for extension.
• Inheritance expresses ˜is a™ relationships.
• A virtual function is bound at run time instead of at compile time.
• We cannot have objects from classes with pure virtual functions.
• We have to pass inherited class objects by reference if we do not wish to change
the virtual functions.
• Virtual functions are implemented via a table of function pointers.
• If a class has a pure virtual functions then it should have a virtual destructor.


3.8 Exercises
Exercise 3.1 Write an inherited class that does power options, and use it to price
some.

Exercise 3.2 Implement an interface in which the user inputs a string and this is
turned into a pay-off class.

Exercise 3.3 In the evil boss™s list of demands in Chapter 1, try to identify as many
inheritance relationships as possible.
4

Bridging with a virtual constructor




4.1 The problem
We have written a simple Monte Carlo program which uses a polymorphic class
PayOff to determine the pay-off of the vanilla option to be priced. If we think about
the real-world objects we wish to model, a very natural object is the option itself.
At the moment, we have two pieces of data, the expiry and the pay-off, it would be
much more natural to have a single piece of data, the option, which encompassed
both.
How would we do this? One simple solution is simply to copy all the pay-off
code we have written, add an extra data member, Expiry, to the base class and
an extra method, GetExpiry, to the base class and be done. However, this rather
spoils the paradigm of code reuse “ we would like to reuse the same code rather
than cut and paste it. In addition, if we do this for each new class of options, then it
will be very time consuming to add new types of pay-offs as we will have to write
a new inherited class for each option type.
A preferable solution would be to de¬ne a Vanilla Option class which has as data
members a PayOff object and a double to represent expiry. However, if we try this
we immediately hit a snag; the class PayOff is abstract. The compiler will squeal
if we attempt to have a data member for our class of type PayOff, as you cannot
instantiate an object from an abstract class. The issues we encounter here are very
similar to those of Section 3.4. As there, making the PayOff class non-abstract
by de¬ning operator() in the base class causes more trouble than it solves. Any
attempt to make the data member equal to an inherited class member will simply
result in the object being copied and truncated into a base class object which is not
what we want.
What we want is for the Vanilla Option object to be able to contain an object
from an unknown class. Note that as the size of the unknown class object will not
be constant, we will not be able to put it directly in the Vanilla Option object as
this would lead to Vanilla Option objects being of variable size. This is something

38
4.2 A ¬rst solution 39

that is not allowed in C++. However, it is possible to refer to extra data outside
the object using pointers or references. This is after all what an array, or a list, or a
string, does.
One solution is therefore to store a reference to a pay-off object instead of a
pay-off object.


4.2 A ¬rst solution
In this section, we implement a Vanilla Option class using a reference to a pay-off
object and then discuss what™s wrong with it.

Listing 4.1 (Vanilla1.h)
#ifndef VANILLA_1_H
#define VANILLA_1_H

#include <PayOff2.h>

class VanillaOption
{
public:
VanillaOption(PayOff& ThePayOff_, double Expiry_);
double GetExpiry() const;
double OptionPayOff(double Spot) const;

private:
double Expiry;
PayOff& ThePayOff;
};
#endif
The source ¬le is

Listing 4.2 (Vanilla1.cpp)
#include <Vanilla1.h>

VanillaOption::VanillaOption(PayOff&ThePayOff_,
double Expiry_)
: ThePayOff(ThePayOff_), Expiry(Expiry_)
{
}
40 Bridging with a virtual constructor

double VanillaOption::GetExpiry() const
{
return Expiry;
}

double VanillaOption::OptionPayOff(double Spot) const
{
return ThePayOff(Spot);
}
This is all very straightforward. The only subtlety is that the class member data is
of type PayOff& instead of PayOff. However, we can use a reference to a pay-off
object in precisely the same way as a pay-off object so this causes no extra coding.
Our class provides two methods, one giving the expiry of the option and the other
stating the pay-off at expiry given spot.
We can now rewrite the Monte Carlo routine to use the VanillaOption class.
We thus have

Listing 4.3 (SimpleMC3.h)

#ifndef SIMPLEMC3_H
#define SIMPLEMC3_H
#include <Vanilla1.h>

double SimpleMonteCarlo3(const VanillaOption& TheOption,
double Spot,
double Vol,
double r,
unsigned long NumberOfPaths);
#endif
and

Listing 4.4 (SimpleMC3.cpp)
#include<SimpleMC3.h>
#include <Random1.h>
#include <cmath>
// the basic math functions should be in namespace
// std but aren™t in VCPP6
#if !defined(_MSC_VER)
using namespace std;
#endif
4.2 A ¬rst solution 41

double SimpleMonteCarlo3(const VanillaOption& TheOption,
double Spot,
double Vol,
double r,
unsigned long NumberOfPaths)
{
double Expiry = TheOption.GetExpiry();

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 = TheOption.OptionPayOff(thisSpot);
runningSum += thisPayOff;
}

double mean = runningSum / NumberOfPaths;
mean *= exp(-r*Expiry);
return mean;
}
/*
Our new routine is very similar to the old one, the difference being that we pass in
an option object instead of pay-off and an expiry separately. We obtain the expiry
from the option via GetExpiry().
Our main routine is then

Listing 4.5 (VanillaMain1.cpp)
/*
requires DoubleDigital.cpp
PayOff2.cpp
Random1.cpp
SimpleMC3.cpp
42 Bridging with a virtual constructor

Vanilla1.cpp
*/

#include<SimpleMC3.h>
#include<DoubleDigital.h>
#include<iostream>
using namespace std;
#include<Vanilla1.h>

int main()
{
double Expiry;
double Low,Up;
double Spot;
double Vol;
double r;
unsigned long NumberOfPaths;

cout << "\nEnter expiry\n";
cin >> Expiry;

cout << "\nEnter low barrier\n";
cin >> Low;

cout << "\nEnter up barrier\n";
cin >> Up;

cout << "\nEnter spot\n";
cin >> Spot;

cout << "\nEnter vol\n";
cin >> Vol;

cout << "\nr\n";
cin >> r;

cout << "\nNumber of paths\n";
cin >> NumberOfPaths;

PayOffDoubleDigital thePayOff(Low,Up);
4.3 Virtual construction 43

VanillaOption theOption(thePayOff, Expiry);

double result = SimpleMonteCarlo3(theOption,
Spot,
Vol,
r,
NumberOfPaths);

cout <<"\nthe price is " << result << "\n";
double tmp;
cin >> tmp;

return 0;
}
The main change is that now we ¬rst pass a PayOff object and the expiry time into
a VanillaOption object and that is then passed into the Monte Carlo.
This program will compile and run but I do not like it. Why not? The
VanillaOption class stores a reference to a PayOff object which was de¬ned
outside the class. This means that if we change that object then the pay-off of
the vanilla option will change. The vanilla option will not exist as independent
object in its own right but will instead always be dependent on the PayOff ob-
ject constructed outside the class. This is a recipe for trouble. The user of the
VanillaOption will not expect changes to the PayOff object to have such an
effect. In addition, if the PayOff object had been created using new as we did in
the last chapter then it might be deleted before the option ceased to exist which
would result in the vanilla option calling methods of a non-existent object which is
bound to cause crashes.
Similarly, if the option was created using new then it would likely exist long
after the PayOff object had ceased to exist, and we would get similarly dangerous
behaviour.


4.3 Virtual construction
What do we really want to do? We want the vanilla option to store its own copy
of the pay-off. However, we do not want the vanilla option to know the type of the
pay-off object nor anything about any of its inherited classes for all the reasons we
discussed in the last chapter. Our solution there was to use virtual functions: how
can we use them here? Well the object knows its own type so it can certainly make
a copy of itself. Thus we de¬ne a virtual method of the base class which causes the
object to create a copy of itself and return a pointer to the copy.
44 Bridging with a virtual constructor

Such a method is called a virtual copy constructor. The method is generally
given the name clone. Thus if we want the PayOff class to be virtually copyable,
we add a pure virtual method to the base class by
virtual PayOff* clone() const=0;
and de¬ne it in each inherited class. For example,
PayOff* PayOffCall::clone() const
{
return new PayOffCall(*this);
}

Note that the statement new PayOffCall(*this); says create a copy of the ob-
ject for which the clone method has been called, as the this pointer always points
to the object being called. The call to clone is then a call to the copy constructor
of PayOffCall which returns a copy of the original PayOffCall, and because
the operator new has been used, we can be sure that the object will continue to
exist.
Note that we have made the return type of clone PayOff* which is a pointer
to the base class object. Strictly speaking according to the standard, we should be
able to change the return type to PayOffCall*, as it is permissible according to the
standard to change the return type of a virtual function from a base class pointer to
a pointer to the inherited class. As inherited class pointers can always be converted
into base class pointers, this does not cause problems. However many compilers
will not compile this syntax, as this is an exception to the general rule that you
cannot override the return type of a virtual function.
We give the revised PayOff class in PayOff3.h. We now have

Listing 4.6 (PayOff3.h)
#ifndef PAYOFF3_H
#define PAYOFF3_H

class PayOff
{
public:
PayOff(){};

virtual double operator()(double Spot) const=0;
virtual ˜PayOff(){}
virtual PayOff* clone() const=0;
4.3 Virtual construction 45

private:
};

class PayOffCall : public PayOff
{
public:
PayOffCall(double Strike_);

virtual double operator()(double Spot) const;
virtual ˜PayOffCall(){}
virtual PayOff* clone() const;

private:
double Strike;
};

class PayOffPut : public PayOff
{
public:
PayOffPut(double Strike_);

virtual double operator()(double Spot) const;
virtual ˜PayOffPut(){}
virtual PayOff* clone() const;

private:
double Strike;
};
#endif

and PayOff3.cpp


Listing 4.7 (PayOff3.cpp)

#include <PayOff3.h>
#include <minmax.h>

PayOffCall::PayOffCall(double Strike_) : Strike(Strike_)
{
}
46 Bridging with a virtual constructor

double PayOffCall::operator () (double Spot) const
{
return max(Spot-Strike,0.0);
}

PayOff* PayOffCall::clone() const
{
return new PayOffCall(*this);
}

double PayOffPut::operator () (double Spot) const
{
return max(Strike-Spot,0.0);
}

PayOffPut::PayOffPut(double Strike_) : Strike(Strike_)
{
}

PayOff* PayOffPut::clone() const
{
return new PayOffPut(*this);
}

We similarly have to change the contents of DoubleDigital to re¬‚ect the extra
method in the base class. We do this in DoubleDigital2.h and in
DoubleDigital2.cpp, which we do not reproduce here.
Using PayOff3.h, we can now make copies of PayOff objects of unknown type
and reimplement the VanillaOption class accordingly.

Listing 4.8 (Vanilla2.h)

#ifndef VANILLA_2_H
#define VANILLA_2_H

#include <PayOff3.h>

class VanillaOption
{
public:
VanillaOption(const PayOff& ThePayOff_, double Expiry_);
4.3 Virtual construction 47

VanillaOption(const VanillaOption& original);
VanillaOption& operator=(const VanillaOption& original);
˜VanillaOption();

double GetExpiry() const;
double OptionPayOff(double Spot) const;

private:
double Expiry;
PayOff* ThePayOffPtr;
};
#endif

and the source ¬le is

Listing 4.9 (Vanilla2.cpp)

#include <Vanilla2.h>

VanillaOption::VanillaOption(const PayOff&
ThePayOff_, double Expiry_)
: Expiry(Expiry_)
{
ThePayOffPtr = ThePayOff_.clone();
}

double VanillaOption::GetExpiry() const
{
return Expiry;
}

double VanillaOption::OptionPayOff(double Spot) const
{
return (*ThePayOffPtr)(Spot);
}

VanillaOption::VanillaOption(const VanillaOption& original)
{
Expiry = original.Expiry;
ThePayOffPtr = original.ThePayOffPtr->clone();
}
48 Bridging with a virtual constructor

VanillaOption& VanillaOption::
operator=(const VanillaOption& original)
{
if (this != &original)
{
Expiry = original.Expiry;
delete ThePayOffPtr;
ThePayOffPtr = original.ThePayOffPtr->clone();
}
return *this;
}

VanillaOption::˜VanillaOption()
{
delete ThePayOffPtr;
}

We modify SimpleMC3 to get SimpleMC4 by changing the name of the include ¬le
to be Vanilla2.h and doing nothing else.

Listing 4.10 (SimpleMC4.h)

#ifndef SIMPLEMC4_H
#define SIMPLEMC4_H

#include <Vanilla2.h>

double SimpleMonteCarlo3(const VanillaOption& TheOption,
double Spot,
double Vol,
double r,
unsigned long NumberOfPaths);

#endif

Listing 4.11 (SimpleMC4.cpp)

#include <SimpleMC4.h>
#include <Random1.h>
#include <cmath>

// the basic math functions should be in namespace std
// but aren™t in VCPP6
4.3 Virtual construction 49

#if !defined(_MSC_VER)
using namespace std;
#endif
double SimpleMonteCarlo3(const VanillaOption& TheOption,
double Spot,
double Vol,
double r,
unsigned long NumberOfPaths)
{

double Expiry = TheOption.GetExpiry();

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 = TheOption.OptionPayOff(thisSpot);
runningSum += thisPayOff;
}

double mean = runningSum / NumberOfPaths;
mean *= exp(-r*Expiry);
return mean;
}
/*
Our main program is now VanillaMain2.cpp.

Listing 4.12 (VanillaMain2.cpp)
/*
requires PayOff3.cpp,
Random1.cpp,
SimpleMC4.cpp
Vanilla2.cpp
*/
50 Bridging with a virtual constructor

#include<SimpleMC4.h>
#include<iostream>
using namespace std;
#include<Vanilla2.h>

int main()
{
double Expiry;
double Strike;
double Spot;
double Vol;
double r;
unsigned long NumberOfPaths;

cout << "\nEnter expiry\n";
cin >> Expiry;

cout << "\nStrike\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;

PayOffCall thePayOff(Strike);

VanillaOption theOption(thePayOff, Expiry);

double result = SimpleMonteCarlo3(theOption,
Spot,
Vol,
r,
NumberOfPaths);
4.4 The rule of three 51

cout <<"\nthe call price is " << result << "\n";

VanillaOption secondOption(theOption);

result = SimpleMonteCarlo3(secondOption,
Spot,
Vol,
r,
NumberOfPaths);

cout <<"\nthe call price is " << result << "\n";

PayOffPut otherPayOff(Strike);
VanillaOption thirdOption(otherPayOff, Expiry);
theOption = thirdOption;

result = SimpleMonteCarlo3(theOption,
Spot,
Vol,
r,
NumberOfPaths);

cout <<"\nthe put price is " << result << "\n";

double tmp;
cin >> tmp;

return 0;
}
/*
The actual syntax in our main program has not changed much.


4.4 The rule of three
One difference between the VanillaOption class and all the classes we have pre-
viously de¬ned is that we have included an assignment operator (i.e. operator=)
and a copy constructor. The reason is that whilst the compiler by default generates
these methods, the compiler™s de¬nitions are inadequate.
If we do not declare the copy constructor then the compiler will perform a shal-
low copy as opposed to a deep copy. A shallow copy means that the data members
have simply been copied, whilst this is adequate when no memory allocation is
52 Bridging with a virtual constructor

required it will lead to disaster when it does. If we have shallow copied a Vanilla-
Option then both copies of the object have the same member ThePayOff-
Ptr, so any modi¬cations to the object we have pointed-to will have the same effect
in each copy. Whilst for our particular object this is not really an issue as we do not
want to change it, in a more complicated class this would certainly lead to trouble.
More seriously, when the one of the two VanillaOption objects goes out of
scope then its destructor will be called and the pointed-to PayOff object will be
deleted. The object remaining will now be in trouble as attempts to use its pointer
will lead to methods of a non-existent object being called. On top of which when
the remaining object goes out of scope, its destructor will be called and there will
be a second attempt to delete the pointed-to object. As the object has already been
deleted, this will generally result in a crash.
Thus if we write a class involving a destructor, we will generally need a copy
constructor too. In fact, we have very similar issues with the assignment operator so
it is necessary to write it as well. This leads to the “rule of three,” which states that
if any one of destructor, assignment operator and copy constructor is needed for a
class then all three are. Whilst it is possible to construct examples for which this is
not true, it is a very good rule of thumb. If you feel that you will never want to copy
or assign objects from a class and do not bother to write the appropriate methods
then you are storing up trouble; when someone does use the copy constructor the
compiler will not complain but the code will crash. One solution is to declare the
copy constructor but make it private. The attempt to use it will then result in a
compile-time error instead of a run-time error which would be more easily spotted
and ¬xed. (Similarly for the assignment operator.)
We analyze the copy constructor from VanillaOption. It copies the value of
Expiry from the original into the copy, naturally enough. For the pointer, we call
the clone method generating a copy of the PayOff object which we store in the
copy™s pointer. Note that the data members of the original and its copy will not be
equal, since the pointers will have different values. However, this is precisely what
we want, as we do not want them to be using the original PayOff object.
Note, however, that if we decided to de¬ne a comparison operator (i.e. opera-
tor==) for the class, we would have to be careful to compare the objects pointed
to rather than the pointers, or we would always get false.
Having analyzed the copy constructor, let™s look at the assignment operator. The
¬rst thing to note is that its return type is VanillaOption&. The effect of this is
that it is legitimate to code
a=b=c;
which is equivalent to
b=c;
a=b;
4.5 The bridge 53

but saves a little typing. The second, odder, point is that it it also legitimate to code
(a=b) = c;
which is equivalent to
a=b;
a=c;
which is not particularly useful. If we made the return type const then the second
of these examples would not compile which might be regarded as an advantage;
however, for built-in types the return type has no const and it is generally better
to be consistent. Note that if we had made the return type void, the ¬rst exam-
ple would not compile. If we had made it VanillaOption rather than Vanilla-
Option& then the two examples would both compile but give odd behaviour. The
¬rst would work but might result in extra copying of objects which would waste
time. The second would end with a being equal to b, as the returned object from
a=b would have nothing to do with a any more and would happily be assigned the
value of c and then disappear.
The second point to note about the assignment operator is that the ¬rst thing we
do is check against self-assignment. If we accidentally coded a=a, we would not
want the code to crash. Whilst it might seem an unlikely occurence when objects
are being accessed through pointers it is not immediately obvious whether two
objects are actually the same object. By checking if the address of the assigning
object is equal to the this pointer, we check against this eventuality and do nothing
if it occurs as nothing is needed to be done to ensure that a is equal to a.
The rest of the assignment operator is really just a combination of destructor and
copy constructor. The destructor part is needed to get rid of the PayOff which the
object owned before, as otherwise it would never be deleted. The copy constructor
part clones the pointed-to object so the new version of the assigned part has its own
copy of the object as desired.

4.5 The bridge
We have now achieved what we desired: the vanilla option class can be happily
copied and moved around just like any other class and it uses the code already
written for the PayOff class so we have no unnecessary duplication. However,
there is still one aspect of our implementation which is slightly annoying “ we had
to write special code to handle assignment, construction and destruction. Every
time we want to write a class with these properties, we will have to do the same
thing again and again. This is rather contrary to the paradigm of reuse. What we
would really like is a pay-off class that has the nice polymorphic features that
our class does, whilst taking care of its own memory management. There are a
couple of approaches to solving this problem. One is to use a wrapper class that has
54 Bridging with a virtual constructor

been templatized: this is really generic programming rather than object-oriented
programming, and we explore this approach in Section 5.4. The other is known
as the bridge pattern. Suppose we take the vanilla option class and get rid of the
member Expiry and the method GetExpiry. We then are left with a class that
does nothing except store a pointer to an option pay-off and takes care of memory
handling. This is precisely what we want.
We present such a class:

Listing 4.13 (PayOffBridge.h)

#ifndef PAYOFFBRIDGE_H
#define PAYOFFBRIDGE_H

#include<PayOff3.h>

class PayOffBridge
{
public:
PayOffBridge(const PayOffBridge& original);
PayOffBridge(const PayOff& innerPayOff);

inline double operator()(double Spot) const;
˜PayOffBridge();
PayOffBridge& operator=(const PayOffBridge& original);

private:
PayOff* ThePayOffPtr;
};

inline double PayOffBridge::operator()(double Spot) const
{
return ThePayOffPtr->operator ()(Spot);
}

#endif

Listing 4.14 (PayOffBridge.cpp)

#include<PayOffBridge.h>

PayOffBridge::PayOffBridge(const PayOffBridge& original)
{
4.5 The bridge 55

ThePayOffPtr = original.ThePayOffPtr->clone();
}

PayOffBridge::PayOffBridge(const PayOff& innerPayOff)
{
ThePayOffPtr = innerPayOff.clone();
}

PayOffBridge::˜PayOffBridge()
{
delete ThePayOffPtr;
}

PayOffBridge& PayOffBridge::operator=
(const PayOffBridge& original)
{
if (this != &original)
{
delete ThePayOffPtr;
ThePayOffPtr = original.ThePayOffPtr->clone();
}

return *this;
}

We test the new class in VanillaMain3.cpp. This ¬le is almost identical to
VanillaMain2.cpp so we do not present it here but it is included on the accom-
panying CD. It includes Vanilla3.h instead of Vanilla2.h and SimpleMC5.h
instead of SimpleMC4.h, the only differences being the inclusion of PayOff-
Bridge.h. In Vanilla3.h, we code the vanilla option in the way we originally
wanted to! That is, we treat the pay-off as an ordinary object requiring no special
treatment.

Listing 4.15 (Vanilla3.h)

#ifndef VANILLA_3_H
#define VANILLA_3_H

#include <PayOffBridge.h>

class VanillaOption
{
56 Bridging with a virtual constructor

public:
VanillaOption(const PayOffBridge&
ThePayOff_,double Expiry);

double OptionPayOff(double Spot) const;
double GetExpiry() const;

private:
double Expiry;
PayOffBridge ThePayOff;
};
#endif
and

Listing 4.16 (Vanilla3.cpp)
#include <Vanilla3.h>

VanillaOption::VanillaOption(const PayOffBridge&
ThePayOff_, double Expiry_)
: ThePayOff(ThePayOff_), Expiry(Expiry_)
{
}

double VanillaOption::GetExpiry() const
{
return Expiry;
}

double VanillaOption::OptionPayOff(double Spot) const
{
return ThePayOff(Spot);
}
Everything in Vanilla3.h is totally straightforward as all the work has already
been done for by the bridged class.
An interesting aspect of VanillaMain3.cpp is that we do not have to change
the lines
PayOffCall thePayOff(Strike);

VanillaOption theOption(thePayOff, Expiry);
4.6 Beware of new 57

Although the VanillaOption constructor expects an argument of type
PayOffBridge, it happily accepts the argument of type PayOffCall. The rea-
son is that there is a constructor for PayOffBridge which takes in an object of
type PayOff&. The compiler automatically accepts the inherited class object as
a substitute for the base class object, and then silently converts it for us into the
PayoffBridge object which is then passed to the VanillaOption constructor.



4.6 Beware of new
We have presented the bridge as a solution to the problem of developing an open-
closed pay-off class. It is a very good solution and we will use this approach again
and again. However, there is a downside which it is important to be aware of:

new is slow.

Everytime we copy a bridged object, we are implicitly using the new command.
So if our code involves a lot of passing around of bridged objects, we had best be
sure that we do not copy them unnecessarily, or we will spend all our time calling
the new function. One easy way to reduce the amount of copying is to always pass
parameters by reference.
Why is new slow? To understand this, we ¬rst have to understand what it actually
does. When we create variables normally, that is when not using new, the compiler
gets them from an area of memory known as the stack. The important point is that
these variables are always destroyed in reverse order from their creation (which is
why the memory area is called the stack). Each variable as declared is added to
the top of the stack, and when destroyed is removed from the top; in fact, all that
happens is that the code remembers a different point as the top.
This is very easy to do but really depends rather heavily on the fact that the
order of creation is the reverse of the order of destruction. Thus the variable to be
destroyed is always the variable at the top of the stack.
Suppose we want to destroy variables in a different order, which is what we are
really doing when we use new; remember that a variable created by new persists
until the coder tells it to disappear. If we were using the stack we would have to
scan down to the point where the variable was stored. We would then need to move
all the variables further up the stack down a bit to cover up the gap caused by the
release of memory. Clearly, this could be very time-consuming.
The compiler therefore does not use the stack for new but instead uses a different
area of memory known as the heap. For this area of memory, the code keeps track
of which pieces are in use and which pieces are not. Everytime new is called, the
compiler has to ¬nd an empty piece of memory which is large enough and mark
58 Bridging with a virtual constructor

the memory as being in use. When delete is called, the code marks the memory
as being free again.
The upshot of all this is that calling new involves a lot of behind the scenes work
which you would probably rather not have to think about.
One solution to the time-consumption of new is to rewrite it. This is allowed by
the standard. It is, perhaps, a little surprising that one can rewrite new to be more
ef¬cient than a good compiler. The reason that this is possible is that the coder
has a better idea of what objects will be needed during his program™s run, and
possibly in what order they will be created. This allows the programmer to make
extra assumptions not available to the compiler, and thus to speed things up. For
example, if the programmer knows that a lot of PayOffCall objects will be used,
he could section off an area just for PayOffCall objects and allocate them and
deallocate them as necessary.
We shall not further explore how to rewrite new, but ¬nish with an admonition
that it should never be used explicitly nor implicitly within time-critical loops.


4.7 A parameters class
We know that eventually the evil boss is going to demand a variable parame-
ters Monte Carlo routine. Let™s apply the ideas of this chapter to developing a
Parameters class which allows easy extension to variable parameters without
actually putting them in. Note the crucial distinction between including variable
parameters, and redesigning so that it would be easy to add them if one so desired.
What should a parameters class do? We want it to be able to store parameters
such as volatility or interest rates or, in a more general set-up, jump intensity. What
information will we want to get out from the class? When implementing a ¬nancial
model, we never actually need the instantaneous value of parameter: it is always
the integral or the integral of the square that is important.
For example, in our simple Monte Carlo model, we need the square integral of
the volatility from time zero to expiry, and the integral of r over the same interval.
Similarly, for jump intensity it is the integral over a time interval that is important.
Our parameters class should therefore be able to tell us the integral or integral
square over any time interval, and nothing else.
What sort of differing parameters might we want? It is important in object-
oriented programming to think to the future, and therefore think about not just
what we want now but what we might want in the future. The simplest possible
sort of parameter is a constant and our class should certainly able to encompass
that. Some other obvious sorts of parameters are a polynomial, a piece-wise con-
stant function, and an exponentially decaying function. For all of these, ¬nding the
integral and square integral over de¬nite intervals is straightforward.
4.7 A parameters class 59

We employ the bridge design. We therefore de¬ne a class Parameters that han-
dles the interaction without the outside world, and the memory handling. Its only
data member is a pointer to an abstract class, ParametersInner, which de¬nes
the interface that the concrete classes we will eventually implement must ful¬ll. We
also include the clone method, as well as Integral and IntegralSquare meth-
ods, so the wrapper class, Parameters, can handle the copying. We then inherit
classes such as ParametersConstant from ParametersInner. As with the pay-
off class, additional classes can then be added in separate ¬les, and their addition
will not require any recompilation or changes in routines that use the Parameters
class.
We give a possible implementation:

Listing 4.17 (Parameters.h)

#ifndef PARAMETERS_H
#define PARAMETERS_H

class ParametersInner
{

public:
ParametersInner(){}

virtual ParametersInner* clone() const=0;
virtual double Integral(double time1,
double time2) const=0;
virtual double IntegralSquare(double time1,
double time2) const=0;
virtual ˜ParametersInner(){}
private:
};

<<

. 2
( 9)



>>