Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
oiscapfloorhelper.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2022 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
23
24#include <ql/cashflows/cashflows.hpp>
25#include <ql/quotes/derivedquote.hpp>
26#include <ql/termstructures/volatility/optionlet/constantoptionletvol.hpp>
27#include <ql/utilities/null_deleter.hpp>
28
29#include <boost/bind/bind.hpp>
30#include <ql/functional.hpp>
31
32using namespace QuantLib;
33using std::ostream;
34
35namespace QuantExt {
36
38 const Period& rateComputationPeriod, QuantLib::Rate strike,
39 const Handle<Quote>& quote,
40 const QuantLib::ext::shared_ptr<QuantLib::OvernightIndex>& index,
41 const Handle<YieldTermStructure>& discountingCurve, bool moving,
42 const QuantLib::Date& effectiveDate, CapFloorHelper::QuoteType quoteType,
43 QuantLib::VolatilityType quoteVolatilityType, QuantLib::Real quoteDisplacement)
44 : RelativeDateBootstrapHelper<OptionletVolatilityStructure>(
45 Handle<Quote>(QuantLib::ext::make_shared<DerivedQuote<QuantLib::ext::function<Real(Real)>>>(
46 quote, QuantLib::ext::bind(&OISCapFloorHelper::npv, this, QuantLib::ext::placeholders::_1)))),
47 type_(type), tenor_(tenor), rateComputationPeriod_(rateComputationPeriod), strike_(strike), index_(index),
48 discountHandle_(discountingCurve), moving_(moving), effectiveDate_(effectiveDate), quoteType_(quoteType),
49 quoteVolatilityType_(quoteVolatilityType), quoteDisplacement_(quoteDisplacement), rawQuote_(quote),
50 initialised_(false) {
51
53 QL_REQUIRE(type_ != CapFloorHelper::Automatic,
54 "Cannot have CapFloorHelper type 'Automatic' with quote type of Premium");
55 }
56
57 QL_REQUIRE(!(moving_ && effectiveDate_ != Date()),
58 "A fixed effective date does not make sense for a moving helper");
59
60 registerWith(index_);
61 registerWith(discountHandle_);
62
64 initialised_ = true;
65}
66
68
69 if (!initialised_ || moving_) {
70
71 Date today = Settings::instance().evaluationDate();
72
73 CapFloor::Type capFloorType = type_ == CapFloorHelper::Cap ? CapFloor::Cap : CapFloor::Floor;
74
75 // Initialise the instrument and a copy
76 // The strike can be Null<Real>() to indicate an ATM cap floor helper
77 Rate dummyStrike = strike_ == Null<Real>() ? 0.01 : strike_;
78 capFloor_ = MakeOISCapFloor(capFloorType, tenor_, index_, rateComputationPeriod_, dummyStrike)
84
85 QL_REQUIRE(!capFloor_.empty(), "OISCapFloorHelper: got empty leg.");
86
87 maturityDate_ = CashFlows::maturityDate(capFloor_);
88
89 // Earliest date is the first optionlet fixing date
90 auto cfon = QuantLib::ext::dynamic_pointer_cast<CappedFlooredOvernightIndexedCoupon>(capFloor_.front());
91 QL_REQUIRE(cfon, "OISCapFloorHelper: Expected the first cashflow on the ois cap floor instrument to be a "
92 "CappedFlooredOvernightIndexedCoupon");
93 earliestDate_ = std::max(today, cfon->underlying()->fixingDates().front());
94
95 // Remaining dates are each equal to the fixing date on the final optionlet
96 auto cfon2 = QuantLib::ext::dynamic_pointer_cast<CappedFlooredOvernightIndexedCoupon>(capFloor_.back());
97 QL_REQUIRE(cfon2, "OISCapFloorHelper: Expected the final cashflow on the cap floor instrument to be a "
98 "CappedFlooredOvernightIndexedCoupon");
99 pillarDate_ = latestDate_ = latestRelevantDate_ = cfon2->underlying()->fixingDates().back();
100 }
101}
102
103void OISCapFloorHelper::setTermStructure(OptionletVolatilityStructure* ovts) {
104
105 if (strike_ == Null<Real>()) {
106 // If the strike is Null<Real>(), we want an ATM helper
107 Rate atm = CashFlows::atmRate(getOisCapFloorUnderlying(capFloor_), **discountHandle_, false);
108 CapFloor::Type capFloorType = type_ == CapFloorHelper::Cap ? CapFloor::Cap : CapFloor::Floor;
116 // If the helper is set to automatically choose the underlying instrument type, do it now based on the ATM rate
117 Rate atm = CashFlows::atmRate(getOisCapFloorUnderlying(capFloor_), **discountHandle_, false);
118 CapFloor::Type capFloorType = atm > strike_ ? CapFloor::Floor : CapFloor::Cap;
125 for (auto const& c : capFloor_) {
126 auto cpn = QuantLib::ext::dynamic_pointer_cast<Coupon>(c);
127 }
128 }
129
130 QuantLib::ext::shared_ptr<OptionletVolatilityStructure> temp(ovts, null_deleter());
131 ovtsHandle_.linkTo(temp, false);
132 RelativeDateBootstrapHelper<OptionletVolatilityStructure>::setTermStructure(ovts);
133
134 auto pricer = QuantLib::ext::make_shared<BlackOvernightIndexedCouponPricer>(ovtsHandle_);
135 for (auto c : capFloor_) {
136 auto f = QuantLib::ext::dynamic_pointer_cast<FloatingRateCoupon>(c);
137 if (f) {
138 f->setPricer(pricer);
139 }
140 }
141
142 // If the quote type is not a premium, we will need to use capFloorCopy_ to return the premium from the volatility
143 // quote
145 Handle<OptionletVolatilityStructure> constOvts;
146 if (quoteVolatilityType_ == ShiftedLognormal) {
147 constOvts = Handle<OptionletVolatilityStructure>(QuantLib::ext::make_shared<ConstantOptionletVolatility>(
148 0, NullCalendar(), Unadjusted, rawQuote_, Actual365Fixed(), ShiftedLognormal, quoteDisplacement_));
149 } else {
150 constOvts = Handle<OptionletVolatilityStructure>(QuantLib::ext::make_shared<ConstantOptionletVolatility>(
151 0, NullCalendar(), Unadjusted, rawQuote_, Actual365Fixed(), Normal));
152 }
153 auto pricer = QuantLib::ext::make_shared<BlackOvernightIndexedCouponPricer>(constOvts, true);
154 for (auto c : capFloorCopy_) {
155 auto f = QuantLib::ext::dynamic_pointer_cast<FloatingRateCoupon>(c);
156 if (f) {
157 f->setPricer(pricer);
158 }
159 }
160 }
161}
162
164 QL_REQUIRE(termStructure_ != 0, "CapFloorHelper's optionlet volatility term structure has not been set");
165 for (auto c : capFloor_) {
166 auto f = QuantLib::ext::dynamic_pointer_cast<LazyObject>(c);
167 if (f) {
168 f->deepUpdate();
169 }
170 }
171 return CashFlows::npv(capFloor_, **discountHandle_, false);
172}
173
174void OISCapFloorHelper::accept(AcyclicVisitor& v) {
175 if (Visitor<OISCapFloorHelper>* v1 = dynamic_cast<Visitor<OISCapFloorHelper>*>(&v))
176 v1->visit(*this);
177 else
178 RelativeDateBootstrapHelper<OptionletVolatilityStructure>::accept(v);
179}
180
181Real OISCapFloorHelper::npv(Real quoteValue) {
183 return quoteValue;
184 } else {
185 // If the quote value is a volatility, return the premium
186 return CashFlows::npv(capFloorCopy_, **discountHandle_, false);
187 }
188}
189
190} // namespace QuantExt
black coupon pricer for capped / floored ON indexed coupons
QuoteType
Enum to indicate the type of the quote provided with the CapFloorHelper.
MakeOISCapFloor & withEffectiveDate(const Date &effectiveDate)
MakeOISCapFloor & withTelescopicValueDates(bool telescopicValueDates)
QuantLib::Handle< QuantLib::Quote > rawQuote_
QuantLib::Period rateComputationPeriod_
QuantLib::Real npv(QuantLib::Real quote)
A method to calculate the cap floor premium from a flat cap floor volatility value.
void accept(QuantLib::AcyclicVisitor &) override
QuantLib::ext::shared_ptr< QuantLib::OvernightIndex > index_
void setTermStructure(QuantLib::OptionletVolatilityStructure *ovts) override
CapFloorHelper::QuoteType quoteType_
OISCapFloorHelper(CapFloorHelper::Type type, const QuantLib::Period &tenor, const QuantLib::Period &rateComputationPeriod, QuantLib::Rate strike, const QuantLib::Handle< QuantLib::Quote > &quote, const QuantLib::ext::shared_ptr< QuantLib::OvernightIndex > &index, const QuantLib::Handle< QuantLib::YieldTermStructure > &discountingCurve, bool moving=true, const QuantLib::Date &effectiveDate=QuantLib::Date(), CapFloorHelper::QuoteType quoteType=CapFloorHelper::Premium, QuantLib::VolatilityType quoteVolatilityType=QuantLib::Normal, QuantLib::Real quoteDisplacement=0.0)
OISCapFloorHelper, similar to CapFloorHelper.
QuantLib::Real impliedQuote() const override
QuantLib::VolatilityType quoteVolatilityType_
QuantLib::Handle< QuantLib::YieldTermStructure > discountHandle_
QuantLib::RelinkableHandle< QuantLib::OptionletVolatilityStructure > ovtsHandle_
helper class to instantiate standard market OIS cap / floors
Leg getOisCapFloorUnderlying(const Leg &oisCapFloor)
get the underlying ON coupons from an OIS cf
Helper for bootstrapping optionlet volatilties from ois cap floor volatilities.
coupon paying the compounded daily overnight rate, copy of QL class, added includeSpread flag