Policy-Based Design/Templates/Quantlib

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

Policy-Based Design/Templates/Quantlib

Nehal Patel

Hi,

            I'm trying to get my head around using policy based design in C++ using templates; it seems that quantlib uses this approach a lot.  My basic question involves trying to figure out under what circumstances templates should be utilized in certain design features (with regard to policy based design - not so much with regards to generic container classes etc.)  As an example, imagine I was going to create a Bond class; I might do it as follows:

 

class Bond : public Security {

protected:

            PrinicipalSchedule principalSchedule;

            CouponSchedule couponSchedule;

            TerminationProvision terminationProvision;

            DefaultGuarantee defaultProvision;

      public: 

      //various useful methods go here

}

 

The basic idea is to abstract away certain things to provide enough flexibility to deal with issues like callabillity, amortizations,  bizarre payment dates, whatever.  Of course classes like TerminationProvision would have to be carefully crafted in order to handle the wide variety in which bonds can cease to exist.  This class would be used by various pricing engine objects to perform calculations.  But in any case I would think that my approach is more or less what someone with a Java background would attempt - with the understanding that occasionally some situations might require using 'instanceof'.

 

My question then is: in c++ is the above approach optimal or is there some more powerful paradigm that would utilize templated classes?

 

Or more relevant to quantlib:

Can someone elaborate on why SwaptionPricer is templated:

 

template<class ModelType>

        class SwaptionPricer : public PricingEngine,

                               public Patterns::Observer,

                               public Patterns::Observable

 

 

as opposed to something like

 

class SwaptionPricer : public PricingEngine,

                  public Patterns::Observer,

                  public Patterns::Observable  {

 

      Handle<SwaptionModel> model_;

 

}

 

class SwaptionModel {

            SwaptionResults calcSwaption(SwaptionParameters parameters);

}

 

 

Thanks,

Nehal

Reply | Threaded
Open this post in threaded view
|

RE: Policy-Based Design/Templates/Quantlib

Lou, Wujiang

This kind of template design for pricer (see after ==>) is less preferred in a trading system because in cases where multiple models are available for the same instrument, the trading system typically allows users to configure their model choice and let them switch around. This dynamic behavior vs the static polymorphism nature of template is mind twisting.

But quantlib may have other concerns that led to its current pricer design.

-Lou, Wujiang

-Zurich Capital Markets

 

==>

Or more relevant to quantlib:

Can someone elaborate on why SwaptionPricer is templated:

 

template<class ModelType>

        class SwaptionPricer : public PricingEngine,

                               public Patterns::Observer,

                               public Patterns::Observable

-----Original Message-----
From: Nehal Patel [mailto:[hidden email]]
Sent: Friday, July 11, 2003 11:20 AM
To: '[hidden email]'
Subject: [Quantlib-users] Policy-Based Design/Templates/Quantlib

Hi,

            I'm trying to get my head around using policy based design in C++ using templates; it seems that quantlib uses this approach a lot.  My basic question involves trying to figure out under what circumstances templates should be utilized in certain design features (with regard to policy based design - not so much with regards to generic container classes etc.)  As an example, imagine I was going to create a Bond class; I might do it as follows:

 

class Bond : public Security {

protected:

            PrinicipalSchedule principalSchedule;

            CouponSchedule couponSchedule;

            TerminationProvision terminationProvision;

            DefaultGuarantee defaultProvision;

      public: 

      //various useful methods go here

}

 

The basic idea is to abstract away certain things to provide enough flexibility to deal with issues like callabillity, amortizations,  bizarre payment dates, whatever.  Of course classes like TerminationProvision would have to be carefully crafted in order to handle the wide variety in which bonds can cease to exist.  This class would be used by various pricing engine objects to perform calculations.  But in any case I would think that my approach is more or less what someone with a Java background would attempt - with the understanding that occasionally some situations might require using 'instanceof'.

 

My question then is: in c++ is the above approach optimal or is there some more powerful paradigm that would utilize templated classes?

 

Or more relevant to quantlib:

Can someone elaborate on why SwaptionPricer is templated:

 

template<class ModelType>

        class SwaptionPricer : public PricingEngine,

                               public Patterns::Observer,

                               public Patterns::Observable

 

 

