Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Public Member Functions | Private Member Functions | Private Attributes | List of all members
DurationAdjustedCmsCouponTsrPricer Class Reference

#include <qle/cashflows/durationadjustedcmscoupontsrpricer.hpp>

+ Inheritance diagram for DurationAdjustedCmsCouponTsrPricer:
+ Collaboration diagram for DurationAdjustedCmsCouponTsrPricer:

Public Member Functions

 DurationAdjustedCmsCouponTsrPricer (const Handle< SwaptionVolatilityStructure > &swaptionVol, const QuantLib::ext::shared_ptr< AnnuityMappingBuilder > &annuityMappingBuilder, const Real lowerIntegrationBound=-0.3, const Real upperIntegrationBound=0.3, const QuantLib::ext::shared_ptr< Integrator > &integrator=QuantLib::ext::shared_ptr< Integrator >())
 
Real swapletPrice () const override
 
Rate swapletRate () const override
 
Real capletPrice (Rate effectiveCap) const override
 
Rate capletRate (Rate effectiveCap) const override
 
Real floorletPrice (Rate effectiveFloor) const override
 
Rate floorletRate (Rate effectiveFloor) const override
 

Private Member Functions

void initialize (const FloatingRateCoupon &coupon) override
 
Real optionletRate (Option::Type type, Real effectiveStrike) const
 

Private Attributes

QuantLib::ext::shared_ptr< AnnuityMappingBuilderannuityMappingBuilder_
 
Real lowerIntegrationBound_
 
Real upperIntegrationBound_
 
QuantLib::ext::shared_ptr< Integrator > integrator_
 
const DurationAdjustedCmsCouponcoupon_
 
Date today_
 
Real swapRate_
 
Real durationAdjustment_
 
Real forwardAnnuity_
 
QuantLib::ext::shared_ptr< SmileSection > smileSection_
 
QuantLib::ext::shared_ptr< AnnuityMappingannuityMapping_
 

Detailed Description

Definition at line 39 of file durationadjustedcmscoupontsrpricer.hpp.

Constructor & Destructor Documentation

◆ DurationAdjustedCmsCouponTsrPricer()

DurationAdjustedCmsCouponTsrPricer ( const Handle< SwaptionVolatilityStructure > &  swaptionVol,
const QuantLib::ext::shared_ptr< AnnuityMappingBuilder > &  annuityMappingBuilder,
const Real  lowerIntegrationBound = -0.3,
const Real  upperIntegrationBound = 0.3,
const QuantLib::ext::shared_ptr< Integrator > &  integrator = QuantLib::ext::shared_ptr<Integrator>() 
)

Definition at line 37 of file durationadjustedcmscoupontsrpricer.cpp.

41 : CmsCouponPricer(swaptionVol), annuityMappingBuilder_(annuityMappingBuilder),
42 lowerIntegrationBound_(lowerIntegrationBound), upperIntegrationBound_(upperIntegrationBound),
43 integrator_(integrator) {
44 if (integrator_ == nullptr)
45 integrator_ = ext::make_shared<GaussKronrodNonAdaptive>(1E-10, 5000, 1E-10);
46 if (annuityMappingBuilder_ != nullptr)
47 registerWith(annuityMappingBuilder_);
48}
QuantLib::ext::shared_ptr< AnnuityMappingBuilder > annuityMappingBuilder_

Member Function Documentation

◆ swapletPrice()

Real swapletPrice ( ) const
override

Definition at line 50 of file durationadjustedcmscoupontsrpricer.cpp.

50 {
51 QL_FAIL("DurationAdjustedCmsCouponTsrPricer::swapletPrice() is not implemented");
52}

◆ swapletRate()

Rate swapletRate ( ) const
override

◆ capletPrice()

Real capletPrice ( Rate  effectiveCap) const
override

Definition at line 54 of file durationadjustedcmscoupontsrpricer.cpp.

54 {
55 QL_FAIL("DurationAdjustedCmsCouponTsrPricer::swapletPrice() is not implemented");
56}

◆ capletRate()

Rate capletRate ( Rate  effectiveCap) const
override

Definition at line 67 of file durationadjustedcmscoupontsrpricer.cpp.

67 {
68 if (coupon_->fixingDate() <= today_) {
69 return durationAdjustment_ * coupon_->gearing() * std::max(swapRate_ - effectiveCap, 0.0);
70 } else {
71 return durationAdjustment_ * coupon_->gearing() * optionletRate(Option::Call, effectiveCap);
72 }
73}
Real optionletRate(Option::Type type, Real effectiveStrike) const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ floorletPrice()

Real floorletPrice ( Rate  effectiveFloor) const
override

Definition at line 58 of file durationadjustedcmscoupontsrpricer.cpp.

