Previously we have explored how to implement a simple, vanilla European option pricer in C++ by using QuantLib’s pre-made tools. While these tools are very nice, we will explore in this post how to create our very own objects in C++, QuantLib-style.

We will encounter new things like creating classes, namespaces (so we don’t interfere with QuantLib’s names), public and private variables within classes, and even look at implementing a subclass that inherits the properties of QuantLib’s pricing engine results.

Other technical aspects of this post will include using pointers once again, but also accessing pointer properties using the arrow operator. We’ll discuss constant variables and mutable variables and why we would use one or the other.

Setup

Open Visual Studio 2017 (VS) and create a new C++ project. I’ve called mine “TestInstrument” because that is also the name of the C++ source file containing the main program that will test our instrument class.

When it opens create two new files: 1) a new Source File called “Instrument.cpp” and a new Header File called “Instrument.h“. These will go in the Source and Header subfolders respectively. Before we even start though we must turn off precompiled headers, because this will interfere with our own headers and namespace declarations! To do this, right-click on your TestInstrument solution and go to Configuration Properties > C/C++ > Precompiled Headers and change the Precompiled Header to “Not Using Precompiled Headers”.

The Instrument Header File

Open up the Instrument.h header file. We begin by wrapping the entire code block in an #ifndef statement. It looks like this:

#ifndef conundrum_instrument_H
#define conundrum_instrument_H

#endif

This #define code block connects our source C++ file with our header file. The names have to be the same, and it’s ideal to have it like [namespace name]_[class name]_H (the H at the end stands for “Header”).

We will attempt to code up as much of the class header as possible without including any files, so to begin with we have no include files.

So that we can use our instrument class in conjunction with QuantLib’s instrument class we will have to wrap our C++ code in a namespace like so:

#ifndef conundrum_instrument_H
#define conundrum_instrument_H

namespace Conundrum {

}

#endif

Inside the namespace we create the base class Instrument like so:

#ifndef conundrum_instrument_H
#define conundrum_instrument_H

namespace Conundrum {
   class Instrument
   {

   };
}

#endif

It is a base class because it is not inheriting anything, for example, a class that inherits a base class would be declared like this: class Instrument : InheritedBaseClass {}. We will use this a little later on.

For now we will just give it the default constructor:

#ifndef conundrum_instrument_H
#define conundrum_instrument_H

namespace Conundrum {
   class Instrument
   {
      // Default Constructor
      Instrument();
   };
}

#endif

So now, when we create this Instrument object in our main program we would type something like this:

#include "Instrument.h"
#include <iostream>

int main(int, char*[])
{
   Conundrum::Instrument option();
}

Try it out. Even with nothing written in the source file and only the header declared, the intellisense should pick up the object when you begin to type Conundrum::.

The NPV Member Function

In our main program, we would like to be able to type something like this: option.NPV() to return the present value of the instrument using the so-called dot operator. NPV is what is called a Member Function of the class, and it would need to be public so that our main program can access it. Furthermore, it would be ideal that it be of type double (like a real number), and be a const function so that we are assured that the member function won’t change the instrument object’s (client-visible) state. So we write in the class header:

#ifndef conundrum_instrument_H
#define conundrum_instrument_H

namespace Conundrum {
   class Instrument
   {
      // Default Constructor
      Instrument();
      // Member Functions
      double NPV() const;
   };
}

#endif

And now, jumping back to the test main program, we are able to type the following with no errors:

#include "Instrument.h"
#include <iostream>

int main(int, char*[])
{
   Conundrum::Instrument option();

   std::cout << "Value of option is = " << option.NPV() << std::endl;

}

Now let's provide some actual source code to our instrument class. As it stands, the constructor and the member function NPV() do absolutely nothing. In fact, you should have little green lines under those functions telling you that no definitions could be found.

To give them definitions we code them in. Now we have two choices, to provide the source code in the .cpp file, or we can provide the definitions as inline definitions in the header file. We will do the latter because this is a very simple class.

