@@ -28,22 +28,48 @@ namespace ore {
2828namespace data {
2929
3030namespace {
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
4975void 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