Skip to content

Commit e8070ad

Browse files
committed
Merge branch 'feature/QPR-11556' into 'master'
QPR-11556 Handle Proxy Configuration for XVA/Exposure Closes QPR-11556 See merge request qs/oreplus!3074
2 parents 4dd84d4 + 5493051 commit e8070ad

8 files changed

Lines changed: 60 additions & 12 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>
@@ -408,17 +409,29 @@ Handle<OptionletVolatilityStructure> DependencyMarket::capFloorVol(const string&
408409
addMarketObject(MarketObject::CapFloorVol, name, config);
409410
// ensure that the dependent ibor indiex is captured
410411
iborIndex(capFloorVolIndexBase(name, config).first, config);
411-
return flatRateCvs();
412+
Handle<OptionletVolatilityStructure> handleflatRateCvs = flatRateCvs();
413+
if (curveConfigs_ && curveConfigs_->hasCapFloorVolCurveConfig(name)) {
414+
auto cc = curveConfigs_->capFloorVolCurveConfig(name);
415+
if (!cc->proxyTargetIndex().empty()){
416+
QuantLib::ext::shared_ptr<QuantExt::ProxyOptionletVolatility> capletVol = QuantLib::ext::make_shared<QuantExt::ProxyOptionletVolatility>(handleflatRateCvs, parseIborIndex(cc->proxySourceIndex()),
417+
parseIborIndex(cc->proxyTargetIndex()), cc->proxySourceRateComputationPeriod(),
418+
cc->proxyTargetRateComputationPeriod(), cc->proxyScalingFactor());
419+
return Handle<OptionletVolatilityStructure>(capletVol);
420+
}
421+
}
422+
return handleflatRateCvs;
412423
}
413424

414425
std::pair<string, QuantLib::Period> DependencyMarket::capFloorVolIndexBase(const string& name,
415426
const string& config) const {
416427
if (curveConfigs_ && curveConfigs_->hasCapFloorVolCurveConfig(name)) {
417428
auto cc = curveConfigs_->capFloorVolCurveConfig(name);
418-
if (!cc->proxyTargetIndex().empty())
429+
if (!cc->proxyTargetIndex().empty()){
419430
return std::make_pair(cc->proxyTargetIndex(), cc->proxyTargetRateComputationPeriod());
420-
else
431+
}
432+
else{
421433
return std::make_pair(cc->index(), cc->rateComputationPeriod());
434+
}
422435
}
423436
QuantLib::ext::shared_ptr<IborIndex> index;
424437
if (tryParseIborIndex(name, index)) {

OREAnalytics/orea/scenario/scenariosimmarket.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,12 +1531,9 @@ ScenarioSimMarket::ScenarioSimMarket(
15311531
string decayModeString = parameters->capFloorVolDecayMode();
15321532
ReactionToTimeDecay decayMode = parseDecayMode(decayModeString);
15331533

1534-
QL_REQUIRE(!QuantLib::ext::dynamic_pointer_cast<ProxyOptionletVolatility>(*wrapper),
1535-
"DynamicOptionletVolatilityStructure does not support ProxyOptionletVolatility surface.");
1534+
QuantLib::ext::shared_ptr<OptionletVolatilityStructure> capletVol =
1535+
QuantLib::ext::make_shared<DynamicOptionletVolatilityStructure>(*wrapper, 0, NullCalendar(), decayMode);
15361536

1537-
QuantLib::ext::shared_ptr<OptionletVolatilityStructure> capletVol =
1538-
QuantLib::ext::make_shared<DynamicOptionletVolatilityStructure>(*wrapper, 0, NullCalendar(),
1539-
decayMode);
15401537
hCapletVol = Handle<OptionletVolatilityStructure>(capletVol);
15411538
}
15421539
hCapletVol->setAdjustReferenceDate(false);

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(), maturity_);
552552
for (auto const& l : legs_)
553553
addToRequiredFixings(l, fdg);
554554

OREData/ored/portfolio/fixingdates.cpp

Lines changed: 28 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,32 @@ 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<QuantExt::DynamicOptionletVolatilityStructure> capletVol =
641+
QuantLib::ext::dynamic_pointer_cast<QuantExt::DynamicOptionletVolatilityStructure>(ovs.currentLink());
642+
if(capletVol){
643+
QuantLib::ext::shared_ptr<OptionletVolatilityStructure> source = capletVol->getSource();
644+
QuantLib::ext::shared_ptr<QuantExt::ProxyOptionletVolatility> pov = QuantLib::ext::dynamic_pointer_cast<QuantExt::ProxyOptionletVolatility>(source);
645+
if(pov){
646+
QuantLib::ext::shared_ptr<QuantLib::IborIndex> baseIndex = pov->getBaseIndex();
647+
// Create a window of fixings [min, max_] to cover all potential fixings
648+
auto fixingDates = c.underlying()->fixingDates();
649+
std::sort(fixingDates.begin(), fixingDates.end());
650+
QuantLib::Date minDate = fixingDates.front() > Settings::instance().evaluationDate()?Settings::instance().evaluationDate():fixingDates.front();
651+
std::vector<QuantLib::Date> businessDates;
652+
for (QuantLib::Date d = minDate; d <= max_; d = d + 1) {
653+
if (baseIndex->fixingCalendar().isBusinessDay(d)) {
654+
businessDates.push_back(d);
655+
}
656+
}
657+
requiredFixings_.addFixingDates(businessDates, IndexNameTranslator::instance().oreName(baseIndex->name()), c.date());
658+
}
659+
}
660+
}
661+
}
635662

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

