56 {
57
59
60 calculate();
61
62 std::vector<QuantLib::ext::shared_ptr<GeneralizedBlackScholesProcess>> processes;
63
65
66 Handle<LocalVolTermStructure> localVol;
68 localVol = Handle<LocalVolTermStructure>(
69 QuantLib::ext::make_shared<LocalConstantVol>(0, NullCalendar(), 0.10, ActualActual(ActualActual::ISDA)));
71
72
73
74 std::vector<Real> checkMaturities, checkMoneynesses, atmForwards;
75 std::vector<std::vector<Real>> callPrices;
76
77
78
79
80 AndreasenHugeVolatilityInterpl::CalibrationSet calSet;
82 if (d <=
curves_.front()->referenceDate())
83 continue;
84 Real t =
processes_.front()->riskFreeRate()->timeFromReference(d);
85 checkMaturities.push_back(t);
86 Real atmLevel =
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);
94
96 continue;
97 auto option =
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);
105 }
106 }
107 }
108
109
111 callPrices);
112 if (!cmCheck.arbitrageFree()) {
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
119 << cmCheck.callSpreadArbitrage()[i][j] << ","
120 << cmCheck.butterflyArbitrage()[i][j] << ","
121 << cmCheck.calendarArbitrage()[i][j]);
122 }
123
124
125 auto ah = QuantLib::ext::make_shared<AndreasenHugeVolatilityInterpl>(
127 AndreasenHugeVolatilityInterpl::CubicSpline, AndreasenHugeVolatilityInterpl::Call, 500, Null<Real>(),
128 Null<Real>());
129 localVol = Handle<LocalVolTermStructure>(QuantLib::ext::make_shared<AndreasenHugeLocalVolAdapter>(ah));
130
131 DLOG(
"Andreasen-Huge local vol calibration for process #"
132 << l
133 << ": "
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(),
145 0.0));
146 } else {
147 QL_FAIL("unexpected local vol type");
148 }
149
150 processes.push_back(QuantLib::ext::make_shared<GeneralizedBlackScholesProcess>(
153 }
154
155 return processes;
156}
std::set< Date > effectiveSimulationDates_
const std::vector< Handle< YieldTermStructure > > curves_
#define DLOG(text)
Logging Macro (Level = Debug)
#define WLOG(text)
Logging Macro (Level = Warning)
Real atmForward(const Real s0, const Handle< YieldTermStructure > &r, const Handle< YieldTermStructure > &q, const Real t)
helper function that computes the atm forward