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

CMS spread - coupon pricer. More...

#include <qle/cashflows/lognormalcmsspreadpricer.hpp>

+ Inheritance diagram for LognormalCmsSpreadPricer:
+ Collaboration diagram for LognormalCmsSpreadPricer:

Public Member Functions

 LognormalCmsSpreadPricer (const QuantLib::ext::shared_ptr< CmsCouponPricer > cmsPricer, const Handle< QuantExt::CorrelationTermStructure > &correlation, const Handle< YieldTermStructure > &couponDiscountCurve=Handle< YieldTermStructure >(), const Size IntegrationPoints=16, const boost::optional< VolatilityType > volatilityType=boost::none, const Real shift1=Null< Real >(), const Real shift2=Null< Real >())
 
virtual Real swapletPrice () const override
 
virtual Rate swapletRate () const override
 
virtual Real capletPrice (Rate effectiveCap) const override
 
virtual Rate capletRate (Rate effectiveCap) const override
 
virtual Real floorletPrice (Rate effectiveFloor) const override
 
virtual Rate floorletRate (Rate effectiveFloor) const override
 
- Public Member Functions inherited from CmsSpreadCouponPricer2
 CmsSpreadCouponPricer2 (const Handle< CorrelationTermStructure > &correlation=Handle< CorrelationTermStructure >())
 
Real correlation (Time t, Real strike=1) const
 
void setCorrelationCurve (const Handle< CorrelationTermStructure > &correlation=Handle< CorrelationTermStructure >())
 

Private Member Functions

void initialize (const FloatingRateCoupon &coupon) override
 
Real rho () const
 
Real optionletPrice (Option::Type optionType, Real strike) const
 
Real integrand (const Real) const
 
Real integrand_normal (const Real) const
 

Private Attributes

QuantLib::ext::shared_ptr< CmsCouponPricercmsPricer_
 
Handle< YieldTermStructure > couponDiscountCurve_
 
const CmsSpreadCoupon * coupon_
 
Date today_
 
Date fixingDate_
 
Date paymentDate_
 
Real fixingTime_
 
Real gearing_
 
Real spread_
 
Real spreadLegValue_
 
Real discount_
 
QuantLib::ext::shared_ptr< SwapSpreadIndex > index_
 
QuantLib::ext::shared_ptr< CumulativeNormalDistribution > cnd_
 
QuantLib::ext::shared_ptr< GaussianQuadrature > integrator_
 
Real swapRate1_
 
Real swapRate2_
 
Real gearing1_
 
Real gearing2_
 
Real adjustedRate1_
 
Real adjustedRate2_
 
Real vol1_
 
Real vol2_
 
Real mu1_
 
Real mu2_
 
bool inheritedVolatilityType_
 
VolatilityType volType_
 
Real shift1_
 
Real shift2_
 
Real phi_
 
Real a_
 
Real b_
 
Real s1_
 
Real s2_
 
Real m1_
 
Real m2_
 
Real v1_
 
Real v2_
 
Real k_
 
Real alpha_
 
Real psi_
 
Option::Type optionType_
 
QuantLib::ext::shared_ptr< CmsCoupon > c1_
 
QuantLib::ext::shared_ptr< CmsCoupon > c2_
 

Friends

class integrand_f
 

Detailed Description

CMS spread - coupon pricer.

The swap rate adjustments are computed using the given volatility structures for the underlyings in every case (w.r.t. volatility type and shift).

For the bivariate spread model, the volatility type and the shifts can be inherited (default), or explicitly specified. In the latter case the type, and (if lognormal) the shifts must be given (or are defaulted to zero, if not given).

References:

Brigo, Mercurio: Interest Rate Models - Theory and Practice, 2nd Edition, Springer, 2006, chapter 13.6.2

http://ssrn.com/abstract=2686998

Definition at line 105 of file lognormalcmsspreadpricer.hpp.

Constructor & Destructor Documentation

◆ LognormalCmsSpreadPricer()