OREData/ored/portfolio/fixingdates.hpp

Lines changed: 4 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, const QuantLib::Date& maturity = Null<Date>()) :
280+
requiredFixings_(requiredFixings), market_(market), max_(maturity) {}
280281

281282
//! \name Visitor interface
282283
//@{
@@ -323,10 +324,12 @@ 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
329331
bool requireFixingStartDates_ = false;
332+
QuantLib::Date max_;
330333
// We may need fixings for an additional FX Index at every fixing date
331334
QuantLib::ext::shared_ptr<QuantExt::FxIndex> additionalFxIndex_;
332335
};

QuantExt/qle/termstructures/dynamicoptionletvolatilitystructure.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,12 @@ using namespace QuantLib;
4242

4343
class DynamicOptionletVolatilityStructure : public OptionletVolatilityStructure {
4444
public:
45+
//Constructor with the reference date based on the global evaluation date
4546
DynamicOptionletVolatilityStructure(const QuantLib::ext::shared_ptr<OptionletVolatilityStructure>& source,
4647
Natural settlementDays, const Calendar& calendar,
4748
ReactionToTimeDecay decayMode = ConstantVariance);
49+
50+
QuantLib::ext::shared_ptr<OptionletVolatilityStructure> getSource() { return source_; }
4851

4952
protected:
5053
//! \name OptionletVolatilityStructure interface

QuantExt/qle/termstructures/proxyoptionletvolatility.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ class ProxyOptionletVolatility : public QuantLib::OptionletVolatilityStructure {
5656
const QuantLib::ext::shared_ptr<QuantLib::IborIndex>& index,
5757
const QuantLib::Period& rateComputationPeriod);
5858

59+
QuantLib::ext::shared_ptr<QuantLib::IborIndex> getBaseIndex() const { return baseIndex_; }
60+
QuantLib::ext::shared_ptr<QuantLib::IborIndex> getTargetIndex() const { return targetIndex_; }
61+
5962
private:
6063
QuantLib::ext::shared_ptr<QuantLib::SmileSection> smileSectionImpl(const QuantLib::Date& optionDate) const override;
6164
QuantLib::ext::shared_ptr<QuantLib::SmileSection> smileSectionImpl(QuantLib::Time optionTime) const override;

0 commit comments

Comments
 (0)