21#include <ql/experimental/fx/blackdeltacalculator.hpp>
22#include <ql/math/comparison.hpp>
23#include <ql/math/interpolations/cubicinterpolation.hpp>
24#include <ql/math/interpolations/linearinterpolation.hpp>
25#include <ql/math/optimization/levenbergmarquardt.hpp>
26#include <ql/pricingengines/blackformula.hpp>
36 const Real spot,
const Real domDisc,
const Real forDisc,
const Real expiryTime,
const std::vector<Real>& deltas,
37 const std::vector<Real>& putVols,
const std::vector<Real>& callVols,
const Real atmVol,
38 const DeltaVolQuote::DeltaType dt,
const DeltaVolQuote::AtmType at,
40 const Size maxIterations)
41 : spot_(spot), domDisc_(domDisc), forDisc_(forDisc), expiryTime_(expiryTime), deltas_(deltas), putVols_(putVols),
42 callVols_(callVols), atmVol_(atmVol), dt_(dt), at_(at), smileInterpolation_(smileInterpolation),
43 accuracy_(accuracy), maxIterations_(maxIterations) {
47 std::vector<Real> x, y;
53 for (Size i = 0; i <
deltas_.size(); ++i) {
58 }
catch (
const std::exception& e) {
59 QL_FAIL(
"SimpleDeltaInterpolatedSmile: strikeFromDelta("
60 << -deltas[i] <<
") could not be computed for spot=" <<
spot_
71 }
catch (
const std::exception& e) {
72 QL_FAIL(
"SimpleDeltaIinterpolatedSmile: atmStrike could not be computed for spot="
75 <<
"), atmVol=" << atmVol <<
", expiry=" <<
expiryTime_ <<
": " << e.what());
78 for (Size i =
deltas_.size(); i > 0; --i) {
84 }
catch (
const std::exception& e) {
85 QL_FAIL(
"SimpleDeltaInterpolatedSmile: strikeFromDelta("
86 << deltas[i - 1] <<
") could not be computed for spot=" <<
spot_
95 std::vector<Size> perm(x.size());
96 std::iota(perm.begin(), perm.end(), 0);
97 std::sort(perm.begin(), perm.end(), [&x](Size a, Size b) { return x[a] < x[b]; });
98 for (Size i = 0; i < perm.size(); ++i) {
99 x_.push_back(x[perm[i]]);
100 y_.push_back(y[perm[i]]);
105 for (Size i = 0; i <
x_.size() - 1; ++i) {
106 QL_REQUIRE(!
close_enough(
x_[i],
x_[i + 1]),
"SmileDeltaInterpolatedSmile: interpolation points x["
107 << i <<
"] = x[" << (i + 1) <<
"] = " <<
x_[i]
108 <<
" are numerically identical.");
114 interpolation_ = QuantLib::ext::make_shared<LinearInterpolation>(
x_.begin(),
x_.end(),
y_.begin());
117 x_.begin(),
x_.end(),
y_.begin(), CubicInterpolation::Spline,
false, CubicInterpolation::SecondDerivative,
118 0.0, CubicInterpolation::SecondDerivative, 0.0);
120 QL_FAIL(
"invalid interpolation, this is unexpected");
127 const DeltaVolQuote::DeltaType dt) {
135 result = c.strikeFromDelta((type == Option::Call ? 1.0 : -1.0) * delta);
136 }
catch (
const std::exception& e) {
137 QL_FAIL(
"SimpleDeltaInterpolatedSmile::strikeFromDelta("
138 << (type == Option::Call ? 1.0 : -1.0) * delta <<
") could not be computed for spot=" <<
spot_
141 <<
", expiry=" <<
expiryTime_ <<
": " << e.what());
145 "SmileDeltaInterpolatedSmile::strikeFromDelta("
146 << (type == Option::Call ? 1.0 : -1.0) * delta <<
"): max iterations (" <<
maxIterations_
147 <<
"), no solution found for accuracy " <<
accuracy_ <<
", last iterations: " << lastResult <<
"/"
162 result = c.atmStrike(at);
163 }
catch (
const std::exception& e) {
164 QL_FAIL(
"SimpleDeltaInterpolatedSmile::atmStrike() could not be computed for spot="
171 "SmileDeltaInterpolatedSmile::atmStrike(): max iterations ("
173 <<
", last iterations: " << lastResult <<
"/" << result <<
", spot=" <<
spot_
181 QL_REQUIRE(std::isfinite(tmp),
"SimpleDeltaInterpolatedSmile::volatilityAtSimpleDelta() non-finite result ("
182 << tmp <<
") for simple delta " << simpleDelta);
188 if (!std::isfinite(tmp)) {
189 std::ostringstream os;
190 for (Size i = 0; i <
x_.size(); ++i) {
191 os <<
"(" <<
x_[i] <<
"," <<
y_[i] <<
")";
193 QL_FAIL(
"SimpleDeltaInterpolatedSmile::volatility() non-finite result ("
196 <<
", interpolation data point are " << os.str());
204 CumulativeNormalDistribution Phi;
208QuantLib::ext::shared_ptr<SimpleDeltaInterpolatedSmile>
209createSmile(
const Real spot,
const Real domDisc,
const Real forDisc,
const Real expiryTime,
210 const std::vector<Real>& deltas,
const std::vector<Real>& bfQuotes,
const std::vector<Real>& rrQuotes,
211 const Real atmVol,
const DeltaVolQuote::DeltaType dt,
const DeltaVolQuote::AtmType at,
212 const Option::Type riskReversalInFavorOf,
const bool butterflyIsBrokerStyle,
215 Real phirr = riskReversalInFavorOf == Option::Call ? 1.0 : -1.0;
216 QuantLib::ext::shared_ptr<SimpleDeltaInterpolatedSmile> resultSmile;
218 if (!butterflyIsBrokerStyle) {
222 std::vector<Real> vol_p, vol_c;
224 for (Size i = 0; i < deltas.size(); ++i) {
225 QL_REQUIRE(atmVol + bfQuotes[i] - 0.5 * std::abs(rrQuotes[i]) > 0.0,
226 "createSmile: atmVol ("
227 << atmVol <<
") + bf (" << bfQuotes[i] <<
") - rr (" << rrQuotes[i]
228 <<
") must be positive when creating smile from smile bf quotes, tte=" << expiryTime);
229 vol_p.push_back(atmVol + bfQuotes[i] - 0.5 * phirr * rrQuotes[i]);
230 vol_c.push_back(atmVol + bfQuotes[i] + 0.5 * phirr * rrQuotes[i]);
235 resultSmile = QuantLib::ext::make_shared<SimpleDeltaInterpolatedSmile>(
236 spot, domDisc, forDisc, expiryTime, deltas, vol_p, vol_c, atmVol, dt, at, smileInterpolation);
240 Real forward = spot / domDisc * forDisc;
245 std::vector<Real> kb_c, kb_p, vb;
247 for (Size i = 0; i < deltas.size(); ++i) {
248 Real stddevb = (atmVol + bfQuotes[i]) * std::sqrt(expiryTime);
249 QL_REQUIRE(stddevb > 0.0,
250 "createSmile: atmVol ("
251 << atmVol <<
") + bf (" << bfQuotes[i]
252 <<
") must be positive when creating smile from broker bf quotes, tte=" << expiryTime);
253 BlackDeltaCalculator cp(Option::Type::Put, dt, spot, domDisc, forDisc, stddevb);
254 BlackDeltaCalculator cc(Option::Type::Call, dt, spot, domDisc, forDisc, stddevb);
255 kb_p.push_back(cp.strikeFromDelta(-deltas[i]));
256 kb_c.push_back(cc.strikeFromDelta(deltas[i]));
257 vb.push_back(blackFormula(Option::Put, kb_p.back(), forward, stddevb) +
258 blackFormula(Option::Call, kb_c.back(), forward, stddevb));
264 Array guess(deltas.size());
265 for (Size i = 0; i < deltas.size(); ++i) {
266 guess[i] = std::log(std::max(0.0001, bfQuotes[i] - 0.5 * std::abs(rrQuotes[i]) + atmVol));
271 struct TargetFunction :
public QuantLib::CostFunction {
272 TargetFunction(Real atmVol, Real phirr, Real spot, Real domDisc, Real forDisc, Real forward,
273 Real expiryTime, DeltaVolQuote::DeltaType dt, DeltaVolQuote::AtmType at,
274 const std::vector<Real>& rrQuotes,
const std::vector<Real>& deltas,
275 const std::vector<Real>& kb_p,
const std::vector<Real>& kb_c,
const std::vector<Real>& vb,
277 : atmVol(atmVol), phirr(phirr), spot(spot), domDisc(domDisc), forDisc(forDisc), forward(forward),
278 expiryTime(expiryTime), dt(dt), at(at), rrQuotes(rrQuotes), deltas(deltas), kb_p(kb_p), kb_c(kb_c),
279 vb(vb), smileInterpolation(smileInterpolation) {}
281 Real atmVol, phirr, spot, domDisc, forDisc, forward, expiryTime;
282 DeltaVolQuote::DeltaType dt;
283 DeltaVolQuote::AtmType at;
284 const std::vector<Real>&rrQuotes, deltas, kb_p, kb_c, vb;
287 mutable Real bestValue = QL_MAX_REAL;
288 mutable QuantLib::ext::shared_ptr<SimpleDeltaInterpolatedSmile> bestSmile;
290 Array values(
const Array& x)
const override {
292 constexpr Real large_error = 1E6;
294 Array smileBfVol(x.size());
295 for (Size i = 0; i < x.size(); ++i)
296 smileBfVol[i] = std::exp(x[i]) + 0.5 * std::abs(rrQuotes[i]) - atmVol;
300 std::vector<Real> vol_c, vol_p;
302 for (Size i = 0; i < deltas.size(); ++i) {
303 vol_p.push_back(atmVol + smileBfVol[i] - 0.5 * phirr * rrQuotes[i]);
304 vol_c.push_back(atmVol + smileBfVol[i] + 0.5 * phirr * rrQuotes[i]);
305 QL_REQUIRE(vol_p.back() > 0.0,
" createSmile: internal error: put vol = "
306 << vol_p.back() <<
" during broker bf fitting");
307 QL_REQUIRE(vol_c.back() > 0.0,
" createSmile: internal error: call vol = "
308 << vol_c.back() <<
" during broker bf fitting");
313 QuantLib::ext::shared_ptr<SimpleDeltaInterpolatedSmile> tmpSmile;
315 tmpSmile = QuantLib::ext::make_shared<SimpleDeltaInterpolatedSmile>(
316 spot, domDisc, forDisc, expiryTime, deltas, vol_p, vol_c, atmVol, dt, at, smileInterpolation);
319 return Array(deltas.size(), large_error);
324 std::vector<Real>
vs;
325 for (Size i = 0; i < deltas.size(); ++i) {
328 pvol = tmpSmile->volatility(kb_p[i]);
329 cvol = tmpSmile->volatility(kb_c[i]);
332 return Array(deltas.size(), large_error);
334 vs.push_back(blackFormula(Option::Put, kb_p[i], forward, pvol * std::sqrt(expiryTime)) +
335 blackFormula(Option::Call, kb_c[i], forward, cvol * std::sqrt(expiryTime)));
340 Array result(deltas.size());
341 for (Size i = 0; i < deltas.size(); ++i) {
342 result[i] = (
vs[i] - vb[i]) / vb[i];
343 if (!std::isfinite(result[i]))
344 result[i] = large_error;
347 Real value = std::sqrt(std::accumulate(result.begin(), result.end(), 0.0,
348 [](Real acc, Real x) { return acc + x * x; })) /
351 if (value < bestValue) {
353 bestSmile = tmpSmile;
360 TargetFunction targetFunction{atmVol, phirr, spot, domDisc, forDisc, forward, expiryTime, dt,
361 at, rrQuotes, deltas, kb_p, kb_c, vb, smileInterpolation};
362 NoConstraint noConstraint;
363 LevenbergMarquardt lm;
364 EndCriteria endCriteria(100, 10, 1E-8, 1E-8, 1E-8);
365 Problem problem(targetFunction, noConstraint, guess);
366 lm.minimize(problem, endCriteria);
368 QL_REQUIRE(targetFunction.bestValue < 0.01,
"createSmile at expiry "
369 << expiryTime <<
" failed: target function value ("
370 << problem.functionValue() <<
") not close to zero");
372 resultSmile = targetFunction.bestSmile;
377 static const std::vector<Real> samplePoints = {0.01, 0.05, 0.1, 0.2, 0.5, 0.8, 0.9, 0.95, 0.99};
378 for (
auto const& simpleDelta : samplePoints) {
379 Real vol = resultSmile->volatilityAtSimpleDelta(simpleDelta);
380 QL_REQUIRE(vol > 0.0001 && vol < 5.0,
"createSmile at expiry " << expiryTime <<
": volatility at simple delta "
381 << simpleDelta <<
" (" << vol
382 <<
") is not plausible.");
391 Date referenceDate,
const std::vector<Date>& dates,
const std::vector<Real>& deltas,
392 const std::vector<std::vector<Real>>& bfQuotes,
const std::vector<std::vector<Real>>& rrQuotes,
393 const std::vector<Real>& atmQuotes,
const DayCounter& dayCounter,
const Calendar& calendar,
394 const Handle<Quote>& spot,
const Size spotDays,
const Calendar spotCalendar,
395 const Handle<YieldTermStructure>& domesticTS,
const Handle<YieldTermStructure>& foreignTS,
396 const DeltaVolQuote::DeltaType dt,
const DeltaVolQuote::AtmType at,
const Period& switchTenor,
397 const DeltaVolQuote::DeltaType ltdt,
const DeltaVolQuote::AtmType ltat,
const Option::Type riskReversalInFavorOf,
399 : BlackVolatilityTermStructure(referenceDate, calendar, Following, dayCounter), dates_(dates), deltas_(deltas),
400 bfQuotes_(bfQuotes), rrQuotes_(rrQuotes), atmQuotes_(atmQuotes), spot_(spot), spotDays_(spotDays),
401 spotCalendar_(spotCalendar), domesticTS_(domesticTS), foreignTS_(foreignTS), dt_(dt), at_(at),
402 switchTenor_(switchTenor), ltdt_(ltdt), ltat_(ltat), riskReversalInFavorOf_(riskReversalInFavorOf),
403 butterflyIsBrokerStyle_(butterflyIsBrokerStyle), smileInterpolation_(smileInterpolation) {
407 QL_REQUIRE(!
dates_.empty(),
"BlackVolatilitySurfaceBFRR: no expiry dates given");
408 QL_REQUIRE(!
deltas_.empty(),
"BlackVolatilitySurfaceBFRR: no deltas given");
410 for (Size i = 0; i <
deltas_.size() - 1; ++i) {
412 "BlackVolatilitySurfaceBFRR: deltas are not strictly ascending at index " << i <<
": " <<
deltas_[i]
416 QL_REQUIRE(
bfQuotes_.size() ==
dates_.size(),
"BlackVolatilitySurfaceBFRR: bfQuotes ("
417 <<
bfQuotes_.size() <<
") mismatch with expiry dates ("
419 QL_REQUIRE(
rrQuotes_.size() ==
dates_.size(),
"BlackVolatilitySurfaceBFRR: rrQuotes ("
420 <<
rrQuotes_.size() <<
") mismatch with expiry dates ("
422 QL_REQUIRE(
atmQuotes_.size() ==
dates_.size(),
"BlackVolatilitySurfaceBFRR: atmQuotes ("
423 <<
atmQuotes_.size() <<
") mismatch with expiry dates ("
426 QL_REQUIRE(q.size() ==
deltas_.size(),
"BlackVolatilitySurfaceBFRR: bfQuotes inner vector ("
427 << q.size() <<
") mismatch with deltas (" <<
deltas_.size() <<
")");
430 QL_REQUIRE(q.size() ==
deltas_.size(),
"BlackVolatilitySurfaceBFRR: bfQuotes inner vector ("
431 << q.size() <<
") mismatch with deltas (" <<
deltas_.size() <<
")");
461 for (
auto const& d :
dates_) {
477 settlLag_ = timeFromReference(settlDate);
489 BlackVolatilityTermStructure::update();
490 LazyObject::update();
506 t = std::max(t, 1.0 / 365.0);
514 return s->second->volatility(strike);
521 Size index_m = index_p == 0 ? Null<Size>() : index_p - 1;
523 index_p = Null<Size>();
527 while (index_m != Null<Size>() && index_m > 0 &&
smileHasError_[index_m])
534 index_m = Null<Size>();
537 index_p = Null<Size>();
539 if (index_m == Null<Size>() && index_p == Null<Size>()) {
544 QL_FAIL(
"BlackVolatilitySurfaceBFRR::blackVolImpl(" << t <<
"," << strike
545 <<
"): no valid smiles, check the market data input.");
555 if (index_m != Null<Size>() &&
smiles_[index_m] ==
nullptr) {
556 DeltaVolQuote::AtmType at;
557 DeltaVolQuote::DeltaType dt;
571 }
catch (
const std::exception& e) {
578 if (index_p != Null<Size>() &&
smiles_[index_p] ==
nullptr) {
579 DeltaVolQuote::AtmType at;
580 DeltaVolQuote::DeltaType dt;
594 }
catch (
const std::exception& e) {
605 DeltaVolQuote::DeltaType dt_c =
606 dt_ == (DeltaVolQuote::Spot ||
dt_ == DeltaVolQuote::Fwd) ? DeltaVolQuote::Fwd : DeltaVolQuote::PaFwd;
607 DeltaVolQuote::AtmType at_c = DeltaVolQuote::AtmDeltaNeutral;
611 Real atmVol_m = 0.0, atmVol_p = 0.0;
612 std::vector<Real> putVols_m, callVols_m, putVols_p, callVols_p;
614 if (index_m != Null<Size>()) {
616 atmVol_m =
smiles_[index_m]->volatility(
smiles_[index_m]->atmStrike(dt_c, at_c));
619 smiles_[index_m]->volatility(
smiles_[index_m]->strikeFromDelta(Option::Put, d, dt_c)));
620 callVols_m.push_back(
621 smiles_[index_m]->volatility(
smiles_[index_m]->strikeFromDelta(Option::Call, d, dt_c)));
623 }
catch (
const std::exception& e) {
630 if (index_p != Null<Size>()) {
632 atmVol_p =
smiles_[index_p]->volatility(
smiles_[index_p]->atmStrike(dt_c, at_c));
635 smiles_[index_p]->volatility(
smiles_[index_p]->strikeFromDelta(Option::Put, d, dt_c)));
636 callVols_p.push_back(
637 smiles_[index_p]->volatility(
smiles_[index_p]->strikeFromDelta(Option::Call, d, dt_c)));
639 }
catch (
const std::exception& e) {
649 std::vector<Real> putVols_i, callVols_i;
651 if (index_p == Null<Size>()) {
654 putVols_i = putVols_m;
655 callVols_i = callVols_m;
656 QL_REQUIRE(atmVol_i > 0.0,
"BlackVolatilitySurfaceBFRR: negative front-extrapolated atm vol " << atmVol_i);
658 QL_REQUIRE(putVols_i[i] > 0.0,
659 "BlackVolatilitySurfaceBFRR: negative front-extrapolated put vol " << putVols_i[i]);
660 QL_REQUIRE(callVols_i[i] > 0.0,
661 "BlackVolatilitySurfaceBFRR: negative front-extrapolated call vol " << callVols_i[i]);
663 }
else if (index_m == Null<Size>()) {
666 putVols_i = putVols_p;
667 callVols_i = callVols_p;
668 QL_REQUIRE(atmVol_i > 0.0,
"BlackVolatilitySurfaceBFRR: negative back-extrapolated atm vol " << atmVol_i);
670 QL_REQUIRE(putVols_i[i] > 0.0,
671 "BlackVolatilitySurfaceBFRR: negative back-extrapolated put vol " << putVols_i[i]);
672 QL_REQUIRE(callVols_i[i] > 0.0,
673 "BlackVolatilitySurfaceBFRR: negative back-extrapolated call vol " << callVols_i[i]);
678 atmVol_i = (1.0 - a) * atmVol_m + a * atmVol_p;
679 QL_REQUIRE(atmVol_i > 0.0,
"BlackVolatilitySurfaceBFRR: negative atm vol "
680 << atmVol_i <<
" = " << (1.0 - a) <<
" * " << atmVol_m <<
" + " << a <<
" * "
683 putVols_i.push_back((1.0 - a) * putVols_m[i] + a * putVols_p[i]);
684 callVols_i.push_back((1.0 - a) * callVols_m[i] + a * callVols_p[i]);
685 QL_REQUIRE(putVols_i.back() > 0.0,
"BlackVolatilitySurfaceBFRR: negative put vol for delta="
687 << (1.0 - a) <<
" * " << putVols_m[i] <<
" + " << a <<
" * "
689 QL_REQUIRE(callVols_i.back() > 0.0,
"BlackVolatilitySurfaceBFRR: negative call vol for delta="
691 << (1.0 - a) <<
" * " << callVols_m[i] <<
" + " << a <<
" * "
704 QuantLib::ext::shared_ptr<detail::SimpleDeltaInterpolatedSmile> smile;
707 smile = QuantLib::ext::make_shared<detail::SimpleDeltaInterpolatedSmile>(
711 }
catch (
const std::exception& e) {
714 Size failureIndex = index_m != Null<Size>() ? index_m : index_p;
726 return smile->volatility(strike);
Black volatility surface based on bf/rr quotes.
std::vector< Date > settlementDates_
std::vector< std::string > smileErrorMessage_
DeltaVolQuote::DeltaType dt_
void performCalculations() const override
std::map< Real, QuantLib::ext::shared_ptr< detail::SimpleDeltaInterpolatedSmile > > cachedInterpolatedSmiles_
bool butterflyIsBrokerStyle_
std::vector< std::vector< Real > > bfQuotes_
std::vector< Date > dates_
const std::vector< std::vector< Real > > & rrQuotes() const
DeltaVolQuote::DeltaType ltdt_
Handle< YieldTermStructure > foreignTS_
const std::vector< std::string > & smileErrorMessage() const
std::vector< Real > deltas_
Handle< YieldTermStructure > domesticTS_
std::vector< Real > expiryTimes_
std::vector< Real > atmQuotes_
Option::Type riskReversalInFavorOf_
BlackVolatilitySurfaceBFRR(Date referenceDate, const std::vector< Date > &dates, const std::vector< Real > &deltas, const std::vector< std::vector< Real > > &bfQuotes, const std::vector< std::vector< Real > > &rrQuotes, const std::vector< Real > &atmQuotes, const DayCounter &dayCounter, const Calendar &calendar, const Handle< Quote > &spot, const Size spotDays, const Calendar spotCalendar, const Handle< YieldTermStructure > &domesticTS, const Handle< YieldTermStructure > &foreignTS, const DeltaVolQuote::DeltaType dt=DeltaVolQuote::DeltaType::Spot, const DeltaVolQuote::AtmType at=DeltaVolQuote::AtmType::AtmDeltaNeutral, const Period &switchTenor=2 *Years, const DeltaVolQuote::DeltaType ltdt=DeltaVolQuote::DeltaType::Fwd, const DeltaVolQuote::AtmType ltat=DeltaVolQuote::AtmType::AtmDeltaNeutral, const Option::Type riskReversalInFavorOf=Option::Call, const bool butterflyIsBrokerStyle=true, const SmileInterpolation smileInterpolation=SmileInterpolation::Cubic)
std::vector< std::vector< Real > > rrQuotes_
Volatility blackVolImpl(Time t, Real strike) const override
SmileInterpolation smileInterpolation_
const std::vector< bool > & smileHasError() const
DeltaVolQuote::AtmType at_
const std::vector< std::vector< Real > > & bfQuotes() const
std::vector< bool > smileHasError_
DeltaVolQuote::AtmType ltat_
std::vector< QuantLib::ext::shared_ptr< detail::SimpleDeltaInterpolatedSmile > > smiles_
std::vector< Real > currentDeltas_
DeltaVolQuote::DeltaType dt_
SimpleDeltaInterpolatedSmile(const Real spot, const Real domDisc, const Real forDisc, const Real expiryTime, const std::vector< Real > &deltas, const std::vector< Real > &putVols, const std::vector< Real > &callVols, const Real atmVol, const DeltaVolQuote::DeltaType dt, const DeltaVolQuote::AtmType at, const BlackVolatilitySurfaceBFRR::SmileInterpolation smileInterpolation, const Real accuracy=1E-6, const Size maxIterations=1000)
Real atmStrike(const DeltaVolQuote::DeltaType dt, const DeltaVolQuote::AtmType at)
Real strikeFromDelta(const Option::Type type, const Real delta, const DeltaVolQuote::DeltaType dt)
Real simpleDeltaFromStrike(const Real strike) const
Real volatility(const Real strike)
Real volatilityAtSimpleDelta(const Real tnp)
std::vector< Real > deltas_
std::vector< Real > callVols_
DeltaVolQuote::AtmType at_
BlackVolatilitySurfaceBFRR::SmileInterpolation smileInterpolation_
QuantLib::ext::shared_ptr< Interpolation > interpolation_
std::vector< Real > putVols_
QuantLib::ext::shared_ptr< SimpleDeltaInterpolatedSmile > createSmile(const Real spot, const Real domDisc, const Real forDisc, const Real expiryTime, const std::vector< Real > &deltas, const std::vector< Real > &bfQuotes, const std::vector< Real > &rrQuotes, const Real atmVol, const DeltaVolQuote::DeltaType dt, const DeltaVolQuote::AtmType at, const Option::Type riskReversalInFavorOf, const bool butterflyIsBrokerStyle, const BlackVolatilitySurfaceBFRR::SmileInterpolation smileInterpolation)
Real untransformVol(const Real w)
Real transformVol(const Real v)
Filter close_enough(const RandomVariable &x, const RandomVariable &y)