26#include <ql/exercise.hpp>
27#include <ql/instruments/payoffs.hpp>
28#include <ql/instruments/vanillaoption.hpp>
29#include <ql/termstructures/volatility/equityfx/andreasenhugelocalvoladapter.hpp>
30#include <ql/termstructures/volatility/equityfx/andreasenhugevolatilityinterpl.hpp>
31#include <ql/termstructures/volatility/equityfx/localconstantvol.hpp>
32#include <ql/termstructures/volatility/equityfx/localvolsurface.hpp>
33#include <ql/termstructures/volatility/equityfx/noexceptlocalvolsurface.hpp>
34#include <ql/time/daycounters/actualactual.hpp>
35#include <ql/pricingengines/vanilla/analyticeuropeanengine.hpp>
41 const std::vector<Handle<YieldTermStructure>>& curves,
42 const std::vector<ext::shared_ptr<GeneralizedBlackScholesProcess>>& processes,
43 const std::set<Date>& simulationDates,
const std::set<Date>& addDates,
const Size timeStepsPerYear,
44 const Type lvType,
const std::vector<Real>& calibrationMoneyness,
const bool dontCalibrate)
46 calibrationMoneyness_(calibrationMoneyness), dontCalibrate_(dontCalibrate) {
62 std::vector<QuantLib::ext::shared_ptr<GeneralizedBlackScholesProcess>> processes;
66 Handle<LocalVolTermStructure> localVol;
68 localVol = Handle<LocalVolTermStructure>(
69 QuantLib::ext::make_shared<LocalConstantVol>(0, NullCalendar(), 0.10, ActualActual(ActualActual::ISDA)));
74 std::vector<Real> checkMaturities, checkMoneynesses, atmForwards;
75 std::vector<std::vector<Real>> callPrices;
80 AndreasenHugeVolatilityInterpl::CalibrationSet calSet;
82 if (d <=
curves_.front()->referenceDate())
84 Real t =
processes_.front()->riskFreeRate()->timeFromReference(d);
85 checkMaturities.push_back(t);
88 Real atmMarketVol = std::max(1e-4,
processes_[l]->blackVolatility()->blackVol(t, atmLevel));
89 callPrices.push_back(std::vector<Real>());
90 atmForwards.push_back(atmLevel);
93 Real marketVol =
processes_[l]->blackVolatility()->blackVol(t, strike);
98 QuantLib::ext::make_shared<VanillaOption>(QuantLib::ext::make_shared<PlainVanillaPayoff>(Option::Call, strike),
99 QuantLib::ext::make_shared<EuropeanExercise>(d));
100 calSet.push_back(std::make_pair(option, QuantLib::ext::make_shared<SimpleQuote>(marketVol)));
101 option->setPricingEngine(QuantLib::ext::make_shared<AnalyticEuropeanEngine>(
processes_[l]));
102 callPrices.back().push_back(option->NPV());
104 checkMoneynesses.push_back(strike / atmLevel);
113 WLOG(
"Andreasen-Huge local vol calibration for process #" << l
114 <<
":, input vol is not arbitrage free:");
115 DLOG(
"time,moneyness,callSpread,butterfly,calendar");
116 for (Size i = 0; i < checkMaturities.size(); ++i)
117 for (Size j = 0; j < checkMoneynesses.size(); ++j)
118 DLOG(checkMaturities[i] <<
"," << checkMoneynesses[i] <<
"," << std::boolalpha
125 auto ah = QuantLib::ext::make_shared<AndreasenHugeVolatilityInterpl>(
127 AndreasenHugeVolatilityInterpl::CubicSpline, AndreasenHugeVolatilityInterpl::Call, 500, Null<Real>(),
129 localVol = Handle<LocalVolTermStructure>(QuantLib::ext::make_shared<AndreasenHugeLocalVolAdapter>(ah));
131 DLOG(
"Andreasen-Huge local vol calibration for process #"
134 "calibration error min="
135 << std::scientific << std::setprecision(6) << QuantLib::ext::get<0>(ah->calibrationError()) <<
" max="
136 << QuantLib::ext::get<1>(ah->calibrationError()) <<
" avg=" << QuantLib::ext::get<2>(ah->calibrationError()));
138 localVol = Handle<LocalVolTermStructure>(
139 QuantLib::ext::make_shared<LocalVolSurface>(
processes_[l]->blackVolatility(),
processes_[l]->riskFreeRate(),
142 localVol = Handle<LocalVolTermStructure>(
143 QuantLib::ext::make_shared<NoExceptLocalVolSurface>(
processes_[l]->blackVolatility(),
processes_[l]->riskFreeRate(),
147 QL_FAIL(
"unexpected local vol type");
150 processes.push_back(QuantLib::ext::make_shared<GeneralizedBlackScholesProcess>(
161 if (d >
curves_.front()->referenceDate()) {
162 timesExt.push_back(
curves_.front()->timeFromReference(d));
165 std::sort(timesExt.begin(), timesExt.end());
166 auto it = std::unique(timesExt.begin(), timesExt.end(),
167 [](
const Real x,
const Real y) { return QuantLib::close_enough(x, y); });
168 timesExt.resize(std::distance(timesExt.begin(), it));
169 return std::vector<std::vector<Real>>(
allCurves_.size(), timesExt);
173 std::vector<std::vector<std::pair<Real, Real>>> volTimesStrikes;
176 return volTimesStrikes;
177 std::vector<Real> times;
180 if (d >
curves_.front()->referenceDate())
181 times.push_back(
processes_.front()->riskFreeRate()->timeFromReference(d));
187 volTimesStrikes.push_back(std::vector<std::pair<Real, Real>>());
188 for (
auto const t : times) {
189 Real atmLevel =
atmForward(p->x0(), p->riskFreeRate(), p->dividendYield(), t);
190 Real atmMarketVol = std::max(1e-4, p->blackVolatility()->blackVol(t, atmLevel));
192 Real strike = atmLevel * std::exp(m * atmMarketVol * std::sqrt(t));
193 volTimesStrikes.back().push_back(std::make_pair(t, strike));
197 return volTimesStrikes;
const std::vector< std::vector< bool > > & butterflyArbitrage() const
bool arbitrageFree() const
const std::vector< std::vector< bool > > & calendarArbitrage() const
const std::vector< std::vector< bool > > & callSpreadArbitrage() const
std::vector< Handle< YieldTermStructure > > allCurves_
const std::set< Date > addDates_
std::set< Date > effectiveSimulationDates_
TimeGrid discretisationTimeGrid_
QuantLib::ext::shared_ptr< MarketObserver > marketObserver_
const std::vector< QuantLib::ext::shared_ptr< GeneralizedBlackScholesProcess > > processes_
const std::vector< Handle< YieldTermStructure > > curves_
std::vector< ext::shared_ptr< GeneralizedBlackScholesProcess > > getCalibratedProcesses() const override
LocalVolModelBuilder(const std::vector< Handle< YieldTermStructure > > &curves, const std::vector< ext::shared_ptr< GeneralizedBlackScholesProcess > > &processes, const std::set< Date > &simulationDates={}, const std::set< Date > &addDates={}, const Size timeStepsPerYear=1, const Type lvType=Type::Dupire, const std::vector< Real > &calibrationMoneyness={ -2.0, -1.0, 0.0, 1.0, 2.0 }, const bool dontCalibrate=false)
std::vector< std::vector< std::pair< Real, Real > > > getVolTimesStrikes() const override
std::vector< std::vector< Real > > getCurveTimes() const override
const std::vector< Real > calibrationMoneyness_
const bool dontCalibrate_
builder for an array of local vol processes
Classes and functions for log message handling.
#define DLOG(text)
Logging Macro (Level = Debug)
#define WLOG(text)
Logging Macro (Level = Warning)
Shared utilities for model building and calibration.
Real atmForward(const Real s0, const Handle< YieldTermStructure > &r, const Handle< YieldTermStructure > &q, const Real t)
helper function that computes the atm forward
Serializable Credit Default Swap.