Go back to the instrument header file and scroll down to a region of the code after the class but before the end of the namespace. We will declare our inline definitions here:

#ifndef conundrum_instrument_H
#define conundrum_instrument_H

namespace Conundrum {
   class Instrument
   {
      // Default Constructor
      Instrument();
      // Member Functions
      double NPV() const;
   };

   // inline definitions
   // Default Constructor
   inline Instrument::Instrument() {}
   // Member Functions
   inline double Instrument::NPV() const {}

}

#endif

These two inline functions still don’t do anything (at least they’re now defined though!). To make them do something we would need to put some code in between the { }. We will leave the constructor empty for now and just provide some code for the NPV() member function.

The easiest code would be to provide the member function with some sort of void function (recall, a void function is a type of function which does not return any values – it just performs some sort of operation) like calculate() which does the actual calculation and then return NPV_ where it would return a double temp variable called NPV_ that was calculated inside the calculate() void function. Writing this in straight will give more undefined errors, but set us off in the right path:

#ifndef conundrum_instrument_H
#define conundrum_instrument_H

namespace Conundrum {
   class Instrument
   {
      // Default Constructor
      Instrument();
      // Member Functions
      double NPV() const;
   };

   // inline definitions
   // Default Constructor
   inline Instrument::Instrument() {}
   // Member Functions
   inline double Instrument::NPV() const 
   {
      calculate();
      return NPV_;
   }

}

#endif

So now we just have to define what calculate() is.

The Calculate Function

The void member function calculate() should not be accessible from outside the object, only from within. So we go back to the header file and declare it as a private void function and give it an inline definition like so:

#ifndef conundrum_instrument_H
#define conundrum_instrument_H

namespace Conundrum {
   class Instrument
   {
   public:
      // Default Constructor
      Instrument();
      // Member Functions
      double NPV() const;
   private:
      void calculate() const;
   };

   // inline definitions
   // Default Constructor
   inline Instrument::Instrument() {}
   // Member Functions
   inline double Instrument::NPV() const 
   {
      calculate();
      return NPV_;
   }
   inline void Instrument::calculate() const {}
}

#endif

Include QuantLib for a Pricing Engine

Now, we’re going to cheat a little bit because I do not want to have to code up an entire pricing engine just for this example of an instrument class. So we are going to have to include the QuantLib include directories and library files. If you are unsure how to do this, read a previous post on the topic here.

After you have added QuantLib to the C++ directories, go to the top of instrument.h and add the following line in: #include .

The Pricing Engine

We want the class to be able to use a Pricing Engine object that the user specifies. So where should we put it? First, it should not be accessible from public; once it is declared it should stay private, so it’s definition should be as a private variable in the instrument class. Second, the engine’s type will be QuantLib’s PricingEngine type. Not only that, but this type should be a smart pointer to the PricingEngine (we covered why this should be so in our previous post). So we need to also include Boost’s shared ptr header file with #include . While we are at it, we also need to declare what type the temp variable NPV_ is back in the instrument class declarations.

Now we add the engine_ and NPV_ temporary variables in to the private part of the instrument class:

#ifndef conundrum_instrument_H
#define conundrum_instrument_H

#include 
#include 

namespace Conundrum {
   class Instrument
   {
   public:
      // Default Constructor
      Instrument();
      // Member Functions
      double NPV() const;
   private:
      void calculate() const;
      double NPV_;
      boost::shared_ptr engine_;
   };

   // inline definitions
   // Default Constructor
   inline Instrument::Instrument() {}
   // Member Functions
   inline double Instrument::NPV() const 
   {
      calculate();
      return NPV_;
   }
   inline void Instrument::calculate() const {}
}

#endif

Finishing off the Calculate Function

and the Arrow operator

The first thing that will happen in the calculate function is that we reset() the engine. This is achieved by writing engine_->reset() (not engine_.reset()! Why? because engine_ is a pointer, so member functions are accessed using the -> operator).

