Skip to content

Commit 5922252

Browse files
committed
Merge branch 'master' into 'master'
Master See merge request qs/ore-github!14
2 parents 18c69be + d4e30d8 commit 5922252

4 files changed

Lines changed: 49 additions & 10 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);

QuantExt/qle/pricingengines/mcmultilegbaseengine.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -566,8 +566,8 @@ McMultiLegBaseEngine::CashflowInfo McMultiLegBaseEngine::createCashflowInfo(boos
566566
info.amountCalculator = [this, indexCcyIdx, sub, simTime, isFxLinked, fxLinkedForeignNominal,
567567
fxLinkedSourceCcyIdx, fxLinkedTargetCcyIdx, fxLinkedFixedFxRate](
568568
const Size n, const std::vector<std::vector<const RandomVariable*>>& states) {
569-
RandomVariable effectiveRate = lgmVectorised_[indexCcyIdx].subPeriodsRate(sub->index(), sub->fixingDates(),
570-
simTime, *states.at(0).at(0));
569+
RandomVariable fixing = lgmVectorised_[indexCcyIdx].subPeriodsRate(sub->index(), sub->fixingDates(),
570+
simTime, *states.at(0).at(0));
571571
RandomVariable fxFixing(n, 1.0);
572572
if (isFxLinked) {
573573
if (fxLinkedFixedFxRate != Null<Real>()) {
@@ -582,6 +582,7 @@ McMultiLegBaseEngine::CashflowInfo McMultiLegBaseEngine::createCashflowInfo(boos
582582
fxFixing = fxSource / fxTarget;
583583
}
584584
}
585+
RandomVariable effectiveRate = RandomVariable(n, sub->gearing()) * fixing + RandomVariable(n, sub->spread());
585586
return RandomVariable(n, (isFxLinked ? fxLinkedForeignNominal : sub->nominal()) * sub->accrualPeriod()) *
586587
effectiveRate * fxFixing;
587588
};

QuantExt/qle/termstructures/iterativebootstrap.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ QuantLib::Real dontThrowFallback(const QuantLib::BootstrapError<Curve>& error, Q
4949
QuantLib::Real stepSize = (xMax - xMin) / steps;
5050

5151
for (QuantLib::Size i = 0; i <= steps; ++i) {
52-
Real x = xMin + stepSize * static_cast<double>(i);
53-
Real absError = QL_MAX_REAL;
52+
QuantLib::Real x = xMin + stepSize * static_cast<double>(i);
53+
QuantLib::Real absError = QL_MAX_REAL;
5454
try {
5555
absError = std::abs(error(x));
5656
} catch (...) {
@@ -176,7 +176,7 @@ template <class Curve> void IterativeBootstrap<Curve>::initialize() const {
176176
latestRelevantDate = helper->latestRelevantDate();
177177
// check that the helper is really extending the curve, i.e. that
178178
// pillar-sorted helpers are also sorted by latestRelevantDate
179-
QL_REQUIRE(latestRelevantDate > maxDate, io::ordinal(j + 1)
179+
QL_REQUIRE(latestRelevantDate > maxDate, QuantLib::io::ordinal(j + 1)
180180
<< " instrument (pillar: " << dates[i]
181181
<< ") has latestRelevantDate (" << latestRelevantDate
182182
<< ") before or equal to "
@@ -219,7 +219,7 @@ template <class Curve> void IterativeBootstrap<Curve>::calculate() const {
219219
const boost::shared_ptr<typename Traits::helper>& helper = ts_->instruments_[j];
220220

221221
// check for valid quote
222-
QL_REQUIRE(helper->quote()->isValid(), io::ordinal(j + 1)
222+
QL_REQUIRE(helper->quote()->isValid(), QuantLib::io::ordinal(j + 1)
223223
<< " instrument (maturity: " << helper->maturityDate()
224224
<< ", pillar: " << helper->pillarDate() << ") has an invalid quote");
225225

xsd/conventions.xsd

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,13 @@
427427
<xs:element type="bool" name="AdjustBeforeOffset" minOccurs="0" maxOccurs="1"/>
428428
<xs:element type="bool" name="IsAveraging" minOccurs="0" maxOccurs="1"/>
429429
<xs:element type="prohibitedExpiriesType" name="ProhibitedExpiries" minOccurs="0" maxOccurs="1"/>
430+
<xs:element name="ValidContractMonths" minOccurs="0" maxOccurs="1">
431+
<xs:complexType>
432+
<xs:sequence>
433+
<xs:element type="monthType" name="Month" minOccurs="1" maxOccurs="12"/>
434+
</xs:sequence>
435+
</xs:complexType>
436+
</xs:element>
430437
<xs:element type="xs:integer" name="OptionExpiryMonthLag" minOccurs="0" maxOccurs="1"/>
431438
<xs:element type="frequencyType" name="OptionContractFrequency" minOccurs="0" maxOccurs="1"/>
432439
<xs:element type="xs:nonNegativeInteger" name="OptionExpiryOffset" minOccurs="0" maxOccurs="1"/>

0 commit comments

Comments
 (0)