Posted by
Luigi Ballabio-4 on
Dec 30, 2001; 6:12am
URL: http://quantlib.414.s1.nabble.com/currency-quep-tp1814p1817.html
Greetings everybody,
Note: rereading what I've written below, I realized I could sound a bit
harsh. My intention was just to state a few facts and a few opinions of
mine (which probably shows a deep lack of PR skills to begin with :) , not
to throw them in anybody's face.
End of note. On with the work.
> At 7:59 PM -0800 12/26/01, Joel Nelson wrote:
> Ferdinando Ametrano wrote
> > What I like is the Currency/Money/ExchangeRate design, including the
> > ExchangeRateManager, the MoneyFormatter, Conversion and Rounding types.
> > I see all this stuff as a building block for the FX framework, and in
> > this sense we could consider to use the OMG spec as guidelines.
> > We could start an iterative process toward strict conformance.
> > Of course if we can obtain strict conformance in only one step with a
> > *reasonable* effort I would not object.
>
> I agree with you and it is in line with the work i have done previously.
> In the redesign of the forex module, we decided to follow the "spirit" of
> the OMG documents for holding rates and converting currencies more than
> directly trying to map the specs to our code. I think that approach
> makes sense with a lot of existing code base
I, too, think that Nando has singled out exactly the classes we need. I'm
inclined to keep the above and discard classes such as StateIdManager and
CurrencyBook which IMHO belong to an enclosing application layer rather
than to a library. Also, I don't think that MoneyCalculator is needed
since unlike CORBA, C++ does have operator overloading among its features.
> Since we are building the currency module pretty much from the ground
> level we can afford to follow the OMG spec a lot more closely. However,
> I agree with you - we don't need to go all out resigning all the related
> classes at this point. Once we have the FX framework in place, we can
> re-evaluate the need.
Also, I would point out that there are a number of guidelines and design
choices in QuantLib---albeit not fully exploited as yet---which pervade the
library and IMHO should be leveraged in the currency module even if it
meant to follow the specs a bit more in the spirit and a bit less in the
letter.
For instance, the conversion factor in an ExchangeRate instance is clearly
the kind of data which is best represented by a MarketElement---being the
more powerful for this. Or again, rounding types could be implemented as
polymorphic strategies (as in "Strategy pattern") rather than an enum type.
But I'm digressing: I'm including a number of such remarks at the end of
the email.
My point is: the specification is clearly written with CORBA in mind, which
is good for the specification itself and the application layer but forces
one to use only a limited set of language features. However, QuantLib is a
C++ library: let's use the full power of C++ instead. Conformance can
be achieved by means of a wrapping layer.
> One class I think we should consider redesigning is the class you
> mentioned below : Time...
>
> > If I got things right the QuantLib Date class could be redesigned to
> > conform to the OMG DTime class.
> > QuantLib::Time is currently only a typedef to double: it measures time
> > in years, with the ambiguity it does not know which DayCount convention
> > has been used to calculate it.
> > The OMG DAmountOfTime represents an absolute (positive) amount of time
> > that can be added to, subtracted from, or used to hold differences of
> > DTime objects. A DAmountOfTime object is defined as a specified number
> > of weeks, days, hours, minutes, and seconds.
>
> Given what you've written, I think it might be wise to take the hit with
> the Time class. It sounds like it has quite a few potential
> shortcomings. Admittedly, I am not that familiar (yet) with the
> requirements of quant systems. However, in the systems I've worked on,
> having a flexible Time class (like DTime) has proven indispensable. I
> would only imagine that we will find uses for it once we have it
> implemented.
>
> Let me know what you guys think.
I think we have a naming problem here. Let me try to straighten things out.
QuantLib::Date is the class which could be made to conform to the
OMG::DTime interface. All the functionalities are already there, the only
difference being that Date doesn't contain hour, minute and second
information. For the reasons I stated above, I would rather wrap Date in
an adapter class to make it fully conformant---our guidelines prefer
d.month() to d.getMonth(), and I repute (d1-d2) more concise and more
expressive than d1.difference(d2).
QuantLib::Period is the best kept secret in QuantLib and expresses the
concept of a length of time such as "2 weeks", "3 days", "6 months", or "10
years". It lacks hours, minutes, and seconds. This class is the one which
can be modeled after OMG::DAmountOfTime.
QuantLib::Time is a typedef to double and we want it that way. It is the
concept of "time" as used in differential equations and such. It's the
physics thing if you like. We need it for finite differences models, Monte
Carlo models, you name it. And yes, it is unfortunate that it is named
just like the OMG "date" thing.
And now, my detailed considerations on the OMG specification. Please
fasten your seatbelt. I'll be referring to Appendix A of the specs,
"Consolidated IDL specifications".
A general consideration first: I would remove "get" from all getters
names, according to the QuantLib guidelines.
A.1:
ConversionType:
we can keep it as an enum.
RoundingType:
I'd rather have an abstract base class with a purely virtual method
round(amount) which will be implemented by derived classes. This would
also allow to use the same logic elsewhere.
Currency: see A2.
Money: see A2.
ExchangeRate:
1) I would keep the currencies themselves inside the class rather than
their mnemonics---the cost of carrying a Handle should be less than the
cost of carrying a std::string, too.
2) I would store the conversion factor as a MarketElement.
3) I would remove all setters. In my opinion, changing a currency to an
existing exchange rate is much more confusing than actually useful. Also,
the change of the conversion factor is managed through the MarketElement.
StateIdManager:
application layer. Not really needed in the library, I think.
CurrencyBook:
application layer. Not really needed in the library, also because we'll be
carrying around currency objects rather than mnemonics.
MoneyCalculator:
we can use operator overloading on class Money instead. Informations such
as rounding type can be extracted by the money currency (I think rounding
rules for, e.g., Euro are determined, are they not?) The base currency can
be kept as a static member of Money. The same applies to the conversion
type.
MoneyFormatter:
we can keep it along with the other data formatters in the library.
However,
1) I would drop the pattern thing: if we use decimal notation for
fractions, the only information we really need is whether the currency
symbol is placed before or after the number, and this can be extracted from
the currency of the money we are formatting.
2) I would drop the parsing. Doing it well would require a regex library.
Moreover, it belongs more to the application layer, not to the library.
3) I would remove setters and just give it a static toString(Money,...)
method which would be passed any needed argument.
ExchangeRateManager:
we can keep it. Also, we could implement it so that adding an exchange
rate between two currencies automatically adds its reciprocal.
A.2:
Currency:
1) I would remove all setters. It doesn't make sense to be able to, e.g.,
change the british pound symbol. Once it is created, a currency should
stay constant. Moreover, an interface reduced to couples of getters and
setters has no encapsulation at all---we might as well define Currency as a
struct with public data members.
2) To reduce the cost of carrying and copying around Currency objects, I
would use the pimpl idiom and store the data not in the Currency itself,
but in a CurrencyData struct instead. The Currency class would contain a
pointer to a CurrencyData instance, thus making it a lot lighter to copy.
This would also allow to use the Singleton pattern for the CurrencyData
referring to a specific currency.
3) Specific currencies such as EUR or USD would not be constructed using
the generic Currency constructor, but would rather be implemented as
derived classes which initialize the CurrencyData with the appropriate
values. This would also allow to use the Singleton pattern for the latter.
Money:
1) the currency would be stored as a Currency object and not its mnemonic.
2) I would remove all setters. I would consider Money as a data type such
as double, int, or Date. A variable of a data type is not changed but
rather reassigned. Also, resetting value and currency independently
doesn't make sense. An exchange rate should be explicitly used for
changing currency, not a bare m.setCurrency(newCurr).
3) Operator overloading would be used for arithmetic and logic.
m1.currency() == m2.currency() seems to me better C++ style than
m1.isOfSameCurrency(m2).
ExchangeRateDateBased:
I have to think about this. One possiblity is to keep it as is. Another
is to implement the same functionality by using ExchangeRateManager for
storing ExchangeRates with an associated start and end date, and add
methods to the former to retrieve the stored ExchangeRate instances.
Factories:
mostly application layer. Also, they are probably needed for CORBA, but
they don't add anything that isn't already in the constructor of the
corresponding class.
A.3:
Decimal:
I'm still trying to understand the usefulness of this. This would be
hidden into Money anyway, so a combination of a double and a rounder object
would give all the needed functionality. But I'm wide open to suggestions:
maybe I'm not seeing the obvious here. Also, the double and the rounder
can be easily composed to yield this class anyway.
AmountOfTime:
QuantLib::Period can be morphed into this. However, I would consider it a
data type and remove setters.
Time:
we could keep QuantLib::Date as we know and love it besides adding hour,
minute and seconds informations. Wrapping it would be straightforward,
were OMG compliance needed.
Factories: see above.
Joel, it's your call. If you want to write the QuEP yourself, you're welcome.
If you want to work together on it, I'm available (we would have to find a
way to work together, though).
Bye for now (man, was this long)
Luigi
--