Alternatively, we could have de-referenced the pointer for regular member access with the dot operator like so:

(*engine_).reset()

Next, we use the member function getArguments() to set the arguments of the engine. Then the member function calculate() to calculate the price, and finally we will get the results and assign the value to the NPV_ variable using the member function getResults().

#ifndef conundrum_instrument_H
#define conundrum_instrument_H

#include <ql/quantlib.hpp>
#include <boost/shared_ptr.hpp>

namespace Conundrum
{

	class Instrument {
	public:
		// Default Constructor
		Instrument();

		// Member Functions
		double NPV() const;

	private:
		void calculate() const;
		double NPV_;
		boost::shared_ptr engine_;
	};

	// inline Defintions:
	// Default Constructor:
	inline Instrument::Instrument() {}
	// Member Functions:
	inline double Instrument::NPV() const 
	{
		calculate();
		return NPV_;
	}
	inline void Instrument::calculate() const
	{
		engine_->reset();
		engine_->getArguments();
		engine_->calculate();
		engine_->getResults();

             NPV_ = 0.0;
	}
}

#endif

We have just set NPV_ equal to 0.0 for now because we are unsure how to get the results out of the Pricing Engine. However, this has instructional value because you should get an error here when we try to assign a value to the variable. The error states: expression must be a modifiable value. To fix this, go back up to where NPV_ was first declared as a double and prefix it with the keyword mutable. This allows the variable to be changed within the class depending on the outcome of the Pricing Engine’s calculation, which is exactly what we want to do.

The Results Class

The annoying thing here is that we need access to the Pricing Engine’s getResults() member function and assign one if its values to the NPV_ variable, but it’s not immediately accessible – at least in the way we want. So to get at it we need to build another class that inherits the Pricing Engine’s result class, then instantiate it as a new object and access the value via the dot operator.

So under the class declaration for instrument, but above the inline definitions, we add a new inherited class called “Instrument::results“:

class Instrument::results : public virtual QuantLib::PricingEngine::results {
	public:
		void reset()
		{
		}
		double value;
		double errorEstimate;
		QuantLib::Date valuationDate;
	};

This class won’t work yet because we have not declared what Instrument::results is in the parent class yet. Furthermore, we have left the inherited member function reset() empty for now, but we will have to fill it in later. Also, you will notice that we are using the default constructor. So let’s define the result object in the parent instrument class (note: the declaration of the child class Instrument::results goes before the default constructor!):

#ifndef conundrum_instrument_H
#define conundrum_instrument_H

#include <ql/quantlib.hpp>
#include <boost/shared_ptr.hpp>

namespace Conundrum
{
	class Instrument {
	public:
		// Member Classes
		class results;

		// Default Constructor
		Instrument();

		// Member Functions
		double NPV() const;

	private:
		void calculate() const;
		mutable double NPV_;
		boost::shared_ptr engine_;
	};

	class Instrument::results : public virtual QuantLib::PricingEngine::results {
	public:
		void reset()
		{
		}
		double value;
		double errorEstimate;
		QuantLib::Date valuationDate;
	};

	// inline Defintions:
	// Default Constructor:
	inline Instrument::Instrument() {}
	// Member Functions:
	inline double Instrument::NPV() const 
	{
		calculate();
		return NPV_;
	}
	inline void Instrument::calculate() const
	{
		engine_->reset();
		engine_->getArguments();
		engine_->calculate();
		engine_->getResults();

		NPV_ = 0;
	}

}

#endif

Now, hopefully, we can just go down to our calculate() definition and fix up the NPV code with:

NPV_ = results->value;

But no, this will be an error. Why? Because Instrument::calculate() doesn’t know what the results object is, at least, it won’t recognise which instance it is – unless we pass it in!

To do that we need to pass it in as an argument to the calculate() member function, and also fix up its declaration in the instrument class so that it will know to expect an argument:

