Skip to content

Commit 3f9982f

Browse files
committed
QPR-13659 start delay for inflation swaps
1 parent a8e44a8 commit 3f9982f

4 files changed

Lines changed: 37 additions & 15 deletions

File tree

OREData/ored/configuration/conventions.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,7 +1313,6 @@ void CdsConvention::fromXML(XMLNode* node) {
13131313
strPaysAtDefaultTime_ = XMLUtils::getChildValue(node, "PaysAtDefaultTime", true);
13141314
strUpfrontSettlementDays_ = XMLUtils::getChildValue(node, "UpfrontSettlementDays", false);
13151315
strLastPeriodDayCounter_ = XMLUtils::getChildValue(node, "LastPeriodDayCounter", false);
1316-
13171316
build();
13181317
}
13191318

@@ -1366,6 +1365,8 @@ void InflationSwapConvention::build() {
13661365
adjustInfObsDates_ = parseBool(strAdjustInfObsDates_);
13671366
infCalendar_ = parseCalendar(strInfCalendar_);
13681367
infConvention_ = parseBusinessDayConvention(strInfConvention_);
1368+
startDelayConvention_ =
1369+
strStartDelayConvention_.empty() ? Following : parseBusinessDayConvention(strStartDelayConvention_);
13691370
if (publicationRoll_ != PublicationRoll::None) {
13701371
QL_REQUIRE(publicationScheduleData_, "Publication roll is " << publicationRoll_ << " for " << id() <<
13711372
" so expect non-null publication schedule data.");
@@ -1389,7 +1390,9 @@ void InflationSwapConvention::fromXML(XMLNode* node) {
13891390
strAdjustInfObsDates_ = XMLUtils::getChildValue(node, "AdjustInflationObservationDates", true);
13901391
strInfCalendar_ = XMLUtils::getChildValue(node, "InflationCalendar", true);
13911392
strInfConvention_ = XMLUtils::getChildValue(node, "InflationConvention", true);
1392-
1393+
startDelay_ = XMLUtils::getChildValueAsInt(node, "StartDelay", false, 0);
1394+
strStartDelayConvention_ = XMLUtils::getChildValue(node, "StartDelayConvention", false);
1395+
13931396
publicationRoll_ = PublicationRoll::None;
13941397
if (XMLNode* n = XMLUtils::getChildNode(node, "PublicationRoll")) {
13951398
publicationRoll_ = parseInflationSwapPublicationRoll(XMLUtils::getNodeValue(n));
@@ -1419,7 +1422,12 @@ XMLNode* InflationSwapConvention::toXML(XMLDocument& doc) const {
14191422
XMLUtils::addChild(doc, node, "AdjustInflationObservationDates", strAdjustInfObsDates_);
14201423
XMLUtils::addChild(doc, node, "InflationCalendar", strInfCalendar_);
14211424
XMLUtils::addChild(doc, node, "InflationConvention", strInfConvention_);
1422-
1425+
if (startDelay_ != 0) {
1426+
XMLUtils::addChild(doc, node, "StartDelay", startDelay_);
1427+
}
1428+
if (!strStartDelayConvention_.empty()) {
1429+
XMLUtils::addChild(doc, node, "StartDelayConvention", strStartDelayConvention_);
1430+
}
14231431
if (publicationRoll_ != PublicationRoll::None) {
14241432
XMLUtils::addChild(doc, node, "PublicationRoll", to_string(publicationRoll_));
14251433
QL_REQUIRE(publicationScheduleData_, "PublicationRoll is " << publicationRoll_ << " for "

OREData/ored/configuration/conventions.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1157,7 +1157,7 @@ class InflationSwapConvention : public Convention {
11571157
InflationSwapConvention(const string& id, const string& strFixCalendar, const string& strFixConvention,
11581158
const string& strDayCounter, const string& strIndex, const string& strInterpolated,
11591159
const string& strObservationLag, const string& strAdjustInfObsDates,
1160-
const string& strInfCalendar, const string& strInfConvention,
1160+
const string& strInfCalendar, const string& strInfConvention,
11611161
PublicationRoll publicationRoll = PublicationRoll::None,
11621162
const QuantLib::ext::shared_ptr<ScheduleData>& publicationScheduleData = nullptr);
11631163

@@ -1173,6 +1173,8 @@ class InflationSwapConvention : public Convention {
11731173
BusinessDayConvention infConvention() const { return infConvention_; }
11741174
PublicationRoll publicationRoll() const { return publicationRoll_; }
11751175
const Schedule& publicationSchedule() const { return publicationSchedule_; }
1176+
int startDelay() const { return startDelay_; }
1177+
BusinessDayConvention startDelayConvention() const { return startDelayConvention_; }
11761178

11771179
virtual void fromXML(XMLNode* node) override;
11781180
virtual XMLNode* toXML(XMLDocument& doc) const override;
@@ -1189,6 +1191,8 @@ class InflationSwapConvention : public Convention {
11891191
Calendar infCalendar_;
11901192
BusinessDayConvention infConvention_;
11911193
Schedule publicationSchedule_;
1194+
int startDelay_ = 0;
1195+
BusinessDayConvention startDelayConvention_ = BusinessDayConvention::Following;
11921196

11931197
// Store the inputs
11941198
string strFixCalendar_;
@@ -1200,6 +1204,8 @@ class InflationSwapConvention : public Convention {
12001204
string strAdjustInfObsDates_;
12011205
string strInfCalendar_;
12021206
string strInfConvention_;
1207+
string strStartDelayConvention_;
1208+
12031209
PublicationRoll publicationRoll_;
12041210
QuantLib::ext::shared_ptr<ScheduleData> publicationScheduleData_;
12051211
};

OREData/ored/utilities/inflationstartdate.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,26 +25,33 @@ using QuantLib::Period;
2525
using QuantLib::Days;
2626

2727
std::pair<QuantLib::Date, QuantLib::Period> getStartAndLag(const QuantLib::Date& asof,
28-
const InflationSwapConvention& conv) {
28+
const InflationSwapConvention& conv, const int startDelay,
29+
const Calendar& cal,
30+
const BusinessDayConvention startDelayConvention) {
31+
32+
Date adjustedAsOf = asof;
33+
if (startDelay != 0) {
34+
adjustedAsOf = cal.advance(asof, startDelay * Days, startDelayConvention);
35+
}
2936

3037
using IPR = InflationSwapConvention::PublicationRoll;
3138

3239
// If no roll schedule, just return (as of, convention's obs lag).
3340
if (conv.publicationRoll() == IPR::None) {
34-
return make_pair(asof, Period());
41+
return make_pair(adjustedAsOf, Period());
3542
}
3643

3744
// If there is a publication roll, call getStart to retrieve the date.
38-
Date d = getInflationSwapStart(asof, conv);
45+
Date d = getInflationSwapStart(adjustedAsOf, conv);
3946

4047
// Date in inflation period related to the inflation index value.
4148
Date dateInPeriod = d - Period(conv.index()->frequency());
4249

43-
// Find period between dateInPeriod and asof. This will be the inflation curve's obsLag.
44-
QL_REQUIRE(dateInPeriod < asof, "InflationCurve: expected date in inflation period ("
45-
<< io::iso_date(dateInPeriod) << ") to be before the as of date ("
46-
<< io::iso_date(asof) << ").");
47-
Period curveObsLag = (asof - dateInPeriod) * Days;
50+
// Find period between dateInPeriod and adjustedAsOf. This will be the inflation curve's obsLag.
51+
QL_REQUIRE(dateInPeriod < adjustedAsOf, "InflationCurve: expected date in inflation period ("
52+
<< io::iso_date(dateInPeriod) << ") to be before the as of date ("
53+
<< io::iso_date(adjustedAsOf) << ").");
54+
Period curveObsLag = (adjustedAsOf - dateInPeriod) * Days;
4855

4956
return make_pair(d, curveObsLag);
5057
}

OREData/ored/utilities/inflationstartdate.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,10 @@ namespace data {
3333
// convention. In general, we take this simply to be (as of date, Period()). However, for AU CPI for
3434
// example, this is more complicated and we need to account for this here if the inflation swap conventions provide
3535
// us with a publication schedule and tell us to roll on that schedule.
36-
std::pair<QuantLib::Date, QuantLib::Period> getStartAndLag(const QuantLib::Date& asof,
37-
const InflationSwapConvention& conv);
38-
36+
std::pair<QuantLib::Date, QuantLib::Period>
37+
getStartAndLag(const QuantLib::Date& asof, const InflationSwapConvention& conv, const int startDelay = 0,
38+
const Calendar& cal = Calendar(),
39+
const BusinessDayConvention startDelayConvention = BusinessDayConvention::Unadjusted);
3940

4041
QuantLib::Date getInflationSwapStart(const QuantLib::Date& asof, const InflationSwapConvention& conv);
4142

0 commit comments

Comments
 (0)