21#include <ql/experimental/math/laplaceinterpolation.hpp>
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) {
43 registerWith(atmVolStructure);
45 for (
auto const& v : volSpreads)
46 for (
auto const& s : v)
51void laplaceInterpolationWithErrorHandling(Matrix& m,
const std::vector<Real>& x,
const std::vector<Real>& y) {
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.");
63 SwaptionVolatilityCube::performCalculations();
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));
78 std::vector<Matrix> interpolatedVolSpreads(strikeSpreads_.size(),
79 Matrix(allSwapLengths.size(), allOptionTimes.size(), Null<Real>()));
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();
95 for (
auto& v : interpolatedVolSpreads) {
96 laplaceInterpolationWithErrorHandling(v, allOptionTimes, allSwapLengths);
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);
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));
116 shift(allOptionTenors[i], allSwapTenors[j]),
122 modelParameters[std::make_pair(allOptionTimes[i], allSwapLengths[j])] = m->second;
137 if (
auto c =
cache_.find(std::make_pair(optionTime, swapLength)); c !=
cache_.end()) {
141 atmStrike(optionDateFromTime(optionTime), std::max<int>(1,
static_cast<int>(swapLength * 12.0 + 0.5)) * Months);
143 auto tmp = boost::make_shared<ParametricVolatilitySmileSection>(
147 cache_[std::make_pair(optionTime, swapLength)] = tmp;
@ ShiftedLognormalVolatility
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_
QuantLib::Real maxAcceptableError_
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.