LognormalCmsSpreadPricer ( const QuantLib::ext::shared_ptr< CmsCouponPricer cmsPricer,
const Handle< QuantExt::CorrelationTermStructure > &  correlation,
const Handle< YieldTermStructure > &  couponDiscountCurve = Handle<YieldTermStructure>(),
const Size  IntegrationPoints = 16,
const boost::optional< VolatilityType >  volatilityType = boost::none,
const Real  shift1 = Null<Real>(),
const Real  shift2 = Null<Real>() 
)

Definition at line 60 of file lognormalcmsspreadpricer.cpp.

66 : CmsSpreadCouponPricer2(correlation), cmsPricer_(cmsPricer), couponDiscountCurve_(couponDiscountCurve) {
67
68 if (!couponDiscountCurve_.empty())
69 registerWith(couponDiscountCurve_);
70 registerWith(cmsPricer_);
71
72 QL_REQUIRE(integrationPoints >= 4, "at least 4 integration points should be used (" << integrationPoints << ")");
73 integrator_ = QuantLib::ext::make_shared<GaussHermiteIntegration>(integrationPoints);
74
75 cnd_ = QuantLib::ext::make_shared<CumulativeNormalDistribution>(0.0, 1.0);
76
77 if (volatilityType == boost::none) {
78 QL_REQUIRE(shift1 == Null<Real>() && shift2 == Null<Real>(),
79 "if volatility type is inherited, no shifts should be "
80 "specified");
82 volType_ = cmsPricer->swaptionVolatility()->volatilityType();
83 } else {
84 shift1_ = shift1 == Null<Real>() ? 0.0 : shift1;
85 shift2_ = shift2 == Null<Real>() ? 0.0 : shift2;
87 volType_ = *volatilityType;
88 }
89}
CmsSpreadCouponPricer2(const Handle< CorrelationTermStructure > &correlation=Handle< CorrelationTermStructure >())
Real correlation(Time t, Real strike=1) const
QuantLib::ext::shared_ptr< GaussianQuadrature > integrator_
QuantLib::ext::shared_ptr< CmsCouponPricer > cmsPricer_
QuantLib::ext::shared_ptr< CumulativeNormalDistribution > cnd_
Handle< YieldTermStructure > couponDiscountCurve_

Member Function Documentation

◆ swapletPrice()

Real swapletPrice ( ) const
overridevirtual

◆ swapletRate()

Rate swapletRate ( ) const
overridevirtual

Definition at line 267 of file lognormalcmsspreadpricer.cpp.

267{ return swapletPrice() / (coupon_->accrualPeriod() * discount_); }
virtual Real swapletPrice() const override
+ Here is the call graph for this function:

◆ capletPrice()

Real capletPrice ( Rate  effectiveCap) const
overridevirtual

Definition at line 269 of file lognormalcmsspreadpricer.cpp.

269 {
270 // caplet is equivalent to call option on fixing
271 if (fixingDate_ <= today_) {
272 // the fixing is determined
273 const Rate Rs = std::max(coupon_->index()->fixing(fixingDate_) - effectiveCap, 0.);
274 Rate price = gearing_ * Rs * coupon_->accrualPeriod() * discount_;
275 return price;
276 } else {
277 Real capletPrice = optionletPrice(Option::Call, effectiveCap);
278 return gearing_ * capletPrice;
279 }
280}
virtual Real capletPrice(Rate effectiveCap) const override
Real optionletPrice(Option::Type optionType, Real strike) const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ capletRate()

Rate capletRate ( Rate  effectiveCap) const
overridevirtual

Definition at line 282 of file lognormalcmsspreadpricer.cpp.

282 {
283 return capletPrice(effectiveCap) / (coupon_->accrualPeriod() * discount_);
284}
+ Here is the call graph for this function:

◆ floorletPrice()

Real floorletPrice ( Rate  effectiveFloor) const
overridevirtual

Definition at line 286 of file lognormalcmsspreadpricer.cpp.

286 {
287 // floorlet is equivalent to put option on fixing
288 if (fixingDate_ <= today_) {
289 // the fixing is determined
290 const Rate Rs = std::max(effectiveFloor - coupon_->index()->fixing(fixingDate_), 0.);
291 Rate price = gearing_ * Rs * coupon_->accrualPeriod() * discount_;
292 return price;
293 } else {
294 Real floorletPrice = optionletPrice(Option::Put, effectiveFloor);
295 return gearing_ * floorletPrice;
296 }
297}
virtual Real floorletPrice(Rate effectiveFloor) const override
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ floorletRate()

