NB: This document is out of date. The QuantLibAddin implementation still reflects the high-level ideas in this document but many of the details have changed. For further information please refer to the QuantLibAddin source code or send email to quant. lib- users @lis ts.sf .net |
Abstract
QuantLibAddin implements an interface supporting a subset of QuantLib functionality. Constructor, member and utility functions are defined in XML metadata from which a Python application generates source code for supported platforms. The ObjectHandler repository is used to provide an object oriented environment even on procedural platforms such as spreadsheets - QuantLib objects may be constructed, interrogated, passed as arguments to other functions, and destructed. Polymorphism is supported, for example function qlNPV returns the NPV of an Instrument and can be invoked on an instance of any derived class - Swap, Bond, etc.
Contents
1. Design
QuantLibAddin uses ObjectHandler to allow the user to build up a repository of QuantLib objects. Each QuantLib class to be available in QuantLibAddin is wrapped in a class descended from Object.
The core QuantLibAddin library can be loaded directly into standalone C++ programs. For other platforms, QuantLibAddin is wrapped in an additional layer providing platform-specific functionality. QuantLibAddin has the same interface on all platforms.
1.1 Classes
The class for each QuantLib object to be stored in ObjectHandler is wrapped in a class derived from Object
. The constructor of the derived Object class calls the constructor of the corresponding QuantLib class, and the resulting QuantLib object is stored as a member variable of the derived Object. The Propery vector in the base Object class is populated appropriately.
1.2 Addins
The core QuantLibAddin binary can be linked directly into end-user C++ applications. For other platforms, QuantLibAddin is linked into a platform-specific library which:
- retrieves inputs in native format from host application
- converts inputs to QuantLib format
- invokes the QuantLibAddin function and captures its return value
- converts the return value to native format and returns it to the host application
The above is wrapped in try/catch. All Addins use standard calls to log exceptions to the QuantLibAddin log file, and may perform addition platform-specific error handling e.g. throwing a new exception for the host application.
1.3 Clients
The client application loads QuantLibAddin, instantiating a single global instance of ObjectHandler. QuantLibAddin functions allow objects to be constructed, interrogated, modified, and passed as input parameters to constructors / member functions of other objects. Objects can be deleted explicitly, otherwise ObjectHandler destroys all objects in its repository when it is destroyed.
2 Implementation
The example below illustrates an implementation of QuantLibAddin and clients, including three QuantLibAddin functions which
- construct a BlackScholesProcess from native datatypes
- construct a VanillaOption from the BlackScholesProcess and native datatypes
- change the Pricing Engine of the VanillaOption.
The example demonstrates how objects may be created, passed as inputs to constructors of other objects, manipulated, and destroyed. The example includes pseudocode, the latest development code can be checked out from the QuantLib CVS repository (module QuantLibAddin) or browsed on line.
2.1 Classes
qla/processes.hpp
qla/processes.cpp
qla/vanillaoption.hpp
qla/vanillaoption.cpp
2.2 Addins
The QuantLibAddin library can be linked directly into an end-user C++ application. For other platforms, QuantLibAddin is wrapped in a further addin providing platform specific functionality. Below is the code for an Excel addin function.
Addins/Excel/options.cpp
2.3 Clients
2.3.1 C++
Example of a standalone C++ client application.
Clients/C++/qlademo.cpp
Output of the above program:
2.3.2 Excel
Same again with cell formulas instead of values:
A description of each section of the spreadsheet:
-
Construct an object from native datatypes: Cell formula qlBlackScholesProcess is called to construct a Black Scholes object from numeric values. The formula accepts a 'handle stub' argument which is automatically decorated to create a unique
Handle
for the object in the ObjectHandler repository. -
Construct an object from native datatypes & other objects: The Black Scholes object created above is passed as an input to qlVanillaOption() which creates an option. Note that only a reference to the cell containing the Black Scholes object - C12 - is passed to qlVanillaOption(). The Addin autmatically accesses cell C12, retrieves the
Handle
of the Black Scholes object ("stoch1~_0000a"), retrieves the Black Scholes object from ObjectHandler, and passes the object as an argument to the Vanilla Option constructor. qlVanillaOption() returns the decoratedHandle
of the new Vanilla Option object, which is passed to formula qlNPV() to display the NPV of the option. -
interrogate an existing object with no prior knowledge of its structure: ohObjectPropertyNames() is called on the
Handle
returned from qlVanillaOption() to get the Object's Property vector. -
Invoke a method of an existing object: The
Handle
of the option is passed to qlOptionSetEngine() which changes the option's pricing engine, reprices the option, and returns the changed state. Note that qlOptionSetEngine() acts on the option stored above in cell C25 - the option object is amended in situ in ObjectHandler.
The interfaces for other spreadsheet Addins are the same and spreadsheets can be shared verbatim between the various products.
3. Autogeneration
The code for the platform-specific addins consists of
- structure - This refers to registration with the host application etc.
- business functionality - The platform-specific implementation of each QuantLibAddin function
The code for each addin's structure is relatively static, this code is written manually when the Addin is created. The code for the business functionality is completely dependent upon the interface defined for QuantLibAddin, this code is generated automatically each time the interface is enhanced.
Autogeneration is accomplished with a Python application, containing one module for each target platform. The application is supplemented with XML files describing the metadata for each function in the QuantLibAddin interface, e.g.:
<Constructor name='qlVanillaOption'> <description>construct and return a handle to a Vanilla Option object</description> <libraryFunction>VanillaOption</libraryFunction> <functionCategory>QuantLib</functionCategory> <Parameters> <Parameter name='handleBlackScholes' libraryClass='BlackScholesProcess'> <type>string</type> <tensorRank>scalar</tensorRank> <description>handle of a Black Scholes Process object</description> </Parameter> <Parameter name='optionType'> <type>string</type> <tensorRank>scalar</tensorRank> <description>option type</description> </Parameter> ... </Parameters> </Constructor>
The autogeneration script loads the metadata from the XML files and passes this to each platform-specific module which automatically generates the business functionality for that Addin, which is then recompiled.