Hi all,
here is where I step forward and show my ignorance, which in Lent is kind of appropriate after all :) The problem in short: FloatingRateCoupon has outgrown its definition. It was born as a coupon at par on a term structure, i.e., one whose amount is calculated simply as (discount(start)/discount(end)-1.0) * nominal as opposed to liborFixing * accrualPeriod * nominal. Our benevolent dictator's rationale for the above choice was that due to holidays and date adjustments, the end date for a 6-months coupon could be a few days off the end date for the fixing of the corresponding 6-months Libor. Therefore, if the second formula was used, one would be accruing a rate over a period which is not exactly its tenor, which causes a (small) convexity error. This does not apply to the first formula, in which the rate is forecast and accrued over the same period. Which didn't persuade me at all; while it is true that there is no convexity error in the first formula, an error is being made just the same: stepping out of the model and into the real world, it is the Libor fixing that the coupon will actually pay, not the forward rate between its start and end dates. So I step forward and ask: which formula has the largest error? Is there any reason to use the one or the other? The reason I ask is that since that choice, FloatingRateCoupon has grown a few clumsy extremities, such as: 1) the possibility to add a spread was added. This forced the coupon to take a Xibor instance as a data member from which to retrieve a day counter for accrual period calculation (since the spread gave an additional amount spread * accrualPeriod * nominal); 2) the possibility to specify a number of fixing days was added; 3) the retrieving of past fixings was delegated to the Xibor data member. Thus, FloatingRateCoupon was made into a sorry excuse for a coupon class. In particular: a) because of 1) and 2), the coupon is no longer at par. However, it retains the limitations of the par coupon calculations, which prevent it from growing more useful: for instance, it is not possible to use a different day counter for accruing. Say 'bye' to basis swaps. b) the parameter list is actually misleading: which curve is used for forecast in the following code? Handle<TermStructure> curve1 = ...; Handle<TermStructure> curve2 = ...; // the first one is passed to the index Handle<Xibor> index(new Euribor(6,Months, RelinkableHandle<TermStructure>(curve1)); // the second one is passed to the coupon FloatingRateCoupon coupon(10000, index, RelinkableHandle<TermStructure>(curve2). startDate, endDate, fixingDays, spread); // which one is used here? std::cout << coupon.amount() << std::endl; As a matter of fact, it is the second. But one shouldn't have to go and read the amount() implementation to know. It should be straightforward---which it isn't. What I would do is: 1) drop this FloatingCoupon mix which cannot be amended; 2) keep a ParCoupon class which only does what its definition claims (no spread, no index, no fixing days, no past fixings, forecast only) 3) write and use a full featured IndexedCoupon class which delegates the forecasting of the fixing to an Index class and does not have any of the limitations of ParCoupon. A hook for a convexity adjustment calculation can be put in place whose default implementation does nothing. But then again, maybe I don't know jack. Any thought? Advice? Screams? Bye, Luigi |
Free forum by Nabble | Edit this page |