Re: TermStructures (Oleg Burundukov)

Posted by Luigi Ballabio on
URL: http://quantlib.414.s1.nabble.com/Re-TermStructures-Oleg-Burundukov-tp11775p11777.html

On Wed, 2008-03-19 at 15:28 +0000, Oleg Burundukov wrote:

> > Hi Oleg, & list,both of the first two layers are really interfaces:- the
> first says what you get- the second (interpolated) says that if you already
> know the answer here is what you get, as you say a data representation.- the
> third layer says how to build something on the second [...]  I would argue (am
> arguing ) against combining levels two and three because combining them would
> force the second layer (interpolated) to be made in a certain way from a
> certain set of input data.
>
>
> I agree with you and the idea to separate level 2 and level 3. Although , ways
> to do this may differ. It would be nice to discuss which is the best.  
> [However,  what I propose may require too large volume of changes.]
>
>
> For sake of clarity let's postulate following:
> Level 2 comprises of static data and collateral methods, all but bootstrapping.
> It also _implements_ what level 1 defines, therefore instances of level2 are  
> creatable. Level 3 subclasses level2, aggregates  the bootstrap and makes curve
> observable.

Hi Oleg,
        just for the sake of clarity: level 1 is already observable. What level
3 adds is lazy calculation.


> Should one level 2 be different from another , if _implementation_ is somewhere
> outside ? Not likely. Data containers and all manipulations with them seem to
> be copied from class to class.

Unfortunately, the level 2 classes are all different.  Each of the
curves implements a different interface.  InterpolatedDiscountCurve
implements the abstract discountImpl() method in YieldTermStructure;
InterpolatedZeroCurve implements zeroImpl() from the ZeroStructure
adapter; and InterpolatedForwardCurve implements forwardImpl() from the
ForwardStructure adapter.  The inflation and credit curves implement
other interfaces.


> Should level 3 be a subclass of level 2?  What if bootstrap is just another
> object, the observer linked to instrument helpers? Then , the curve is
> essentially level2, with _implementation_ and data arrays has been filled up by
> extern  bootstrap.  We pay for having another instance, bootstrap, in the
> program.  But does not this decouple bare curve and its bootstrap?

I was under the impression that the base curve(s) and the bootstrap were
pretty much decoupled already---the generic bootstrap class does the
filling for all curves, and the piecewise curves are only a thin layer
over level 2 that call the bootstrap instance.  Having the bootstrap as
an external instance (as opposed to a data member) doesn't give us much
of an advantage---especially since the curve would then have to register
with the bootstrapper, and thus store it as a data member implicitly.


> What prevents us from separating bootstrap and curve?  Bootstrap uses very
> limited set of operations to modify curve points. Basically, these are: reset
> (size), add(time, value), set(index, value). All these interpolator->update()
> look redundant, because we should assume that the bare curve knows about how to
> update its interpolator _better_ than bootstrap does. So we can decouple them
> to having just a common interface, e.g. CurveBuildStrategy.

Here we agree completely.  It is indeed possible to create a generic
InterpolatedCurve<Interpolation> class that stores the data and the
methods to manipulate them, and that the interpolated curves can inherit
from. Unfortunately, we'd still need all level 2 curves because they
have to implement different interfaces; but their common code would be
written just once in InterpolatedCurve.  I'd be happy to include the
class in the library.


> What keeps bootsrapper inside the level 3 _now_  is observability, namely, the
> issue with calling calculate() inside every member. Since bootstrap is
> separate, curve has to be able to wake it. It can be done surprisingly simple.

It's not only observability---it's also laziness.  But let's start with
observability.  Let's say the bootstrap is an external object and stores
the helpers itself.  We instantiate it, we ask it to create a curve, and
pass the curve to an instrument.  The instrument has to be notified when
the value of a helper quote changes.  Also, the instrument should not
know that a bootstrap is involved; it only knows it holds a
YieldTermStructure instance.

This means that either:
a) the term structure registers as an observer of the bootstrap, and
asks the bootstrap to redo its magic when needed. But this requires the
curve to store the bootstrap, so I guess this isn't what you had in
mind.
b) the bootstrap observes the helpers, and makes sure the curve is up to
date whenever they change by performing the calculation.  However, this
causes us to lose laziness.  If the curve is based on, say, ten helpers,
and we want to change the value of all ten, this implementation would
cause 10 bootstrap to be performed, nine of which we didn't need---only
the final one gives us the result we wanted.  In the current
implementation, instead, setting the ten values just flips a boolean
flag, and only one bootstrap is performed when we ask the curve for
data.  (Incidentally, we could already remove all the calculate() calls
by calling it just once inside the curve update() method. But we would
have the same issue with the ten bootstraps.)

Later,
        Luigi


--

Flon's Law:
There is not now, and never will be, a language in
which it is the least bit difficult to write bad programs.



-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev