Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
swaptionsabrcube.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2024 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
20
21#include <ql/experimental/math/laplaceinterpolation.hpp>
22
23namespace QuantExt {
24
26 const Handle<SwaptionVolatilityStructure>& atmVolStructure, const std::vector<Period>& optionTenors,
27 const std::vector<Period>& swapTenors, const std::vector<Period>& atmOptionTenors,
28 const std::vector<Period>& atmSwapTenors, const std::vector<Spread>& strikeSpreads,
29 const std::vector<std::vector<Handle<Quote>>>& volSpreads, const boost::shared_ptr<SwapIndex>& swapIndexBase,
30 const boost::shared_ptr<SwapIndex>& shortSwapIndexBase,
32 const boost::optional<QuantLib::VolatilityType> outputVolatilityType,
33 const std::map<std::pair<Period, Period>, std::vector<std::pair<Real, bool>>>& initialModelParameters,
34 const QuantLib::Size maxCalibrationAttempts, const QuantLib::Real exitEarlyErrorThreshold,
35 const QuantLib::Real maxAcceptableError)
36 : SwaptionVolatilityCube(atmVolStructure, optionTenors, swapTenors, strikeSpreads, volSpreads, swapIndexBase,
37 shortSwapIndexBase, false),
38 atmOptionTenors_(atmOptionTenors), atmSwapTenors_(atmSwapTenors), modelVariant_(modelVariant),
39 outputVolatilityType_(outputVolatilityType), initialModelParameters_(initialModelParameters),
40 maxCalibrationAttempts_(maxCalibrationAttempts), exitEarlyErrorThreshold_(exitEarlyErrorThreshold),
41 maxAcceptableError_(maxAcceptableError) {
42
43 registerWith(atmVolStructure);
44
45 for (auto const& v : volSpreads)
46 for (auto const& s : v)
47 registerWith(s);
48}
49
50namespace {
51void laplaceInterpolationWithErrorHandling(Matrix& m, const std::vector<Real>& x, const std::vector<Real>& y) {
52 try {
53 laplaceInterpolation(m, x, y, 1e-6, 100);
54 } catch (const std::exception& e) {
55 QL_FAIL("Error during laplaceInterpolation() in SwaptionSabrCube: "
56 << e.what() << ", this might be related to the numerical parameters relTol, maxIterMult. Contact dev.");
57 }
58}
59} // namespace
60
62
63 SwaptionVolatilityCube::performCalculations();
64
65 cache_.clear();
66
67 // build matrices of vol spreads on either given atm options / swap tenors or the smile option / swap tenors
68
69 std::vector<Period> allOptionTenors = atmOptionTenors_.empty() ? optionTenors_ : atmOptionTenors_;
70 std::vector<Period> allSwapTenors = atmSwapTenors_.empty() ? swapTenors_ : atmSwapTenors_;
71
72 std::vector<Real> allOptionTimes, allSwapLengths;
73 for (auto const& p : allOptionTenors)
74 allOptionTimes.push_back(timeFromReference(optionDateFromTenor(p)));
75 for (auto const& p : allSwapTenors)
76 allSwapLengths.push_back(swapLength(p));
77
78 std::vector<Matrix> interpolatedVolSpreads(strikeSpreads_.size(),
79 Matrix(allSwapLengths.size(), allOptionTimes.size(), Null<Real>()));
80
81 for (Size k = 0; k < strikeSpreads_.size(); ++k) {
82 for (Size i = 0; i < allOptionTenors.size(); ++i) {
83 for (Size j = 0; j < allSwapTenors.size(); ++j) {
84 Size i0 = std::distance(optionTenors_.begin(),
85 std::find(optionTenors_.begin(), optionTenors_.end(), allOptionTenors[i]));
86 Size j0 = std::distance(swapTenors_.begin(),
87 std::find(swapTenors_.begin(), swapTenors_.end(), allSwapTenors[j]));
88 if (i0 < optionTenors_.size() && j0 < swapTenors_.size()) {
89 interpolatedVolSpreads[k](j, i) = volSpreads_[i0 * swapTenors_.size() + j0][k]->value();
90 }
91 }
92 }
93 }
94
95 for (auto& v : interpolatedVolSpreads) {
96 laplaceInterpolationWithErrorHandling(v, allOptionTimes, allSwapLengths);
97 }
98
99 // build market smiles on the grid
100
101 std::vector<ParametricVolatility::MarketSmile> marketSmiles;
102 std::map<std::pair<QuantLib::Real, QuantLib::Real>, std::vector<std::pair<Real, bool>>> modelParameters;
103 for (Size i = 0; i < allOptionTenors.size(); ++i) {
104 for (Size j = 0; j < allSwapTenors.size(); ++j) {
105 Real forward = atmStrike(allOptionTenors[i], allSwapTenors[j]);
106 Real sigma = atmVol()->volatility(allOptionTenors[i], allSwapTenors[j], forward);
107 std::vector<Real> strikes;
108 std::vector<Real> vols;
109 for (Size k = 0; k < strikeSpreads_.size(); ++k) {
110 strikes.push_back(forward + strikeSpreads_[k]);
111 vols.push_back(sigma + interpolatedVolSpreads[k](j, i));
112 }
113 marketSmiles.push_back(ParametricVolatility::MarketSmile{allOptionTimes[i],
114 allSwapLengths[j],
115 forward,
116 shift(allOptionTenors[i], allSwapTenors[j]),
117 {},
118 strikes,
119 vols});
120 if (auto m = initialModelParameters_.find(std::make_pair(allOptionTenors[i], allSwapTenors[j]));
121 m != initialModelParameters_.end()) {
122 modelParameters[std::make_pair(allOptionTimes[i], allSwapLengths[j])] = m->second;
123 }
124 }
125 }
126
127 parametricVolatility_ = boost::make_shared<SabrParametricVolatility>(
129 volatilityType() == QuantLib::Normal ? ParametricVolatility::MarketQuoteType::NormalVolatility
131 Handle<YieldTermStructure>(), modelParameters, maxCalibrationAttempts_, exitEarlyErrorThreshold_,
133}
134
135boost::shared_ptr<SmileSection> SwaptionSabrCube::smileSectionImpl(Time optionTime, Time swapLength) const {
136 calculate();
137 if (auto c = cache_.find(std::make_pair(optionTime, swapLength)); c != cache_.end()) {
138 return c->second;
139 }
140 Real forward =
141 atmStrike(optionDateFromTime(optionTime), std::max<int>(1, static_cast<int>(swapLength * 12.0 + 0.5)) * Months);
142 QuantLib::VolatilityType outVolType = outputVolatilityType_ ? *outputVolatilityType_ : volatilityType();
143 auto tmp = boost::make_shared<ParametricVolatilitySmileSection>(
144 optionTime, swapLength, forward, parametricVolatility_,
145 outVolType == QuantLib::Normal ? ParametricVolatility::MarketQuoteType::NormalVolatility
147 cache_[std::make_pair(optionTime, swapLength)] = tmp;
148 return tmp;
149}
150
151} // namespace QuantExt
void performCalculations() const override
std::map< std::pair< QuantLib::Period, QuantLib::Period >, std::vector< std::pair< Real, bool > > > initialModelParameters_
boost::optional< QuantLib::VolatilityType > outputVolatilityType_
QuantLib::Real exitEarlyErrorThreshold_
QuantExt::SabrParametricVolatility::ModelVariant modelVariant_
std::map< std::pair< Real, Real >, QuantLib::ext::shared_ptr< ParametricVolatilitySmileSection > > cache_
std::vector< Period > atmSwapTenors_
QuantLib::ext::shared_ptr< ParametricVolatility > parametricVolatility_
QuantLib::ext::shared_ptr< SmileSection > smileSectionImpl(Time optionTime, Time swapLength) const override
QuantLib::Size maxCalibrationAttempts_
SwaptionSabrCube(const Handle< SwaptionVolatilityStructure > &atmVolStructure, const std::vector< Period > &optionTenors, const std::vector< Period > &swapTenors, const std::vector< Period > &atmOptionTenors, const std::vector< Period > &atmSwapLengths, const std::vector< Spread > &strikeSpreads, const std::vector< std::vector< Handle< Quote > > > &volSpreads, const QuantLib::ext::shared_ptr< SwapIndex > &swapIndexBase, const QuantLib::ext::shared_ptr< SwapIndex > &shortSwapIndexBase, const QuantExt::SabrParametricVolatility::ModelVariant modelVariant, const boost::optional< QuantLib::VolatilityType > outputVolatilityType=boost::none, const std::map< std::pair< Period, Period >, std::vector< std::pair< Real, bool > > > &initialModelParameters={}, const QuantLib::Size maxCalibrationAttempts=10, const QuantLib::Real exitEarlyErrorThreshold=0.005, const QuantLib::Real maxAcceptableError=0.05)
std::vector< Period > atmOptionTenors_
SABR Swaption volatility cube.
vector< Real > strikes