as opposed to something like

 

class SwaptionPricer : public PricingEngine,

                  public Patterns::Observer,

                  public Patterns::Observable  {

 

      Handle<SwaptionModel> model_;

 

}

 

class SwaptionModel {

            SwaptionResults calcSwaption(SwaptionParameters parameters);

}

 

 

Thanks,

Nehal



This email and any attachments are confidential and may be

legally privileged. No confidentiality or privilege is waived

or lost by any transmission in error. If you are not the

intended recipient you are hereby notified that any use,

printing, copying or disclosure is strictly prohibited.

Please delete this email and any attachments, without

printing, copying, forwarding or saving them and notify the

sender immediately by reply e-mail. Zurich Capital Markets

and its affiliates reserve the right to monitor all e-mail

communications through its networks. Unless otherwise

stated, any pricing information in this e-mail is indicative

only, is subject to change and does not constitute an offer

to enter into any transaction at such price and any terms in

relation to any proposed transaction are indicative only and

subject to express final confirmation.

Reply | Threaded
Open this post in threaded view
|

RE: Policy-Based Design/Templates/Quantlib

Luigi Ballabio-2
In reply to this post by Nehal Patel
Hi all,
         sorry, I don't have much time for answering at lenght---it will
have to wait a few days. However:

At 09:14 AM 7/14/03 -0400, Lou, Wujiang wrote:
>This kind of template design for pricer (see after ==>) is less preferred
>in a trading system because in cases where multiple models are available
>for the same instrument, the trading system typically allows users to
>configure their model choice and let them switch around. This dynamic
>behavior vs the static polymorphism nature of template is mind twisting.

run-time polymorphism is not prevented by the current design. In general,
compile-time and run-time polymorphism do not exclude each other--they can
be mixed, as in:

class Model {
   public:
     virtual void foo() = 0;
};

class SomeInstrument {
   public:
     double calculate(Model* m);
};

template <class Policy1, class Policy2=SomeDefault>
class Foo : public Model {
   public:
     void foo() { /* whatever, using the chosen policies */ }
};

Model* modelFactory(int tag) {
     switch (tag) {
       case 1:
         return new Foo<SomePolicy>;
       case 2:
         return new Foo<SomeOtherPolicy>;
       case 3:
         return new Foo<SomeOtherPolicy,NotTheDefault>;
       default:
         return NULL;
     }
}

int main() {

     std::cout << "Choose a model:" << std::endl;
     std::cout << "[1]: vanilla-flavored" << std::endl;
     std::cout << "[2]: peppermint-flavored" << std::endl;
     std::cout << "[3]: caffeinated" << std::endl;

     Model* model;
     int tag;
     std::cin >> tag;
     model = modelFactory(tag);
     while (model == NULL) {
         std::cout << "Wrong choice, try again" << std::endl;
         std::cin >> tag;
         model = modelFactory(tag);
     }

     SomeInstrument i;
     std::cout << "Your result is " << i.calculate(model) << std::endl;
     delete model;

     return 0;
}

et voila', run-time polymorphism! (of course in a real trading system the
factory would be called behind a configuration window with checkboxes and
stuff, and it would be passed more arguments based on which the correct
model is to be chosen.)

Later,
         Luigi

P.S. Also, you can easily turn compile-time polymorphism into run-time
polymorphism by means of a polymorphic proxy class, but you can't do the
opposite...



Reply | Threaded
Open this post in threaded view
|

RE: Policy-Based Design/Templates/Quantlib

Nehal Patel
In reply to this post by Nehal Patel
Thanks for the post(s).  For whatever reason I have yet to get a good grasp
on the benefits of compile time polymorphism/templates -- that is: how does
one identify which situations are good for applying templates (again
ignoring the standard examples of containers or generic algorithms or smart
pointers)?  At this point, the major benefits seem to be: 1) Ability to
avoid certain runtime, type check errors 2)Ability to produce optimized code
in certain situations (for instance you can get away with inline expansion
in some cases for which normal runtime polymorphism would have lead to an
indirection + real function call).  I guess at the end of the day, templates
provide a way of providing optimized code without sacrificing too much of
the design?  The tradeoff is that it is not easy to document the "required"
interface for a class template parameter(but of course the compiler will
quickly tell you if you try to use a class with an incomplete interface for
a given template -- but of course the error message will be  book-lengthed
and utterly unintelligible :)  Anyway I guess I am looking for a killer
example of some templated policy design that would have been difficult to
achieve using an inner class member variable with a fixed interface.

