28#include <ql/exercise.hpp>
29#include <ql/models/shortrate/calibrationhelpers/swaptionhelper.hpp>
33using std::ostringstream;
35using std::setprecision;
44Real impliedVolatility(
const QuantLib::ext::shared_ptr<BlackCalibrationHelper>& h) {
47 if (h->volatilityType() == QuantLib::ShiftedLognormal) {
54 return h->impliedVolatility(h->modelValue(), 1e-4, 1000, minVol, maxVol);
71map<Date, HelperValues> jyHelperValues(
const vector<QuantLib::ext::shared_ptr<CalibrationHelper>>& cb,
const Array& times) {
73 map<Date, HelperValues> result;
75 for (
const auto& ci : cb) {
77 if (QuantLib::ext::shared_ptr<CpiCapFloorHelper> h = QuantLib::ext::dynamic_pointer_cast<CpiCapFloorHelper>(ci)) {
79 hv.modelValue = h->modelValue();
80 hv.marketValue = h->marketValue();
81 hv.error = hv.modelValue - hv.marketValue;
82 auto d = h->instrument()->fixingDate();
87 if (QuantLib::ext::shared_ptr<YoYCapFloorHelper> h = QuantLib::ext::dynamic_pointer_cast<YoYCapFloorHelper>(ci)) {
89 hv.modelValue = h->modelValue();
90 hv.marketValue = h->marketValue();
91 hv.error = hv.modelValue - hv.marketValue;
92 auto d = h->yoyCapFloor()->lastYoYInflationCoupon()->fixingDate();
97 if (QuantLib::ext::shared_ptr<YoYSwapHelper> h = QuantLib::ext::dynamic_pointer_cast<YoYSwapHelper>(ci)) {
99 hv.modelValue = h->modelRate();
100 hv.marketValue = h->marketRate();
101 hv.error = hv.modelValue - hv.marketValue;
102 auto d = h->yoySwap()->maturityDate();
107 QL_FAIL(
"Expected JY calibration instruments to be one of: CPI cap floor, YoY cap floor or YoY swap.");
110 QL_REQUIRE(result.size() == times.size() + 1,
"Expected JY times to be 1 less the number of instruments.");
113 for (
auto& kv : result) {
114 if (ctr < times.size())
115 kv.second.maturity = times[ctr++];
117 kv.second.maturity = times.empty() ? 0.0 : times.back();
126 const std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>>& basket,
127 const QuantLib::ext::shared_ptr<IrLgm1fParametrization>& parametrization) {
128 std::ostringstream
log;
129 log << std::right << std::setw(3) <<
"#" << std::setw(14) <<
"time" << std::setw(14) <<
"modelVol" << std::setw(14)
130 <<
"marketVol" << std::setw(14) <<
"(diff)" << std::setw(14) <<
"modelValue" << std::setw(14) <<
"marketValue"
131 << std::setw(14) <<
"(diff)" << std::setw(14) <<
"irlgm1fAlpha" << std::setw(14) <<
"irlgm1fKappa"
132 << std::setw(16) <<
"irlgm1fHwSigma\n";
133 Real t = 0.0, modelAlpha = 0.0, modelKappa = 0.0, modelHwSigma = 0.0;
135 for (Size j = 0; j < basket.size(); j++) {
139 Volatility modelVol = 0, marketVol = 0, volDiff = 0;
140 QuantLib::ext::shared_ptr<SwaptionHelper> swaption = QuantLib::ext::dynamic_pointer_cast<SwaptionHelper>(basket[j]);
141 if (swaption !=
nullptr && parametrization !=
nullptr) {
143 t = parametrization->termStructure()->timeFromReference(swaption->swaption()->exercise()->date(0));
144 modelAlpha = parametrization->alpha(t - 1E-4);
145 modelKappa = parametrization->kappa(t - 1E-4);
146 modelHwSigma = parametrization->hullWhiteSigma(t - 1E-4);
149 marketVol = basket[j]->volatility()->value();
150 modelVol = impliedVolatility(basket[j]);
151 volDiff = modelVol - marketVol;
152 log << std::setw(3) << j << std::setprecision(6) << std::setw(14) << t << std::setw(14) << modelVol
153 << std::setw(14) << marketVol << std::setw(14) << volDiff << std::setw(14) <<
modelValue << std::setw(14)
154 <<
marketValue << std::setw(14) << valueDiff << std::setw(14) << modelAlpha << std::setw(14) << modelKappa
155 << std::setw(16) << modelHwSigma <<
"\n";
159 if (parametrization !=
nullptr) {
161 modelAlpha = parametrization->alpha(t + 1E-4);
162 modelKappa = parametrization->kappa(t + 1E-4);
163 modelHwSigma = parametrization->hullWhiteSigma(t + 1E-4);
165 log <<
"t >= " << t <<
": irlgm1fAlpha = " << modelAlpha <<
" irlgm1fKappa = " << modelKappa
166 <<
" irlgm1fHwSigma = " << modelHwSigma <<
"\n";
171 const QuantLib::ext::shared_ptr<FxBsParametrization>& parametrization,
172 const QuantLib::ext::shared_ptr<Parametrization>& domesticIrModel) {
173 auto lgmParametrization = QuantLib::ext::dynamic_pointer_cast<IrLgm1fParametrization>(domesticIrModel);
174 if (lgmParametrization) {
177 return std::string();
182 const QuantLib::ext::shared_ptr<FxBsParametrization>& parametrization,
183 const QuantLib::ext::shared_ptr<IrLgm1fParametrization>& domesticLgm) {
184 std::ostringstream
log;
185 log << std::right << std::setw(3) <<
"#" << std::setw(14) <<
"time" << std::setw(14) <<
"modelVol" << std::setw(14)
186 <<
"marketVol" << std::setw(14) <<
"(diff)" << std::setw(14) <<
"modelValue" << std::setw(14) <<
"marketValue"
187 << std::setw(14) <<
"(diff)" << std::setw(14) <<
"fxbsSigma\n";
188 Real t = 0.0, modelSigma = 0.0;
189 for (Size j = 0; j < basket.size(); j++) {
193 Volatility modelVol = 0, marketVol = 0, volDiff = 0;
194 QuantLib::ext::shared_ptr<FxEqOptionHelper> fxoption = QuantLib::ext::dynamic_pointer_cast<FxEqOptionHelper>(basket[j]);
195 if (fxoption !=
nullptr && parametrization !=
nullptr && domesticLgm !=
nullptr) {
197 t = domesticLgm->termStructure()->timeFromReference(fxoption->option()->exercise()->date(0));
198 modelSigma = parametrization->sigma(t - 1E-4);
200 marketVol = basket[j]->volatility()->value();
201 modelVol = impliedVolatility(basket[j]);
202 volDiff = modelVol - marketVol;
203 log << std::setw(3) << j << std::setprecision(6) << std::setw(14) << t << std::setw(14) << modelVol
204 << std::setw(14) << marketVol << std::setw(14) << volDiff << std::setw(14) <<
modelValue << std::setw(14)
205 <<
marketValue << std::setw(14) << valueDiff << std::setw(14) << modelSigma <<
"\n";
207 if (parametrization !=
nullptr) {
209 modelSigma = parametrization->sigma(t + 1E-4);
211 log <<
"t >= " << t <<
": fxbsSigma = " << modelSigma <<
"\n";
216 const QuantLib::ext::shared_ptr<EqBsParametrization>& parametrization,
217 const QuantLib::ext::shared_ptr<Parametrization>& domesticIrModel) {
218 auto lgmParametrization = QuantLib::ext::dynamic_pointer_cast<IrLgm1fParametrization>(parametrization);
219 if (lgmParametrization) {
222 return std::string();
227 const QuantLib::ext::shared_ptr<EqBsParametrization>& parametrization,
228 const QuantLib::ext::shared_ptr<IrLgm1fParametrization>& domesticLgm) {
229 std::ostringstream
log;
230 log << std::right << std::setw(3) <<
"#" << std::setw(14) <<
"time" << std::setw(14) <<
"modelVol" << std::setw(14)
231 <<
"marketVol" << std::setw(14) <<
"(diff)" << std::setw(14) <<
"modelValue" << std::setw(14) <<
"marketValue"
232 << std::setw(14) <<
"(diff)" << std::setw(14) <<
"eqbsSigma\n";
233 Real t = 0.0, modelSigma = 0.0;
234 for (Size j = 0; j < basket.size(); j++) {
238 Volatility modelVol = 0, marketVol = 0, volDiff = 0;
239 QuantLib::ext::shared_ptr<FxEqOptionHelper> eqoption = QuantLib::ext::dynamic_pointer_cast<FxEqOptionHelper>(basket[j]);
240 if (eqoption !=
nullptr && parametrization !=
nullptr && domesticLgm !=
nullptr) {
241 t = domesticLgm->termStructure()->timeFromReference(eqoption->option()->exercise()->date(0));
242 modelSigma = parametrization->sigma(t - 1E-4);
244 marketVol = basket[j]->volatility()->value();
245 modelVol = impliedVolatility(basket[j]);
246 volDiff = modelVol - marketVol;
247 log << std::setw(3) << j << std::setprecision(6) << std::setw(14) << t << std::setw(14) << modelVol
248 << std::setw(14) << marketVol << std::setw(14) << volDiff << std::setw(14) <<
modelValue << std::setw(14)
249 <<
marketValue << std::setw(14) << valueDiff << std::setw(14) << modelSigma <<
"\n";
251 if (parametrization !=
nullptr) {
252 modelSigma = parametrization->sigma(t + 1E-4);
254 log <<
"t >= " << t <<
": eqbsSigma = " << modelSigma <<
"\n";
259 const QuantLib::ext::shared_ptr<CommoditySchwartzParametrization>& parametrization) {
260 std::ostringstream
log;
261 log << std::right << std::setw(3) <<
"#" << std::setw(14) <<
"time" << std::setw(14) <<
"modelVol" << std::setw(14)
262 <<
"marketVol" << std::setw(14) <<
"(diff)" << std::setw(14) <<
"modelValue" << std::setw(14) <<
"marketValue"
263 << std::setw(14) <<
"(diff)" << std::setw(14) <<
"Sigma" << setw(14) <<
"Kappa\n";
265 Real modelSigma = parametrization->sigmaParameter();
266 Real modelKappa = parametrization->kappaParameter();
267 for (Size j = 0; j < basket.size(); j++) {
271 Volatility modelVol = 0, marketVol = 0, volDiff = 0;
272 QuantLib::ext::shared_ptr<FutureOptionHelper> option = QuantLib::ext::dynamic_pointer_cast<FutureOptionHelper>(basket[j]);
273 if (option !=
nullptr && parametrization !=
nullptr) {
274 t = option->priceCurve()->timeFromReference(option->option()->exercise()->date(0));
277 marketVol = basket[j]->volatility()->value();
278 modelVol = impliedVolatility(basket[j]);
279 volDiff = modelVol - marketVol;
280 log << std::setw(3) << j << std::setprecision(6) << std::setw(14) << t << std::setw(14) << modelVol
281 << std::setw(14) << marketVol << std::setw(14) << volDiff << std::setw(14) <<
modelValue << std::setw(14)
282 <<
marketValue << std::setw(14) << valueDiff << std::setw(14) << modelSigma <<
" " << modelKappa <<
"\n";
284 if (parametrization !=
nullptr) {
285 modelSigma = parametrization->sigma(t + 1E-4);
287 log <<
"t >= " << t <<
": Sigma = " << modelSigma <<
", Kappa = " << modelKappa <<
"\n";
292 const QuantLib::ext::shared_ptr<InfDkParametrization>& parametrization,
293 bool indexIsInterpolated) {
294 std::ostringstream
log;
295 log << std::right << std::setw(3) <<
"#" << std::setw(14) <<
"time" << std::setw(14) <<
"modelValue"
296 << std::setw(14) <<
"marketValue" << std::setw(14) <<
"(diff)" << std::setw(14) <<
"infdkAlpha" << std::setw(14)
298 Real t = 0.0, modelAlpha = 0.0, modelH = 0.0;
299 for (Size j = 0; j < basket.size(); j++) {
303 QuantLib::ext::shared_ptr<CpiCapFloorHelper> instr = QuantLib::ext::dynamic_pointer_cast<CpiCapFloorHelper>(basket[j]);
304 if (instr !=
nullptr && parametrization !=
nullptr) {
306 t = inflationYearFraction(
307 parametrization->termStructure()->frequency(), indexIsInterpolated,
308 parametrization->termStructure()->dayCounter(), parametrization->termStructure()->baseDate(),
309 instr->instrument()->payDate() - parametrization->termStructure()->observationLag());
310 modelAlpha = parametrization->alpha(t - 1.0 / 250.0);
311 modelH = parametrization->H(t - 1.0 / 250.0);
314 log << std::setw(3) << j << std::setprecision(6) << std::setw(14) << t << std::setw(14) <<
modelValue
315 << std::setw(14) <<
marketValue << std::setw(14) << valueDiff << std::setw(14) << modelAlpha
316 << std::setw(14) << modelH <<
"\n";
318 if (parametrization !=
nullptr) {
320 modelAlpha = parametrization->alpha(t + 1.0 / 250.0);
321 modelH = parametrization->H(t + 1.0 / 2500.0);
323 log <<
"t >= " << t <<
": infDkAlpha = " << modelAlpha <<
" infDkH = " << modelH <<
"\n";
328 const vector<QuantLib::ext::shared_ptr<CalibrationHelper>>& idxBasket,
329 const QuantLib::ext::shared_ptr<InfJyParameterization>& p,
bool calibrateRealRateVol) {
332 Real epsTime = 0.0001;
335 if (!rrBasket.empty()) {
338 log <<
"Real rate calibration:\n";
339 log << right << setw(3) <<
"#" << setw(5) <<
"](-" << setw(12) <<
"inst_date" << setw(12) <<
"time" << setw(14)
340 <<
"modelValue" << setw(14) <<
"marketValue" << setw(14) <<
"(diff)" << setw(14) <<
"infJyAlpha" << setw(14)
344 Array times = calibrateRealRateVol ? p->realRate()->parameterTimes(0) : p->realRate()->parameterTimes(1);
345 auto helperValues = jyHelperValues(rrBasket, times);
348 for (
const auto& kv : helperValues) {
350 t = hv.maturity - epsTime;
352 if (helperValues.size() == 1) {
354 }
else if (ctr == helperValues.size() - 1) {
358 auto alpha = p->realRate()->alpha(t);
359 auto h = p->realRate()->H(t);
360 log << setw(3) << ctr++ << setw(5) << bound << setw(6) << io::iso_date(kv.first) << setprecision(6)
361 << setw(12) << hv.maturity << setw(14) << hv.modelValue << setw(14) << hv.marketValue << setw(14)
362 << hv.error << setw(14) << alpha << setw(14) << h <<
"\n";
367 if (!idxBasket.empty()) {
370 log <<
"Inflation index calibration:\n";
371 log << right << setw(3) <<
"#" << setw(5) <<
"](-" << setw(12) <<
"inst_date" << setw(12) <<
"time" << setw(14)
372 <<
"modelValue" << setw(14) <<
"marketValue" << setw(14) <<
"(diff)" << setw(14) <<
"infJySigma\n";
375 Array times = p->index()->parameterTimes(0);
376 auto helperValues = jyHelperValues(idxBasket, times);
379 for (
const auto& kv : helperValues) {
381 t = hv.maturity - epsTime;
383 if (helperValues.size() == 1) {
385 }
else if (ctr == helperValues.size() - 1) {
389 auto sigma = p->index()->sigma(t);
390 log << setw(3) << ctr++ << setw(5) << bound << setw(6) << io::iso_date(kv.first) << setprecision(6)
391 << setw(12) << hv.maturity << setw(14) << hv.modelValue << setw(14) << hv.marketValue << setw(14)
392 << hv.error << setw(14) << sigma <<
"\n";
400 std::ostringstream
log;
402 log << right << setw(3) <<
"#" << setw(14) <<
"time" << setw(14) <<
"irlgm1fAlpha" << setw(14)
403 <<
"irlgm1fHwSigma\n";
406 for (; j < parametrization->parameterTimes(0).
size(); ++j) {
407 t = parametrization->parameterTimes(0)[j];
408 Real alpha = parametrization->alpha(t - 1E-4);
409 Real sigma = parametrization->hullWhiteSigma(t - 1E-4);
410 log << setw(3) << j << setprecision(6) << setw(14) << t << setw(14) << alpha << setw(14) << sigma <<
"\n";
412 log << setw(3) << j << setprecision(6) << setw(14) << (std::to_string(t) +
"+") << setw(14)
413 << parametrization->alpha(t + 1E-4) << setw(14) << parametrization->hullWhiteSigma(t + 1E-4) <<
"\n";
415 log << right << setw(3) <<
"#" << setw(14) <<
"time" << setw(14) <<
"irlgm1fKappa" << setw(14) <<
"irlgm1fH\n";
418 for (; j < parametrization->parameterTimes(1).
size(); ++j) {
419 t = parametrization->parameterTimes(0)[j];
420 Real kappa = parametrization->kappa(t - 1E-4);
421 Real H = parametrization->H(t - 1E-4);
422 log << setw(3) << j << setprecision(6) << setw(14) << t << setw(14) << kappa << setw(14) << H <<
"\n";
424 log << setw(3) << j << setprecision(6) << setw(14) << (std::to_string(t) +
"+") << setw(14)
425 << parametrization->kappa(t + 1E-4) << setw(14) << parametrization->H(t + 1E-4) <<
"\n";
432struct MaturityGetter : boost::static_visitor<Date> {
434 MaturityGetter(
const Calendar& calendar,
const Date& referenceDate)
437 Date operator()(
const Date& d)
const {
return d; }
439 Date operator()(
const Period& p)
const {
return calendar.advance(referenceDate, p); }
454 const QuantLib::ext::shared_ptr<ZeroInflationTermStructure>& curve,
455 const QuantLib::Date& optionMaturityDate) {
456 if (
auto abs = QuantLib::ext::dynamic_pointer_cast<AbsoluteStrike>(strike)) {
457 return abs->strike();
458 }
else if (
auto atm = QuantLib::ext::dynamic_pointer_cast<AtmStrike>(strike)) {
459 QL_REQUIRE(atm->atmType() == DeltaVolQuote::AtmFwd,
460 "only atm forward allowed as atm strike for cpi cap floors");
461 return curve->zeroRate(optionMaturityDate);
463 QL_FAIL(
"cpi cap floor strike type not supported, expected absolute strike or atm fwd strike, got '"
464 << strike->toString());
469 const QuantLib::ext::shared_ptr<YoYInflationTermStructure>& curve,
470 const QuantLib::Date& optionMaturityDate) {
471 if (
auto abs = QuantLib::ext::dynamic_pointer_cast<AbsoluteStrike>(strike)) {
472 return abs->strike();
473 }
else if (
auto atm = QuantLib::ext::dynamic_pointer_cast<AtmStrike>(strike)) {
474 QL_REQUIRE(atm->atmType() == DeltaVolQuote::AtmFwd,
475 "only atm forward allowed as atm strike for cpi cap floors");
476 return curve->yoyRate(optionMaturityDate);
478 QL_FAIL(
"yoy cap floor strike type not supported, expected absolute strike or atm fwd strike, got '"
479 << strike->toString());
483Real
atmForward(
const Real s0,
const Handle<YieldTermStructure>& r,
const Handle<YieldTermStructure>& q,
const Real t) {
484 return s0 * q->discount(t) / r->discount(t);
Classes and functions for log message handling.
Shared utilities for model building and calibration.
RandomVariable log(RandomVariable x)
RandomVariable abs(RandomVariable x)
Real yoyCapFloorStrikeValue(const QuantLib::ext::shared_ptr< BaseStrike > &strike, const QuantLib::ext::shared_ptr< YoYInflationTermStructure > &curve, const QuantLib::Date &optionMaturityDate)
Return a yoy cap/floor strike value, the input strike can be of type absolute or atm forward.
Size size(const ValueType &v)
Real atmForward(const Real s0, const Handle< YieldTermStructure > &r, const Handle< YieldTermStructure > &q, const Real t)
helper function that computes the atm forward
Date optionMaturity(const boost::variant< Date, Period > &maturity, const QuantLib::Calendar &calendar, const QuantLib::Date &referenceDate)
std::string getCalibrationDetails(LgmCalibrationInfo &info, const std::vector< QuantLib::ext::shared_ptr< BlackCalibrationHelper > > &basket, const QuantLib::ext::shared_ptr< IrLgm1fParametrization > ¶metrization)
Real cpiCapFloorStrikeValue(const QuantLib::ext::shared_ptr< BaseStrike > &strike, const QuantLib::ext::shared_ptr< ZeroInflationTermStructure > &curve, const QuantLib::Date &optionMaturityDate)
Return a cpi cap/floor strike value, the input strike can be of type absolute or atm forward.
Serializable Credit Default Swap.
std::vector< LgmCalibrationData > lgmCalibrationData