Skip to content

Commit b464478

Browse files
pcaspersjenkins
authored andcommitted
QPR-12070 add BusinessWeek and CalendarWeek schedule generators
1 parent 13b3172 commit b464478

1 file changed

Lines changed: 35 additions & 4 deletions

File tree

OREData/ored/portfolio/schedule.cpp

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,48 @@ namespace ore {
2828
namespace data {
2929

3030
namespace {
31-
std::vector<Date> everyThursdayDates(const Date& startDate, const Date& endDate, const Date& firstDate) {
31+
std::vector<Date> everyWeekDayDates(const Date& startDate, const Date& endDate, const Date& firstDate, const QuantLib::Weekday weekday) {
3232
std::vector<Date> result;
3333
if (firstDate != Date())
3434
result.push_back(firstDate);
3535
Date d = startDate;
36-
while (d <= endDate && (d.weekday() != QuantLib::Thursday || d < firstDate)) {
36+
while (d <= endDate && (d.weekday() != weekday || d < firstDate)) {
3737
++d;
3838
}
39-
if (d.weekday() == QuantLib::Thursday && (result.empty() || result.back() != d))
39+
if (d.weekday() == weekday && (result.empty() || result.back() != d))
4040
result.push_back(d);
4141
while (d + 7 <= endDate) {
4242
d += 7;
4343
result.push_back(d);
4444
}
4545
return result;
4646
}
47+
48+
std::vector<Date> weeklyDates(const Date& startDate, const Date& endDate, const Date& firstDate,
49+
bool includeWeekend = false) {
50+
QuantLib::Weekday weekday = includeWeekend ? QuantLib::Sunday : QuantLib::Friday;
51+
// We want the first period to span from
52+
// [startDate, first Friday/SunDay following startDate]
53+
// or
54+
// [firstDate, first Friday/SunDay following firstDate]
55+
Date effectiveFirstDate = firstDate == Date() ? startDate : firstDate;
56+
auto dates = everyWeekDayDates(startDate, endDate, effectiveFirstDate, weekday);
57+
// Handle broken period
58+
if (!dates.empty()) {
59+
// If startDate/first Date falls on end of week,
60+
// the first period is consist of only one day, so first periods should be
61+
// [startDate, startDate], [startDate+1, next end of the week], ...
62+
if (effectiveFirstDate.weekday() == weekday) {
63+
dates.insert(dates.begin(), effectiveFirstDate);
64+
}
65+
// add the enddate if the enddate doesnt fall on friday, last broken period
66+
if (dates.back() < endDate) {
67+
dates.push_back(endDate);
68+
}
69+
}
70+
return dates;
71+
}
72+
4773
} // namespace
4874

4975
void ScheduleRules::fromXML(XMLNode* node) {
@@ -334,7 +360,12 @@ Schedule makeSchedule(const ScheduleRules& data, const Date& openEndDateReplacem
334360
// handle special rules outside the QuantLib date generation rules
335361

336362
if (data.rule() == "EveryThursday") {
337-
auto dates = everyThursdayDates(startDate, endDate, firstDate);
363+
auto dates = everyWeekDayDates(startDate, endDate, firstDate, QuantLib::Thursday);
364+
for (auto& d : dates)
365+
d = calendar.adjust(d, bdc);
366+
return Schedule(dates, calendar, bdc, bdcEnd, tenor, rule, endOfMonth);
367+
} else if (data.rule() == "BusinessWeek" || data.rule() == "CalendarWeek") {
368+
auto dates = weeklyDates(startDate, endDate, firstDate, data.rule() == "CalendarWeek");
338369
for (auto& d : dates)
339370
d = calendar.adjust(d, bdc);
340371
return Schedule(dates, calendar, bdc, bdcEnd, tenor, rule, endOfMonth);

0 commit comments

Comments
 (0)