Writing good financial code is a difficult task, one that cannot be done in isolation. As a software engineer, you frequently need to collaborate with others to achieve your development goals. You also need to use code that has been written by other groups. In particular, developers are constantly using libraries created by other companies or open source projects. Integrating these libraries into your own work is a major step to improve productivity.
Boost introduction: The boost repository provides access to many C++ libraries that are based on templates for higher efficiency. You will learn how to install and use boost, as well as integrate particular libraries in the repository to your own applications.
Boost odeint: The odeint library is a well-tested and efficient set of algorithms for the solution of ordinary differential equations (ODEs). You will learn about the different algorithms contained in odeint and the different situations in which they can be employed.
QuantLib: The QuantLib library has been designed as a repository for quantitative algorithms and assorted utilities for financial applications. Many parts of this code can be used to simplify the process of analyzing options and derivatives. You will learn how to use this library and see a few of the most commonly used classes and algorithms that are available in the QuantLib repository.
Boost Libraries
In the last few years, the boost project has become well known for providing high-quality libraries for C++ applications. As a result, the boost project is now the de facto repository for extensions to the STL. In fact, many of the libraries that started as part of the boost repository have been incorporated to the C++ standard, including, for example, std::shared_ptr and std::unique_ptr. A few of the developers working on boost libraries have also become part of the standard C++ committee.
The boost project focuses on using the modern features of the C++ language, including, but not exclusively, the employment of templates for high performance. Many of the libraries included in boost provide template-based interfaces that make the resulting system much more flexible. For example, different algorithms can be specialized at the template level, so that you can combine different algorithms through the use of templates, when deciding on the optimal techniques to solve a specific problem. This is a much more adaptable strategy, rather than relying on decisions made by library designers.
Solving ODEs: Ordinary differential equations appear frequently in the solution of numerical problems in the area of finance. As you have seen, to solve some options analysis models, it is necessary to efficiently compute the value of ODEs. The odeint library gives you access to such functionality, as you see in the next section.
uBLAS: The Basic Linear Algebra System library provides a C++ interface to an advanced linear algebra library. uBLAS can be used to support more complex matrix-related code, as well as the solution of systems of equations.
Multi-array: Many applications require the use of multidimensional arrays when working in areas such as 3D animation, weather predictions, and so on. The multi-array library provides an easy interface for the creation and manipulation of arrays that can be indexed using multiple indices.
Managing file and directories: The <filesystem> header file contains a set of templates that can be used to manage files and directories. It handles different operating systems, so that you don’t need to rely on system-specific libraries for common file-based operations.
The filesystem library has become part of the C++ standard library in the C++17 version. Previously, filesystem was part of the boost library, which was needed to gain access to this functionality. However, you can still access this library using boost, which makes it portable to earlier compilers.
List of Commonly Used Boost Libraries
Library | Description |
---|---|
Odeint | Implements algorithms to solve ordinary differential equations (ODEs). |
filesystem | A set of classes to manipulate files and directories in an OS-independent way. |
Multi-array | Provides arrays with multiple dimensions; useful for scientific code. |
MPI | Implements the Message Passing Interface, a standard for parallel processing. |
Math | A set of mathematical functions not included in the standard library. |
Graph | A library that extends the STL and provides containers and algorithms to handle graphs. |
Functional | Provides templates that simplify functional programming techniques. |
Algorithm | A set of generic algorithms that extends the algorithm header in the STL. |
uBLAS | A modern C++ implementation of BLAS (Basic Linear Algebra Subprograms). |
Variant | A container that safely stores a union container, capable of storing different data types. |
Sort | Implements several sorting strategies using templates for high performance. |
Regex | Provides support for regular expressions in C++. |
Python | A set of templates and classes that allows interaction between Python and C++ code. |
Installing Boost
The first step in using the boost libraries is to install them on your machine. Being an open source repository, boost packages are made available through the Web and mirrored in several websites. The canonical website for the repository is www.boost.org, where you can find instructions for installing boost in several architectures and operating systems.
The most common way to install boost is to download the compressed file containing the headers and source files. Once the files are uncompressed, you can use the main installation script that is provided, bootstrap.sh, to build and install the software on the desired path in the local disk.
Another way to install boost libraries is to use third-party installers or package managers. For example, if you use Linux, it is possible to install boost as a package using the local package manager, such as dpkg on Debian systems. On Windows systems, you can also install cygwin, which contains a package manager with several common C++ programming packages, including the boost libraries.
Boost.Filesystem
Boost.IOStreams
Boost.ProgramOptions
Boost.Python
Boost.Regex
Boost.Serialization
Boost.Signals
Boost.Thread
Boost.Wave
Boost libraries are built using a C++ build system called bjam. The build script will try to find bjam in your machine or build it. You can also download bjam from its binary distribution located in boost.org/build.
In the next few sections, you will see how to use a few libraries available from boost. First, you will see how to solve ordinary differential equations with the odeint library.
Solving ODEs with Boost
In the previous chapter, you saw how ordinary differential equations (ODEs) can be implemented directly using C++ code. Due to how options are defined and represented, ODE models arise naturally in the design of financial algorithms. As a result, being able to quickly implement such methods is a great advantage for the quantitative software developer. Moreover, it is much easier to reuse an ODE implementation that has already been reviewed and thoroughly tested, especially considering that numerical errors are hard to catch in many cases.
List of Integration Techniques Available When Using odeint
Class Name | Description |
---|---|
Euler | Original Euler’s algorithm to solve ODEs. |
runge_kutta4 | Uses the Runge-Kutta method, with fourth-order approximation. |
runge_kutta_cash_karp54 | Runge-Kutta method. |
runge_kutta_fehlberg78 | Variation of Runge-Kutta that uses the Fehlberg algorithm. |
adams_moulton | A multistep algorithm for solving ODEs. |
dense_output_runge_kutta | An implementation of Runge-Kutta that uses dense output. |
bulirsch_stoer | Based on the Bulirsch-Stoer algorithm, provides higher accuracy in the solution of complex ODEs. |
implicit_euler | A variation of Euler’s algorithm in which the equation is given in implicit form and requires the use of the associated Jacobian. |
The algorithms made available in the odeint library are implemented as separate template classes. Each class corresponds to an algorithm or algorithmic concept. The odeint library contains a set of integration methods that can be parameterized using the provided templates. These templates make it possible to use different strategies through the combination of the given algorithms and concepts.
runge_kutta4
euler
runge_kutta_cash_karp54
runge_kutta_dopri5
runge_kutta_fehlberg78
modified_midpoint
rosenbrock4
Solving a Simple ODE
Here, y is a function of x, y' is the first derivative of y, and f(x, y) is a general equation that may depend both on x and y.
Creating Histograms with Boost
Another useful application for boost is the creation of support code such as histograms. A histogram is a useful chart in financial applications that shows the frequency of each particular value in a time sequence. This can be applied, for example, to prices of underlying assets for an options analysis package.
In this sample application, the boost/histogram header file is imported to provide the required class and template definitions. The use of this class occurs on function main. The make_histogram function is useful to instantiate a histogram class using default value along with the passed parameters.
The parameters specified in the example determine that the axis for the histogram is regular, with five partitions (bins), starting on value -1.0 and extending to value 1.0. Then, a few values are added to some of the bins maintained by the histogram class.
The QuantLib Library
The second example of a library that is used in quantitative finance and options analysis is the QuantLib library. QuantLib is a well-established repository of quantitative code for C++. The library has been tested and used by many developers, which means that you can take advantage of the hard work that went into creating and testing the algorithms.
Being an open source project, QuantLib is free and can be used by anyone by just downloading and building the source code. The project also accepts contributed code, which means that many people can fix bugs and participate in the improvement of the library.
Date handling: Many algorithms for options and derivatives analysis are based on dates. Therefore, accurate information about trading dates, holidays, and other calendar-specific events are very important for the correct results of such algorithms. QuantLib provides a number of classes that encapsulate the concepts needed for data handling in financial applications.
Design patterns: The QuantLib library puts a lot of effort in following well-established design patterns. Most algorithms use design patterns that make them easier to understand and to maintain. For this reason, QuantLib has a rich implementation of common design patterns, including Singleton, Observer, Composite, and others.
Monte Carlo methods: A few of the classes provided by QuantLib are used to simplify the implementation of Monte Carlo methods. These classes make it easier to create, for example, random paths for financial instruments, as well as similar models based on Brownian motion.
Pricing engines: Another area that is covered by QuantLib is the implementation of efficient pricing engines for options and derivatives. The library provides several techniques for options pricing, which are carefully packaged into C++ classes. These pricing engines include barrier option engines, Asian option engines, basket option engines, and vanilla option engines.
Optimizers: Another utility that is frequently employed in financial applications is an optimization engine. The QuantLib library contains a few classes dedicated to some common optimization strategies. Using such optimization algorithms, it is possible to quickly solve complex problems where the objective is to find the minimum or the maximum of a given function.
In the remaining of this section, you will see a few examples using classes from QuantLib. You will learn how to use some of the main classes available in the library and integrate them to your applications.
On a macOS computer, you can easily install QuantLib using the brew package manager with the following command:
brew install quantlib
Handling Dates
One of the most common tasks in financial algorithms is handling dates correctly. You saw in Chapter 3 that there are several ways to store and transform values stored as dates. The QuantLib library tries to simplify some of these tasks with the introduction of carefully designed date and time classes.
Managing holidays is one of the most difficult problems when using dates in financial applications. Since the number of trading days constitutes part of the calculation, when computing the price of an option, it becomes very important to have precise representations of date intervals, considering which of those days are trading days.
In this code, the operators are used to add a period of two days and three months, respectively, to the original date. The Days and Month identifiers are simple data types that concisely represent a time period and can be used to simplify the handling of intervals.
Additional tools are provided to answer common questions related to dates. For example, member functions of the Date class are used to determine if a particular date occurs in a leap year, if it occurs at the end of the month, or if the date is a weekday. These are exemplified by the code in the following section.
Working with Calendars
Another aspect of dates that causes a lot of confusion is handling local holidays. Each country has nontrading days that are determined by holidays, which also change according to the year in which they occur. To handle these issues, QuantLib provides a set of Calendar objects. These calendars are localized and can be used to determine if a particular date is a holiday.
The first line of the useCalendar function shows how to create a new calendar for a particular region. In this case, the calendar corresponds to the United States and in particular to the New York Stock Exchange.
With this calendar loaded, it is possible to answer a number of questions about dates in the United States. For example, the next few lines show how to list all holidays with the holidayList function . The function receives as arguments the calendar and the desired start and end date. The result is a container with all the holidays for the given period.
The next few lines show how to use QuantLib Calendar object to answer a few common questions related to the day of the week and the month. The first call is to isBusinessDay, and it returns true if the given date occurs in a business day (usually Monday to Friday in most markets). The second member function is isHoliday, which returns true only if the given date is a holiday.
Finally, you can see the member function isEndOfMonth example. This function returns true if the given date occurs at the end of a month, which may be an important date in some kinds of financial contracts.
Another interesting feature of the Calendar class is that you can create and manage your own calendars. This is necessary when creating code for countries that are not already covered by the library, or when you’re working on particular institutions or markets that use a distinct calendar.
This function starts with the creation of a new calendar object based on the US calendar, more specifically using the NYSE list of holidays. The function then proceeds to modify the original calendar, adding a common holiday and adding another so the number of holidays remains the same. The code also prints the list of holidays for the year 2016 to the standard output. Finally, the createNewCalendar function returns the newly created calendar as the result.
In the beginning, the getNumberOfDays function creates a calendar using the US locale. The next step is to determine the number of business days between two given dates. Then, the function prints the value of this difference and returns that value as the final result.
Computing Solutions for Black-Scholes Equations
The next example of QuantLib is directly related to the problem of pricing options. The main formula for pricing options is derived from the Black-Scholes differential equations. This makes it really important to have a library that can quickly solve Black-Scholes models, at least as an initial step for further analysis.
The QuantLib provides classes that are specifically designed to solve Black-Scholes models. Unlike other ODE and PDE packages that can be used to solve general differential equations (as seen in the previous section on boost), the QuantLib classes target efficient techniques to solve a single model in particular. This results in a very specialized algorithm that can be relied on for the efficient solution of Black-Scholes models.
A class representing the option and the associated payoff: QuantLib provides a set of classes for this purpose. An example of such a class is PlainVanillaPayoff, which represents a common (vanilla) option and its associated payoff.
A class representing the pricing method: This class encapsulates the algorithm that is used to compute the option price. This example is interested in the class representing the Black-Scholes algorithm, which is named the BlackScholes calculator.
These classes are exemplified in the following sample code, which includes a function that performs the computation and an associated test function.
The spot price for the underlying instrument
The strike price for the desired option
The current interest rate
The forward interest rate
The volatility of the underlying instrument
This code works in the following way. The first instruction is necessary to create a new object describing the required option. This is done with the instantiation of an object of class PlainVanilllaPayoff, which indicates that the new option is of plain vanilla type (i.e., it is a standard option). The arguments passed are the type of option (either a call or a put) and the strike. These two parameters determine the type of option that you’re handling, independent of the current characteristics of the market. The object of type PlainVanillaPayoff is stored in a shared_ptr, which automatically manages the lifetime of the object, cleaning up the pointer at the end of the scope of the local variable.
The next part of the callBlackScholes function initializes some of the parameters necessary to use the options pricer. The parameters include the current and forward discount rate, which are computed from the given interest rate using an exponential transformation. Another important parameter is the standard deviation, which measures the volatility of the underlying instrument.
Once the parameters for the options pricing model are available, you can instantiate the BlackScholesCalculator class, passing as parameters the object that describes the option, the current price, and the other parameters discussed previously.
The delta: Represents the marginal change in value with respect to the price of the underlying
The gamma: Represents the marginal change in delta with respect to the price of the underlying
The vega: Represents the marginal change in value with respect to the change in volatility
The theta: Represents the marginal change in value with respect to the change in remaining time
Creating a C++ Interface
Based on the previous functions, it is easy to create a generic class that encapsulates a vanilla Black-Scholes pricing strategy. I called this class BlackScholesPricer, and it presents a simple interface that can be called without external references to QuantLib.
The constructor for BlackScholesPricer is responsible for initializing all the parameters with the passed arguments. Inside the constructor, you can see the code that initializes the payoff class. The option payoff can be a put or a call, depending on the value of the first parameter.
Complete Code
Implementation File BlackScholesPrices.cpp
To compile this code, you need to install the QuantLib library for your platform and add that library to the project. For example, using the gcc compiler, you need to use the –lQuantLib option.
Conclusion
Using good libraries is an important aspect of effective software development. Financial code, especially when options and derivatives are involved, requires the use of efficient and well-tested algorithms. For this reason, it is important that developers be acquainted with high-quality libraries that can be used to simplify the development process.
In this chapter, you learned about some libraries, such as boost and QuantLib, which have been successfully used to create financial applications handling options and other derivatives. The first example was from the boost repository, which contains several special-purpose libraries that use modern C++ features. The odeint library in particular, which is contained in the boost repository, can be used to simplify the computation of solutions to ODEs.
Another important library used in the financial software community is QuantLib. This open source financial library provides many useful algorithms implemented in modern, efficient C++. You saw examples of common utilities provided by QuantLib. The most common classes are for date handling. These utility classes can handle business calendars, date intervals, and sequences in a way that makes it possible to handle financial applications.
You also saw how to use QuantLib to quickly create options and derivative models. The BlackScholesCalculator class encapsulates the solution to the Black-Scholes model. This model is the basis for most techniques that can be used to analyze prices and variations of values for financial derivatives.
The next chapter will cover additional algorithms that can be used to process more complex derivatives, with special attention to credit derivatives. These algorithms will be compared and implemented in C++.