21#include <ql/instruments/creditdefaultswap.hpp>
22#include <ql/pricingengines/credit/midpointcdsengine.hpp>
32 const std::vector<Handle<CreditCurve>>& termCurves,
const Type& type)
33 : VolatilityTermStructure(bdc, dc), terms_(terms), termCurves_(termCurves), type_(type) {
37CreditVolCurve::CreditVolCurve(
const Natural settlementDays,
const Calendar& cal, BusinessDayConvention bdc,
38 const DayCounter& dc,
const std::vector<Period>& terms,
39 const std::vector<Handle<CreditCurve>>& termCurves,
const Type& type)
40 : VolatilityTermStructure(settlementDays, cal, bdc, dc), terms_(terms), termCurves_(termCurves), type_(type) {
44CreditVolCurve::CreditVolCurve(
const Date& referenceDate,
const Calendar& cal, BusinessDayConvention bdc,
45 const DayCounter& dc,
const std::vector<Period>& terms,
46 const std::vector<Handle<CreditCurve>>& termCurves,
const Type& type)
47 : VolatilityTermStructure(referenceDate, cal, bdc, dc), terms_(terms), termCurves_(termCurves), type_(type) {
51void CreditVolCurve::init() {
52 QL_REQUIRE(terms_.size() == termCurves_.size(),
"CreditVolCurve: terms size (" << terms_.size()
53 <<
") must match termCurves size ("
54 << termCurves_.size());
57 std::vector<Size> p(terms_.size());
58 std::iota(p.begin(), p.end(), 0);
59 std::sort(p.begin(), p.end(), [
this](Size i, Size j) { return this->terms_[i] < this->terms_[j]; });
61 std::vector<Period> sortedTerms(terms_.size());
62 std::vector<Handle<CreditCurve>> sortedCurves(terms_.size());
63 std::transform(p.begin(), p.end(), sortedTerms.begin(), [
this](Size i) { return this->terms_[i]; });
64 std::transform(p.begin(), p.end(), sortedCurves.begin(), [
this](Size i) { return this->termCurves_[i]; });
67 termCurves_ = sortedCurves;
71 for (
const auto& c : termCurves_)
75Real CreditVolCurve::volatility(
const Date& exerciseDate,
const Period& underlyingTerm,
const Real strike,
76 const Type& targetType)
const {
77 return volatility(exerciseDate,
periodToTime(underlyingTerm), strike, targetType);
80Real CreditVolCurve::volatility(
const Real exerciseTime,
const Real underlyingLength,
const Real strike,
81 const CreditVolCurve::Type& targetType)
const {
82 Date d = lowerDate(exerciseTime, referenceDate(), dayCounter());
83 Real t1 = timeFromReference(d);
84 Real t2 = timeFromReference(d + 1);
85 Real alpha = (t2 - exerciseTime) / (t2 - t1);
86 Real v1 = volatility(d, underlyingLength, strike, targetType);
87 if (close_enough(alpha, 1.0))
89 return alpha * v1 + (1.0 - alpha) * volatility(d + 1, underlyingLength, strike, targetType);
92const std::vector<Period>& CreditVolCurve::terms()
const {
return terms_; }
94const std::vector<Handle<CreditCurve>>& CreditVolCurve::termCurves()
const {
return termCurves_; }
98Date CreditVolCurve::maxDate()
const {
return Date::maxDate(); }
100Real CreditVolCurve::minStrike()
const {
return -QL_MAX_REAL; }
102Real CreditVolCurve::maxStrike()
const {
return QL_MAX_REAL; }
104Real CreditVolCurve::moneyness(
const Real strike,
const Real atmStrike)
const {
105 if (strike == Null<Real>())
107 if (type() == Type::Spread) {
108 return strike - atmStrike;
109 }
else if (type() == Type::Price) {
110 return std::log(strike / atmStrike);
112 QL_FAIL(
"InterpolatingCreditVolCurve::moneyness(): internal error, type not handled");
116Real CreditVolCurve::strike(
const Real moneyness,
const Real atmStrike)
const {
117 if (type() == Type::Spread) {
118 return atmStrike + moneyness;
119 }
else if (type() == Type::Price) {
120 return atmStrike * std::exp(moneyness);
122 QL_FAIL(
"InterpolatingCreditVolCurve::strike(): internal error, type not handled");
126Real CreditVolCurve::atmStrike(
const Date& expiry,
const Period& term)
const {
130Real CreditVolCurve::atmStrike(
const Date& expiry,
const Real underlyingLength)
const {
135 auto v = atmStrikeCache_.find(std::make_pair(expiry, underlyingLength));
136 if (v != atmStrikeCache_.end())
143 return type() == Type::Price ? 1.0 : 0.0;
147 std::vector<Real> termLengths;
148 for (
auto const& p : terms())
149 termLengths.push_back(periodToTime(p));
151 Size termIndex_m, termIndex_p;
153 std::tie(termIndex_m, termIndex_p, term_alpha) = interpolationIndices(termLengths, underlyingLength);
157 std::map<Period, QuantLib::ext::shared_ptr<QuantExt::CreditDefaultSwap>> underlyings;
159 const CreditCurve::RefData& refData = termCurves_[termIndex_m]->refData();
160 QL_REQUIRE(refData.runningSpread != Null<Real>(),
"CreditVolCurve: need runningSpread for ATM strike computation. "
161 "Is the running spread in the term curve configuration?");
165 Date mat = std::max(cdsMaturity(refData.startDate != Null<Date>() ? refData.startDate : referenceDate(),
166 terms_[termIndex_m], refData.rule),
167 referenceDate() + 1);
168 Date effExp = std::min(mat - 1, expiry);
169 Schedule schedule(effExp, mat, refData.tenor, refData.calendar, refData.convention, refData.termConvention,
170 refData.rule, refData.endOfMonth);
171 Date protectionStartDate = (refData.rule == DateGeneration::CDS || refData.rule == DateGeneration::CDS2015)
173 : schedule.dates().front();
174 DayCounter lastPeriodDayCounter = refData.lastPeriodDayCounter.empty() && refData.dayCounter == Actual360()
176 : refData.lastPeriodDayCounter;
177 underlyings[terms_[termIndex_m]] = QuantLib::ext::make_shared<CreditDefaultSwap>(
178 Protection::Buyer, 1.0, refData.runningSpread, schedule, refData.payConvention, refData.dayCounter,
true,
179 CreditDefaultSwap::atDefault, protectionStartDate, QuantLib::ext::shared_ptr<Claim>(), lastPeriodDayCounter,
true,
180 effExp, refData.cashSettlementDays);
182 QL_REQUIRE(!termCurves_[termIndex_m]->rateCurve().empty() && !termCurves_[termIndex_p]->rateCurve().empty(),
183 "CreditVolCurve: need discounting rate curve of index for ATM strike computation.");
184 QL_REQUIRE(!termCurves_[termIndex_m]->recovery().empty() && !termCurves_[termIndex_p]->recovery().empty(),
185 "CreditVolCurve: need recovery rate of index for ATM strike computation.");
187 auto engine = QuantLib::ext::make_shared<MidPointCdsEngine>(termCurves_[termIndex_m]->curve(),
188 termCurves_[termIndex_m]->recovery()->value(),
189 termCurves_[termIndex_m]->rateCurve());
191 underlyings[terms_[termIndex_m]]->setPricingEngine(engine);
196 Real fep1, fep2, fairSpread1, fairSpread2, rpv01_1, rpv01_2, adjFairSpread1 = 0.0, adjFairSpread2 = 0.0,
197 discToExercise = 1.0, forwardPrice1, forwardPrice2,
198 adjForwardPrice1 = 1.0, adjForwardPrice2 = 1.0;
200 discToExercise = termCurves_[termIndex_m]->rateCurve()->discount(effExp);
201 fep1 = (1.0 - termCurves_[termIndex_m]->recovery()->value()) *
202 termCurves_[termIndex_m]->curve()->defaultProbability(effExp) * discToExercise;
203 if (type() == Type::Spread) {
204 fairSpread1 = underlyings[terms_[termIndex_m]]->fairSpreadClean();
205 rpv01_1 = std::abs(underlyings[terms_[termIndex_m]]->couponLegNPV() +
206 underlyings[terms_[termIndex_m]]->accrualRebateNPV()) /
207 underlyings[terms_[termIndex_m]]->runningSpread();
208 adjFairSpread1 = fairSpread1 + fep1 / rpv01_1;
209 atmStrike = adjFairSpread1;
210 }
else if (type() == Type::Price) {
211 forwardPrice1 = 1.0 - underlyings[terms_[termIndex_m]]->NPV() / discToExercise;
212 adjForwardPrice1 = forwardPrice1 - fep1 / discToExercise;
213 atmStrike = adjForwardPrice1;
215 QL_FAIL(
"InterpolatingCreditVolCurve::atmStrike(): internal error, type not handled");
219 Date mat = std::max(cdsMaturity(refData.startDate != Null<Date>() ? refData.startDate : referenceDate(),
220 terms_[termIndex_p], refData.rule),
221 referenceDate() + 1);
222 Date effExp = std::min(mat - 1, expiry);
223 Schedule schedule(effExp, mat, refData.tenor, refData.calendar, refData.convention, refData.termConvention,
224 refData.rule, refData.endOfMonth);
225 Date protectionStartDate = (refData.rule == DateGeneration::CDS || refData.rule == DateGeneration::CDS2015)
227 : schedule.dates().front();
228 underlyings[terms_[termIndex_p]] = QuantLib::ext::make_shared<CreditDefaultSwap>(
229 Protection::Buyer, 1.0, refData.runningSpread, schedule, refData.payConvention, refData.dayCounter,
true,
230 CreditDefaultSwap::atDefault, protectionStartDate, QuantLib::ext::shared_ptr<Claim>(), lastPeriodDayCounter,
true,
231 effExp, refData.cashSettlementDays);
232 auto engine = QuantLib::ext::make_shared<MidPointCdsEngine>(termCurves_[termIndex_p]->curve(),
233 termCurves_[termIndex_p]->recovery()->value(),
234 termCurves_[termIndex_p]->rateCurve());
235 underlyings[terms_[termIndex_p]]->setPricingEngine(engine);
237 fep2 = (1.0 - termCurves_[termIndex_p]->recovery()->value()) *
238 termCurves_[termIndex_p]->curve()->defaultProbability(effExp) * discToExercise;
239 if (type() == Type::Spread) {
240 fairSpread2 = underlyings[terms_[termIndex_p]]->fairSpreadClean();
241 rpv01_2 = std::abs(underlyings[terms_[termIndex_p]]->couponLegNPV() +
242 underlyings[terms_[termIndex_p]]->accrualRebateNPV()) /
243 underlyings[terms_[termIndex_p]]->runningSpread();
244 adjFairSpread2 = fairSpread2 + fep2 / rpv01_2;
245 atmStrike = term_alpha * adjFairSpread1 + (1.0 - term_alpha * adjFairSpread2);
246 }
else if (type() == Type::Price) {
247 forwardPrice2 = 1.0 - underlyings[terms_[termIndex_p]]->NPV() / discToExercise;
248 adjForwardPrice2 = forwardPrice2 - fep2 / discToExercise;
249 atmStrike = term_alpha * adjForwardPrice1 + (1.0 - term_alpha) * adjForwardPrice2;
251 QL_FAIL(
"InterpolatingCreditVolCurve::atmStrike(): internal error, type not handled");
257 atmStrikeCache_[std::make_pair(expiry, underlyingLength)] = atmStrike;
261void CreditVolCurve::performCalculations()
const { atmStrikeCache_.clear(); }
263InterpolatingCreditVolCurve::InterpolatingCreditVolCurve(
264 const Natural settlementDays,
const Calendar& cal, BusinessDayConvention bdc,
const DayCounter& dc,
265 const std::vector<Period>& terms,
const std::vector<Handle<CreditCurve>>& termCurves,
266 const std::map<std::tuple<Date, Period, Real>, Handle<Quote>>& quotes,
const Type& type)
267 :
CreditVolCurve(settlementDays, cal, bdc, dc, terms, termCurves, type), quotes_(quotes) {
272 const Date& referenceDate,
const Calendar& cal, BusinessDayConvention bdc,
const DayCounter& dc,
273 const std::vector<Period>& terms,
const std::vector<Handle<CreditCurve>>& termCurves,
274 const std::map<std::tuple<Date, Period, Real>, Handle<Quote>>& quotes,
const Type& type)
275 : CreditVolCurve(referenceDate, cal, bdc, dc, terms, termCurves, type), quotes_(quotes) {
281 registerWith(q.second);
285 const Type& targetType)
const {
289 QL_REQUIRE(targetType ==
type(),
"InterpolatingCreditVolCurve: Vol type conversion between strike types 'Price' "
290 "and 'Spread' is not supported. The vol "
291 "surface used to price an option must have the same strike type as the option.");
297 Size termIndex_m, termIndex_p;
303 Size expiryIndex_m, expiryIndex_p;
305 Real t = timeFromReference(expiry);
317 Real atm_1_1 = smile_1_1.first;
318 Real atm_1_2 = smile_1_2.first;
319 Real atm_2_1 = smile_2_1.first;
320 Real atm_2_2 = smile_2_2.first;
325 Real vol_1_1 = smile_1_1.second->operator()(this->
strike(m, atm_1_1));
326 Real vol_1_2 = smile_1_2.second->operator()(this->
strike(m, atm_1_2));
327 Real vol_2_1 = smile_2_1.second->operator()(this->
strike(m, atm_2_1));
328 Real vol_2_2 = smile_2_2.second->operator()(this->
strike(m, atm_2_2));
332 Real vol_1 = term_alpha * vol_1_1 + (1.0 - term_alpha) * vol_1_2;
333 Real vol_2 = term_alpha * vol_2_1 + (1.0 - term_alpha) * vol_2_2;
337 return std::sqrt((expiry_alpha * (vol_1 * vol_1 *
smileExpiryTimes_[expiryIndex_m]) +
346 QL_REQUIRE(!
quotes_.empty(),
"InterpolatingCreditVolCurve: no quotes given, can not build a volatility curve.");
358 Period currentTerm = 0 * Days;
359 Date currentExpiry = Null<Date>();
360 std::vector<Real> currentStrikes;
361 std::vector<Real> currentVols;
368 for (Size i = 0; i <=
quotes_.size(); ++i) {
370 expiry = std::get<0>(q->first);
371 term = std::get<1>(q->first);
372 strike = std::get<2>(q->first);
373 vol = q->second->value();
377 currentExpiry = expiry;
379 if (term != currentTerm || expiry != currentExpiry || i ==
quotes_.size()) {
380 if (!currentStrikes.empty()) {
381 if (currentStrikes.size() == 1) {
382 currentStrikes.push_back(currentStrikes.back() + 0.01);
383 currentVols.push_back(currentVols.back());
385 auto key = std::make_pair(currentExpiry, currentTerm);
386 auto s =
strikes_.insert(std::make_pair(key, currentStrikes)).first;
387 auto v =
vols_.insert(std::make_pair(key, currentVols)).first;
388 auto tmp = QuantLib::ext::make_shared<FlatExtrapolation>(
389 QuantLib::ext::make_shared<LinearInterpolation>(s->second.begin(), s->second.end(), v->second.begin()));
390 tmp->enableExtrapolation();
392 currentStrikes.clear();
398 currentExpiry = expiry;
401 currentStrikes.push_back(
strike);
402 currentVols.push_back(vol);
421 auto key = std::make_pair(expiry, term);
426 Date expiry_m = Null<Date>();
427 Date expiry_p = Null<Date>();
428 for (
auto const& s :
smiles_) {
429 if (s.first.second != term)
431 if (s.first.first >= expiry) {
432 expiry_p = s.first.first;
435 expiry_m = s.first.first;
440 if (expiry_m == expiry || expiry_p == expiry)
445 if (expiry_m == Null<Date>() && expiry_p != Null<Date>()) {
448 }
else if (expiry_m != Null<Date>() && expiry_p != Null<Date>()) {
451 }
else if (expiry_m != Null<Date>() && expiry_p == Null<Date>()) {
455 QL_FAIL(
"InterpolatingCreditVolCurve: internal error, expiry_m = expiry_p = null, i.e. there are "
456 "no smiles for term "
466 bool operator()(Real x, Real y)
const {
return x < y && !
close_enough(x, y); }
471 const Date& expiry_p)
const {
473 if (expiry_p == Null<Date>()) {
474 auto key = std::make_pair(expiry_m, term);
477 std::vector<Real> vols;
478 for (
auto const& k :
strikes_[key]) {
482 vols.push_back(smile.second->operator()(k));
484 auto v =
vols_.insert(std::make_pair(key, vols));
485 auto tmp = QuantLib::ext::make_shared<FlatExtrapolation>(QuantLib::ext::make_shared<LinearInterpolation>(
486 s.first->second.begin(), s.first->second.end(), v.first->second.begin()));
487 tmp->enableExtrapolation();
488 smiles_[std::make_pair(expiry, term)] = std::make_pair(thisAtm, tmp);
489 }
else if (expiry_m == Null<Date>()) {
490 auto key = std::make_pair(expiry_p, term);
493 std::vector<Real> vols;
494 for (
auto const& k :
strikes_[key]) {
498 vols.push_back(smile.second->operator()(k));
500 auto v =
vols_.insert(std::make_pair(key, vols));
501 auto tmp = QuantLib::ext::make_shared<FlatExtrapolation>(QuantLib::ext::make_shared<LinearInterpolation>(
502 s.first->second.begin(), s.first->second.end(), v.first->second.begin()));
503 tmp->enableExtrapolation();
504 smiles_[std::make_pair(expiry, term)] = std::make_pair(thisAtm, tmp);
506 auto key_m = std::make_pair(expiry_m, term);
507 auto key_p = std::make_pair(expiry_p, term);
510 std::set<Real, CompClose> strikes_set;
511 for (
auto const& k :
strikes_[key_m]) {
514 for (
auto const& k :
strikes_[key_p]) {
517 std::vector<Real>
strikes(strikes_set.begin(), strikes_set.end());
518 std::vector<Real> vols;
519 Real t = timeFromReference(expiry);
520 Real t_m = timeFromReference(expiry_m);
521 Real t_p = timeFromReference(expiry_m);
522 Real alpha = (t_p - t) / (t_p - t_m);
523 for (
auto const& k :
strikes) {
524 Real vol_m = smile_m.second->operator()(k);
525 Real vol_p = smile_p.second->operator()(k);
526 vols.push_back(std::sqrt((alpha * (vol_m * vol_m * t_m) + (1.0 - alpha) * (vol_p * vol_p * t_p)) / t));
528 auto s =
strikes_.insert(std::make_pair(std::make_pair(expiry, term),
strikes));
529 auto v =
vols_.insert(std::make_pair(std::make_pair(expiry, term), vols));
530 auto tmp = QuantLib::ext::make_shared<FlatExtrapolation>(QuantLib::ext::make_shared<LinearInterpolation>(
531 s.first->second.begin(), s.first->second.end(), v.first->second.begin()));
532 tmp->enableExtrapolation();
533 smiles_[std::make_pair(expiry, term)] = std::make_pair(thisAtm, tmp);
538 const std::vector<QuantLib::Period>& terms,
539 const std::vector<QuantLib::Handle<CreditCurve>>& termCurves)
540 :
CreditVolCurve(source->businessDayConvention(), source->dayCounter(), terms.empty() ? source->terms() : terms,
541 termCurves.empty() ? source->termCurves() : termCurves, source->type()),
544 QL_REQUIRE(
terms.size() ==
termCurves.size(),
"ProxyCreditVolCurve: given terms (" <<
terms.size()
545 <<
") do not match term curves ("
547 registerWith(source);
551 const QuantLib::Real underlyingLength,
const QuantLib::Real strike,
552 const Type& targetType)
const {
556 Real effectiveStrike =
strike;
557 if (!this->
terms().empty() && !
source_->terms().empty()) {
559 source_->atmStrike(exerciseDate, underlyingLength));
561 return source_->volatility(exerciseDate, underlyingLength, effectiveStrike,
type());
567 const std::vector<Handle<Quote>> spreads,
const bool stickyMoneyness,
568 const std::vector<Period>& terms,
569 const std::vector<Handle<CreditCurve>>& termCurves)
570 :
CreditVolCurve(baseCurve->businessDayConvention(), baseCurve->dayCounter(), terms, termCurves, baseCurve->type()),
571 baseCurve_(baseCurve), expiries_(expiries), spreads_(spreads), stickyMoneyness_(stickyMoneyness) {
572 for (
auto const& s : spreads)
583 times_.push_back(timeFromReference(d));
594 const Type& targetType)
const {
596 Real effectiveStrike =
strike;
599 baseCurve_->atmStrike(exerciseDate, underlyingLength));
601 Real base =
baseCurve_->volatility(exerciseDate, underlyingLength, effectiveStrike, targetType);
603 return base + spread;
607 :
CreditVolCurve(vol->businessDayConvention(), vol->dayCounter(), {}, {}, Type::Spread),
vol_(vol) {
612 const Type& targetType)
const {
613 return vol_->blackVol(exerciseDate,
strike,
true);
619 const Real underlyingLength)
620 : BlackVolatilityTermStructure(vol->businessDayConvention(), vol->dayCounter()),
vol_(vol),
621 underlyingLength_(underlyingLength) {}
QuantLib::ext::shared_ptr< SimpleQuote > vol_
QuantLib::Handle< QuantExt::CreditVolCurve > vol_
QuantLib::Real blackVolImpl(QuantLib::Real t, QuantLib::Real strike) const override
const QuantLib::Date & referenceDate() const override
QuantLib::Real minStrike() const override
BlackVolFromCreditVolWrapper(const QuantLib::Handle< QuantExt::CreditVolCurve > &vol, const QuantLib::Real underlyingLength)
QuantLib::Date maxDate() const override
QuantLib::Real underlyingLength_
QuantLib::Real maxStrike() const override
void performCalculations() const override
QuantLib::Real moneyness(const QuantLib::Real strike, const QuantLib::Real atmStrike) const
QuantLib::Real atmStrike(const QuantLib::Date &expiry, const QuantLib::Period &term) const
CreditVolCurve(QuantLib::BusinessDayConvention bdc, const QuantLib::DayCounter &dc, const std::vector< QuantLib::Period > &terms, const std::vector< QuantLib::Handle< CreditCurve > > &termCurves, const Type &type)
QuantLib::Real strike(const QuantLib::Real moneyness, const QuantLib::Real atmStrike) const
virtual const std::vector< QuantLib::Handle< CreditCurve > > & termCurves() const
const Type & type() const
virtual const std::vector< QuantLib::Period > & terms() const
CreditVolCurveWrapper(const QuantLib::Handle< QuantLib::BlackVolTermStructure > &vol)
const QuantLib::Date & referenceDate() const override
QuantLib::Real volatility(const QuantLib::Date &exerciseDate, const QuantLib::Real underlyingLength, const QuantLib::Real strike, const Type &targetType) const override
QuantLib::Handle< QuantLib::BlackVolTermStructure > vol_
std::vector< QuantLib::Date > smileExpiries_
std::map< Key, std::vector< QuantLib::Real > > strikes_
std::map< Key, std::vector< QuantLib::Real > > vols_
void performCalculations() const override
std::map< Key, Smile > smiles_
std::pair< QuantLib::Real, QuantLib::ext::shared_ptr< QuantLib::Interpolation > > Smile
QuantLib::Real volatility(const QuantLib::Date &exerciseDate, const QuantLib::Real underlyingLength, const QuantLib::Real strike, const Type &targetType) const override
std::vector< QuantLib::Real > smileTermLengths_
InterpolatingCreditVolCurve(const QuantLib::Natural settlementDays, const QuantLib::Calendar &cal, QuantLib::BusinessDayConvention bdc, const QuantLib::DayCounter &dc, const std::vector< QuantLib::Period > &terms, const std::vector< QuantLib::Handle< CreditCurve > > &termCurves, const std::map< std::tuple< QuantLib::Date, QuantLib::Period, QuantLib::Real >, QuantLib::Handle< QuantLib::Quote > > "es, const Type &type)
std::vector< QuantLib::Real > smileExpiryTimes_
std::map< std::tuple< QuantLib::Date, QuantLib::Period, QuantLib::Real >, QuantLib::Handle< QuantLib::Quote > > quotes_
std::vector< QuantLib::Period > smileTerms_
void createSmile(const QuantLib::Date &expiry, const QuantLib::Period &term, const QuantLib::Date &expiry_m, const QuantLib::Date &expiry_p) const
ProxyCreditVolCurve(const QuantLib::Handle< CreditVolCurve > &source, const std::vector< QuantLib::Period > &terms={}, const std::vector< QuantLib::Handle< CreditCurve > > &termCurves={})
QuantLib::Real volatility(const QuantLib::Date &exerciseDate, const QuantLib::Real underlyingLength, const QuantLib::Real strike, const Type &targetType) const override
const QuantLib::Date & referenceDate() const override
QuantLib::Handle< CreditVolCurve > source_
void performCalculations() const override
std::vector< QuantLib::Handle< QuantLib::Quote > > spreads_
QuantLib::ext::shared_ptr< QuantLib::Interpolation > interpolatedSpreads_
const QuantLib::Date & referenceDate() const override
QuantLib::Real volatility(const QuantLib::Date &exerciseDate, const QuantLib::Real underlyingLength, const QuantLib::Real strike, const Type &targetType) const override
std::vector< QuantLib::Real > spreadValues_
std::vector< QuantLib::Real > times_
std::vector< QuantLib::Date > expiries_
SpreadedCreditVolCurve(const QuantLib::Handle< CreditVolCurve > baseCurve, const std::vector< QuantLib::Date > expiries, const std::vector< QuantLib::Handle< QuantLib::Quote > > spreads, const bool stickyMoneyness, const std::vector< QuantLib::Period > &terms={}, const std::vector< QuantLib::Handle< CreditCurve > > &termCurves={})
const bool stickyMoneyness_
QuantLib::Handle< CreditVolCurve > baseCurve_
std::tuple< Size, Size, Real > interpolationIndices(const T &x, const Real v)
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
Real periodToTime(const Period &p)