Skip to content

Commit 9c76396

Browse files
author
sebastien.bouvard
committed
QPR-11556 Handle Capfloor Proxy Configuration for XVA/Exposure
1 parent 1d43708 commit 9c76396

9 files changed

Lines changed: 49 additions & 9 deletions

File tree

OREAnalytics/orea/engine/dependencymarket.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <qle/termstructures/pricecurve.hpp>
3737
#include <qle/termstructures/zeroinflationcurveobservermoving.hpp>
3838
#include <qle/termstructures/yoyinflationcurveobservermoving.hpp>
39+
#include <qle/termstructures/proxyoptionletvolatility.hpp>
3940

4041
#include <ql/currencies/europe.hpp>
4142
#include <ql/indexes/ibor/eonia.hpp>
@@ -407,17 +408,29 @@ Handle<OptionletVolatilityStructure> DependencyMarket::capFloorVol(const string&
407408
addMarketObject(MarketObject::CapFloorVol, name, config);
408409
// ensure that the dependent ibor indiex is captured
409410
iborIndex(capFloorVolIndexBase(name, config).first, config);
410-
return flatRateCvs();
411+
Handle<OptionletVolatilityStructure> handleflatRateCvs = flatRateCvs();
412+
if (curveConfigs_ && curveConfigs_->hasCapFloorVolCurveConfig(name)) {
413+
auto cc = curveConfigs_->capFloorVolCurveConfig(name);
414+
if (!cc->proxyTargetIndex().empty()){
415+
QuantLib::ext::shared_ptr<ProxyOptionletVolatility> capletVol = QuantLib::ext::make_shared<ProxyOptionletVolatility>(handleflatRateCvs, parseIborIndex(cc->proxySourceIndex()),
416+
parseIborIndex(cc->proxyTargetIndex()), cc->proxySourceRateComputationPeriod(),
417+
cc->proxyTargetRateComputationPeriod(), cc->proxyScalingFactor());
418+
return Handle<OptionletVolatilityStructure>(capletVol);
419+
}
420+
}
421+
return handleflatRateCvs;
411422
}
412423