Rate floorletRate ( Rate  effectiveFloor) const
overridevirtual

Definition at line 299 of file lognormalcmsspreadpricer.cpp.

299 {
300 return floorletPrice(effectiveFloor) / (coupon_->accrualPeriod() * discount_);
301}
+ Here is the call graph for this function:

◆ initialize()

void initialize ( const FloatingRateCoupon coupon)
overrideprivate

Definition at line 129 of file lognormalcmsspreadpricer.cpp.

129 {
130
131 coupon_ = dynamic_cast<const CmsSpreadCoupon*>(&coupon);
132 QL_REQUIRE(coupon_, "CMS spread coupon needed");
133 index_ = coupon_->swapSpreadIndex();
134 gearing_ = coupon_->gearing();
135 spread_ = coupon_->spread();
136
137 fixingDate_ = coupon_->fixingDate();
138 paymentDate_ = coupon_->date();
139
140 // if no coupon discount curve is given just use the discounting curve
141 // from the _first_ swap index.
142 // for rate calculation this curve cancels out in the computation, so
143 // e.g. the discounting
144 // swap engine will produce correct results, even if the
145 // couponDiscountCurve is not set here.
146 // only the price member function in this class will be dependent on the
147 // coupon discount curve.
148
149 today_ = QuantLib::Settings::instance().evaluationDate();
150
151 if (couponDiscountCurve_.empty())
152 couponDiscountCurve_ = index_->swapIndex1()->exogenousDiscount()
153 ? index_->swapIndex1()->discountingTermStructure()
154 : index_->swapIndex1()->forwardingTermStructure();
155
156 discount_ =
157 paymentDate_ > couponDiscountCurve_->referenceDate() ? couponDiscountCurve_->discount(paymentDate_) : 1.0;
158
159 spreadLegValue_ = spread_ * coupon_->accrualPeriod() * discount_;
160
161 gearing1_ = index_->gearing1();
162 gearing2_ = index_->gearing2();
163
164 QL_REQUIRE(gearing1_ > 0.0 && gearing2_ < 0.0, "gearing1 (" << gearing1_ << ") should be positive while gearing2 ("
165 << gearing2_ << ") should be negative");
166
167 c1_ = QuantLib::ext::shared_ptr<CmsCoupon>(
168 new CmsCoupon(coupon_->date(), coupon_->nominal(), coupon_->accrualStartDate(), coupon_->accrualEndDate(),
169 coupon_->fixingDays(), index_->swapIndex1(), 1.0, 0.0, coupon_->referencePeriodStart(),
170 coupon_->referencePeriodEnd(), coupon_->dayCounter(), coupon_->isInArrears()));
171
172 c2_ = QuantLib::ext::shared_ptr<CmsCoupon>(
173 new CmsCoupon(coupon_->date(), coupon_->nominal(), coupon_->accrualStartDate(), coupon_->accrualEndDate(),
174 coupon_->fixingDays(), index_->swapIndex2(), 1.0, 0.0, coupon_->referencePeriodStart(),
175 coupon_->referencePeriodEnd(), coupon_->dayCounter(), coupon_->isInArrears()));
176
177 c1_->setPricer(cmsPricer_);
178 c2_->setPricer(cmsPricer_);
179
180 if (fixingDate_ > today_) {
181
182 fixingTime_ = cmsPricer_->swaptionVolatility()->timeFromReference(fixingDate_);
183
184 swapRate1_ = c1_->indexFixing();
185 swapRate2_ = c2_->indexFixing();
186
187 adjustedRate1_ = c1_->adjustedFixing();
188 adjustedRate2_ = c2_->adjustedFixing();
189
190 QuantLib::ext::shared_ptr<SwaptionVolatilityStructure> swvol = *cmsPricer_->swaptionVolatility();
191 QuantLib::ext::shared_ptr<SwaptionVolatilityCube> swcub = QuantLib::ext::dynamic_pointer_cast<SwaptionVolatilityCube>(swvol);
192
193 if (inheritedVolatilityType_ && volType_ == ShiftedLognormal) {
194 shift1_ = swvol->shift(fixingDate_, index_->swapIndex1()->tenor());
195 shift2_ = swvol->shift(fixingDate_, index_->swapIndex2()->tenor());
196 }
197
198 if (swcub == NULL) {
199 // not a cube, just an atm surface given, so we can
200 // not easily convert volatilities and just forbid it
201 QL_REQUIRE(inheritedVolatilityType_, "if only an atm surface is given, the volatility "
202 "type must be inherited");
203 vol1_ = swvol->volatility(fixingDate_, index_->swapIndex1()->tenor(), swapRate1_);
204 vol2_ = swvol->volatility(fixingDate_, index_->swapIndex2()->tenor(), swapRate2_);
205 } else {
206 vol1_ = swcub->smileSection(fixingDate_, index_->swapIndex1()->tenor())
207 ->volatility(swapRate1_, volType_, shift1_);
208 vol2_ = swcub->smileSection(fixingDate_, index_->swapIndex2()->tenor())
209 ->volatility(swapRate2_, volType_, shift2_);
210 }
211
212 if (volType_ == ShiftedLognormal) {
213 mu1_ = 1.0 / fixingTime_ * std::log((adjustedRate1_ + shift1_) / (swapRate1_ + shift1_));
214 mu2_ = 1.0 / fixingTime_ * std::log((adjustedRate2_ + shift2_) / (swapRate2_ + shift2_));
215 }
216 // for the normal volatility case we do not need the drifts
217 // but rather use adjusted rates directly in the integrand
218
219 } else {
220 // fixing is in the past or today
221 adjustedRate1_ = c1_->indexFixing();
222 adjustedRate2_ = c2_->indexFixing();
223 }
224}
QuantLib::ext::shared_ptr< CmsCoupon > c1_
QuantLib::ext::shared_ptr< CmsCoupon > c2_
QuantLib::ext::shared_ptr< SwapSpreadIndex > index_

