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

Black volatility surface based on std devs (standardised log moneyness) More...

#include <qle/termstructures/spreadedblackvolatilitysurfacemoneyness.hpp>

+ Inheritance diagram for SpreadedBlackVolatilitySurfaceStdDevs:
+ Collaboration diagram for SpreadedBlackVolatilitySurfaceStdDevs:

Public Member Functions

 SpreadedBlackVolatilitySurfaceMoneyness (const Handle< BlackVolTermStructure > &referenceVol, const Handle< Quote > &movingSpot, const std::vector< Time > &times, const std::vector< Real > &moneyness, const std::vector< std::vector< Handle< Quote > > > &volSpreads, const Handle< Quote > &stickySpot, const Handle< YieldTermStructure > &stickyDividendTs, const Handle< YieldTermStructure > &stickyRiskFreeTs, const Handle< YieldTermStructure > &movingDividendTs, const Handle< YieldTermStructure > &movingRiskFreeTs, bool stickyStrike)
 
- Public Member Functions inherited from SpreadedBlackVolatilitySurfaceMoneyness
 SpreadedBlackVolatilitySurfaceMoneyness (const Handle< BlackVolTermStructure > &referenceVol, const Handle< Quote > &movingSpot, const std::vector< Time > &times, const std::vector< Real > &moneyness, const std::vector< std::vector< Handle< Quote > > > &volSpreads, const Handle< Quote > &stickySpot, const Handle< YieldTermStructure > &stickyDividendTs, const Handle< YieldTermStructure > &stickyRiskFreeTs, const Handle< YieldTermStructure > &movingDividendTs, const Handle< YieldTermStructure > &movingRiskFreeTs, bool stickyStrike)
 
Date maxDate () const override
 
const Date & referenceDate () const override
 
Calendar calendar () const override
 
Natural settlementDays () const override
 
Real minStrike () const override
 
Real maxStrike () const override
 
void update () override
 
const std::vector< QuantLib::Real > & moneyness () const
 

Private Member Functions

Real strikeFromMoneyness (Time t, Real moneyness, const bool stickyReference) const override
 
Real moneynessFromStrike (Time t, Real strike, const bool stickyReference) const override
 

Additional Inherited Members

virtual Real strikeFromMoneyness (Time t, Real moneyness, const bool stickyReference) const =0
 
virtual Real moneynessFromStrike (Time t, Real strike, const bool stickyReference) const =0
 
- Protected Attributes inherited from SpreadedBlackVolatilitySurfaceMoneyness
Handle< BlackVolTermStructurereferenceVol_
 
Handle< Quote > movingSpot_
 
std::vector< Time > times_
 
std::vector< Real > moneyness_
 
std::vector< std::vector< Handle< Quote > > > volSpreads_
 
Handle< Quote > stickySpot_
 
Handle< YieldTermStructure > stickyDividendTs_
 
Handle< YieldTermStructure > stickyRiskFreeTs_
 
Handle< YieldTermStructure > movingDividendTs_
 
Handle< YieldTermStructure > movingRiskFreeTs_
 
bool stickyStrike_
 
Matrix data_
 
Interpolation2D volSpreadSurface_
 

Detailed Description

Black volatility surface based on std devs (standardised log moneyness)

Definition at line 128 of file spreadedblackvolatilitysurfacemoneyness.hpp.

Member Function Documentation

◆ strikeFromMoneyness()

Real strikeFromMoneyness ( Time  t,
Real  moneyness,
const bool  stickyReference 
) const
overrideprivatevirtual

Implements SpreadedBlackVolatilitySurfaceMoneyness.

Definition at line 308 of file spreadedblackvolatilitysurfacemoneyness.cpp.

309 {
310 Real stickyForward = stickySpot_->value() * stickyDividendTs_->discount(t) / stickyRiskFreeTs_->discount(t);
311 Real forward;
312 if (stickyReference) {
313 forward = stickyForward;
314 } else {
315 QL_REQUIRE(!movingSpot_.empty(), "SpreadedBlackVolatilitySurfaceStdDevs: movingSpot is empty");
316 QL_REQUIRE(!movingDividendTs_.empty(), "SpreadedBlackVolatilitySurfaceStdDevs: movingDividendTs is empty");
317 QL_REQUIRE(!movingRiskFreeTs_.empty(), "SpreadedBlackVolatilitySurfaceStdDevs: mocingRiskFreeTs is empty");
318 forward = movingSpot_->value() * movingDividendTs_->discount(t) / movingRiskFreeTs_->discount(t);
319 }
320 // We use the sticky forward to read the vol for the definition of the standardised moneyness to
321 // avoid that this changes under forward curve changes. In the end this is a matter of definition and
322 // we might want to revise this later.
323 Real vol = referenceVol_->blackVol(t, stickyForward);
324 return std::exp(moneyness * vol * std::sqrt(t)) * forward;
325}
+ Here is the call graph for this function:

◆ moneynessFromStrike()

Real moneynessFromStrike ( Time  t,
Real  strike,
const bool  stickyReference 
) const
overrideprivatevirtual

Implements SpreadedBlackVolatilitySurfaceMoneyness.

Definition at line 283 of file spreadedblackvolatilitysurfacemoneyness.cpp.

