Financial instruments are assets that can be traded and thus have a financial value attached to them. The value is usually expressed by the net present value (NPV) which is the financial value of the instrument at a given date. QuantLib defines a base class Instrument which forms the base for all financial instruments. This is an abstract class and it derives from LazyObject. This means that the actual evaluation of the NPV and any additional data is performed in the performCalculations() method. Instrument implements a default version of this method that uses an object of type PricingEngine do do the actual calculations. We will not go into the details of PricingEngine here; instead we will present a short introduction into the methods provided by the Instrument base class.
The Instrument constructor, Instrument(), does not take any arguments. Derived classes will change this to include the data needed to evaluate the NPV of the instrument. Three methods give access to the evaluated data.
Real NPV() const; Real errorEstimate() const; const Date& valuationDate() const;
NPV() returns the net present value, errorEstimate() returns an estimate of the error contained in the NPV, and valuationDate() returns the date at which the instrument is valued. These methods are defined as const, since they apparently only access the underlying data. Because Instrument is a LazyObject these methods do, however, call the performCalculations() method which updates the internal data if necessary. Depending on the type of instrument, there may be additional data calculated along with the core values of NPV and the error estimate. These can be retrieved using the generic result() method.
template <typename T> T result(const std::string& tag) const;
This method takes the name of the result as argument and returns the value of that result. The caller of the result() method must know the type of the data that is stored under the given name. For example Swaption, which indirectly inherits from Instrument, also calculates the vega of the swaption. Imagine you have a Swaption object called swaption, then the vega can be accessed in the following way.
Real vega = swaption.result<Real>("vega");
Internally the additional results are stored in a STL map containing the names of the results as keys. The values are stored in boost::any objects. This allows any kind of data to be stored in the map but places the responsibility on the user to know exactly what type of data is stored. The complete map can be accessed through additionalResults().
const std::map<std::string,boost::any>& additionalResults() const;
This method just returns a constant reference to the internally kept map of additional results. The results contained in the map depend on the implementation of the specific instrument class or, alternatively, the implementation of the pricing engine if this is used.
virtual bool isExpired() const = 0;
Because Instrument is derived from LazyObject it implements the method performCalculations().
protected: virtual void performCalculations() const;
The default implementation of performCalculations() uses a pricing engine, derived from PricingEngine, to carry out the calculations. This default implementation makes sure that the right arguments are passed to the pricing engine and that they are validated for consistency before calculations are carried out. Finally it copies the results from the pricing engine to instrument’s internal fields. I will go into the details of pricing engines in a separate post. If the instrument should not use a pricing engine to calculate the results the performCalculations() method should be overridden. If a pricing engine is used it can be set with the setPricingEngine() method.
void setPricingEngine(const boost::shared_ptr<PricingEngine>&);
The following two methods are needed when a pricing engine is used. They are defined public but usually don’t need to be called because they are called from within performCalculations().
virtual void setupArguments(PricingEngine::arguments*) const; virtual void fetchResults(const PricingEngine::results*) const;
The method setupArguments() sets up the arguments for the pricing engine to calculate the results. But note that the default implementation will throw an exception if called. This means that setupArguments() must be implemented if a pricing engine is used! If, on the other hand, the performCalculations() method is overridden and doesn’t use a pricing engine, then setupArguments() is not needed and doesn’t have to be implemented. The method fetchResults() fetches the NPV, the error estimate and any additional results from the pricing engine and stores them in the internal fields of the Instrument class.
protected: virtual void calculate() const;
Instrument overrides the calculate() method of the LazyObject class. As discussed in the post about lazy evaluation, this is not generally needed for lazy objects. Instrument modifes the existing behaviour to check for expiration of the instrument. If the instrument has expired then the NPV and error estimate is simply set to zero by calling and no evaluation takes place. If the instrument is not expired, the calculate() method of the parent class LazyObject is called to update the data.
protected: virtual void setupExpired() const;
This method is called when the instrument is expired to set the NPV and the error estimate to zero in case the instrument has expired. All the additional results are cleared from the internal storage and should not be accessed once this method has been called. If any other data should be cleared or any other action should be taken the setupExpired() method needs to be overridden. In that case it should be ensured, however, that the parent’s setupExpired() method is called.