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

Class that converts a supplied SwaptionVolatilityStructure to one of another type with possibly different shifts. More...

#include <qle/termstructures/swaptionvolatilityconverter.hpp>

+ Collaboration diagram for SwaptionVolatilityConverter:

Public Member Functions

 SwaptionVolatilityConverter (const Date &asof, const QuantLib::ext::shared_ptr< SwaptionVolatilityStructure > &svsIn, const Handle< YieldTermStructure > &discount, const Handle< YieldTermStructure > &shortDiscount, const QuantLib::ext::shared_ptr< SwapConventions > &conventions, const QuantLib::ext::shared_ptr< SwapConventions > &shortConventions, const Period &conventionsTenor, const Period &shortConventionsTenor, const VolatilityType targetType, const Matrix &targetShifts=Matrix())
 Construct from SwapConventions. More...
 
 SwaptionVolatilityConverter (const Date &asof, const QuantLib::ext::shared_ptr< SwaptionVolatilityStructure > &svsIn, const QuantLib::ext::shared_ptr< SwapIndex > &swapIndex, const QuantLib::ext::shared_ptr< SwapIndex > &shortSwapIndex, const VolatilityType targetType, const Matrix &targetShifts=Matrix())
 Construct from SwapIndex. More...
 
QuantLib::ext::shared_ptr< SwaptionVolatilityStructureconvert () const
 Method that returns the converted SwaptionVolatilityStructure More...
 
Real convert (const Date &expiry, const Period &swapTenor, Real strikeSpread, const DayCounter &volDayCounter, VolatilityType outType, Real outShift=0.0) const
 
Real & accuracy ()
 Set implied volatility solver accuracy. More...
 
Natural & maxEvaluations ()
 Set implied volatility solver max evaluations. More...
 

Private Member Functions

void checkInputs () const
 
QuantLib::ext::shared_ptr< SwaptionVolatilityStructureconvert (const QuantLib::ext::shared_ptr< SwaptionVolatilityMatrix > &svMatrix) const
 

Private Attributes

const Date asof_
 
const QuantLib::ext::shared_ptr< SwaptionVolatilityStructuresvsIn_
 
Handle< YieldTermStructure > discount_
 
Handle< YieldTermStructure > shortDiscount_
 
const QuantLib::ext::shared_ptr< SwapConventionsconventions_
 
const QuantLib::ext::shared_ptr< SwapConventionsshortConventions_
 
const Period conventionsTenor_
 
const Period shortConventionsTenor_
 
const VolatilityType targetType_
 
const Matrix targetShifts_
 
Real accuracy_
 
Natural maxEvaluations_
 

Static Private Attributes

static const Volatility minVol_ = 1.0e-7
 
static const Volatility maxVol_ = 10.0
 
static const Real minVega_ = 1.0e-6
 

Detailed Description

Class that converts a supplied SwaptionVolatilityStructure to one of another type with possibly different shifts.

Warning:
the converted SwaptionVolatilityStructure object has a fixed reference date equal to asof and fixed market data regardless of the type of reference date and market data of the original SwaptionVolatilityStructure that is passed in

Definition at line 74 of file swaptionvolatilityconverter.hpp.

Constructor & Destructor Documentation

◆ SwaptionVolatilityConverter() [1/2]

SwaptionVolatilityConverter ( const Date &  asof,
const QuantLib::ext::shared_ptr< SwaptionVolatilityStructure > &  svsIn,
const Handle< YieldTermStructure > &  discount,
const Handle< YieldTermStructure > &  shortDiscount,
const QuantLib::ext::shared_ptr< SwapConventions > &  conventions,
const QuantLib::ext::shared_ptr< SwapConventions > &  shortConventions,
const Period &  conventionsTenor,
const Period &  shortConventionsTenor,
const VolatilityType  targetType,
const Matrix &  targetShifts = Matrix() 
)

Construct from SwapConventions.

Definition at line 38 of file swaptionvolatilityconverter.cpp.

44 : asof_(asof), svsIn_(svsIn), discount_(discount), shortDiscount_(shortDiscount), conventions_(conventions),
45 shortConventions_(shortConventions), conventionsTenor_(conventionsTenor),
46 shortConventionsTenor_(shortConventionsTenor), targetType_(targetType), targetShifts_(targetShifts),
47 accuracy_(1.0e-5), maxEvaluations_(100) {
48
49 // Some checks
51}
const QuantLib::ext::shared_ptr< SwapConventions > conventions_
const QuantLib::ext::shared_ptr< SwaptionVolatilityStructure > svsIn_
const QuantLib::ext::shared_ptr< SwapConventions > shortConventions_
+ Here is the call graph for this function:

