Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
capfloortermvolsurface.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2019 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/bicubicsplineinterpolation.hpp>
20#include <ql/math/interpolations/bilinearinterpolation.hpp>
21#include <ql/quotes/simplequote.hpp>
22#include <ql/utilities/dataformatters.hpp>
24
25using namespace QuantLib;
26using std::ostream;
27
28namespace QuantExt {
29
30// floating reference date, floating market data
31CapFloorTermVolSurfaceExact::CapFloorTermVolSurfaceExact(Natural settlementDays, const Calendar& calendar,
32 BusinessDayConvention bdc, const std::vector<Period>& optionTenors,
33 const std::vector<Rate>& strikes,
34 const std::vector<std::vector<Handle<Quote> > >& vols,
35 const DayCounter& dc, InterpolationMethod interpolationMethod)
36 : CapFloorTermVolSurface(settlementDays, calendar, bdc, dc, optionTenors, strikes), nOptionTenors_(optionTenors.size()),
37 optionDates_(nOptionTenors_), optionTimes_(nOptionTenors_), nStrikes_(strikes.size()), volHandles_(vols),
38 vols_(vols.size(), vols[0].size()), interpolationMethod_(interpolationMethod) {
39 checkInputs();
40 initializeOptionDatesAndTimes();
41 for (Size i = 0; i < nOptionTenors_; ++i)
42 QL_REQUIRE(volHandles_[i].size() == nStrikes_, io::ordinal(i + 1)
43 << " row of vol handles has size " << volHandles_[i].size()
44 << " instead of " << nStrikes_);
45 registerWithMarketData();
46 for (Size i = 0; i < vols_.rows(); ++i)
47 for (Size j = 0; j < vols_.columns(); ++j)
48 vols_[i][j] = volHandles_[i][j]->value();
49 interpolate();
50}
51
52// fixed reference date, floating market data
53CapFloorTermVolSurfaceExact::CapFloorTermVolSurfaceExact(const Date& settlementDate, const Calendar& calendar,
54 BusinessDayConvention bdc, const std::vector<Period>& optionTenors,
55 const std::vector<Rate>& strikes,
56 const std::vector<std::vector<Handle<Quote> > >& vols,
57 const DayCounter& dc, InterpolationMethod interpolationMethod)
58 : CapFloorTermVolSurface(settlementDate, calendar, bdc, dc, optionTenors, strikes), nOptionTenors_(optionTenors.size()),
59 optionDates_(nOptionTenors_), optionTimes_(nOptionTenors_), nStrikes_(strikes.size()), volHandles_(vols),
60 vols_(vols.size(), vols[0].size()), interpolationMethod_(interpolationMethod) {
61 checkInputs();
62 initializeOptionDatesAndTimes();
63 for (Size i = 0; i < nOptionTenors_; ++i)
64 QL_REQUIRE(volHandles_[i].size() == nStrikes_, io::ordinal(i + 1)
65 << " row of vol handles has size " << volHandles_[i].size()
66 << " instead of " << nStrikes_);
67 registerWithMarketData();
68 for (Size i = 0; i < vols_.rows(); ++i)
69 for (Size j = 0; j < vols_.columns(); ++j)
70 vols_[i][j] = volHandles_[i][j]->value();
71 interpolate();
72}
73
74// fixed reference date, fixed market data
75CapFloorTermVolSurfaceExact::CapFloorTermVolSurfaceExact(const Date& settlementDate, const Calendar& calendar,
76 BusinessDayConvention bdc, const std::vector<Period>& optionTenors,
77 const std::vector<Rate>& strikes, const Matrix& vols,
78 const DayCounter& dc, InterpolationMethod interpolationMethod)
79 : CapFloorTermVolSurface(settlementDate, calendar, bdc, dc, optionTenors, strikes), nOptionTenors_(optionTenors.size()),
80 optionDates_(nOptionTenors_), optionTimes_(nOptionTenors_), nStrikes_(strikes.size()), volHandles_(vols.rows()), vols_(vols),
81 interpolationMethod_(interpolationMethod) {
82 checkInputs();
83 initializeOptionDatesAndTimes();
84 // fill dummy handles to allow generic handle-based computations later
85 for (Size i = 0; i < nOptionTenors_; ++i) {
86 volHandles_[i].resize(nStrikes_);
87 for (Size j = 0; j < nStrikes_; ++j)
88 volHandles_[i][j] = Handle<Quote>(ext::shared_ptr<Quote>(new SimpleQuote(vols_[i][j])));
89 }
90 interpolate();
91}
92
93// floating reference date, fixed market data
94CapFloorTermVolSurfaceExact::CapFloorTermVolSurfaceExact(Natural settlementDays, const Calendar& calendar,
95 BusinessDayConvention bdc, const std::vector<Period>& optionTenors,
96 const std::vector<Rate>& strikes, const Matrix& vols,
97 const DayCounter& dc, InterpolationMethod interpolationMethod)
98 : CapFloorTermVolSurface(settlementDays, calendar, bdc, dc, optionTenors, strikes), nOptionTenors_(optionTenors.size()),
99 optionDates_(nOptionTenors_), optionTimes_(nOptionTenors_),
100 nStrikes_(strikes.size()), volHandles_(vols.rows()), vols_(vols),
101 interpolationMethod_(interpolationMethod) {
102 checkInputs();
103 initializeOptionDatesAndTimes();
104 // fill dummy handles to allow generic handle-based computations later
105 for (Size i = 0; i < nOptionTenors_; ++i) {
106 volHandles_[i].resize(nStrikes_);
107 for (Size j = 0; j < nStrikes_; ++j)
108 volHandles_[i][j] = Handle<Quote>(ext::shared_ptr<Quote>(new SimpleQuote(vols_[i][j])));
109 }
110 interpolate();
111}
112
113void CapFloorTermVolSurfaceExact::checkInputs() const {
114
115 QL_REQUIRE(!optionTenors_.empty(), "empty option tenor vector");
116 QL_REQUIRE(nOptionTenors_ == vols_.rows(), "mismatch between number of option tenors ("
117 << nOptionTenors_ << ") and number of volatility rows ("
118 << vols_.rows() << ")");
119 QL_REQUIRE(optionTenors_[0] > 0 * Days, "negative first option tenor: " << optionTenors_[0]);
120 for (Size i = 1; i < nOptionTenors_; ++i)
121 QL_REQUIRE(optionTenors_[i] > optionTenors_[i - 1],
122 "non increasing option tenor: " << io::ordinal(i) << " is " << optionTenors_[i - 1] << ", "
123 << io::ordinal(i + 1) << " is " << optionTenors_[i]);
124
125 QL_REQUIRE(nStrikes_ == vols_.columns(),
126 "mismatch between strikes(" << strikes_.size() << ") and vol columns (" << vols_.columns() << ")");
127 for (Size j = 1; j < nStrikes_; ++j)
128 QL_REQUIRE(strikes_[j - 1] < strikes_[j],
129 "non increasing strikes: " << io::ordinal(j) << " is " << io::rate(strikes_[j - 1]) << ", "
130 << io::ordinal(j + 1) << " is " << io::rate(strikes_[j]));
131}
132
133void CapFloorTermVolSurfaceExact::registerWithMarketData() {
134 for (Size i = 0; i < nOptionTenors_; ++i)
135 for (Size j = 0; j < nStrikes_; ++j)
136 registerWith(volHandles_[i][j]);
137}
138
139void CapFloorTermVolSurfaceExact::interpolate() {
140 if (interpolationMethod_ == BicubicSpline)
141 interpolation_ =
142 QuantLib::BicubicSpline(strikes_.begin(), strikes_.end(), optionTimes_.begin(), optionTimes_.end(), vols_);
143 else if (interpolationMethod_ == Bilinear)
144 interpolation_ =
145 BilinearInterpolation(strikes_.begin(), strikes_.end(), optionTimes_.begin(), optionTimes_.end(), vols_);
146 else {
147 QL_FAIL("Invalid InterpolationMethod");
148 }
149}
150
151void CapFloorTermVolSurfaceExact::update() {
152 // recalculate dates if necessary...
153 if (moving_) {
154 Date d = Settings::instance().evaluationDate();
155 if (evaluationDate_ != d) {
156 evaluationDate_ = d;
157 initializeOptionDatesAndTimes();
158 }
159 }
160 CapFloorTermVolSurface::update();
161}
162
163void CapFloorTermVolSurfaceExact::initializeOptionDatesAndTimes() const {
164 for (Size i = 0; i < nOptionTenors_; ++i) {
165 optionDates_[i] = optionDateFromTenor(optionTenors_[i]);
166 optionTimes_[i] = timeFromReference(optionDates_[i]);
167 }
168}
169
170void CapFloorTermVolSurfaceExact::performCalculations() const {
171 // check if date recalculation must be called here
172
173 for (Size i = 0; i < nOptionTenors_; ++i)
174 for (Size j = 0; j < nStrikes_; ++j)
175 vols_[i][j] = volHandles_[i][j]->value();
176
177 interpolation_.update();
178}
179
181 switch (method) {
182 case CapFloorTermVolSurfaceExact::BicubicSpline:
183 return out << "BicubicSpline";
184 case CapFloorTermVolSurfaceExact::Bilinear:
185 return out << "Bilinear";
186 default:
187 QL_FAIL("Unknown CapFloorTermVolSurface::InterpolationMethod (" << Integer(method) << ")");
188 }
189}
190
191} // namespace QuantExt
Cap/floor smile volatility surface.
CapFloorTermVolSurfaceExact(Natural settlementDays, const Calendar &calendar, BusinessDayConvention bdc, const std::vector< Period > &optionTenors, const std::vector< Rate > &strikes, const std::vector< std::vector< Handle< Quote > > > &, const DayCounter &dc=Actual365Fixed(), InterpolationMethod interpolationMethod=BicubicSpline)
floating reference date, floating market data
std::ostream & operator<<(std::ostream &out, EquityReturnType t)
vector< Real > strikes