Skip to content

Commit e0342ca

Browse files
committed
manual update from oreplus
1 parent 2cc069d commit e0342ca

1 file changed

Lines changed: 56 additions & 10 deletions

File tree

OREAnalytics/orea/engine/parsensitivityanalysis.cpp

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <qle/instruments/oibasisswap.hpp>
4141
#include <qle/instruments/subperiodsswap.hpp>
4242
#include <qle/instruments/tenorbasisswap.hpp>
43+
#include <qle/instruments/doubleoibasisswap.hpp>
4344
#include <qle/math/blockmatrixinverse.hpp>
4445
#include <qle/pricingengines/crossccyswapengine.hpp>
4546
#include <qle/pricingengines/depositengine.hpp>
@@ -119,6 +120,12 @@ Real impliedQuote(const boost::shared_ptr<Instrument>& i) {
119120
else
120121
return boost::dynamic_pointer_cast<OvernightIndexedBasisSwap>(i)->fairIborSpread();
121122
}
123+
if (boost::dynamic_pointer_cast<DoubleOvernightIndexedBasisSwap>(i)) {
124+
if (boost::dynamic_pointer_cast<DoubleOvernightIndexedBasisSwap>(i)->spreadOnShort())
125+
return boost::dynamic_pointer_cast<DoubleOvernightIndexedBasisSwap>(i)->fairPaySpread();
126+
else
127+
return boost::dynamic_pointer_cast<DoubleOvernightIndexedBasisSwap>(i)->fairRecSpread();
128+
}
122129
if (boost::dynamic_pointer_cast<FixedBMASwap>(i))
123130
return boost::dynamic_pointer_cast<FixedBMASwap>(i)->fairRate();
124131
if (boost::dynamic_pointer_cast<SubPeriodsSwap>(i))
@@ -1497,6 +1504,7 @@ std::pair<boost::shared_ptr<QuantLib::Instrument>, Date> ParSensitivityAnalysis:
14971504
boost::shared_ptr<IborIndex> longIndex = parseIborIndex(conv->longIndexName());
14981505
boost::shared_ptr<IborIndex> shortIndex = parseIborIndex(conv->shortIndexName());
14991506
boost::shared_ptr<OvernightIndex> shortIndexOn = boost::dynamic_pointer_cast<OvernightIndex>(shortIndex);
1507+
boost::shared_ptr<OvernightIndex> longIndexOn = boost::dynamic_pointer_cast<OvernightIndex>(longIndex);
15001508