413424
std::pair<string, QuantLib::Period> DependencyMarket::capFloorVolIndexBase(const string& name,
414425
const string& config) const {
415426
if (curveConfigs_ && curveConfigs_->hasCapFloorVolCurveConfig(name)) {
416427
auto cc = curveConfigs_->capFloorVolCurveConfig(name);
417-
if (!cc->proxyTargetIndex().empty())
428+
if (!cc->proxyTargetIndex().empty()){
418429
return std::make_pair(cc->proxyTargetIndex(), cc->proxyTargetRateComputationPeriod());
419-
else
430+
}
431+
else{
420432
return std::make_pair(cc->index(), cc->rateComputationPeriod());
433+
}
421434
}
422435
QuantLib::ext::shared_ptr<IborIndex> index;
423436
if (tryParseIborIndex(name, index)) {

OREAnalytics/orea/simulation/fixingmanager.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,13 @@ void FixingManager::initialise(const QuantLib::ext::shared_ptr<Portfolio>& portf
7070
auto r = t->requiredFixings();
7171
r.unsetPayDates();
7272
for (auto const& [name, fixingDates] : r.fixingDatesIndices(QuantLib::Date::maxDate())) {
73+
std::cout<<"name = "<<name<<std::endl;
7374
std::set<Date> dates;
7475
for (const auto& [d, _] : fixingDates) {
76+
std::cout<<d<<"|";
7577
dates.insert(d);
7678
}
79+
std::cout<<std::endl;
7780
try {
7881
auto rawIndex = parseIndex(name);
7982
if (auto index = QuantLib::ext::dynamic_pointer_cast<EquityIndex2>(rawIndex)) {

OREData/ored/portfolio/capfloor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ void CapFloor::build(const QuantLib::ext::shared_ptr<EngineFactory>& engineFacto
548548
QuantLib::ext::make_shared<VanillaInstrument>(qlInstrument, multiplier, additionalInstruments, additionalMultipliers);
549549

550550
// axdd required fixings
551-
auto fdg = QuantLib::ext::make_shared<FixingDateGetter>(requiredFixings_);
551+
auto fdg = QuantLib::ext::make_shared<FixingDateGetter>(requiredFixings_, engineFactory->market());
552552
for (auto const& l : legs_)
553553
addToRequiredFixings(l, fdg);
554554

OREData/ored/portfolio/fixingdates.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
#include <qle/indexes/fallbackovernightindex.hpp>
5858
#include <qle/indexes/genericindex.hpp>
5959
#include <qle/indexes/offpeakpowerindex.hpp>
60+
#include <qle/termstructures/proxyoptionletvolatility.hpp>
61+
#include <qle/termstructures/dynamicoptionletvolatilitystructure.hpp>
6062

6163
using namespace QuantLib;
6264
using namespace QuantExt;
@@ -631,7 +633,22 @@ void FixingDateGetter::visit(QuantExt::OvernightIndexedCoupon& c) {
631633
requiredFixings_.addFixingDates(c.fixingDates(), IndexNameTranslator::instance().oreName(indexName), c.date());
632634
}
633635

634-
void FixingDateGetter::visit(QuantExt::CappedFlooredOvernightIndexedCoupon& c) { c.underlying()->accept(*this); }
636+
void FixingDateGetter::visit(QuantExt::CappedFlooredOvernightIndexedCoupon& c) {
637+
c.underlying()->accept(*this);
638+
if(market_){
639+
Handle<OptionletVolatilityStructure> ovs = market_->capFloorVol(IndexNameTranslator::instance().oreName(c.index()->name()));
640+
QuantLib::ext::shared_ptr<DynamicOptionletVolatilityStructure> capletVol =
641+
QuantLib::ext::dynamic_pointer_cast<DynamicOptionletVolatilityStructure>(ovs.currentLink());
642+
if(capletVol){
643+
QuantLib::ext::shared_ptr<OptionletVolatilityStructure> source = capletVol->getSource();
644+
QuantLib::ext::shared_ptr<ProxyOptionletVolatility> pov = QuantLib::ext::dynamic_pointer_cast<ProxyOptionletVolatility>(source);
645+
if(pov){
646+
QuantLib::ext::shared_ptr<QuantLib::IborIndex> baseIndex = pov->getBaseIndex();
647+
requiredFixings_.addFixingDates(c.underlying()->fixingDates(), IndexNameTranslator::instance().oreName(baseIndex->name()), c.date());
648+
}
649+
}
650+
}
651+
}
635652

636653
void FixingDateGetter::visit(AverageBMACoupon& c) {
637654
requiredFixings_.addFixingDates(c.fixingDates(), IndexNameTranslator::instance().oreName(c.index()->name()),

OREData/ored/portfolio/fixingdates.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,8 @@ class FixingDateGetter : public QuantLib::AcyclicVisitor,
276276

277277
public:
278278
//! Constructor
279-
FixingDateGetter(RequiredFixings& requiredFixings) : requiredFixings_(requiredFixings) {}
279+
FixingDateGetter(RequiredFixings& requiredFixings, const QuantLib::ext::shared_ptr<ore::data::Market>& market = nullptr) :
280+
requiredFixings_(requiredFixings), market_(market) {}
280281

281282
//! \name Visitor interface
282283
//@{
@@ -323,6 +324,7 @@ class FixingDateGetter : public QuantLib::AcyclicVisitor,
323324
protected:
324325
std::string oreIndexName(const std::string& qlIndexName) const;
325326
RequiredFixings& requiredFixings_;
327+
QuantLib::ext::shared_ptr<ore::data::Market> market_;
326328

327329
private:
328330
// flag to indicate if coupon start date fixings are always required, even if initial prices provided

QuantExt/qle/termstructures/dynamicoptionletvolatilitystructure.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ namespace QuantExt {
2222
DynamicOptionletVolatilityStructure::DynamicOptionletVolatilityStructure(
2323
const QuantLib::ext::shared_ptr<OptionletVolatilityStructure>& source, Natural settlementDays, const Calendar& calendar,
2424
ReactionToTimeDecay decayMode)
25-
: OptionletVolatilityStructure(settlementDays, calendar, source->businessDayConvention(), source->dayCounter()),
25+
: OptionletVolatilityStructure(source->referenceDate(), calendar, source->businessDayConvention(), source->dayCounter()),
2626
source_(source), decayMode_(decayMode), originalReferenceDate_(source->referenceDate()),
2727
volatilityType_(source->volatilityType()), displacement_(source->displacement()) {
2828
QL_REQUIRE(decayMode_ != ForwardForwardVariance,
@@ -48,7 +48,9 @@ Date DynamicOptionletVolatilityStructure::maxDate() const {
4848
QL_FAIL("unexpected decay mode (" << decayMode_ << ")");
4949
}
5050

51-
void DynamicOptionletVolatilityStructure::update() { TermStructure::update(); }
51+
void DynamicOptionletVolatilityStructure::update() {
52+
TermStructure::update();
53+
}
5254

5355
QuantLib::ext::shared_ptr<SmileSection> DynamicOptionletVolatilityStructure::smileSectionImpl(Time optionTime) const {
5456
return source_->smileSection(optionTime);

QuantExt/qle/termstructures/dynamicoptionletvolatilitystructure.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ class DynamicOptionletVolatilityStructure : public OptionletVolatilityStructure
4545
DynamicOptionletVolatilityStructure(const QuantLib::ext::shared_ptr<OptionletVolatilityStructure>& source,
4646
Natural settlementDays, const Calendar& calendar,
4747
ReactionToTimeDecay decayMode = ConstantVariance);
48+
49+
QuantLib::ext::shared_ptr<OptionletVolatilityStructure> getSource() { return source_; }
4850

4951
protected:
5052
//! \name OptionletVolatilityStructure interface

QuantExt/qle/termstructures/proxyoptionletvolatility.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ ProxyOptionletVolatility::ProxyOptionletVolatility(const Handle<OptionletVolatil
5252
: OptionletVolatilityStructure(baseVol->businessDayConvention(), baseVol->dayCounter()), baseVol_(baseVol),
5353
baseIndex_(baseIndex), targetIndex_(targetIndex), baseRateComputationPeriod_(baseRateComputationPeriod),
5454
targetRateComputationPeriod_(targetRateComputationPeriod), scalingFactor_(scalingFactor) {
55-
5655
QL_REQUIRE(baseIndex != nullptr, "ProxyOptionletVolatility: no base index given.");
5756
QL_REQUIRE(targetIndex != nullptr, "ProxyOptionletVolatility: no target index given.");
5857
QL_REQUIRE((!isOis(targetIndex_) && !isBMA(targetIndex)) || targetRateComputationPeriod != 0 * Days,

QuantExt/qle/termstructures/proxyoptionletvolatility.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ class ProxyOptionletVolatility : public QuantLib::OptionletVolatilityStructure {
4343
VolatilityType volatilityType() const override { return baseVol_->volatilityType(); }
4444
Real displacement() const override { return baseVol_->displacement(); }
4545
Calendar calendar() const override { return baseVol_->calendar(); }
46+
QuantLib::ext::shared_ptr<QuantLib::IborIndex> getBaseIndex() const { return baseIndex_; }
47+
QuantLib::ext::shared_ptr<QuantLib::IborIndex> getTargetIndex() const { return targetIndex_; }
4648

4749
private:
4850
QuantLib::ext::shared_ptr<QuantLib::SmileSection> smileSectionImpl(const QuantLib::Date& optionDate) const override;

0 commit comments

Comments
 (0)