Sorry my reply to Luigi's was mistakely posted directly to him. Here it is
again. Luigi, Let me go at this using an example. Say you want a piece of code used to price any swap instrument. The calendar to use being passed in as a parameter. One way of doing it would be: double priceSwap(Calendar aCal) { Code goes here to price... } int main(argc, argv[]) { if (!strcmp(argv[1], "JHB")) std::cout << priceSwap(Johannesburg()); else if (!strcmp(argv[1], "HLK")) std::cout << priceSwap(Helsinki()); etc... } Unfortunately each time a new calendar is added you would need to change the code. I realize that Calendar is only one example, but similarily it could apply to an Index, and probably a few other data-dependant objects as well. In my mind by writing the Calendar data to some persistant store and reading it when needed you could have one generic Calendar class that instantiates itself from this as needed? This would the reduce the above to: int main(argc, argv[]) { std::cout << priceSwap(Calendar(argv[1])); // where the Calendar constructor would build itself from the data written away previously. } I realize this is not a QuantLib issue, but was wondering how you guys handle it? Remember also that I come from an Objective-C background, maybe C++ offers a different, as yet undiscovered, way of doing something like this? Thanx Andre ------------------------------------------------------------------------- This e-mail is intended only for the use of the individual or entity named above and may contain information that is confidential and privileged, proprietary to the company and protected by law. If you are not the intended recipient, you are hereby notified that any dissemination, distribution or copying of this e-mail is strictly prohibited. Opinions, conclusions and other information in this message that do not relate to the official business of our company shall be understood as neither given nor endorsed by it. |
Hi Andre,
thanks, now I see your point. I admit that when you wrote: >In my mind by writing the Calendar data to some persistant store and >reading it when needed you could have one generic Calendar class that >instantiates >itself from this as needed? This would the reduce the above to: > >int main(argc, argv[]) { > std::cout << priceSwap(Calendar(argv[1])); >} at first I took it as "given a number of calendars I can instantiate, I want to pass a tag to select which should I use this time" since this is what we usually do (see below). But then Rod wrote: >I think you are talking about what I would call "static data". That is >any data type which may change (albeit not regularly) and for that reason >it should be used by the code but not form part of the code. Things like >currencies, holidays, countries and trading locations should not really be >hard-coded. and I took it to mean that information such as "which days are holidays for the TARGET calendar" or "what calendar is to be used for Euribor fixings" should be stored externally. This is a quite different issue, and an interesting one too. I'm intrigued, but it will require some thought depending on the class. Two examples just off the top of my head: Example 1: the Xibor class constructor is very close to what you want: it takes a number of parameters (calendar, day count, tenor, etc.) and creates an instance of a Libor-like index. The Euribor, GBPLibor, USDLibor and such are just some kind of curried constructors which fix some of the parameters (e.g., Euribor specifies TARGET as the calendar): one is free to forget about them and use the Xibor constructor directly. Therefore, on any specific platform it would not be hard to write a simple function which takes an index tag, retrieves the corresponding parameters from a database, and instantiates the desired Libor. However, it is not so easy to do the same with the base Index class, which currently has a single child (Xibor) but in future could have children such as IrsRate. The children would have different data members, and what counts most, different behavior with regard to forecasting their fixing. Therefore, the Xibor approach could not be easily generalized: the steps to instantiate an Index would be: - lookup the tag in the database and determine the index type - if it's a Libor: - fetch parameters from the appropriate table - return Handle<Index>(new Xibor(params)) - if it's a swap rate: - fetch parameters from the appropriate table - return Handle<Index>(new IrsRate(params)) In particular, the choice between allocating a Xibor or a IrsRate could not be embodied in an Index constructor (apart from the fact that I wouldn't even if I could :) Example 2: the Calendar class has currently no data at all: this is because we took a rule-based approach, i.e., we coded "see if this date is a Saturday; if not, see if it is a Sunday; if not, see if it is New Year's Day; etc." which is pure code, instead of "look for this date in this list of known holidays" which relies on data---the holiday list. This is partly for clarity, and partly because we had the feeling that checking whether a date satisfied any of a dozen rules (and since the "saturday or sunday" check is the first if clause, the large majority of holidays return "true" after the first check) could take less time than using bisection to look up a date in a big list of (100 holidays/year)*(200 years) dates. Therefore, we have no static data: only behavior. To take the data-driven approach in Calendar, we would have two choices. The first is to switch to a date-based approach and give it a constructor Calendar(std::vector<Date>& holidays); or better yet template<class Iter> Calendar(Iter begin, Iter end); However, I somehow dislike this since it would obscure the logic in the calendars, and would make it a lot more difficult to spot errors in the holiday enumeration. The second choice would be to reify the calendar rules: something like class CalendarRule { public: virtual bool appliesTo(const Date& d) const == 0; } class isWeekday : public CalendarRule { ... }; class isDayOfYear : public CalendarRule { ... }; class isNthOfMonth : public CalendarRule { ... }; in terms of which one would implement Calendar as: Calendar(std::vector<Handle<CalendarRule> >&); // or iterators bool Calendar::isHoliday(const Date& d) { std::vector<Handle<CalendarRule> >::const_iterator rule; for (rule = rules_.begin(); i != rules.end(); ++i) if (*rule)->appliesTo(d) return true; return false; } Then, one could instantiate, say, the New York calendar as (omitting the Handles for easier reading---it would be a bit messier in reality): std::vector<CalendarRule*> rules; rules.push_back(new IsWeekday(Saturday)); rules.push_back(new IsWeekday(Sunday)); rules.push_back(new IsDayOfYear(1,January)); // Thanksgiving is the 4th Thursday in November rules.push_back(new IsNthOfMonth(4,Thursday,November)); NY = Calendar(rules); However, this has drawbacks, such as: - it would be less efficient (virtual function galore) - it wouldn't be easy to store rules in a database table---or in XML - it's more than I'm motivated to do now :) Anyway, I'd like to make it very clear that the above was not to reject your approach, but only to put a few issues on the table so that we can think about them. >I realize this is not a QuantLib issue, but was wondering how you guys >handle it? Well, we are currently satisfied with the calendars already implemented, so we simply use something like Calendar make_calendar(std::string s) { s = StringFormatter::toLowercase(s); // make it case-insensitive if (s == "target") return TARGET(); else if (s == "london") return London(); else if (s == "newyork") return NewYork(); ... else throw Error("unknown calendar: "+s); } which allows us to write: int main(argc, argv[]) { std::cout << priceSwap(make_calendar(argv[1])); } Also, we mostly use QuantLib-Python for our own work. And since SWIG allows one to add methods and constructors to the exported Python classes without actually modifying the C++ classes, the above make_calendar can be packaged in a constructor and the Python code becomes: print priceSwap(Calendar(sys.argv[1])) which for our present needs is close enough to get the cigar. Bye, Luigi |
Free forum by Nabble | Edit this page |