15011509
if (market != nullptr) {
15021510
if (!expDiscountCurve.empty()) {
@@ -1526,6 +1534,8 @@ std::pair<boost::shared_ptr<QuantLib::Instrument>, Date> ParSensitivityAnalysis:
15261534
shortIndex = shortIndex->clone(shortIndexCurve);
15271535
if (shortIndexOn)
15281536
shortIndexOn = boost::static_pointer_cast<OvernightIndex>(shortIndexOn->clone(shortIndexCurve));
1537+
if (longIndexOn)
1538+
longIndexOn = boost::static_pointer_cast<OvernightIndex>(longIndexOn->clone(longIndexCurve));
15291539
boost::shared_ptr<Swap> helper;
15301540
Date latestRelevantDate;
15311541
boost::shared_ptr<Libor> longIndexAsLibor = boost::dynamic_pointer_cast<Libor>(longIndex);
@@ -1536,10 +1546,15 @@ std::pair<boost::shared_ptr<QuantLib::Instrument>, Date> ParSensitivityAnalysis:
15361546
shortIndexAsLibor != nullptr ? shortIndexAsLibor->jointCalendar() : shortIndex->fixingCalendar();
15371547
removeTodaysFixingIndices_.insert(shortIndex->name());
15381548
removeTodaysFixingIndices_.insert(longIndex->name());
1539-
if (shortIndexOn) {
1549+
1550+
if(!shortIndexOn && longIndexOn)
1551+
QL_FAIL("This is unexpected: long index is overnight, short index is longer");
1552+
1553+
Date settlementDate = longIndexCalendar.advance(
1554+
longIndexCalendar.adjust(asof_), longIndex->fixingDays() * Days);
1555+
1556+
if (shortIndexOn && !longIndexOn) {
15401557
// OIS vs Libor
1541-
Date settlementDate =
1542-
longIndexCalendar.advance(longIndexCalendar.adjust(asof_), longIndex->fixingDays() * Days);
15431558
Schedule oisSchedule = MakeSchedule()
15441559
.from(settlementDate)
15451560
.to(settlementDate + term)
@@ -1562,17 +1577,48 @@ std::pair<boost::shared_ptr<QuantLib::Instrument>, Date> ParSensitivityAnalysis:
15621577
boost::shared_ptr<QuantLib::OvernightIndexedCoupon> lastCoupon2 =
15631578
boost::dynamic_pointer_cast<QuantLib::OvernightIndexedCoupon>(
15641579
boost::static_pointer_cast<OvernightIndexedBasisSwap>(helper)->overnightLeg().back());
1580+
latestRelevantDate = std::max(helper->maturityDate(),
1581+
std::max(lastCoupon1->fixingEndDate(),
1582+
shortIndexOn->fixingCalendar().advance(lastCoupon2->valueDates().back(), 1 * Days)));
1583+
} else if (shortIndexOn && longIndexOn) {
1584+
// OIS vs OIS
1585+
// from userguide: long index ... should be interpreted as the index of the received leg.
1586+
Schedule shortSchedule = MakeSchedule()
1587+
.from(settlementDate)
1588+
.to(settlementDate + term)
1589+
.withTenor(conv->shortPayTenor())
1590+
.withCalendar(shortIndexCalendar)
1591+
.withConvention(shortIndex->businessDayConvention())
1592+
.forwards();
1593+
Schedule longSchedule = MakeSchedule()
1594+
.from(settlementDate)
1595+
.to(settlementDate + term)
1596+
.withTenor(longIndex->tenor())
1597+
.withCalendar(longIndexCalendar)
1598+
.withConvention(longIndex->businessDayConvention())
1599+
.forwards();
1600+
1601+
helper = boost::make_shared<DoubleOvernightIndexedBasisSwap>(
1602+
100.0, shortSchedule, shortIndexOn, longSchedule, longIndexOn, 0.0, 0.0, conv->spreadOnShort(), false);
1603+
1604+
boost::shared_ptr<QuantLib::OvernightIndexedCoupon> lastCouponShort =
1605+
boost::dynamic_pointer_cast<QuantLib::OvernightIndexedCoupon>(
1606+
boost::static_pointer_cast<DoubleOvernightIndexedBasisSwap>(helper)->payLeg().back());
1607+
1608+
boost::shared_ptr<QuantLib::OvernightIndexedCoupon> lastCouponLong =
1609+
boost::dynamic_pointer_cast<QuantLib::OvernightIndexedCoupon>(
1610+
boost::static_pointer_cast<DoubleOvernightIndexedBasisSwap>(helper)->recLeg().back());
1611+
15651612
latestRelevantDate =
15661613
std::max(helper->maturityDate(),
1567-
std::max(lastCoupon1->fixingEndDate(),
1568-
shortIndexOn->fixingCalendar().advance(lastCoupon2->valueDates().back(), 1 * Days)));
1614+
std::max(shortIndexOn->fixingCalendar().advance(lastCouponShort->valueDates().back(), 1 * Days),
1615+
longIndexOn->fixingCalendar().advance(lastCouponLong->valueDates().back(), 1 * Days)));
1616+
15691617
} else {
15701618
// Libor vs Libor
1571-
Date settlementDate =
1572-
longIndexCalendar.advance(longIndexCalendar.adjust(asof_), longIndex->fixingDays() * Days);
1573-
helper = boost::make_shared<TenorBasisSwap>(
1574-
settlementDate, 1.0, term, true, longIndex, 0.0, shortIndex, 0.0, conv->shortPayTenor(),
1575-
DateGeneration::Backward, conv->includeSpread(), conv->spreadOnShort(), conv->subPeriodsCouponType());
1619+
helper = boost::make_shared<TenorBasisSwap>(settlementDate, 1.0, term, true, longIndex, 0.0, shortIndex, 0.0,
1620+
conv->shortPayTenor(), DateGeneration::Backward,
1621+
conv->includeSpread(), conv->spreadOnShort(), conv->subPeriodsCouponType());
15761622
boost::shared_ptr<IborCoupon> lastCoupon1 = boost::dynamic_pointer_cast<IborCoupon>(
15771623
boost::static_pointer_cast<TenorBasisSwap>(helper)->longLeg().back());
15781624
Date maxDate2;

0 commit comments

Comments
 (0)