22#include <ql/optional.hpp>
23#include <ql/settings.hpp>
24#include <ql/time/imm.hpp>
25#include <ql/time/schedule.hpp>
33 Date result = Date(20, d.
month(), d.
year());
40 Month m = result.month();
49 bool allowsEndOfMonth(
const Period& tenor) {
50 return (tenor.units() ==
Months || tenor.units() ==
Years)
60 const ext::optional<BusinessDayConvention>& terminationDateConvention,
61 const ext::optional<Period>& tenor,
62 const ext::optional<DateGeneration::Rule>& rule,
63 const ext::optional<bool>& endOfMonth,
64 std::vector<bool> isRegular)
65 : tenor_(tenor), calendar_(
std::move(calendar)), convention_(convention),
66 terminationDateConvention_(terminationDateConvention), rule_(rule), dates_(dates),
67 isRegular_(
std::move(isRegular)) {
76 <<
") must be zero or equal to the number of dates minus 1 ("
77 <<
dates.size() - 1 <<
")");
81 const Date& terminationDate,
89 const Date& nextToLast)
90 : tenor_(tenor), calendar_(
std::move(cal)), convention_(convention),
91 terminationDateConvention_(terminationDateConvention), rule_(rule),
92 endOfMonth_(allowsEndOfMonth(tenor) ? endOfMonth : false),
93 firstDate_(first == effectiveDate ?
Date() : first),
94 nextToLastDate_(nextToLast == terminationDate ?
Date() : nextToLast) {
96 QL_REQUIRE(terminationDate !=
Date(),
"null termination date");
100 if (effectiveDate==
Date() && first==
Date()
103 QL_REQUIRE(evalDate < terminationDate,
"null effective date");
105 if (nextToLast !=
Date()) {
106 y = (nextToLast - evalDate)/366 + 1;
107 effectiveDate = nextToLast - y*
Years;
109 y = (terminationDate - evalDate)/366 + 1;
110 effectiveDate = terminationDate - y*
Years;
113 QL_REQUIRE(effectiveDate !=
Date(),
"null effective date");
115 QL_REQUIRE(effectiveDate < terminationDate,
116 "effective date (" << effectiveDate
117 <<
") later than or equal to termination date ("
118 << terminationDate <<
")");
124 "non positive tenor (" <<
tenor <<
") not allowed");
133 ") out of effective-termination date range (" <<
134 effectiveDate <<
", " << terminationDate <<
"]");
141 ") is not an IMM date");
149 QL_FAIL(
"first date incompatible with " << *
rule_ <<
150 " date generation rule");
162 ") out of effective-termination date range [" <<
163 effectiveDate <<
", " << terminationDate <<
")");
170 ") is not an IMM date");
178 QL_FAIL(
"next to last date incompatible with " << *
rule_ <<
179 " date generation rule");
194 dates_.push_back(effectiveDate);
195 dates_.push_back(terminationDate);
201 dates_.push_back(terminationDate);
203 seed = terminationDate;
215 exitDate = effectiveDate;
222 if (temp < exitDate) {
257 "endOfMonth convention incompatible with " << *
rule_ <<
258 " date generation rule");
268 dates_.push_back(prev20th);
270 dates_.push_back(effectiveDate);
289 Date next20th = nextTwentieth(effectiveDate, *
rule_);
293 if (next20th - effectiveDate < stubDays) {
295 next20th = nextTwentieth(next20th + 1, *
rule_);
298 if (next20th != effectiveDate) {
299 dates_.push_back(next20th);
305 exitDate = terminationDate;
311 if (temp > exitDate) {
338 dates_.push_back(nextTwentieth(terminationDate, *
rule_));
341 dates_.push_back(terminationDate);
374 terminationDateConvention);
413 QL_ENSURE(
dates_.size()>1,
414 "degenerate single date (" <<
dates_[0] <<
") schedule" <<
415 "\n seed date: " << seed <<
416 "\n exit date: " << exitDate <<
417 "\n effective date: " << effectiveDate <<
418 "\n first date: " << first <<
419 "\n next to last date: " << nextToLast <<
420 "\n termination date: " << terminationDate <<
421 "\n generation rule: " << *
rule_ <<
428 QL_REQUIRE(truncationDate < result.
dates_.back(),
429 "truncation date " << truncationDate <<
430 " must be before the last schedule date " <<
432 if (truncationDate > result.
dates_[0]) {
434 while (result.
dates_[0] < truncationDate) {
441 if (truncationDate != result.
dates_.front()) {
442 result.
dates_.insert(result.
dates_.begin(), truncationDate);
462 QL_REQUIRE(truncationDate>result.
dates_[0],
463 "truncation date " << truncationDate <<
464 " must be later than schedule first date " <<
466 if (truncationDate<result.
dates_.back()) {
468 while (result.
dates_.back()>truncationDate) {
475 if (truncationDate!=result.
dates_.back()) {
476 result.
dates_.push_back(truncationDate);
492 std::vector<Date>::const_iterator
497 return std::lower_bound(
dates_.begin(),
dates_.end(), d);
520 "full interface (isRegular) not available");
522 "index (" << i <<
") must be in [1, " <<
528 QL_REQUIRE(!
isRegular_.empty(),
"full interface (isRegular) not available");
600 QL_REQUIRE(effectiveDate_ !=
Date(),
"effective date not provided");
601 QL_REQUIRE(terminationDate_ !=
Date(),
"termination date not provided");
602 QL_REQUIRE(tenor_,
"tenor/frequency not provided");
608 convention = *convention_;
610 if (!calendar_.empty()) {
621 if (terminationDateConvention_) {
622 terminationDateConvention = *terminationDateConvention_;
625 terminationDateConvention = convention;
630 if (calendar.
empty()) {
635 return Schedule(effectiveDate_, terminationDate_, *tenor_, calendar,
636 convention, terminationDateConvention,
637 rule_, endOfMonth_, firstDate_, nextToLastDate_);
bool isEndOfMonth(const Date &d) const
bool empty() const
Returns whether or not the calendar is initialized.
Date adjust(const Date &, BusinessDayConvention convention=Following) const
Date advance(const Date &, Integer n, TimeUnit unit, BusinessDayConvention convention=Following, bool endOfMonth=false) const
Date endOfMonth(const Date &d) const
last business day of the month to which the given date belongs
static Date endOfMonth(const Date &d)
last day of the month to which the given date belongs
std::int_fast32_t serial_type
serial number type
static Date nthWeekday(Size n, Weekday w, Month m, Year y)
n-th given weekday in the given month and year
MakeSchedule & withConvention(BusinessDayConvention)
ext::optional< BusinessDayConvention > convention_
MakeSchedule & withTerminationDateConvention(BusinessDayConvention)
ext::optional< Period > tenor_
ext::optional< BusinessDayConvention > terminationDateConvention_
MakeSchedule & withRule(DateGeneration::Rule)
MakeSchedule & backwards()
MakeSchedule & to(const Date &terminationDate)
MakeSchedule & withTenor(const Period &)
DateGeneration::Rule rule_
MakeSchedule & withFirstDate(const Date &d)
MakeSchedule & from(const Date &effectiveDate)
MakeSchedule & endOfMonth(bool flag=true)
MakeSchedule & withFrequency(Frequency)
MakeSchedule & forwards()
MakeSchedule & withNextToLastDate(const Date &d)
MakeSchedule & withCalendar(const Calendar &)
Calendar for reproducing theoretical calculations.
Date nextDate(const Date &refDate) const
ext::optional< Period > tenor_
ext::optional< BusinessDayConvention > terminationDateConvention_
std::vector< Date > dates_
const std::vector< Date > & dates() const
std::vector< bool > isRegular_
Date previousDate(const Date &refDate) const
BusinessDayConvention convention_
ext::optional< bool > endOfMonth_
ext::optional< DateGeneration::Rule > rule_
Schedule after(const Date &truncationDate) const
truncated schedule
DateGeneration::Rule rule() const
const_iterator lower_bound(const Date &d=Date()) const
const std::vector< bool > & isRegular() const
const Date & date(Size i) const
bool hasIsRegular() const
Schedule until(const Date &truncationDate) const
const Period & tenor() const
DateProxy & evaluationDate()
the date at which pricing is to be performed.
static Settings & instance()
access to the unique instance
Frequency
Frequency of events.
BusinessDayConvention
Business Day conventions.
unsigned QL_INTEGER Natural
positive integer
QL_INTEGER Integer
integer number
std::size_t Size
size of a container
Date previousTwentieth(const Date &d, DateGeneration::Rule rule)
@ ThirdWednesdayInclusive
static bool isIMMdate(const Date &d, bool mainCycle=true)
returns whether or not the given date is an IMM date