◆ rho()

Real rho ( ) const
private

Definition at line 125 of file lognormalcmsspreadpricer.hpp.

125{ return std::max(std::min(correlation(fixingTime_), 0.9999), -0.9999); }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ optionletPrice()

Real optionletPrice ( Option::Type  optionType,
Real  strike 
) const
private

Definition at line 226 of file lognormalcmsspreadpricer.cpp.

226 {
227 // this method is only called for future fixings
228 optionType_ = optionType;
229 phi_ = optionType == Option::Call ? 1.0 : -1.0;
230 Real res = 0.0;
231 if (volType_ == ShiftedLognormal) {
232 // (shifted) lognormal volatility
233 if (strike >= 0.0) {
234 a_ = gearing1_;
235 b_ = gearing2_;
238 m1_ = mu1_;
239 m2_ = mu2_;
240 v1_ = vol1_;
241 v2_ = vol2_;
242 k_ = strike + gearing1_ * shift1_ + gearing2_ * shift2_;
243 } else {
244 a_ = -gearing2_;
245 b_ = -gearing1_;
248 m1_ = mu2_;
249 m2_ = mu1_;
250 v1_ = vol2_;
251 v2_ = vol1_;
252 k_ = -strike - gearing1_ * shift1_ - gearing2_ * shift2_;
253 res += phi_ * (gearing1_ * adjustedRate1_ + gearing2_ * adjustedRate2_ - strike);
254 }
255 res += 1.0 / M_SQRTPI * (*integrator_)(integrand_f(this));
256 } else {
257 // normal volatility
259 Real stddev =
261 2.0 * gearing1_ * gearing2_ * rho() * vol1_ * vol2_));
262 res = bachelierBlackFormula(optionType_, strike, forward, stddev, 1.0);
263 }
264 return res * discount_ * coupon_->accrualPeriod();
265}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ integrand()

Real integrand ( const Real  x) const
private

Definition at line 91 of file lognormalcmsspreadpricer.cpp.

