QuEP 5: using replaceable pricing engines.

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

QuEP 5: using replaceable pricing engines.

johan bosaeus-2
Hi,
My first impression is that it is really good. Nice "pattern-thinking". A
possible extension could be
to make use of an abstract factory (Gang of Four, Design Patterns), in order
to create "sets" of
<parameter, result, engine and  instrument> objects. For example, one
subclass of such a factory
could be "EuropeanOptionWithXXEngineFactory". The create() method of that
class should create
all relevant objects and "link" them together the way you describe. What do
you think? I like using
the "Prototype pattern" also to provide object "sets" for an application.

You are using "degenerated" base classes for arguments and results. Have you
considered using a
template as the engine subclass instead. Where the template parameters
indicate which type of
parameters and results you are using as "strategies"? It's just an
alternative, which, of my
knowledge, is used extensively. (For example in ACE/TAO
(www.cs.wustl.edu/¨schmidt)).

                                        Nice suggestion indeed,
                                                                /Johan
Bosaeus




_________________________________________________________________
MSN Photos is the easiest way to share and print your photos:
http://photos.msn.com/support/worldwide.aspx



Reply | Threaded
Open this post in threaded view
|

Re: QuEP 5: using replaceable pricing engines.

Luigi Ballabio-4
Tjena Johan,
         thanks for the kind words.

At 03:25 PM 12/27/01 +0000, johan bosaeus wrote:
>A possible extension could be to make use of an abstract factory (Gang of
>Four, Design Patterns), in order to create "sets" of
><parameter, result, engine and  instrument> objects. For example, one
>subclass of such a factory could be "EuropeanOptionWithXXEngineFactory".
>The create() method of that class should create all relevant objects and
>"link" them together the way you describe. What do you think?

Well, I think this is an external layer that can be easily added on top of
the design. Being lazy though, I wouldn't start writing factories for all
the XXXOptionWithYYYEngines---I would probably write each of them as I need it.

Also, the QuEP didn't mention the possibility to create an option with an
engine and change it later (mostly because I didn't give it much thought)
but it would be straightforward to do it. In this case, it might be a bit
confusing to create the option with a strategy hidden inside a factory, and
later change the calculation model by explicitly passing the engine. For
instance, the following code (with Handles removed for clarity)

// here the option parameters (real-world quantities) are well separated
// from the engine and its own parameters (implementation details)
EuropeanOption opt(Option::Call, underlying, strike, dividendYield,
                    termStructure, maturity, volatility,
                    EuropeanMCEngine(accuracy));
// now we reprice it with another engine
opt.setEngine(AnalyticEuropeanEngine())

looks to me more consistent and less confusing than

// option and calculation parameters are not separated
EuropeanOption opt = EuropeanOptionWithMCEngine::create(
                          Option::Call, underlying, strike, dividendYield,
                          termStructure, maturity, volatility, accuracy)
// now we reprice it with another engine
opt.setEngine(AnalyticEuropeanEngine())
// what is this engine thing now? I didn't see it when I created the option.
// and what happened to accuracy anyway? Is it still used or is it lost?


>You are using "degenerated" base classes for arguments and results. Have
>you considered using a template as the engine subclass instead. Where the
>template parameters indicate which type of parameters and results you are
>using as "strategies"? It's just an alternative, which, of my knowledge,
>is used extensively. (For example in ACE/TAO (www.cs.wustl.edu/¨schmidt)).

I admit that the template design you suggest is not entirely clear to me,
so please do correct me if I'm wrong. I kind of suspect that the
templatization would propagate to the given option class, i.e., the option
should be an EuropeanOption<ParameterType,ResultType> in order to be able
to interact with an EuropeanEngine<ParameterType,ResultType>. I'd rather
trade this for a bit more run-time flexibility---such as the possibility of
setting a different engine to an already constructed option. Also,
scripting languages come to mind towards which we export the library, such
as Python. The latter doesn't know about templates, which means that two
different instantiations of the same template class would have to be
exported as two different classes in Python. This would be against the goal
of having, e.g., a single "European option" concept.

However, it might just be that I misunderstood your proposal---wouldn't be
the first time, either :)

Thanks again for the feedback,
                                 Luigi



Reply | Threaded
Open this post in threaded view
|

Re: QuEP 5: using replaceable pricing engines.