Cheers, nehal



-----Original Message-----
From: Luigi Ballabio [mailto:[hidden email]]
Sent: Monday, July 14, 2003 11:34 AM
To: [hidden email]
Subject: RE: [Quantlib-users] Policy-Based Design/Templates/Quantlib


Hi all,
         sorry, I don't have much time for answering at lenght---it will
have to wait a few days. However:

At 09:14 AM 7/14/03 -0400, Lou, Wujiang wrote:
>This kind of template design for pricer (see after ==>) is less preferred
>in a trading system because in cases where multiple models are available
>for the same instrument, the trading system typically allows users to
>configure their model choice and let them switch around. This dynamic
>behavior vs the static polymorphism nature of template is mind twisting.

run-time polymorphism is not prevented by the current design. In general,
compile-time and run-time polymorphism do not exclude each other--they can
be mixed, as in:

class Model {
   public:
     virtual void foo() = 0;
};

class SomeInstrument {
   public:
     double calculate(Model* m);
};

template <class Policy1, class Policy2=SomeDefault>
class Foo : public Model {
   public:
     void foo() { /* whatever, using the chosen policies */ }
};

Model* modelFactory(int tag) {
     switch (tag) {
       case 1:
         return new Foo<SomePolicy>;
       case 2:
         return new Foo<SomeOtherPolicy>;
       case 3:
         return new Foo<SomeOtherPolicy,NotTheDefault>;
       default:
         return NULL;
     }
}

int main() {

     std::cout << "Choose a model:" << std::endl;
     std::cout << "[1]: vanilla-flavored" << std::endl;
     std::cout << "[2]: peppermint-flavored" << std::endl;
     std::cout << "[3]: caffeinated" << std::endl;

     Model* model;
     int tag;
     std::cin >> tag;
     model = modelFactory(tag);
     while (model == NULL) {
         std::cout << "Wrong choice, try again" << std::endl;
         std::cin >> tag;
         model = modelFactory(tag);
     }

     SomeInstrument i;
     std::cout << "Your result is " << i.calculate(model) << std::endl;
     delete model;

     return 0;
}

et voila', run-time polymorphism! (of course in a real trading system the
factory would be called behind a configuration window with checkboxes and
stuff, and it would be passed more arguments based on which the correct
model is to be chosen.)

Later,
         Luigi

P.S. Also, you can easily turn compile-time polymorphism into run-time
polymorphism by means of a polymorphic proxy class, but you can't do the
opposite...



-------------------------------------------------------
This SF.Net email sponsored by: Parasoft
Error proof Web apps, automate testing & more.
Download & eval WebKing and get a free book.
www.parasoft.com/bulletproofapps1
_______________________________________________
Quantlib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users


Reply | Threaded
Open this post in threaded view
|

RE: Policy-Based Design/Templates/Quantlib

Luigi Ballabio-2
At 01:19 PM 7/14/03 -0400, Nehal Patel wrote:
>Thanks for the post(s).  For whatever reason I have yet to get a good grasp
>on the benefits of compile time polymorphism/templates -- that is: how does
>one identify which situations are good for applying templates (again
>ignoring the standard examples of containers or generic algorithms or smart
>pointers)?

As a very, very rough rule of thumb, I'd use run-time polymorphism for
interfaces and compile-time polymorphism for implementations. Something like:

class Engine {
   public:
     virtual void calculate() const = 0;
};

template <typename T, class Policy>
class SomeEngine : public Engine {
   public:
     void calculate() const;
};

but I'm sure there are very obvious counter-examples to the above. I mostly
go by gut-feeling myself...

>At this point, the major benefits seem to be: 1) Ability to
>avoid certain runtime, type check errors

True, and it can go way further than you would expect: for an application
we won't be using in QuantLib, see

http://oonumerics.org/tmpw01/brown.pdf