91 {
92
93 // this is Brigo, 13.16.2 with x = v / sqrt(2)
94
95 Real v = M_SQRT2 * x;
96 Real h = k_ - b_ * s2_ * std::exp((m2_ - 0.5 * v2_ * v2_) * fixingTime_ + v2_ * std::sqrt(fixingTime_) * v);
97 Real phi1, phi2;
98 phi1 = (*cnd_)(phi_ *
99 (std::log(a_ * s1_ / h) + (m1_ + (0.5 - rho() * rho()) * v1_ * v1_) * fixingTime_ +
100 rho() * v1_ * std::sqrt(fixingTime_) * v) /
101 (v1_ * std::sqrt(fixingTime_ * (1.0 - rho() * rho()))));
102 phi2 = (*cnd_)(
103 phi_ *
104 (std::log(a_ * s1_ / h) + (m1_ - 0.5 * v1_ * v1_) * fixingTime_ + rho() * v1_ * std::sqrt(fixingTime_) * v) /
105 (v1_ * std::sqrt(fixingTime_ * (1.0 - rho() * rho()))));
106 Real f = a_ * phi_ * s1_ *
107 std::exp(m1_ * fixingTime_ - 0.5 * rho() * rho() * v1_ * v1_ * fixingTime_ +
108 rho() * v1_ * std::sqrt(fixingTime_) * v) *
109 phi1 -
110 phi_ * h * phi2;
111 return std::exp(-x * x) * f;
112}
+ Here is the call graph for this function:

◆ integrand_normal()

Real integrand_normal ( const Real  x) const
private

Definition at line 114 of file lognormalcmsspreadpricer.cpp.

114 {
115
116 // this is http://ssrn.com/abstract=2686998, 3.20 with x = s / sqrt(2)
117
118 Real s = M_SQRT2 * x;
119
120 Real beta = phi_ * (gearing1_ * adjustedRate1_ + gearing2_ * adjustedRate2_ - k_ +
121 std::sqrt(fixingTime_) * (rho() * gearing1_ * vol1_ + gearing2_ * vol2_) * s);
122 Real f = close_enough(alpha_, 0.0)
123 ? std::max(beta, 0.0)
124 : psi_ * alpha_ / (M_SQRTPI * M_SQRT2) * std::exp(-beta * beta / (2.0 * alpha_ * alpha_)) +
125 beta * (1.0 - (*cnd_)(-psi_ * beta / alpha_));
126 return std::exp(-x * x) * f;
127}
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
CompiledFormula exp(CompiledFormula x)
+ Here is the call graph for this function:

Friends And Related Function Documentation

◆ integrand_f

friend class integrand_f
friend

Definition at line 132 of file lognormalcmsspreadpricer.hpp.

Member Data Documentation

◆ cmsPricer_

QuantLib::ext::shared_ptr<CmsCouponPricer> cmsPricer_
private

Definition at line 134 of file lognormalcmsspreadpricer.hpp.

◆ couponDiscountCurve_

Handle<YieldTermStructure> couponDiscountCurve_
private

Definition at line 136 of file lognormalcmsspreadpricer.hpp.

◆ coupon_

const CmsSpreadCoupon* coupon_
private

Definition at line 138 of file lognormalcmsspreadpricer.hpp.

◆ today_

Date today_
private

Definition at line 140 of file lognormalcmsspreadpricer.hpp.

◆ fixingDate_

Date fixingDate_
private

Definition at line 140 of file lognormalcmsspreadpricer.hpp.

◆ paymentDate_

Date paymentDate_
private

Definition at line 140 of file lognormalcmsspreadpricer.hpp.

◆ fixingTime_

Real fixingTime_
private

Definition at line 142 of file lognormalcmsspreadpricer.hpp.

◆ gearing_

Real gearing_
private

Definition at line 144 of file lognormalcmsspreadpricer.hpp.

◆ spread_

Real spread_
private

Definition at line 144 of file lognormalcmsspreadpricer.hpp.

◆ spreadLegValue_

Real spreadLegValue_
private

Definition at line 145 of file lognormalcmsspreadpricer.hpp.