◆ SwaptionVolatilityConverter() [2/2]

SwaptionVolatilityConverter ( const Date &  asof,
const QuantLib::ext::shared_ptr< SwaptionVolatilityStructure > &  svsIn,
const QuantLib::ext::shared_ptr< SwapIndex > &  swapIndex,
const QuantLib::ext::shared_ptr< SwapIndex > &  shortSwapIndex,
const VolatilityType  targetType,
const Matrix &  targetShifts = Matrix() 
)

Construct from SwapIndex.

Definition at line 53 of file swaptionvolatilityconverter.cpp.

58 : asof_(asof), svsIn_(svsIn), discount_(swapIndex->discountingTermStructure()),
59 shortDiscount_(shortSwapIndex->discountingTermStructure()),
60 conventions_(QuantLib::ext::make_shared<SwapConventions>(swapIndex->fixingDays(), swapIndex->fixedLegTenor(),
61 swapIndex->fixingCalendar(), swapIndex->fixedLegConvention(),
62 swapIndex->dayCounter(), swapIndex->iborIndex())),
63 shortConventions_(QuantLib::ext::make_shared<SwapConventions>(
64 shortSwapIndex->fixingDays(), shortSwapIndex->fixedLegTenor(), shortSwapIndex->fixingCalendar(),
65 shortSwapIndex->fixedLegConvention(), shortSwapIndex->dayCounter(), shortSwapIndex->iborIndex())),
66 conventionsTenor_(swapIndex->tenor()), shortConventionsTenor_(shortSwapIndex->tenor()), targetType_(targetType),
67 targetShifts_(targetShifts), accuracy_(1.0e-5), maxEvaluations_(100) {
68
69 // Some checks
70 if (discount_.empty())
71 discount_ = swapIndex->iborIndex()->forwardingTermStructure();
72 if (shortDiscount_.empty())
73 shortDiscount_ = shortSwapIndex->iborIndex()->forwardingTermStructure();
75}
+ Here is the call graph for this function:

Member Function Documentation

◆ convert() [1/3]

QuantLib::ext::shared_ptr< SwaptionVolatilityStructure > convert ( ) const

Method that returns the converted SwaptionVolatilityStructure

Definition at line 87 of file swaptionvolatilityconverter.cpp.

87 {
88
89 QuantLib::ext::shared_ptr<SwaptionVolatilityDiscrete> svDisc;
90
91 // We expect either the wrapper adding ATM to a cube or a swaption vol discrete
92 // instance (like a matrix, a regular cube).
93
94 vector<Real> strikeSpreads(1, 0.0);
95 QuantLib::ext::shared_ptr<SwapIndex> swapIndexBase, shortSwapIndexBase;
96 QuantLib::ext::shared_ptr<SwaptionVolatilityCube> cube;
97 if (QuantLib::ext::dynamic_pointer_cast<SwaptionVolCubeWithATM>(svsIn_)) {
98 cube = QuantLib::ext::static_pointer_cast<SwaptionVolCubeWithATM>(svsIn_)->cube();
99 }
100 if (QuantLib::ext::dynamic_pointer_cast<SwaptionVolatilityCube>(svsIn_)) {
101 cube = QuantLib::ext::static_pointer_cast<SwaptionVolatilityCube>(svsIn_);
102 }
103 if (cube) {
104 svDisc = cube;
105 strikeSpreads = cube->strikeSpreads();
106 swapIndexBase = cube->swapIndexBase();
107 shortSwapIndexBase = cube->shortSwapIndexBase();
108 } else if (QuantLib::ext::dynamic_pointer_cast<SwaptionVolatilityDiscrete>(svsIn_)) {
109 svDisc = QuantLib::ext::static_pointer_cast<SwaptionVolatilityDiscrete>(svsIn_);
110 } else {
111 QL_FAIL("SwaptionVolatilityConverter: unknown input volatility structure");
112 }
113
114 // Some aspects of original volatility structure that we will need
115 DayCounter dayCounter = svDisc->dayCounter();
116 bool extrapolation = svDisc->allowsExtrapolation();
117 Calendar calendar = svDisc->calendar();
118 BusinessDayConvention bdc = svDisc->businessDayConvention();
119
120 const vector<Date>& optionDates = svDisc->optionDates();
121 const vector<Period>& optionTenors = svDisc->optionTenors();
122 const vector<Period>& swapTenors = svDisc->swapTenors();
123 const vector<Time>& optionTimes = svDisc->optionTimes();
124 const vector<Time>& swapLengths = svDisc->swapLengths();
125 Size nOptionTimes = optionTimes.size();
126 Size nSwapLengths = swapLengths.size();
127 Size nStrikeSpreads = strikeSpreads.size();
128
129 Real targetShift = 0.0;
130
131 // If target type is ShiftedLognormal and shifts are provided, check size
132 if (targetType_ == ShiftedLognormal && !targetShifts_.empty()) {
133 QL_REQUIRE(targetShifts_.rows() == nOptionTimes,
134 "SwaptionVolatilityConverter: number of shift rows does not equal the number of option tenors");
135 QL_REQUIRE(targetShifts_.columns() == nSwapLengths,
136 "SwaptionVolatilityConverter: number of shift columns does not equal the number of swap tenors");
137 }
138
139 // Calculate the converted ATM volatilities
140 Matrix volatilities(nOptionTimes, nSwapLengths);
141 for (Size i = 0; i < nOptionTimes; ++i) {
142 for (Size j = 0; j < nSwapLengths; ++j) {
143 if (!targetShifts_.empty())
144 targetShift = targetShifts_[i][j];
145 volatilities[i][j] = convert(optionDates[i], swapTenors[j], 0.0, dayCounter, targetType_, targetShift);
146 }
147 }
148
149 // Build ATM matrix
150 Handle<SwaptionVolatilityStructure> atmStructure;
151 if (calendar.empty() || optionTenors.empty()) {
152 // Original matrix was created with fixed option dates
153 atmStructure = Handle<SwaptionVolatilityStructure>(
154 QuantLib::ext::make_shared<SwaptionVolatilityMatrix>(asof_, calendar, bdc, optionDates, swapTenors, volatilities,
155 Actual365Fixed(), extrapolation, targetType_, targetShifts_));
156 } else {
157 atmStructure = Handle<SwaptionVolatilityStructure>(QuantLib::ext::shared_ptr<SwaptionVolatilityMatrix>(
158 new SwaptionVolatilityMatrix(asof_, calendar, bdc, optionTenors, swapTenors, volatilities, Actual365Fixed(),
159 extrapolation, targetType_, targetShifts_)));
160 }
161
162 // no cube input => we are done
163 if (!cube)
164 return *atmStructure;
165
166 // convert non-ATM volatilities, note that we use the ATM option tenors and swap tenors here!
167
168 std::vector<std::vector<Handle<Quote> > > volSpreads(nOptionTimes * nSwapLengths,
169 std::vector<Handle<Quote> >(nStrikeSpreads));
170 for (Size k = 0; k < nStrikeSpreads; ++k) {
171 for (Size i = 0; i < nOptionTimes; ++i) {
172 for (Size j = 0; j < nSwapLengths; ++j) {
173 if (!targetShifts_.empty())
174 targetShift = targetShifts_[i][j];
175 Real outVol =
176 convert(optionDates[i], swapTenors[j], strikeSpreads[k], dayCounter, targetType_, targetShift);
177 volSpreads[i * nSwapLengths + j][k] = Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(outVol));
178 }
179 }
180 }
181
182 // Build and return cube, note that we hardcode flat extrapolation
183 QuantLib::ext::shared_ptr<SwaptionVolatilityCube> cubeOut = QuantLib::ext::shared_ptr<QuantExt::SwaptionVolCube2>(
184 new QuantExt::SwaptionVolCube2(atmStructure, optionTenors, swapTenors, strikeSpreads, volSpreads, swapIndexBase,
185 shortSwapIndexBase, false, true, false));
186 cubeOut->enableExtrapolation(cube->allowsExtrapolation());
187 return QuantLib::ext::make_shared<SwaptionVolCubeWithATM>(cubeOut);
188
189} // namespace QuantExt
QuantLib::ext::shared_ptr< SwaptionVolatilityStructure > convert() const
Method that returns the converted SwaptionVolatilityStructure
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ convert() [2/3]

Real convert ( const Date &  expiry,
const Period &  swapTenor,
Real  strikeSpread,
const DayCounter &  volDayCounter,
VolatilityType  outType,
Real  outShift = 0.0 
) const

Definition at line 191 of file swaptionvolatilityconverter.cpp.

193 {
194
195 const QuantLib::ext::shared_ptr<SwapConventions> tmpConv =
197 Handle<YieldTermStructure> tmpDiscount = swapTenor <= shortConventionsTenor_ ? shortDiscount_ : discount_;
198
199 // Create the underlying swap with fixed rate = fair rate
200 // We rely on the fact that MakeVanillaSwap sets the fixed rate to the fair rate if it is left null in the ctor
201 Date effectiveDate = tmpConv->fixedCalendar().advance(expiry, tmpConv->settlementDays(), Days);
202 QuantLib::ext::shared_ptr<PricingEngine> engine = QuantLib::ext::make_shared<DiscountingSwapEngine>(tmpDiscount);
203 QuantLib::ext::shared_ptr<VanillaSwap> swap = MakeVanillaSwap(swapTenor, tmpConv->floatIndex())
204 .withType(strikeSpread < 0.0 ? VanillaSwap::Receiver : VanillaSwap::Payer)
205 .withEffectiveDate(effectiveDate)
206 .withFixedLegCalendar(tmpConv->fixedCalendar())
207 .withFixedLegDayCount(tmpConv->fixedDayCounter())
208 .withFixedLegTenor(tmpConv->fixedTenor())
209 .withFixedLegConvention(tmpConv->fixedConvention())
210 .withFixedLegTerminationDateConvention(tmpConv->fixedConvention())
211 .withFloatingLegSpread(0.0)
212 .withPricingEngine(engine);
213 // we need this also for non-atm swaps
214 Rate atmRate = swap->fairRate(), strike;
215 if (!close_enough(strikeSpread, 0.0)) {
216 strike = atmRate + strikeSpread;
217 swap = MakeVanillaSwap(swapTenor, tmpConv->floatIndex(), strike)
218 .withEffectiveDate(effectiveDate)
219 .withFixedLegTenor(tmpConv->fixedTenor())
220 .withFixedLegDayCount(tmpConv->fixedDayCounter())
221 .withFloatingLegSpread(0.0)
222 .withPricingEngine(engine);
223 } else {
224 strike = atmRate;
225 }
226
227 Real inShift = svsIn_->shift(expiry, swapTenor);
228 VolatilityType inType = svsIn_->volatilityType();
229
230 // if strike is invalid w.r.t. the given input or output vol types, return zero vol
231 // (for a lognormal cube e.g. it is common that some effective strikes are negative)
232 Real inMinStrike = inType == ShiftedLognormal ? -inShift : -QL_MAX_REAL;
233 Real outMinStrike = outType == ShiftedLognormal ? -outShift : -QL_MAX_REAL;
234 if (strike < inMinStrike || strike < outMinStrike)
235 return 0.0;
236
237 Real inVol = svsIn_->volatility(expiry, swapTenor, strike);
238
239 // Create the swaption
240 QuantLib::ext::shared_ptr<Exercise> exercise = QuantLib::ext::make_shared<EuropeanExercise>(expiry);
241 QuantLib::ext::shared_ptr<Swaption> swaption = QuantLib::ext::make_shared<Swaption>(swap, exercise, Settlement::Physical);
242
243 // Price the swaption with the input volatility
244 QuantLib::ext::shared_ptr<PricingEngine> swaptionEngine;
245 if (inType == ShiftedLognormal) {
246 swaptionEngine = QuantLib::ext::make_shared<BlackSwaptionEngine>(discount_, inVol, volDayCounter, inShift);
247 } else {
248 swaptionEngine = QuantLib::ext::make_shared<BachelierSwaptionEngine>(discount_, inVol, volDayCounter);
249 }
250 swaption->setPricingEngine(swaptionEngine);
251
252 // zero might be the actual implied vol (if we e.g. convert from LN to N with a strike near zero),
253 // but the Swaption::impliedVolatility function will not find this, so we check for this case
254 // explicitly here
255 Real vega = swaption->result<Real>("vega");
256 if (vega < minVega_)
257 return 0.0;
258
259 Volatility impliedVol = 0.0;
260 try {
261 Real npv = swaption->NPV();
262
263 // Calculate guess for implied volatility solver
264 Real guess = 0.0;
265 if (outType == ShiftedLognormal) {
266 QL_REQUIRE(atmRate + outShift > 0.0, "SwaptionVolatilityConverter: ATM rate + shift must be > 0.0");
267 if (inType == Normal)
268 guess = inVol / (atmRate + outShift);
269 else
270 guess = inVol * (atmRate + inShift) / (atmRate + outShift);
271 } else {
272 if (inType == Normal)
273 guess = inVol;
274 else
275 guess = inVol * (atmRate + inShift);
276 }
277
278 // Note: In implying the volatility the volatility day counter is hardcoded to Actual365Fixed
279 impliedVol = swaption->impliedVolatility(npv, discount_, guess, accuracy_, maxEvaluations_, minVol_, maxVol_,
280 outType, outShift);
281
282 } catch (std::exception& e) {
283 // couldn't find implied volatility
284 QL_FAIL("SwaptionVolatilityConverter: volatility conversion failed while trying to convert volatility"
285 " for expiry "
286 << expiry << " and swap tenor " << swapTenor << ". Error: " << e.what());
287 }
288
289 return impliedVol;
290}
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
+ Here is the call graph for this function:

◆ accuracy()

Real & accuracy ( )

Set implied volatility solver accuracy.

Definition at line 98 of file swaptionvolatilityconverter.hpp.

98{ return accuracy_; }

◆ maxEvaluations()

Natural & maxEvaluations ( )

Set implied volatility solver max evaluations.

Definition at line 100 of file swaptionvolatilityconverter.hpp.

100{ return maxEvaluations_; }

◆ checkInputs()

void checkInputs ( ) const
private

Definition at line 77 of file swaptionvolatilityconverter.cpp.

77 {
78 QL_REQUIRE(svsIn_->referenceDate() == asof_,
79 "SwaptionVolatilityConverter requires the asof date and reference date to align");
80 QL_REQUIRE(!discount_.empty() && discount_->referenceDate() == asof_,
81 "SwaptionVolatilityConverter requires a valid discount curve with reference date equal to asof date");
82 Handle<YieldTermStructure> forwardCurve = conventions_->floatIndex()->forwardingTermStructure();
83 QL_REQUIRE(!forwardCurve.empty() && forwardCurve->referenceDate() == asof_,
84 "SwaptionVolatilityConverter requires a valid forward curve with reference date equal to asof date");
85}
+ Here is the caller graph for this function:

◆ convert() [3/3]

QuantLib::ext::shared_ptr< SwaptionVolatilityStructure > convert ( const QuantLib::ext::shared_ptr< SwaptionVolatilityMatrix > &  svMatrix) const
private

Member Data Documentation

◆ asof_

const Date asof_
private

Definition at line 110 of file swaptionvolatilityconverter.hpp.

◆ svsIn_

const QuantLib::ext::shared_ptr<SwaptionVolatilityStructure> svsIn_
private

Definition at line 111 of file swaptionvolatilityconverter.hpp.

◆ discount_

Handle<YieldTermStructure> discount_
private

Definition at line 112 of file swaptionvolatilityconverter.hpp.

◆ shortDiscount_

Handle<YieldTermStructure> shortDiscount_
private

Definition at line 112 of file swaptionvolatilityconverter.hpp.

◆ conventions_

const QuantLib::ext::shared_ptr<SwapConventions> conventions_
private

Definition at line 113 of file swaptionvolatilityconverter.hpp.

◆ shortConventions_

const QuantLib::ext::shared_ptr<SwapConventions> shortConventions_
private

Definition at line 113 of file swaptionvolatilityconverter.hpp.

◆ conventionsTenor_

const Period conventionsTenor_
private

Definition at line 114 of file swaptionvolatilityconverter.hpp.

◆ shortConventionsTenor_

const Period shortConventionsTenor_
private

Definition at line 114 of file swaptionvolatilityconverter.hpp.

◆ targetType_

const VolatilityType targetType_
private

Definition at line 115 of file swaptionvolatilityconverter.hpp.

◆ targetShifts_

const Matrix targetShifts_
private

Definition at line 116 of file swaptionvolatilityconverter.hpp.

◆ accuracy_

Real accuracy_
private

Definition at line 119 of file swaptionvolatilityconverter.hpp.

◆ maxEvaluations_

Natural maxEvaluations_
private

Definition at line 120 of file swaptionvolatilityconverter.hpp.

◆ minVol_

const Volatility minVol_ = 1.0e-7
staticprivate

Definition at line 121 of file swaptionvolatilityconverter.hpp.

◆ maxVol_

const Volatility maxVol_ = 10.0
staticprivate

Definition at line 122 of file swaptionvolatilityconverter.hpp.

◆ minVega_

const Real minVega_ = 1.0e-6
staticprivate

Definition at line 123 of file swaptionvolatilityconverter.hpp.