58 {
59 QL_FAIL("DurationAdjustedCmsCouponTsrPricer::swapletPrice() is not implemented");
60}

◆ floorletRate()

Rate floorletRate ( Rate  effectiveFloor) const
override

Definition at line 75 of file durationadjustedcmscoupontsrpricer.cpp.

75 {
76 if (coupon_->fixingDate() <= today_) {
77 return durationAdjustment_ * coupon_->gearing() * std::max(effectiveFloor - swapRate_, 0.0);
78 } else {
79 return durationAdjustment_ * coupon_->gearing() * optionletRate(Option::Put, effectiveFloor);
80 }
81}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ initialize()

void initialize ( const FloatingRateCoupon coupon)
overrideprivate

Definition at line 83 of file durationadjustedcmscoupontsrpricer.cpp.

83 {
84
85 coupon_ = dynamic_cast<const DurationAdjustedCmsCoupon*>(&coupon);
86 QL_REQUIRE(coupon_, "DurationAdjustedCmsCoupon needed");
87 today_ = QuantLib::Settings::instance().evaluationDate();
89
90 if (coupon_->fixingDate() > today_) {
91 Handle<YieldTermStructure> discountCurve;
92 if (coupon_->swapIndex()->exogenousDiscount())
93 discountCurve = coupon_->swapIndex()->discountingTermStructure();
94 else
95 discountCurve = coupon_->swapIndex()->forwardingTermStructure();
96 auto swap = coupon_->swapIndex()->underlyingSwap(coupon_->fixingDate());
97 swapRate_ = swap->fairRate();
98 forwardAnnuity_ = 1.0E4 * std::fabs(swap->fixedLegBPS()) / discountCurve->discount(coupon_->date());
99 smileSection_ = swaptionVolatility()->smileSection(coupon_->fixingDate(), coupon_->swapIndex()->tenor());
100 // if the smile section does not have an ATM level, we add one
101 if (smileSection_->atmLevel() == Null<Real>())
102 smileSection_ = ext::make_shared<AtmSmileSection>(smileSection_, swapRate_);
104 annuityMappingBuilder_->build(today_, coupon_->fixingDate(), coupon_->date(), *swap, discountCurve);
105 } else {
106 swapRate_ = coupon_->swapIndex()->fixing(coupon_->fixingDate());
107 }
108}
const QuantLib::ext::shared_ptr< SwapIndex > & swapIndex() const
QuantLib::ext::shared_ptr< SmileSection > smileSection_
QuantLib::ext::shared_ptr< AnnuityMapping > annuityMapping_
+ Here is the call graph for this function:

◆ optionletRate()

Real optionletRate ( Option::Type  type,
Real  effectiveStrike 
) const
private

Definition at line 110 of file durationadjustedcmscoupontsrpricer.cpp.