◆ discount_

Real discount_
private

Definition at line 146 of file lognormalcmsspreadpricer.hpp.

◆ index_

QuantLib::ext::shared_ptr<SwapSpreadIndex> index_
private

Definition at line 148 of file lognormalcmsspreadpricer.hpp.

◆ cnd_

QuantLib::ext::shared_ptr<CumulativeNormalDistribution> cnd_
private

Definition at line 150 of file lognormalcmsspreadpricer.hpp.

◆ integrator_

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

Definition at line 151 of file lognormalcmsspreadpricer.hpp.

◆ swapRate1_

Real swapRate1_
private

Definition at line 153 of file lognormalcmsspreadpricer.hpp.

◆ swapRate2_

Real swapRate2_
private

Definition at line 153 of file lognormalcmsspreadpricer.hpp.

◆ gearing1_

Real gearing1_
private

Definition at line 153 of file lognormalcmsspreadpricer.hpp.

◆ gearing2_

Real gearing2_
private

Definition at line 153 of file lognormalcmsspreadpricer.hpp.

◆ adjustedRate1_

Real adjustedRate1_
private

Definition at line 154 of file lognormalcmsspreadpricer.hpp.

◆ adjustedRate2_

Real adjustedRate2_
private

Definition at line 154 of file lognormalcmsspreadpricer.hpp.

◆ vol1_

Real vol1_
private

Definition at line 155 of file lognormalcmsspreadpricer.hpp.

◆ vol2_

Real vol2_
private

Definition at line 155 of file lognormalcmsspreadpricer.hpp.

◆ mu1_

Real mu1_
private

Definition at line 156 of file lognormalcmsspreadpricer.hpp.

◆ mu2_

Real mu2_
private

Definition at line 156 of file lognormalcmsspreadpricer.hpp.

◆ inheritedVolatilityType_

bool inheritedVolatilityType_
private

Definition at line 158 of file lognormalcmsspreadpricer.hpp.

◆ volType_

VolatilityType volType_
private

Definition at line 159 of file lognormalcmsspreadpricer.hpp.

◆ shift1_

Real shift1_
private

Definition at line 160 of file lognormalcmsspreadpricer.hpp.

◆ shift2_

Real shift2_
private

Definition at line 160 of file lognormalcmsspreadpricer.hpp.

◆ phi_

Real phi_
mutableprivate

Definition at line 162 of file lognormalcmsspreadpricer.hpp.

◆ a_

Real a_
private

Definition at line 162 of file lognormalcmsspreadpricer.hpp.

◆ b_

Real b_
private

Definition at line 162 of file lognormalcmsspreadpricer.hpp.

◆ s1_

Real s1_
private

Definition at line 162 of file lognormalcmsspreadpricer.hpp.

◆ s2_

Real s2_
private

Definition at line 162 of file lognormalcmsspreadpricer.hpp.

◆ m1_

Real m1_
private

Definition at line 162 of file lognormalcmsspreadpricer.hpp.

◆ m2_

Real m2_
private

Definition at line 162 of file lognormalcmsspreadpricer.hpp.

◆ v1_

Real v1_
private

Definition at line 162 of file lognormalcmsspreadpricer.hpp.

◆ v2_

Real v2_
private

Definition at line 162 of file lognormalcmsspreadpricer.hpp.

◆ k_

Real k_
private

Definition at line 162 of file lognormalcmsspreadpricer.hpp.

◆ alpha_

Real alpha_
mutableprivate

Definition at line 163 of file lognormalcmsspreadpricer.hpp.

◆ psi_

Real psi_
private

Definition at line 163 of file lognormalcmsspreadpricer.hpp.

◆ optionType_

Option::Type optionType_
mutableprivate

Definition at line 164 of file lognormalcmsspreadpricer.hpp.

◆ c1_

QuantLib::ext::shared_ptr<CmsCoupon> c1_
private

Definition at line 166 of file lognormalcmsspreadpricer.hpp.

◆ c2_

QuantLib::ext::shared_ptr<CmsCoupon> c2_
private

Definition at line 166 of file lognormalcmsspreadpricer.hpp.