Monte Carlo for Interest Rates derivatives
The valuation problem
Let us consider an instrument 1 ,
, that pays the following
cash–flows
on dates
At this stage we do not really care what type of cash–flows represent. Let us just
consider them to be random.
The problem we face when pricing such a derivative is of calculating
the following expected value 2 where:
is the expectation operator;
represents the risk–neutral measure chosen;
is the value of the numeraire linked to the pricing measure
with expiry
.
The pricing–measure / numeraire problem
We left unspecified the choice of pricing measure and numeraire
in Eq. [eqn:pricing] as that might change
depending on applications.
Typically we can expect to be using on of the following pricing measures for calculating prices and risks of a derivative:
risk–neutral measure. This is usually denoted by
and its numeraire by
, defined as
–terminal measure. This is usually denoted by
. The numeraire associated to it is the zero–coupon bond with maturity
. Its price at time
is denoted by
.
TODO add others
What all these choices have in common is that they all depend on interest rates. This means that in pricing IR derivatives (or, in fact, hybrid derivatives), our Monte Carlo engine must be able to consistently apply modelling rules both to cashflows and numeraires.
Main classes
In the following sections, we will describe what are the responsibilities of the main classes involved in the valuation/risk calculation problem:
the concept of a Monte Carlo model is discussed in 1.2;
the concept of a payoff is discussed in
a Monte Carlo engine is discussed in.
Monte Carlo model
State variables representation
The first building block of a Monte Carlo model in our context is
simulating the model state variables. Let us refer to them as .
In particular, what we expect from such model is the definition of the state variables dynamics:
Meta programming techniques in C++
Polymorphism
Dynamic polymorphism
By dynamic dispatch we mean the usual virtual function based inheritance mechanism:
class base
{
public:
virtual void do_something() const = 0;
*@/*\marginpar{Dynamic polymorphism example}*/ @*
}
class derived : public base
{
public:
virtual void do_something() const override
{
//...;
}
}This approach has its advantages. The main one is that both base and derived classes are fully defined classes. This allows the compiler to know exactly what their size is at runtime. This makes possible to use pointers to base class
base* b;
b = new derived(/*...*/);to achieve polymorphic behaviour from a function that expects a base type
void function_on_base(base* arg){ \* ...*\};A function like that can be invoked with a derived type pointer as argument
vfunction_on_base(b);Moreover, homogeneous containers can be used to store pointers to base class objects, even though each element of the vector can be of a different derived type:
std::vector<base*> v;
v.push_back(new derived(\*...*\));Regrettably, this approach ha also disadvantages when it comes to performances. Given that the hierarchy structure can be as deep as a programmer want, the compiler doesn’t know when to stop looking for overrides. As a result, virtual functions cannot be inlined.
Inline
TODO explain
Static polymorphism
Static polymorphism, on the other hand, does not rely on virtual functions. TODO mention burtle and noble book
template<class derived>
class base
{
const derived& true_this() const
{
return static_cast<const derived&>(*this);
*@/* \marginpar{static\_cast can be used
to traverse the class hyerarchy}*/ @*
}
public:
void do_something() const
{
true_this().do_something();
*@/* \marginpar{and base can statically
dispatch to derived implementation}*/ @*
}
};
class derived : public base<derived>
{
public:
void do_something() const
{
//...;
}
};