Constructing one-day swaps in the vicinity of holidays throws schedule exceptions
I'm not sure how much of this, if any, is a bug.
One of my users tried to create a series of one-day swaps starting on each of a span of weekdays, as a way of getting a crude plot of a yield curve. This resulted in "degenerate single date" exceptions in many cases. In particular, it resulted in these exceptions in some cases where the start date was not a holiday, which surprised me. Here are three cases in the year from today:
2022-07-29
is business day: yes
adjusted: 2022-07-29
following: 2022-08-01
exception: degenerate single date (July 29th, 2022) schedule
seed date: July 30th, 2022
exit date: July 29th, 2022
effective date: July 29th, 2022
first date: null date
next to last date: null date
termination date: July 30th, 2022
generation rule: Backward
end of month: 0
2022-12-30
is business day: yes
adjusted: 2022-12-30
following: 2023-01-03
exception: degenerate single date (December 30th, 2022) schedule
seed date: December 31st, 2022
exit date: December 30th, 2022
effective date: December 30th, 2022
first date: null date
next to last date: null date
termination date: December 31st, 2022
generation rule: Backward
end of month: 0
2023-04-28
is business day: yes
adjusted: 2023-04-28
following: 2023-05-02
exception: degenerate single date (April 28th, 2023) schedule
seed date: April 29th, 2023
exit date: April 28th, 2023
effective date: April 28th, 2023
first date: null date
next to last date: null date
termination date: April 29th, 2023
generation rule: Backward
end of month: 0
I think what's happening here is that the end date falls on a holiday, so it gets adjusted, but using the modified following rule, which adjusts it backwards, making it the same as the start date. Does this seem correct?
I see similar exceptions when creating two- and three-day swaps, if i search enough start dates.
What i would really like is to be able to ask for a swap starting on any date (ideally including holidays), of any tenor, and for the dates to be adjusted in some way that results in a valid swap. Is there a way to achieve this?
I don't mind adjusting the start date myself. But i can't see any way to make a manual adjustment of a calculated end date before an exception is thrown.
This issue was automatically marked as stale because it has been open 60 days with no activity. Remove stale label or comment, or this will be closed in two weeks.
Hi Tom,
does it help if you explicitly set the Following rule like this:
ext::shared_ptr<VanillaSwap> swap =
MakeVanillaSwap(Period(1, TimeUnit::Days), floatingLegIndex)
.withEffectiveDate(date)
.withFixedLegConvention(Following)
.withFixedLegTerminationDateConvention(Following)
.withFloatingLegConvention(Following)
.withFloatingLegTerminationDateConvention(Following)
.withPricingEngine(engine);
In my case your error does not occur anymore for the EOM cases.
I guess you still need to check if the dates, the coupons, the fair rate etc. are as expected.
Holidays are a different story though.
What i would really like is to be able to ask for a swap starting on any date (ideally including holidays), of any tenor, and for the dates to be adjusted in some way that results in a valid swap. Is there a way to achieve this?
The MakeVanillaSwap class makes quiet some assumptions here (fixed tenor based on the index currency etc.). Not sure if this can be easily achieved. (Or put it the other way: is a one-day swap with 3M USDLibor still vanilla?)
But can't you use the VanillaSwap constructor directly by using Schedule(const std::vector<Date>& dates) to set the start- and end-date?
https://github.com/lballabio/QuantLib/blob/c5ff5ae7bc6cbc3e8f32c9bc2abb31d9a1e53f8d/ql/instruments/vanillaswap.hpp#L70-L80
Regards Ralf
Or put it the other way: is a one-day swap with 3M USDLibor still vanilla?
That is a fantastic way of putting it!
Your response has really helped me think about MakeVanillaSwap in a more useful way, i think. I had been trying to use it for all swaps, but it seems clear that this is just not appropriate. I just need to handle some special cases differently.