lballabio / QuantLib

The QuantLib C++ library
http://quantlib.org
Other
5.43k stars 1.8k forks source link

Using instance evaluationDate when creating holidays in a calendar #2083

Open piterdias opened 1 month ago

piterdias commented 1 month ago

After upgrading from QuantLib (Python) 1.29 to 1.35 realized that #1879 broke some of my tests due to new holidays added to Brazil calendar. I made a quick (and dirty) fix by upgrading my tests to a newer date, but I understand that should not be the proper solution for a regression test because the previous calculation are not wrong. How about using the instance evaluationDate in order to test if a holiday should exist in that date? If a law in, let's say, 2023 creates a calendar em 2024, may calculation as of 2022 should give the plain old values. I can try adding this rule to Brazil calendar if you understand that makes sense.

jongbongan commented 1 month ago

You may create your own calendar class (or instance if Python) by using a customized calendar (e.g. BespokeCalendar) and combine some methods (removeHolidays, addHolidays) to create an old one from the updated one.

lballabio commented 1 month ago

I see—you're saying that if a new holiday is declared in 2024, calculations made with evaluation date in 2023 should not consider it because at that point in time the holiday didn't exist.

It makes sense, but it's tricky to implement—we could check the evaluation date in the calendar method, as you say, but we'd have confusing cases like this one. Let's say we have a new holiday h declared on date d. If we write:

Settings::instance().evaluationDate() = d - 1*Weeks;
auto schedule = MakeSchedule(...) // this is some schedule affected by whether h is a holiday or not
auto bond = FixedRateBond(..., schedule, ...);
auto price = bond.cleanPrice();

we'll have a bond evaluated one week before d whose price is calculated based on h not being a holiday, while if we write:

Settings::instance().evaluationDate() = d + 1*Weeks;
auto schedule = MakeSchedule(...) // same inputs
auto bond = FixedRateBond(..., schedule, ...);
Settings::instance().evaluationDate() = d - 1*Weeks;
auto price = bond.cleanPrice();

we'll have the same bond also evaluated one week before d but whose price is calculated based on h being a holiday, because the schedule was created at a different evaluation date (which will happen if, for instance, we create the bond and want to see how its price changed in time).

I'm not sure what the right thing to do would be. Both of the above are sensible, and one would expect them to have the same result. I might be inclined to leave it to the user to add or remove holidays explicitly depending on the evaluation date...

piterdias commented 1 month ago

I didn't think properly about side effects. It is better using the calendars as reference implementation if changing holidays automagically may lead to unpredictable results. The application, not QuantLib, would take care of fine tuning the holidays.