23#include <ql/math/interpolations/bilinearinterpolation.hpp>
24#include <ql/math/interpolations/flatextrapolation2d.hpp>
31 const Handle<SwaptionVolatilityStructure>& base,
const std::vector<Period>& optionTenors,
32 const std::vector<Period>& swapTenors,
const std::vector<Real>& strikeSpreads,
33 const std::vector<std::vector<Handle<Quote>>>& volSpreads,
const QuantLib::ext::shared_ptr<SwapIndex>& baseSwapIndexBase,
34 const QuantLib::ext::shared_ptr<SwapIndex>& baseShortSwapIndexBase,
35 const QuantLib::ext::shared_ptr<SwapIndex>& simulatedSwapIndexBase,
36 const QuantLib::ext::shared_ptr<SwapIndex>& simulatedShortSwapIndexBase,
const bool stickyAbsMoney)
39 base_(base), strikeSpreads_(strikeSpreads), volSpreads_(volSpreads), baseSwapIndexBase_(baseSwapIndexBase),
40 baseShortSwapIndexBase_(baseShortSwapIndexBase), simulatedSwapIndexBase_(simulatedSwapIndexBase),
41 simulatedShortSwapIndexBase_(simulatedShortSwapIndexBase), stickyAbsMoney_(stickyAbsMoney) {
42 enableExtrapolation(
base_->allowsExtrapolation());
47 "SpreadedSwaptionVolatility: baseSwapIndexBase and baseShortSwapIndexBase must be both null or non-null");
50 "SpreadedSwaptionVolatility: simulatedSwapIndexBase and simulatedShortSwapIndexBase must be both null "
60 QL_REQUIRE(!
strikeSpreads_.empty(),
"SpreadedSwaptionVolatility: empty strike spreads");
61 QL_REQUIRE(!optionTenors_.empty(),
"SpreadedSwaptionVolatility: empty option tenors");
62 QL_REQUIRE(!swapTenors_.empty(),
"SpreadedSwaptionVolatility: empty swap tenors");
63 QL_REQUIRE(optionTenors.size() * swapTenors.size() == volSpreads.size(),
64 "SpreadedSwaptionVolatility: optionTenors (" << optionTenors.size() <<
") * swapTenors ("
65 << swapTenors.size() <<
") inconsistent with vol spreads ("
66 << volSpreads.size() <<
")");
69 <<
" strike spreads, but "
70 << s.size() <<
" vol spreads");
71 for (
auto const& q : s)
95 const QuantLib::ext::shared_ptr<SwapIndex> swapIndexBase,
96 const QuantLib::ext::shared_ptr<SwapIndex> shortSwapIndexBase)
const {
97 Date optionDate = optionDateFromTime(optionTime);
99 Period swapTenor(
static_cast<Integer
>(rounder(swapLength * 12.0)), Months);
100 optionDate = swapTenor > shortSwapIndexBase->tenor()
101 ? swapIndexBase->fixingCalendar().adjust(optionDate, Following)
102 : shortSwapIndexBase->fixingCalendar().adjust(optionDate, Following);
103 if (swapTenor > shortSwapIndexBase->tenor()) {
104 return swapIndexBase->clone(swapTenor)->fixing(optionDate);
106 return shortSwapIndexBase->clone(swapTenor)->fixing(optionDate);
112 auto baseSection =
base_->smileSection(optionTime, swapLength);
113 Real baseAtmLevel = Null<Real>();
114 Real simulatedAtmLevel = Null<Real>();
117 "SpreadedSwaptionVolatility::smileSecitonImpl: require baseSwapIndexBase, since stickyAbsMoney is "
118 "true and the base vol smile section does not provide an ATM level.");
123 "simualtedSwapIndexBase, since stickyAbsMoney is true");
128 for (Size k = 0; k < volSpreads.size(); ++k) {
132 return QuantLib::ext::make_shared<SpreadedSmileSection2>(
base_->smileSection(optionTime, swapLength), volSpreads,
138 if (strike == Null<Real>()) {
142 for (Size k = 0; k < volSpreads.size(); ++k) {
146 if (volSpreads.size() > 1) {
147 auto spreadInterpolation =
149 volSpread = spreadInterpolation(0.0);
151 volSpread = volSpreads.front();
153 return base_->volatility(optionTime, swapLength, strike) + volSpread;
161 return base_->shift(optionDate, swapTenor);
165 return base_->shift(optionTime, swapLength);
169 SwaptionVolatilityDiscrete::performCalculations();
171 for (Size i = 0; i < optionTenors_.size(); ++i) {
172 for (Size j = 0; j < swapTenors_.size(); ++j) {
173 Size index = i * swapTenors_.size() + j;
174 QL_REQUIRE(!
volSpreads_[index][k].empty(),
"SpreadedSwaptionVolatility: vol spread quote at index ("
175 << i <<
"," << j <<
"," << k <<
") is empty");
180 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), optionTimes_.end(),
volSpreadValues_[k]));
Linear-interpolation and flat extrapolation factory and traits
Interpolation interpolate(const I1 &xBegin, const I1 &xEnd, const I2 &yBegin) const
void performCalculations() const override
QuantLib::ext::shared_ptr< SwapIndex > simulatedShortSwapIndexBase_
Calendar calendar() const override
Real getAtmLevel(const Real optionTime, const Real swapLength, const QuantLib::ext::shared_ptr< SwapIndex > swapIndexBase, const QuantLib::ext::shared_ptr< SwapIndex > shortSwapIndexBase) const
Volatility volatilityImpl(Time optionTime, Time swapLength, Rate strike) const override
Rate maxStrike() const override
Rate minStrike() const override
QuantLib::ext::shared_ptr< SmileSection > smileSectionImpl(Time optionTime, Time swapLength) const override
void deepUpdate() override
const Handle< SwaptionVolatilityStructure > & baseVol()
QuantLib::ext::shared_ptr< SwapIndex > baseSwapIndexBase_
SpreadedSwaptionVolatility(const Handle< SwaptionVolatilityStructure > &base, const std::vector< Period > &optionTenors, const std::vector< Period > &swapTenors, const std::vector< Real > &strikeSpreads, const std::vector< std::vector< Handle< Quote > > > &volSpreads, const QuantLib::ext::shared_ptr< SwapIndex > &baseSwapIndexBase=nullptr, const QuantLib::ext::shared_ptr< SwapIndex > &baseShortSwapIndexBase=nullptr, const QuantLib::ext::shared_ptr< SwapIndex > &simulatedSwapIndexBase=nullptr, const QuantLib::ext::shared_ptr< SwapIndex > &simulatedShortSwapIndexBase=nullptr, const bool stickyAbsMoney=false)
Real shiftImpl(const Date &optionDate, const Period &swapTenor) const override
Handle< SwaptionVolatilityStructure > base_
const Date & referenceDate() const override
VolatilityType volatilityType() const override
QuantLib::ext::shared_ptr< SwapIndex > simulatedSwapIndexBase_
Natural settlementDays() const override
std::vector< Interpolation2D > volSpreadInterpolation_
DayCounter dayCounter() const override
Date maxDate() const override
std::vector< Matrix > volSpreadValues_
std::vector< Real > strikeSpreads_
std::vector< std::vector< Handle< Quote > > > volSpreads_
const Period & maxSwapTenor() const override
Time maxTime() const override
QuantLib::ext::shared_ptr< SwapIndex > baseShortSwapIndexBase_
smile section with linear interpolated vol spreads
swaption cube defined via atm vol spreads over another cube