void calculate(const QuantLib::PricingEngine::results*) const;

So what should we pass in? Well, since we are assigning the NPV_ variable to a pointer, the argument should also be a pointer. QuantLib’s Pricing Engine has a subclass called results so we will pass in a pointer to that object and call it simply r with the following code:

inline void Instrument::calculate(const QuantLib::PricingEngine::results* r) const

Inside the calculate member function we will define a new variable ourResults of type Instrument::results* and dynamically cast QuantLib’s Pricing Engine results to it with the following code:

const Instrument::results* ourResults = dynamic_cast(r);

Note how we are dynamically casting QuantLib’s result object in to our own result object! See here for more information on what it does. Admittedly, it’s a little advanced for this post, and I might cover more on it in a later post. But for now, we just accept that it is a nice shortcut way to move around objects of similar types.

Our calculate() member function looks like this:

inline void Instrument::calculate(const QuantLib::PricingEngine::results* r) const
{
	const Instrument::results* ourResults = dynamic_cast(r);

	engine_->reset();
	engine_->getArguments();
	engine_->calculate();
	engine_->getResults();

	NPV_ = ourResults->value;
}

Full Listing of TestInstrument.cpp

Going back to our main we can now access the instrument’s NPV function with the following code and it should compile but NOT run (as we have not coded instructions for the instrument class to handle actual pricing engines or payoff objects):

#include "Instrument.h"
#include <iostream>

int main(int, char*[])
{
    
	Conundrum::Instrument option;

	std::cout << "Value of option is = " << option.NPV() << std::endl;

	return 0;

}

Summary

We have created our own Instrument class by creating a base class (inherits nothing) and a child class called Results to interpret QuantLib’s Pricing Engine results.

We have covered C++ topics such as Namespaces (to avoid confusion with QuantLib’s instrument class), inheriting QuantLib classes to get at particular member functions and return results and inline member function definitions.

In addition to the above, we have also looked at accessing member functions of pointers (using the -> operator), we’ve looked at passing in pointers as arguments, and talked about making certain variables either const so that they do not get changed or mutable because they can get changed.

We have implemented the instrument class by utilising Boost shared pointers and QuantLib’s Pricing Engine to define an NPV member function that returns the value of the instrument.

Full Listing of Instrument.h

Please note that while this code compiles, it will not work fully as we have not created the reset() member function for the subclass Instrument::results nor have we given it a constructor that can take in a Pricing Engine and a Payoff type. These will be covered in the next posts! This header is still a good representation of a skeleton class though and shows the basic ingredients required to get one working.

#ifndef conundrum_instrument_H
#define conundrum_instrument_H

#include <ql/quantlib.hpp>
#include <boost/shared_ptr.hpp>

namespace Conundrum
{

	class Instrument {
	public:
		// Member Classes
		class results;

		// Default Constructor
		Instrument();

		// Member Functions
		double NPV() const;

	private:
		void calculate(const QuantLib::PricingEngine::results*) const;
		mutable double NPV_;
		boost::shared_ptr engine_;
	};

	class Instrument::results : public virtual QuantLib::PricingEngine::results {
	public:
		void reset()
		{
			//value = errorEstimate = Null();
			//valuationDate = QuantLib::Date();
			//additionalResults.clear()
		}
		double value;
		double errorEstimate;
		QuantLib::Date valuationDate;
	};

	// inline Defintions:
	// Default Constructor:
	inline Instrument::Instrument() {}
	// Member Functions:
	inline double Instrument::NPV() const 
	{
		calculate(engine_->getResults());
		return NPV_;
	}
	inline void Instrument::calculate(const QuantLib::PricingEngine::results* r) const
	{
		const Instrument::results* ourResults = dynamic_cast(r);

		engine_->reset();
		engine_->getArguments();
		engine_->calculate();
		engine_->getResults();

		NPV_ = ourResults->value;
	}
}

#endif

In the following posts we will be adding more functionality to this class.