Luigi Ballabio-4
In reply to this post by johan bosaeus-2
At 11:25 PM 12/30/01 +0000, johan bosaeus wrote:

> >Well, I think this is an external layer that can be easily added on
> >top of the design. Being lazy though, I wouldn't start writing
> >factories for all the XXXOptionWithYYYEngines---I would probably
> >write each of them as I need it.
>
>Right. It's only when one need a few configuration options - that is a few
>object sets - and when each "object set" is quite complicated, my idea
>works well. Sure, one can view it as an external layer. However, my
>thought was, that if the framework provided an/a few interface(s) for such
>an abstract factory, each vendor could provide its own implementation of
>them. An analogy in TAO: There are Acceptor- and Connector registries
>which are abstract factories for creating transport protocols. If I tell
>TAO to use IIOP as transport, the corresponding subclass of the registries
>are created, and their create() methods will create all the objects I need
>to make use of this protocol. The implementation of those registries can
>be exchanged dynamically using the ACE Service Configurator. If you think
>one will make use of most combinations of <parameters, result, engine,
>instrument>, I do indeed agree with you though.
>
> >Also, the QuEP didn't mention the possibility to create an option
> >with an engine and change it later (mostly because I didn't give it
> >much thought) but it would be straightforward to do it. In this
> >case, it might be a bit confusing to create the option with a
> >strategy hidden inside a factory, and later change the calculation
> >model by explicitly passing the engine.
>
>Sure, I do agree, but I had hoped one could simply let the abstract
>factory encapsulate all those parameters. Such as:
>MyEuropeanOptionCalculator::create(). Sending the engine as a parameter
>(strategy) is nice though, and then in run-time substitute it for another one.

I'm kind of puzzled by this create() without arguments. Is this meant to
create an option instance, or an option calculator? The former is an
instrument with a definite identity, i.e., a given type, strike, underlying
instrument, etc. while the latter is not an instrument but rather a facility
which can instantiate an instrument and return its value. More explicitly, in
the first case the factory would be used as:

EuropeanOption option = MyEuropeanOptionCalculator::create();
double value = option.NPV();

while in the second case the use would be:

EuropeanOptionCalculator calculator = MyEuropeanOptionCalculator::create();
double value = calculator.NPV(underlying,strike,...);

In the first case, setting up the factory would require the same parameters
one would pass to the option constructor, so I don't see much use for the
former, unless you want to create the very same option over and over again.
But then you would have to create a factory per option, instead than a factory
per option _type_. In this case, I would rather store the option in some kind
of map and retrieve it later, as in:

EuropeanOption option = myGlobalOptionMap["optionCode"];
double value = option.NPV();

Instead, if it is a calculator that you want to create, it could be provided.
But then again, I would rather see it as a facility for an external layer
since Option instances are much more powerful. For one thing, an option object
stored somewhere can keep track of changes in the parameters it depends upon,
recalculate itself only when needed, and notify the change if asked to do so.
Calculator objects as the one outlined above would create Option instances
only temporarily, thus preventing this kind of "smart" calculation.
Furthermore, options could be grouped into portfolios and books were the
latter classes available (they will when we wrap our head around a decent
design). Doing the same with parameter sets together with the associated
calculators would be a lot more messy.


> >I admit that the template design you suggest is not entirely clear
> >to me, so please do correct me if I'm wrong. I kind of suspect that
> >the templatization would propagate to the given option class.
> >I'd rather trade this for a bit more run-time flexibility---such as
> >the possibility of setting a different engine to an already constructed
> >option.
>
>Well, my intention was that templatization wouldn't necessarily propagate
>to the option class nor restrict any run-time flexibility. Maybe I'm wrong
>though. It's just that I really don't like subclassing, unless it is
>necessary, because of its strong binding. When I feel it is necessary, is
>when I can say "this subclass IS A baseclass", and then I have some
>virtual methods to write. So, if one needs an arbitrary parameter type,
>such as the result or parameters, used by the engine, I would rather like
>the engine class look like:
>
>template<class PARAMETERS, class RESULT>
>class xxEngine {
>public:
>    xxEngine(PARAMETERS* param, RESULT* result);
>private:
>   PARAMETERS* _param;
>   RESULT* _result;
>}
>
>The engine could then use the use the parameters and result straight on,
>without any downcasting, which would be required when using "degenerated"
>base classes. It's perfectly OK then to subclass the template, provided
>it's done appropriately (you know, "subclasses should require no more and
>promise no less"), the engine would then, transparently, make use of C++
>polymorphic behaviour. Does it make sense for you?

