Skip to content

MakeVanillaSwap should adjust the default dates for ThirdWednesday #833

@tomwhoiscontrary

Description

@tomwhoiscontrary

Using MakeVanillaSwap with the ThirdWednesday date generation rule creates a swap where cashflows are aligned to quarterly IMM dates. However, it does not adjust the start or termination dates of the swap.

Market practice for "IMM rolls" swaps is to have the start and termination dates aligned to quarterly IMM dates. At the moment, this must be done manually, by supplying correct start and end dates, in addition to specifying the ThirdWednesday date generation rule.

Could MakeVanillaSwap be changed so that when ThirdWednesday is in effect, the start and end dates are adjusted according to market practice? If this is too large a change, it would still be useful if the end date was adjusted, leaving the front date the responsibility of the user.

A consequence of adjusting the start date would be that a forward-starting swap was created, even though no forward start was specified. I don't know if there are negative consequences of this.

As a pedantic aside, MakeVanillaSwap and VanillaSwap seem to have inconsistent terms for dates: MakeVanilla swap takes an effective date and a termination date, but a VanillaSwap has a start date and a maturity date.

The following code, given a suitable definition of iborIndex:

Date today = Date(9, Month::June, 2020);
Period tenor = Period(2, TimeUnit::Years);

Settings::instance().evaluationDate() = today;

shared_ptr<VanillaSwap> immRollsSwap =
    MakeVanillaSwap(tenor, iborIndex)
        .withRule(DateGeneration::Rule::ThirdWednesday);

std::cerr << "immRollsSwap:                           "
          << " start=" << QuantLib::io::iso_date(immRollsSwap->startDate())
          << " termination=" << QuantLib::io::iso_date(immRollsSwap->maturityDate())
          << "\n";

shared_ptr<VanillaSwap> immRollsSwapWithStartDate =
    MakeVanillaSwap(tenor, iborIndex)
        .withRule(DateGeneration::Rule::ThirdWednesday)
        .withEffectiveDate(IMM::nextDate(today));

std::cerr << "immRollsSwapWithStartDate:              "
          << " start=" << QuantLib::io::iso_date(immRollsSwapWithStartDate->startDate())
          << " termination=" << QuantLib::io::iso_date(immRollsSwapWithStartDate->maturityDate())
          << "\n";

Date startDate=IMM::nextDate(today);
shared_ptr<VanillaSwap> immRollsSwapWithStartAndTerminationDate =
    MakeVanillaSwap(tenor, iborIndex)
        .withRule(DateGeneration::Rule::ThirdWednesday)
        .withEffectiveDate(startDate)
        .withTerminationDate(Date::nthWeekday(3,
                                              Weekday::Wednesday,
                                              (startDate + tenor).month(),
                                              (startDate + tenor).year()));

std::cerr << "immRollsSwapWithStartAndTerminationDate:"
          << " start=" << QuantLib::io::iso_date(immRollsSwapWithStartAndTerminationDate->startDate())
          << " termination=" << QuantLib::io::iso_date(immRollsSwapWithStartAndTerminationDate->maturityDate())
          << "\n";

Prints:

immRollsSwap:                            start=2020-06-11 termination=2022-06-13
immRollsSwapWithStartDate:               start=2020-06-17 termination=2022-06-17
immRollsSwapWithStartAndTerminationDate: start=2020-06-17 termination=2022-06-15

I am suggesting that all of the cases should print the same dates as the final case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions