Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Public Member Functions | List of all members
ConventionsBasedFutureExpiry Class Reference

Perform date calculations for future contracts based on conventions. More...

#include <ored/utilities/conventionsbasedfutureexpiry.hpp>

+ Inheritance diagram for ConventionsBasedFutureExpiry:
+ Collaboration diagram for ConventionsBasedFutureExpiry:

Public Member Functions

 ConventionsBasedFutureExpiry (const std::string &commName, QuantLib::Size maxIterations=10)
 
 ConventionsBasedFutureExpiry (const CommodityFutureConvention &convention, QuantLib::Size maxIterations=10)
 
QuantLib::Date nextExpiry (bool includeExpiry=true, const QuantLib::Date &referenceDate=QuantLib::Date(), QuantLib::Natural offset=0, bool forOption=false) override
 
QuantLib::Date priorExpiry (bool includeExpiry=true, const QuantLib::Date &referenceDate=QuantLib::Date(), bool forOption=false) override
 
QuantLib::Date expiryDate (const QuantLib::Date &contractDate, QuantLib::Natural monthOffset=0, bool forOption=false) override
 
QuantLib::Date contractDate (const QuantLib::Date &expiryDate) override
 
QuantLib::Date applyFutureMonthOffset (const QuantLib::Date &contractDate, Natural futureMonthOffset) override
 
- Public Member Functions inherited from FutureExpiryCalculator
virtual ~FutureExpiryCalculator ()
 
virtual QuantLib::Date nextExpiry (bool includeExpiry=true, const QuantLib::Date &referenceDate=QuantLib::Date(), QuantLib::Natural offset=0, bool forOption=false)=0
 
virtual QuantLib::Date priorExpiry (bool includeExpiry=true, const QuantLib::Date &referenceDate=QuantLib::Date(), bool forOption=false)=0
 
virtual QuantLib::Date expiryDate (const QuantLib::Date &contractDate, QuantLib::Natural monthOffset=0, bool forOption=false)=0
 
virtual QuantLib::Date contractDate (const QuantLib::Date &expiryDate)=0
 
virtual QuantLib::Date applyFutureMonthOffset (const QuantLib::Date &contractDate, Natural futureMonthOffset)=0
 

Inspectors

CommodityFutureConvention convention_
 
QuantLib::Size maxIterations_
 
const CommodityFutureConventioncommodityFutureConvention () const
 Return the commodity future convention. More...
 
QuantLib::Size maxIterations () const
 Return the maximum iterations parameter. More...
 
QuantLib::Date expiry (QuantLib::Day dayOfMonth, QuantLib::Month contractMonth, QuantLib::Year contractYear, QuantLib::Natural monthOffset, bool forOption) const
 Given a contractMonth, a contractYear and conventions, calculate the contract expiry date. More...
 
QuantLib::Date nextExpiry (const QuantLib::Date &referenceDate, bool forOption) const
 Do the next expiry work. More...
 
QuantLib::Date avoidProhibited (const QuantLib::Date &expiry, bool forOption) const
 Account for prohibited expiries. More...
 

Detailed Description

Perform date calculations for future contracts based on conventions.

Definition at line 33 of file conventionsbasedfutureexpiry.hpp.

Constructor & Destructor Documentation

◆ ConventionsBasedFutureExpiry() [1/2]

ConventionsBasedFutureExpiry ( const std::string &  commName,
QuantLib::Size  maxIterations = 10 
)

◆ ConventionsBasedFutureExpiry() [2/2]

ConventionsBasedFutureExpiry ( const CommodityFutureConvention convention,
QuantLib::Size  maxIterations = 10 
)

Definition at line 38 of file conventionsbasedfutureexpiry.cpp.

QuantLib::Size maxIterations() const
Return the maximum iterations parameter.

Member Function Documentation

◆ nextExpiry() [1/2]

QuantLib::Date nextExpiry ( bool  includeExpiry = true,
const QuantLib::Date &  referenceDate = QuantLib::Date(),
QuantLib::Natural  offset = 0,
bool  forOption = false 
)
overridevirtual

Implements FutureExpiryCalculator.

+ Here is the caller graph for this function:

◆ priorExpiry()

Date priorExpiry ( bool  includeExpiry = true,
const QuantLib::Date &  referenceDate = QuantLib::Date(),
bool  forOption = false 
)
overridevirtual

Implements FutureExpiryCalculator.

Definition at line 65 of file conventionsbasedfutureexpiry.cpp.

65 {
66
67 // Set the date relative to which we are calculating the preceding expiry
68 Date today = referenceDate == Date() ? Settings::instance().evaluationDate() : referenceDate;
69
70 // Get the next expiry relative to the reference date (including the reference date)
71 Date expiry = nextExpiry(true, today, 0, forOption);
72
73 // If that expiry is equal to reference date and we have set includeExpiry to true, we are done.
74 if (includeExpiry && expiry == today)
75 return expiry;
76
77 // Get the preceding expiry.
79 Date baseDate = convention_.expiryCalendar().advance(expiry, -p);
80 expiry = nextExpiry(true, baseDate, 0, forOption);
81
82 // May still not have the preceding expiry but must be close
83 Size counter = maxIterations_;
84 while (expiry >= today && counter > 0) {
85 baseDate--;
86 counter--;
87 expiry = nextExpiry(true, baseDate, 0, forOption);
88 }
89 QL_REQUIRE(expiry < today, "Expected that expiry " << io::iso_date(expiry) << " would be less than reference date "
90 << io::iso_date(today) << ".");
91
92 return expiry;
93}
const QuantLib::Calendar & expiryCalendar() const
QuantLib::Frequency contractFrequency() const
QuantLib::Date nextExpiry(bool includeExpiry=true, const QuantLib::Date &referenceDate=QuantLib::Date(), QuantLib::Natural offset=0, bool forOption=false) override
QuantLib::Date expiry(QuantLib::Day dayOfMonth, QuantLib::Month contractMonth, QuantLib::Year contractYear, QuantLib::Natural monthOffset, bool forOption) const
Given a contractMonth, a contractYear and conventions, calculate the contract expiry date.
Date referenceDate
Definition: utilities.cpp:442
+ Here is the call graph for this function:

◆ expiryDate()

Date expiryDate ( const QuantLib::Date &  contractDate,
QuantLib::Natural  monthOffset = 0,
bool  forOption = false 
)
overridevirtual

Implements FutureExpiryCalculator.

Definition at line 95 of file conventionsbasedfutureexpiry.cpp.

95 {
96 if (convention_.contractFrequency() == Daily) {
97 return nextExpiry(contractDate, forOption);
98 } else {
99 return expiry(contractDate.dayOfMonth(), contractDate.month(), contractDate.year(), monthOffset, forOption);
100 }
101}
QuantLib::Date contractDate(const QuantLib::Date &expiryDate) override
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ contractDate()

QuantLib::Date contractDate ( const QuantLib::Date &  expiryDate)
overridevirtual

Implements FutureExpiryCalculator.

Definition at line 103 of file conventionsbasedfutureexpiry.cpp.

103 {
104
105 if (convention_.contractFrequency() == Monthly) {
106
107 // do not attempt to invert the logic in expiry(), instead just search for a valid contract month
108 // in a reasonable range
109
110 for (Size m = 0; m < 120; ++m) {
111 try {
112 Date tmp = Date(15, expiryDate.month(), expiryDate.year()) + m * Months;
113 if (expiry(tmp.dayOfMonth(), tmp.month(), tmp.year(), 0, false) == expiryDate)
114 return tmp;
115 } catch (...) {
116 }
117 try {
118 Date tmp = Date(15, expiryDate.month(), expiryDate.year()) - m * Months;
119 if (expiry(tmp.dayOfMonth(), tmp.month(), tmp.year(), 0, false) == expiryDate)
120 return tmp;
121 } catch (...) {
122 }
123 }
124
125 } else {
126
127 // daily of weekly contract frequency => we can use contract date = expiry date
128
129 return expiryDate;
130 }
131
132 QL_FAIL("ConventionsBasedFutureExpiry::contractDate(" << expiryDate << "): could not imply contract date. This is an internal error. Contact support.");
133}
QuantLib::Date expiryDate(const QuantLib::Date &contractDate, QuantLib::Natural monthOffset=0, bool forOption=false) override
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ applyFutureMonthOffset()

QuantLib::Date applyFutureMonthOffset ( const QuantLib::Date &  contractDate,
Natural  futureMonthOffset 
)
overridevirtual

Implements FutureExpiryCalculator.

Definition at line 135 of file conventionsbasedfutureexpiry.cpp.

136 {
137
138 Date tmp = contractDate;
139
140 if (convention_.contractFrequency() == Monthly) {
141 tmp = Date(15, contractDate.month(), contractDate.year()) + futureMonthOffset * Months;
142 }
143
144 return tmp;
145}
+ Here is the call graph for this function:

◆ commodityFutureConvention()

const CommodityFutureConvention & commodityFutureConvention ( ) const

Return the commodity future convention.

Definition at line 308 of file conventionsbasedfutureexpiry.cpp.

308{ return convention_; }

◆ maxIterations()

Size maxIterations ( ) const

Return the maximum iterations parameter.

Definition at line 310 of file conventionsbasedfutureexpiry.cpp.

310{ return maxIterations_; }

◆ expiry()

Date expiry ( QuantLib::Day  dayOfMonth,
QuantLib::Month  contractMonth,
QuantLib::Year  contractYear,
QuantLib::Natural  monthOffset,
bool  forOption 
) const
private

Given a contractMonth, a contractYear and conventions, calculate the contract expiry date.

Definition at line 147 of file conventionsbasedfutureexpiry.cpp.

148 {
149
150 Date expiry;
151 if (convention_.contractFrequency() == Weekly) {
153 "Please change anchorType to WeeklyDayOfTheWeek for weekly contract expiries");
154 Date d(dayOfMonth, contractMonth, contractYear);
155 expiry = convention_.expiryCalendar().adjust(d - d.weekday() + convention_.weekday(),
157 } else {
158 // Apply month offset if non-zero
159 if (monthOffset > 0) {
160 Date newDate = Date(15, contractMonth, contractYear) + monthOffset * Months;
161 contractMonth = newDate.month();
162 contractYear = newDate.year();
163 }
164
165 // Move n months before (+ve) or after (-ve) for the expiry if necessary
166 if (convention_.expiryMonthLag() != 0) {
167 Date newDate = Date(15, contractMonth, contractYear) - convention_.expiryMonthLag() * Months;
168 contractMonth = newDate.month();
169 contractYear = newDate.year();
170 }
171
172 if (convention_.contractFrequency() == Monthly && !convention_.validContractMonths().empty() &&
173 convention_.validContractMonths().size() < 12 &&
174 convention_.validContractMonths().count(contractMonth) == 0) {
175 // contractMonth is in the not in the list of valid contract months
176 return Date();
177 }
178 // Calculate the relevant date in the expiry month and year
180 Date last = Date::endOfMonth(Date(1, contractMonth, contractYear));
181 if (convention_.dayOfMonth() > static_cast<Natural>(last.dayOfMonth())) {
182 expiry = last;
183 } else {
184 expiry = Date(convention_.dayOfMonth(), contractMonth, contractYear);
185 }
187 expiry = Date::nthWeekday(convention_.nth(), convention_.weekday(), contractMonth, contractYear);
189 expiry = Date(1, contractMonth, contractYear) - convention_.calendarDaysBefore() * Days;
191 if (convention_.businessDaysAfter() > 0) {
192 expiry = convention_.expiryCalendar().advance(Date(1, contractMonth, contractYear) - 1 * Days,
194 } else {
195 expiry = convention_.expiryCalendar().advance(Date(1, contractMonth, contractYear),
197 }
199 expiry = QuantExt::DateUtilities::lastWeekday(convention_.weekday(), contractMonth, contractYear);
200 } else {
201 QL_FAIL("Did not recognise the commodity future convention's anchor type");
202 }
203 // If expiry date is not a good business day, adjust it before applying the offset.
206 }
207
208 // Apply offset adjustments if necessary. A negative integer indicates that we move forward that number of days.
210 }
211
212 // If we want the option contract expiry, do the extra work here.
213 if (forOption && convention_.optionContractFrequency() == Weekly) {
215 "Please change anchorType to WeeklyDayOfTheWeek for weekly contract expiries");
216 Date d(expiry.dayOfMonth(), expiry.month(), expiry.year());
217 expiry = convention_.expiryCalendar().adjust(d - d.weekday() + convention_.optionWeekday(),
220 } else if (forOption) {
222 auto optionMonth = expiry.month();
223 auto optionYear = expiry.year();
224
226 Date newDate = Date(15, optionMonth, optionYear) - convention_.optionExpiryMonthLag() * Months;
227 optionMonth = newDate.month();
228 optionYear = newDate.year();
229 }
230
231 auto d = convention_.optionExpiryDay();
232 Date last = Date::endOfMonth(Date(1, optionMonth, optionYear));
233 if (d > static_cast<Natural>(last.dayOfMonth())) {
234 expiry = last;
235 } else {
236 expiry = Date(d, optionMonth, optionYear);
237 }
240 QL_REQUIRE(convention_.optionExpiryMonthLag() == 0 ||
242 "The expiry month lag "
243 << "and the option expiry month lag should be the same if using option expiry offset days.");
244
246 expiry, -static_cast<Integer>(convention_.optionExpiryOffset()), Days);
248 auto optionMonth = expiry.month();
249 auto optionYear = expiry.year();
250
252 Date newDate = Date(15, optionMonth, optionYear) - convention_.optionExpiryMonthLag() * Months;
253 optionMonth = newDate.month();
254 optionYear = newDate.year();
255 }
256 expiry = Date::nthWeekday(convention_.optionNth(), convention_.optionWeekday(), optionMonth, optionYear);
259 auto optionMonth = expiry.month();
260 auto optionYear = expiry.year();
261
263 Date newDate = Date(15, optionMonth, optionYear) - convention_.optionExpiryMonthLag() * Months;
264 optionMonth = newDate.month();
265 optionYear = newDate.year();
266 }
269 }
270
272
273 } else {
274 // If expiry date is one of the prohibited dates, move to preceding or following business day
275 expiry = avoidProhibited(expiry, false);
276 }
277
278 return expiry;
279}
QuantLib::BusinessDayConvention optionBusinessDayConvention() const
QuantLib::Natural optionExpiryOffset() const
QuantLib::Weekday weekday() const
QuantLib::BusinessDayConvention businessDayConvention() const
QuantLib::Integer businessDaysAfter() const
QuantLib::Frequency optionContractFrequency() const
OptionAnchorType optionAnchorType() const
QuantLib::Natural optionNth() const
QuantLib::Size optionExpiryMonthLag() const
QuantLib::Natural optionExpiryDay() const
QuantLib::Natural dayOfMonth() const
const std::set< QuantLib::Month > & validContractMonths() const
QuantLib::Integer offsetDays() const
QuantLib::Weekday optionWeekday() const
QuantLib::Natural nth() const
QuantLib::Natural calendarDaysBefore() const
QuantLib::Size expiryMonthLag() const
QuantLib::Date avoidProhibited(const QuantLib::Date &expiry, bool forOption) const
Account for prohibited expiries.
Date lastWeekday(Weekday dayOfWeek, Month m, Year y)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nextExpiry() [2/2]

QuantLib::Date nextExpiry ( const QuantLib::Date &  referenceDate,
bool  forOption 
) const
private

Do the next expiry work.

◆ avoidProhibited()

Date avoidProhibited ( const QuantLib::Date &  expiry,
bool  forOption 
) const
private

Account for prohibited expiries.

Definition at line 312 of file conventionsbasedfutureexpiry.cpp.

312 {
313
314 // If expiry date is one of the prohibited dates, move to preceding or following business day.
315 using PE = CommodityFutureConvention::ProhibitedExpiry;
316 Date result = expiry;
317 const auto& pes = convention_.prohibitedExpiries();
318 auto it = pes.find(PE(result));
319
320 while (it != pes.end()) {
321
322 // If not relevant, exit.
323 if ((!forOption && !it->forFuture()) || (forOption && !it->forOption()))
324 break;
325
326 auto bdc = !forOption ? it->futureBdc() : it->optionBdc();
327
328 if (bdc == Preceding || bdc == ModifiedPreceding) {
329 result = convention_.calendar().advance(result, -1, Days, bdc);
330 } else if (bdc == Following || bdc == ModifiedFollowing) {
331 result = convention_.calendar().advance(result, 1, Days, bdc);
332 } else {
333 QL_FAIL("Convention " << bdc << " associated with prohibited expiry " << io::iso_date(result)
334 << " is not supported.");
335 }
336
337 it = pes.find(PE(result));
338 }
339
340 return result;
341}
const QuantLib::Calendar & calendar() const
const std::set< ProhibitedExpiry > & prohibitedExpiries() const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Member Data Documentation

◆ convention_

CommodityFutureConvention convention_
private

Definition at line 61 of file conventionsbasedfutureexpiry.hpp.

◆ maxIterations_

QuantLib::Size maxIterations_
private

Definition at line 62 of file conventionsbasedfutureexpiry.hpp.