Yes, it does now. Holidays must have obfuscated my brain somehow :)
However, I think templatization is orthogonal to the problem of avoiding
downcast in the engine. As a matter of fact, the latter is already implemented
in the proof-of-concept EuropeanEngine currently in the library: the
implementation is like (not precisely):

class OptionEngine {
   public:
     virtual Arguments* parameters() = 0;
     virtual const Results* results() const = 0;
     // etc.
};

class EuropeanEngine {
   private:
     EuropeanParameters parameters_;
     EuropeanResults results_;
   public:
     Arguments* parameters() { return &parameters_; }
     const Results* results() const { return &results_; }
     // etc.
};

so that the engine can already read the parameters and write the results
without downcasting.

The template class you propose, instead, is a useful device for making
declarations easier, just as inheriting from std::unary_function<This,That>
gives you a few useful typedefs for free. For instance, the above
EuropeanEngine declaration would be shortened to:

class EuropeanEngine : public xxEngine<EuropeanParameters,EuropeanResults> {
   public:
     Arguments* parameters() { return parameters_; }
     const Results* results() const { return results_; }
     // etc.
};

I'm pretty much in favor of adding this to the library.


>Sure, assume you pass a templatized engine as a parameter in the
>EuropeanOption as you described above, one need at least a template
>function. But the engine's base class can be a non-template! Does the
>option need to know the types of the result and parameters? If so, I think
>it boils down to whether that knowledge should be hard-coded as downcasts
>in the option and engine classes/subclasses or determined at creation
>through templates. Do you follow me?

Absolutely. The option doesn't need to know the _exact_ type of the results
and the parameters, therefore we don't need to templatize it (is this a real
word, or am I making it up?) The key is defining a number of classes
corresponding to small parameter groups; then the full parameter structure can
be built by multiple inheritance. What the option does is just to test whether
the parameter/result pointer can be downcasted to the type it needs. The exact
type could even be hidden from the option, as in:

class MyOptionEngine {
   private:
     // parameter class defined on the fly and private
     class MyPrivateParametersClass : public OptionParams,
                                      public UnderlyingParams,
                                      etc. {};
     // the same for results
     class MyPrivateResultsClass : public OptionValue,
                                   public OptionGreeks {}
     // instances
     MyPrivateParametersClass parameters_;
     MyPrivateResultsClass results_;
   public:
     Arguments* parameters() { return &parameters_; }
     const Results* results() const { return &results_; }
     etc.
};

void MyOption::setupEngine() const {
     // get the pointer to base class
     Parameters* params = engine_->parameters();
     // I want to set the option parameters, so I try to cast to
     // the corresponding parameter group
     OptionParams* optionParams = dynamic_cast<OptionParams*>(params);
     if (optionParams != 0) {
         // succeeded
         optionParams->type = Call;
         optionParams->strike = 100.0;
         // etc.
     } else {
         // take some action, most probably raise an error
     }
     // the same goes for other parameter groups
}

void MyOption::performCalculations() const {
     // trigger the calculation in the engine
     engine_->calculate();
     // collect the results
     // get the pointer to base class
     const Results* results = engine_->results();
     const OptionValue* optionValue =
         dynamic_cast<const OptionValue*>(results);
     if (optionValue != 0) {
         // succeeded
         NPV_ = optionValue->value;
     } else {
         // raise an error since this is a required result
     }
     // now check whether the engine could calculate greeks as well
     const OptionGreeks* greeks =
         dynamic_cast<const OptionGreeks*>(results);
     if (greeks != 0) {
         // succeeded
         delta_ = greeks->delta;
         etc.
     } else {
         // take some action - maybe we won't raise an error here
         // but rather just signal that greeks are not available
     }
}


>Well, exporting templates to Python seems to be a bit of a problem.

Yes, but luckily it is one we avoided since we cleared up how templates are
to be used. They won't show up in Python this way.


Thanks for your observations---forcing me to clarify these matters will be
of great help the day I have to write some documentation on this.

Bye,
         Luigi