where templates are used for (brace yourself) compile-time dimensional
analysis of physical formulas...

>2)Ability to produce optimized code in certain situations (for instance
>you can get away with inline expansion in some cases for which normal
>runtime polymorphism would have lead to an indirection + real function call).

Also, compilers often cannot do their fancy optimizations around virtual
calls. And adding up inlining and optimization you can save quite a few
cycles, as you just found out for the BermudanSwaption example...

>I guess at the end of the day, templates provide a way of providing
>optimized code without sacrificing too much of the design?

Yes. Also, 3) with run-time polymorphism you can have virtual methods, but
not "virtual types", while templates allow you to use traits---see e.g.

http://www.moderncppdesign.com/publications/traits.html


>   The tradeoff is that it is not easy to document the "required"
> interface for a class template parameter (but of course the compiler will
> quickly tell you if you try to use a class with an incomplete interface
> for a given template -- but of course the error message will be
> book-lengthed and utterly unintelligible :)

I agree---the required interface should be documented.


>Anyway I guess I am looking for a killer example of some templated policy
>design that would have been difficult to achieve using an inner class
>member variable with a fixed interface.

Hmm, I don't really know about killer apps... for a survey of template
programming and its use for efficient calculations, you can have a look at

http://osl.iu.edu/~tveldhui/papers/techniques/techniques.ps

For examples of what is possible to do with templates, see Todd
Veldhuizen's papers at

http://osl.iu.edu/~tveldhui/papers/

and Andrei Alexandrescu's at

http://www.moderncppdesign.com/publications/


Later,
         Luigi



Reply | Threaded
Open this post in threaded view
|

Instruments, Arguments, Results and Pricing Engines

Neil P Firth
Hello,

Before taking on Basket options I thought I'd port the Barrier option code
to the PricingEngine framework, and then attempt Monte Carlo for
Barriers.

I need some guidance on the separation of concerns of the different
directories. I think that it would be cleanest if all enum declarations
(for OptionType, BarrierType, CapFloor::Type) were in the same location.
It would also make sense if we had a pattern for the declarations for
Arguments and Results, currently some are in with the Instruments, and
some are in with the PricingEngines.

I suggest that the Instruments have 'ownership' of their Arguments and
Results, as there may be many Engines for each Instrument (I realise it is
actually a many-to-many relationship). This would mean, for example,
moving the VanillaOptionArguments from vanillaengines.hpp to
vanillaoption.hpp. There should then be no references to specific
PricingEngines in the Instruments.

Any suggestions / objections / comments?

Thanks,
Neil

---------------------------------------------------
  Neil Firth
  Brasenose College Oxford OX1 4AJ United Kingdom
  Office: 01865 280616
  [hidden email]
  http://www.maths.ox.ac.uk/~firth
---------------------------------------------------


Reply | Threaded
Open this post in threaded view
|

Re: Instruments, Arguments, Results and Pricing Engines

Luigi Ballabio-2
In reply to this post by Luigi Ballabio-2
Hi Neil,

At 03:57 PM 9/4/03 +0100, Neil P Firth wrote:
>I need some guidance on the separation of concerns of the different
>directories. I think that it would be cleanest if all enum declarations
>(for OptionType, BarrierType, CapFloor::Type) were in the same location.

Hmm, except for the fact that e.g., Option::Type lives inside Option and
CapFloor::Type inside CapFloor... there's hope, but I don't think I'm
tackling this right now.


>It would also make sense if we had a pattern for the declarations for
>Arguments and Results, currently some are in with the Instruments, and
>some are in with the PricingEngines.
>
>I suggest that the Instruments have 'ownership' of their Arguments and
>Results, as there may be many Engines for each Instrument (I realise it is
>actually a many-to-many relationship). This would mean, for example,
>moving the VanillaOptionArguments from vanillaengines.hpp to
>vanillaoption.hpp. There should then be no references to specific
>PricingEngines in the Instruments.

Yes, I second that. Incidentally, this also goes towards moving the engine
machinery up to the Instrument class (right now it's in Option only.)
I guess I'll have to see whether there's some way to abstract the
instrument/arguments/result/engine thing so that it's easier to declare...

Later,
         Luigi