QuantLib
QuantLib copied to clipboard
calendar advance EOM rule - only activate if end of calendar month
Hi,
Currently I believe the EOM rule kicks in for date advance() if the start date is the last business day of the month. However, there are use cases where the user wants the EOM rule to kick in only if the start date is the last calendar day of the month. For example this is what Bloomberg does in its date generation in the terminal function ICVS.
Implementing this in QuantLib's user land would be quite tricky because the isEndOfMonth function, as defined in calendar.hpp, is not virtual, so I can't override it in my own calendar classes even if I wanted to. We can't just change isEndOfMonth either since it was officially documented as whether date is last business day of month. It's almost as if we'll need another argument to advance(), maybe endOfCalendarMonth?
import QuantLib as ql
cal = ql.WeekendsOnly()
start = ql.Date(29, ql.April, 2022) # last business day of month
tenor = ql.Period(1, ql.Months)
eom = True
cal.advance(start, tenor, ql.Following, eom)
# output Date(31,5,2022) because eom rule activated,
# but some user may want Date(30,5,2022) ie for eom rule to not activate because
# the start date is only last business day but not last calendar day of month
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.
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 @klin333, I tried to debug a test case and I think that the EOM rule is triggering also for the last calendar day of the month. The source code in calendar.cpp which is managing the functionality of calendar advance is the following:
Date d1 = d + n*unit;
// we are sure the unit is Months or Years
if (endOfMonth && isEndOfMonth(d))
return Calendar::endOfMonth(d1);
return adjust(d1, c);
endOfMonth is the argument passed to function Calendar::advance, isEndOfMonth(d) is the function which is checking if the start date d is on or after the last business day for that month. Hence the EOM rule is triggered also when the function is called with the last calendar day of the month, which can of course be after the last business day of the month. The function Calendar::endOfMonth(d1) is returning the last business day of the calculated date d1.
Let's for instance consider the following test case: start date 30 April 2023 (Sunday, it is not the last business day of the month, which is Friday 28 April 2023) tenor 1 Month endOfMonth true
The result seems consistent: start date: April 30th, 2023 EOM argument endOfMonth: true start date isEndOfMonth: true last business day for start date EndOfMonth: April 28th, 2023 start date + tenor: May 30th, 2023 Calendar::advance date: May 31st, 2023
It looks like that the EOM rule has been triggered successfully even if the start date is not the last business date of the month. It is in fact the last calendar date of the month. Maybe I am missing something but I can't see any inconsistency here. Any comment from QuantLib experienced developers is welcome. I paste here the source code used for the test.
#include <iostream>
#include <ql/time/all.hpp>
using namespace std;
using namespace QuantLib;
int main() {
Calendar cal = WeekendsOnly();
Date start = Date(30, April, 2023);
bool endom_flag = cal.isEndOfMonth(start);
Date endom = cal.endOfMonth(start);
Period tenor = Period(1, Months);
bool eom = true;
Date next = cal.advance(start, tenor, Following, eom);
cout << "start date: " << start << '\n'
<< "EOM argument endOfMonth: " << (eom?"true":"false") << '\n'
<< "start date isEndOfMonth: " << (endom_flag?"true":"false") << '\n'
<< "last business day for start date EndOfMonth: " << endom << '\n'
<< "start date + tenor: " << start + 1*TimeUnit::Months << '\n'
<< "Calendar::advance date: " << next << '\n';
return 0;
}
Hi @lballabio since I haven't received any feedback from @klin333 about the analysis above, do you think that this issue can be closed?
I think what they wanted was for the rule to trigger only on the last calendar day of the month, and not on previous ones even if they're the last business day.
I'd leave the issue open for a while more to have more chances of feedback. It will be closed automatically if there's no activity for a while.
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.
This issue was automatically closed because it has been stalled for two weeks with no further activity.