Welcome back.

So, as I said, the QuantLib Python Cookbook is available on Leanpub; thanks to those who bought it so far. Does it mean that C++ users are left out in the cold? Well, no.

My choice of using Python notebooks to demonstrate QuantLib features was due to a number of factors. (I’m speaking for myself, here, but I’m guessing that Goutham thought something similar when he started his series of posts). Notebooks are interactive, and so I can also use them live in my courses (the next of which is in September, thanks for asking); and the platform, more or less out of the box, provides excellent modules like matplotlib for graphing and pandas for data analysis. Add into the mix that I was already familiar with the language, and notebooks were the winners, hands down.

However, it’s easy enough to translate the Python code shown in the book into the corresponding C++ code. As an example, I’ll go through a bit of code from the notebook on instruments and pricing engines (the complete notebook is in the free sample).

In [1]: from QuantLib import *


This line imports the QuantLib module and adds the classes and functions it contains to the global namespace. The C++ equivalent would be:

#include <ql/quantlib.hpp>

using namespace QuantLib;


Of course, the above is for illustration purposes. In production code, you’re not forced (or even advised) to use the using directory; you can keep the names in their namespace and qualify them when you use them. It’s also possible to include more specific headers, instead of the global quantlib.hpp.

In [2]: today = Date(7, March, 2014)
Settings.instance().evaluationDate = today


The code above has a couple of caveats. The first line is easy enough to translate; you’ll have to declare the type to the variable (or use auto if you’re compiling in C++11 mode). The second line is trickier. To begin with, the syntax to call static methods differs in Python and C++, so you’ll have to replace the first dot by a double colon. Then, evaluationDate is a property in Python but a method in C++; it was changed in the Python module to be more idiomatic, since it’s not that usual in Python to assign to the result of a method. Luckily, you won’t find many such cases. The translated code is:

Date today(7, March, 2014);
Settings::instance().evaluationDate() = today;


Next:

In [3]: option = EuropeanOption(PlainVanillaPayoff(Option.Call, 100.0),
EuropeanExercise(Date(7, June, 2014)))


Again, you’ll have to declare the type of the variable. Furthermore, the constructor of EuropeanOption takes its arguments by pointer, or more precisely, by boost::shared_ptr. This is hidden in Python, since there’s no concept of pointer in the language; the SWIG wrappers take care of exporting boost::shared_ptr<T> simply as T. The corresponding C++ code:

EuropeanOption option(
boost::make_shared<PlainVanillaPayoff>(Option.Call, 100.0),
boost::make_shared<EuropeanExercise(Date(7, June, 2014)));


(A note: in the remainder of the example, I’ll omit the boost:: namespace for brevity.)

In [4]: u = SimpleQuote(100.0)
r = SimpleQuote(0.01)
sigma = SimpleQuote(0.20)


Quotes, too, are stored and passed around as shared_ptr instances; this is the case for most polymorphic classes (when in doubt, you can look at the C++ headers and check the signatures of the functions you want to call). The above becomes:

shared_ptr<SimpleQuote> u = make_shared<SimpleQuote>(100.0);
shared_ptr<SimpleQuote> r = make_shared<SimpleQuote>(0.01);
shared_ptr<SimpleQuote> sigma = make_shared<SimpleQuote>(0.20);


Depending on what you need to do with them, the variables might also be declared as shared_ptr<Quote>. I used the above, since I’ll need to call a method of SimpleQuote in a later part of the code.

In [5]: riskFreeCurve = FlatForward(0, TARGET(),
QuoteHandle(r), Actual360())
volatility = BlackConstantVol(0, TARGET(),
QuoteHandle(sigma), Actual360())


The Handle template class couldn’t be exported as such, because Python doesn’t have templates. Thus, the SWIG wrappers have to declare separate classes QuoteHandle, YieldTermStructureHandle and so on. In C++, you can go back to the original syntax.

shared_ptr<YieldTermStructure> riskFreeCurve =
make_shared<FlatForward>(0, TARGET(),
Handle<Quote>(r), Actual360());
shared_ptr<BlackVolTermStructure> volatility =
make_shared<BlackConstantVol>(0, TARGET(),
Handle<Quote>(sigma), Actual360());


Next,

In [6]: process = BlackScholesProcess(QuoteHandle(u),
YieldTermStructureHandle(riskFreeCurve),
BlackVolTermStructureHandle(volatility))


turns into

shared_ptr<BlackScholesProcess> process =
make_shared<BlackConstantVol>(
Handle<Quote>(u),
Handle<YieldTermStructure>(riskFreeCurve),
Handle<BlackVolTermStructure>(volatility));


and

In [7]: engine = AnalyticEuropeanEngine(process)


into

shared_ptr<PricingEngine> engine =
make_shared<AnalyticEuropeanEngine>(process);


So far, we’ve been calling constructors. Method invocation works the same in Python and C++, except that in C++ we might be calling methods through a pointer. Therefore,

In [8]: option.setPricingEngine(engine)

In [9]: print option.NPV()

In [10]: print option.delta()
print option.gamma()
print option.vega()


becomes

option.setPricingEngine(engine);

cout << option.NPV() << endl;

cout << option.delta() << endl;
cout << option.gamma() << endl;
cout << option.vega() << endl;


whereas

In [11]: u.setValue(105.0)


turns into

u->setValue(105.0);


Of course, the direct translation I’ve been doing only applies to the QuantLib code; I’m not able to point you to libraries that replace the graphing functionality in matplotlib, or the data-analysis facilities in pandas, or the parallel math functions in numpy. However, I hope that the above can still enable you to extract value from the cookbook, even if you’re programming in C++.

Follow me on Twitter if you want to be notified of new posts, or add me to your Google+ circles, or subscribe via RSS: the buttons for that are in the footer. Also, make sure to check my Training page.