Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
fxblackvolsurface.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2017 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
19#include <ql/math/interpolations/backwardflatinterpolation.hpp>
20#include <ql/math/interpolations/linearinterpolation.hpp>
21#include <ql/time/calendars/nullcalendar.hpp>
23
24using namespace std;
25
26namespace QuantExt {
27
29 const Date& referenceDate, const std::vector<Date>& dates, const std::vector<Volatility>& atmVols,
30 const std::vector<Volatility>& rr, const std::vector<Volatility>& bf, const DayCounter& dayCounter,
31 const Calendar& cal, const Handle<Quote>& fxSpot, const Handle<YieldTermStructure>& domesticTS,
32 const Handle<YieldTermStructure>& foreignTS, bool requireMonotoneVariance, const DeltaVolQuote::AtmType atmType,
33 const DeltaVolQuote::DeltaType deltaType, const Real delta, const Period& switchTenor,
34 const DeltaVolQuote::AtmType longTermAtmType, const DeltaVolQuote::DeltaType longTermDeltaType)
35 : BlackVolatilityTermStructure(referenceDate, cal), times_(dates.size()), dayCounter_(dayCounter), fxSpot_(fxSpot),
36 domesticTS_(domesticTS), foreignTS_(foreignTS),
37 atmCurve_(referenceDate, dates, atmVols, dayCounter, requireMonotoneVariance), rr_(rr), bf_(bf),
38 atmType_(atmType), deltaType_(deltaType), delta_(delta), switchTenor_(switchTenor),
39 longTermAtmType_(longTermAtmType), longTermDeltaType_(longTermDeltaType) {
40
41 QL_REQUIRE(dates.size() >= 1, "at least 1 date required");
42 maxDate_ = dates.back();
43
44 QL_REQUIRE(dates.size() == rr.size(), "mismatch between date vector and RR vector");
45 QL_REQUIRE(dates.size() == bf.size(), "mismatch between date vector and BF vector");
46
47 // this has already been done for dates
48 for (Size i = 0; i < dates.size(); i++) {
49 QL_REQUIRE(referenceDate < dates[i], "Dates must be greater than reference date");
50 times_[i] = timeFromReference(dates[i]);
51 if (i > 0) {
52 QL_REQUIRE(times_[i] > times_[i - 1], "dates must be sorted unique!");
53 }
54 }
55
56 // set up the 3 interpolators
57 if (dates.size() > 1) {
58 rrCurve_ = LinearInterpolation(times_.begin(), times_.end(), rr_.begin());
59 bfCurve_ = LinearInterpolation(times_.begin(), times_.end(), bf_.begin());
60 } else {
61 rrCurve_ = BackwardFlatInterpolation(times_.begin(), times_.end(), rr_.begin());
62 bfCurve_ = BackwardFlatInterpolation(times_.begin(), times_.end(), bf_.begin());
63 }
64
65 atmCurve_.enableExtrapolation();
66
67 registerWith(domesticTS_);
68 registerWith(foreignTS_);
69 registerWith(fxSpot_);
70}
71
72QuantLib::ext::shared_ptr<FxSmileSection> FxBlackVolatilitySurface::blackVolSmile(Time t) const {
73 // we interpolate on the 3 curves independently
74 Volatility atm = atmCurve_.blackVol(t, 0); // blackVol returns atm vol when strike is 0
75
76 // Flat extrapolation for RR + BF.
77 Volatility rr, bf;
78 if (t < times_.front()) {
79 // flat RR + BF
80 rr = rrCurve_(times_.front());
81 bf = bfCurve_(times_.front());
82
83 // we account cases where the FxSmileSection requires t > 0 by using the first pillar point
84 QL_REQUIRE(t >= 0, "FxBlackVolatilitySurface::blackVolSmileImpl(): non-negative expiry time expected");
85 t = times_.front();
86 } else if (t < times_.back()) {
87 rr = rrCurve_(t, true);
88 bf = bfCurve_(t, true);
89 } else {
90 // flat RR + BF
91 rr = rrCurve_(times_.back());
92 bf = bfCurve_(times_.back());
93 }
94
95 Real rd = domesticTS_->zeroRate(t, Continuous);
96 Real rf = foreignTS_->zeroRate(t, Continuous);
97
98 return blackVolSmileImpl(fxSpot_->value(), rd, rf, t, atm, rr, bf);
99}
100
101Volatility FxBlackVolatilitySurface::blackVolImpl(Time t, Real strike) const {
102 // If asked for strike == 0, just return the ATM value.
103 if (strike == 0 || strike == Null<Real>())
104 return atmCurve_.blackVol(t, 0);
105 else
106 return blackVolSmile(t)->volatility(strike);
107}
108
109QuantLib::ext::shared_ptr<FxSmileSection> FxBlackVannaVolgaVolatilitySurface::blackVolSmileImpl(Real spot, Real rd, Real rf,
110 Time t, Volatility atm,
111 Volatility rr,
112 Volatility bf) const {
113 QL_REQUIRE(t > 0, "FxBlackVannaVolgaVolatilitySurface::blackVolSmileImpl(): positive expiry time expected");
114 Real switchTime = switchTenor_ == 0 * Days ? QL_MAX_REAL : timeFromReference(optionDateFromTenor(switchTenor_));
115 DeltaVolQuote::AtmType at;
116 DeltaVolQuote::DeltaType dt;
117 if (t < switchTime && !close_enough(t, switchTime)) {
118 at = atmType_;
119 dt = deltaType_;
120 } else {
121 at = longTermAtmType_;
123 }
124 return QuantLib::ext::make_shared<VannaVolgaSmileSection>(spot, rd, rf, t, atm, rr, bf, firstApprox_, at, dt, delta_);
125}
126
127} // namespace QuantExt
virtual QuantLib::ext::shared_ptr< FxSmileSection > blackVolSmileImpl(Real spot, Real rd, Real rf, Time t, Volatility atm, Volatility rr, Volatility bf) const override
this must be implemented.
FxBlackVolatilitySurface(const Date &referenceDate, const std::vector< Date > &dates, const std::vector< Volatility > &atmVols, const std::vector< Volatility > &rr, const std::vector< Volatility > &bf, const DayCounter &dayCounter, const Calendar &cal, const Handle< Quote > &fxSpot, const Handle< YieldTermStructure > &domesticTS, const Handle< YieldTermStructure > &foreignTS, bool requireMonotoneVariance=true, const DeltaVolQuote::AtmType atmType=DeltaVolQuote::AtmType::AtmDeltaNeutral, const DeltaVolQuote::DeltaType deltaType=DeltaVolQuote::DeltaType::Spot, const Real delta=0.25, const Period &switchTenor=0 *Days, const DeltaVolQuote::AtmType longTermAtmType=DeltaVolQuote::AtmType::AtmDeltaNeutral, const DeltaVolQuote::DeltaType longTermDeltaType=DeltaVolQuote::DeltaType::Spot)
virtual QuantLib::ext::shared_ptr< FxSmileSection > blackVolSmileImpl(Real spot, Real rd, Real rf, Time t, Volatility atm, Volatility rr, Volatility bf) const =0
this must be implemented.
Handle< YieldTermStructure > foreignTS_
Handle< YieldTermStructure > domesticTS_
QuantLib::ext::shared_ptr< FxSmileSection > blackVolSmile(Time t) const
Return an FxSmile for the time t.
DeltaVolQuote::AtmType longTermAtmType_
virtual Volatility blackVolImpl(Time t, Real strike) const override
DeltaVolQuote::DeltaType deltaType_
DeltaVolQuote::DeltaType longTermDeltaType_
FX Black volatility surface that incorporates an FxSmile.
Filter close_enough(const RandomVariable &x, const RandomVariable &y)