283 {
284 if (strike == Null<Real>() || close_enough(strike, 0.0) || close_enough(t, 0.0))
285 return 0.0;
286 else {
287 QL_REQUIRE(!stickySpot_.empty(), "SpreadedBlackVolatilitySurfaceStdDevs: stickySpot is empty");
288 QL_REQUIRE(!stickyDividendTs_.empty(), "SpreadedBlackVolatilitySurfaceStdDevs: stickyDividendTs is empty");
289 QL_REQUIRE(!stickyRiskFreeTs_.empty(), "SpreadedBlackVolatilitySurfaceStdDevs: stickyRiskFreeTs is empty");
290 Real stickyForward = stickySpot_->value() * stickyDividendTs_->discount(t) / stickyRiskFreeTs_->discount(t);
291 Real forward;
292 if (stickyReference) {
293 forward = stickyForward;
294 } else {
295 QL_REQUIRE(!movingSpot_.empty(), "SpreadedBlackVolatilitySurfaceStdDevs: movingSpot is empty");
296 QL_REQUIRE(!movingDividendTs_.empty(), "SpreadedBlackVolatilitySurfaceStdDevs: movingDividendTs is empty");
297 QL_REQUIRE(!movingRiskFreeTs_.empty(), "SpreadedBlackVolatilitySurfaceStdDevs: mocingRiskFreeTs is empty");
298 forward = movingSpot_->value() * movingDividendTs_->discount(t) / movingRiskFreeTs_->discount(t);
299 }
300 // We use the sticky forward to read the vol for the definition of the standardised moneyness to
301 // avoid that this changes under forward curve changes. In the end this is a matter of definition and
302 // we might want to revise this later.
303 Real vol = referenceVol_->blackVol(t, stickyForward);
304 return std::log(strike / forward) / (vol * std::sqrt(t));
305 }
306}
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
+ Here is the call graph for this function:

◆ SpreadedBlackVolatilitySurfaceMoneyness()

SpreadedBlackVolatilitySurfaceMoneyness ( const Handle< BlackVolTermStructure > &  referenceVol,
const Handle< Quote > &  movingSpot,
const std::vector< Time > &  times,
const std::vector< Real > &  moneyness,
const std::vector< std::vector< Handle< Quote > > > &  volSpreads,
const Handle< Quote > &  stickySpot,
const Handle< YieldTermStructure > &  stickyDividendTs,
const Handle< YieldTermStructure > &  stickyRiskFreeTs,
const Handle< YieldTermStructure > &  movingDividendTs,
const Handle< YieldTermStructure > &  movingRiskFreeTs,
bool  stickyStrike 
)

Definition at line 43 of file spreadedblackvolatilitysurfacemoneyness.cpp.

40 : BlackVolatilityTermStructure(referenceVol->businessDayConvention(), referenceVol->dayCounter()),
41 referenceVol_(referenceVol), movingSpot_(movingSpot), times_(times), moneyness_(moneyness),
42 volSpreads_(volSpreads), stickySpot_(stickySpot), stickyDividendTs_(stickyDividendTs),
43 stickyRiskFreeTs_(stickyRiskFreeTs), movingDividendTs_(movingDividendTs), movingRiskFreeTs_(movingRiskFreeTs),
44 stickyStrike_(stickyStrike) {
45
46 // register with observables
47
48 registerWith(referenceVol_);
49 registerWith(movingSpot_);
50 registerWith(stickySpot_);
51
52 for (auto const& v : volSpreads_)
53 for (auto const& s : v)
54 registerWith(s);
55
56 registerWith(stickyDividendTs_);
57 registerWith(stickyRiskFreeTs_);
58 registerWith(movingDividendTs_);
59 registerWith(movingRiskFreeTs_);
60
61 // check our preconditions on the inputs
62
63 QL_REQUIRE(!times_.empty(), "no times given");
64 QL_REQUIRE(!moneyness_.empty(), "no moneyness values given");
65 QL_REQUIRE(moneyness_.size() == volSpreads_.size(), "mismatch between moneyness vector and vol matrix rows");
66
67 for (auto const& v : volSpreads_) {
68 QL_REQUIRE(times_.size() == v.size(), "mismatch between times vector and vol matrix columns");
69 }
70
71 for (Size j = 1; j < times_.size(); ++j) {
72 QL_REQUIRE(times_[j] > times_[j - 1], "Times must be sorted and unique but found that the "
73 << io::ordinal(j) << " time, " << times_[j]
74 << ", is not greater than the " << io::ordinal(j - 1) << " time, "
75 << times_[j - 1] << ".");
76 }
77
78 // add an artificial time if there is only one to make the interpolation work
79
80 if (times_.size() == 1) {
81 times_.push_back(times_.back() + 1.0);
82 for (auto& v : volSpreads_)
83 v.push_back(v.back());
84 }
85
86 // add an artificial moneyness if there is only one to make the interpolation work
87
88 if (moneyness_.size() == 1) {
89 moneyness_.push_back(moneyness_.back() + 1.0);
90 volSpreads_.push_back(volSpreads_.back());
91 }
92
93 // create data matrix used for interpolation and the interpolation object
94
95 data_ = Matrix(moneyness_.size(), times_.size(), 0.0);
96 volSpreadSurface_ = FlatExtrapolator2D(QuantLib::ext::make_shared<BilinearInterpolation>(
97 times_.begin(), times_.end(), moneyness_.begin(), moneyness_.end(), data_));
98 volSpreadSurface_.enableExtrapolation();
99}