QuantLib icon indicating copy to clipboard operation
QuantLib copied to clipboard

Constructing one-day swaps in the vicinity of holidays throws schedule exceptions

Open tomwhoiscontrary opened this issue 3 years ago • 4 comments

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.

OneDaySwapDemo.cpp.txt

tomwhoiscontrary avatar Jun 14 '22 17:06 tomwhoiscontrary

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.

github-actions[bot] avatar Aug 14 '22 02:08 github-actions[bot]

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

ralfkonrad avatar Aug 15 '22 15:08 ralfkonrad

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.

tomwhoiscontrary avatar Aug 16 '22 15:08 tomwhoiscontrary