110 {
111
112 Real effectiveLowerIntegrationBound = lowerIntegrationBound_;
113 Real effectiveUpperIntegrationBound = upperIntegrationBound_;
114
115 // adjust the lower integration bound if the vol type is lognormal
116
117 if (swaptionVolatility()->volatilityType() == ShiftedLognormal) {
118 effectiveLowerIntegrationBound = std::max(
119 lowerIntegrationBound_, -swaptionVolatility()->shift(coupon_->fixingDate(), coupon_->swapIndex()->tenor()));
120 }
121
122 // the payoff function and its 1st and 2nd derivatives vanish for arguments > strike (call) resp. < strike (put)
123
124 if (optionType == Option::Call)
125 effectiveLowerIntegrationBound = std::max(effectiveLowerIntegrationBound, strike);
126 else
127 effectiveUpperIntegrationBound = std::min(effectiveUpperIntegrationBound, strike);
128
129 Real integral = 0.0;
130 Real omega = optionType == Option::Call ? 1.0 : -1.0;
131
132 // compute the relevant integral
133
134 if (effectiveLowerIntegrationBound < effectiveUpperIntegrationBound &&
135 !close_enough(effectiveLowerIntegrationBound, effectiveUpperIntegrationBound)) {
136
137 auto f = [this, strike, omega](const Real S) -> Real {
138 return std::max(omega * (S - strike), 0.0) * this->durationAdjustment_;
139 };
140
141 auto fp = [this, strike, omega](const Real S) -> Real {
142 if (this->coupon_->duration() == 0) {
143 return omega * (omega * S > omega * strike ? 1.0 : 0.0);
144 } else {
145 Real dp = 0.0;
146 for (Size i = 0; i < this->coupon_->duration(); ++i) {
147 dp -= static_cast<Real>(i + 1) / std::pow(1.0 + this->swapRate_, i + 2);
148 }
149 return this->durationAdjustment_ * omega * (omega * S > omega * strike ? 1.0 : 0.0) +
150 dp * std::max(omega * (S - strike), 0.0);
151 }
152 };
153
154 auto fpp = [this, strike, omega](const Real S) -> Real {
155 if (this->coupon_->duration() == 0) {
156 return 0.0;
157 } else {
158 Real dp1 = 0.0, dp2 = 0.0;
159 for (Size i = 0; i < this->coupon_->duration(); ++i) {
160 dp1 -= static_cast<Real>(i + 1) / std::pow(1.0 + this->swapRate_, i + 2);
161 dp2 += static_cast<Real>(i + 1) * static_cast<Real>(i + 2) / std::pow(1.0 + this->swapRate_, i + 3);
162 }
163 return dp1 * omega * (omega * S > omega * strike ? 1.0 : 0.0) +
164 dp2 * std::max(omega * (S - strike), 0.0);
165 }
166 };
167
168 auto integrand = [this, &f, &fp, &fpp](const Real S) -> Real {
169 Real f2 = 0.0;
170 if (this->coupon_->duration() != 0) {
171 f2 = this->annuityMapping_->map(S) * fpp(S);
172 }
173 Real f1 = 2.0 * fp(S) * this->annuityMapping_->mapPrime(S);
174 Real f0 = 0.0;
175 if (!this->annuityMapping_->mapPrime2IsZero())
176 f0 = annuityMapping_->mapPrime2(S) * f(S);
177 return (f0 + f1 + f2) * this->smileSection_->optionPrice(S, S < swapRate_ ? Option::Put : Option::Call);
178 };
179
180 // calculate two integrals up to and from the fair swap rate => is that better than a single integral?
181 Real tmpBound;
182 tmpBound = std::min(effectiveUpperIntegrationBound, swapRate_);
183 if (tmpBound > effectiveLowerIntegrationBound)
184 integral += (*integrator_)(integrand, effectiveLowerIntegrationBound, tmpBound);
185 tmpBound = std::max(effectiveLowerIntegrationBound, swapRate_);
186 if (effectiveUpperIntegrationBound > tmpBound)
187 integral += (*integrator_)(integrand, tmpBound, effectiveUpperIntegrationBound);
188
189 integral = (*integrator_)(integrand, effectiveLowerIntegrationBound, effectiveUpperIntegrationBound);
190 }
191
192 // add payoff function * annuityMapping at fair swap rate and Dirac delta contributions from integral
193
194 Real singularTerms =
195 annuityMapping_->map(swapRate_) * durationAdjustment_ * std::max(omega * (swapRate_ - strike), 0.0) +
196 annuityMapping_->map(strike) * durationAdjustment_ *
197 smileSection_->optionPrice(strike, strike < swapRate_ ? Option::Put : Option::Call);
198
199 return forwardAnnuity_ * (integral + singularTerms) / durationAdjustment_;
200}
Real integral(const CrossAssetModel &model, const E &e, const Real a, const Real b)
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Member Data Documentation

◆ annuityMappingBuilder_

QuantLib::ext::shared_ptr<AnnuityMappingBuilder> annuityMappingBuilder_
private

Definition at line 58 of file durationadjustedcmscoupontsrpricer.hpp.

◆ lowerIntegrationBound_

Real lowerIntegrationBound_
private

Definition at line 59 of file durationadjustedcmscoupontsrpricer.hpp.

◆ upperIntegrationBound_

Real upperIntegrationBound_
private

Definition at line 59 of file durationadjustedcmscoupontsrpricer.hpp.

◆ integrator_

QuantLib::ext::shared_ptr<Integrator> integrator_
private

Definition at line 60 of file durationadjustedcmscoupontsrpricer.hpp.

◆ coupon_

const DurationAdjustedCmsCoupon* coupon_
private

Definition at line 62 of file durationadjustedcmscoupontsrpricer.hpp.

◆ today_

Date today_
private

Definition at line 63 of file durationadjustedcmscoupontsrpricer.hpp.

◆ swapRate_

Real swapRate_
private

Definition at line 64 of file durationadjustedcmscoupontsrpricer.hpp.

◆ durationAdjustment_

Real durationAdjustment_
private

Definition at line 64 of file durationadjustedcmscoupontsrpricer.hpp.

◆ forwardAnnuity_

Real forwardAnnuity_
private

Definition at line 64 of file durationadjustedcmscoupontsrpricer.hpp.

◆ smileSection_

QuantLib::ext::shared_ptr<SmileSection> smileSection_
private

Definition at line 65 of file durationadjustedcmscoupontsrpricer.hpp.

◆ annuityMapping_

QuantLib::ext::shared_ptr<AnnuityMapping> annuityMapping_
private

Definition at line 66 of file durationadjustedcmscoupontsrpricer.hpp.