1268 {
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284 std::map<std::pair<std::string, std::string>,
1285 std::tuple<Handle<QuantExt::CorrelationTermStructure>, Period, Period>>
1286 tmpCorrelations;
1290
1291
1292 if (firstEntry.first == secondEntry.first)
1293 continue;
1294 auto e = tmpCorrelations.find(std::make_pair(firstEntry.first, secondEntry.first));
1295 if (e == tmpCorrelations.end() ||
1296 (firstEntry.second > std::get<1>(e->second) && secondEntry.second > std::get<2>(e->second))) {
1297 tmpCorrelations[std::make_pair(firstEntry.first, secondEntry.first)] =
1298 std::make_tuple(c.second, firstEntry.second, secondEntry.second);
1299 }
1300 }
1301
1302 map<CorrelationKey, Handle<Quote>> camCorrelations;
1303 for (auto const& c : tmpCorrelations) {
1306
1307
1309 if (f_1.type == CrossAssetModel::AssetType::INF)
1310 f_1.index = 1;
1311 if (f_2.type == CrossAssetModel::AssetType::INF)
1312 f_2.index = 1;
1313 }
1314 auto q = Handle<Quote>(QuantLib::ext::make_shared<CorrelationValue>(std::get<0>(c.second), 0.0));
1315 camCorrelations[std::make_pair(f_1, f_2)] = q;
1316 DLOG(
"added correlation for " << c.first.first <<
"/" << c.first.second <<
": " << q->value());
1317 }
1318
1319
1320
1321 std::set<CorrelationFactor> allCorrRiskFactors;
1322
1330 allCorrRiskFactors.insert({CrossAssetModel::AssetType::IR, ccy, 0});
1331
1332 for (auto const& c1 : allCorrRiskFactors) {
1333 for (auto const& c2 : allCorrRiskFactors) {
1334
1335 Size nf_1 = c1.type == CrossAssetModel::AssetType::INF &&
infModelType_ ==
"JY" ? 2 : 1;
1336 Size nf_2 = c2.type == CrossAssetModel::AssetType::INF &&
infModelType_ ==
"JY" ? 2 : 1;
1337 for (Size k = 0; k < nf_1; ++k) {
1338 for (Size l = 0; l < nf_2; ++l) {
1339 auto f_1 = c1;
1340 auto f_2 = c2;
1341 f_1.index = k;
1342 f_2.index = l;
1343 if (f_1 == f_2)
1344 continue;
1345
1348 std::set<std::string> lookupnames1, lookupnames2;
1349 lookupnames1.insert(s_1);
1350 lookupnames2.insert(s_2);
1351 if (k == 0)
1352 lookupnames1.insert(s_1.substr(0, s_1.size() - 2));
1353 if (l == 0)
1354 lookupnames2.insert(s_2.substr(0, s_2.size() - 2));
1355 for (auto const& l1 : lookupnames1) {
1356 for (auto const& l2 : lookupnames2) {
1358 "Correlation",
1360 false);
1361 !overwrite.empty()) {
1362 camCorrelations[std::make_pair(f_1, f_2)] =
1363 Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(
parseReal(overwrite)));
1364 }
1365 }
1366 }
1367 }
1368 }
1369 }
1370 }
1371
1372
1373
1374
1375
1376 std::vector<QuantLib::ext::shared_ptr<IrModelData>> irConfigs;
1377 std::vector<QuantLib::ext::shared_ptr<InflationModelData>> infConfigs;
1378 std::vector<QuantLib::ext::shared_ptr<FxBsData>> fxConfigs;
1379 std::vector<QuantLib::ext::shared_ptr<EqBsData>> eqConfigs;
1380 std::vector<QuantLib::ext::shared_ptr<CommoditySchwartzData>> comConfigs;
1381
1382
1383
1385 std::vector<Date> calibrationDates;
1386 std::vector<std::string> calibrationExpiries, calibrationTerms;
1387
1390 calibrationDates.push_back(d);
1392
1394 }
1395 }
1396
1397
1398 std::vector<Real> calibrationTimes;
1399 for (Size i = 0; i + 1 < calibrationDates.size(); ++i) {
1400 calibrationTimes.push_back(
modelCurves_.front()->timeFromReference(calibrationDates[i]));
1401 }
1402
1403
1404 for (Size i = 0; i <
modelCcys_.size(); ++i) {
1405 auto config = QuantLib::ext::make_shared<IrLgmData>();
1409 config->calibrateH() = false;
1411 config->hTimes() = std::vector<Real>();
1412 config->shiftHorizon() =
1414 config->scaling() = 1.0;
1416
1417
1421 [&ccy](const std::pair<std::string, QuantLib::ext::shared_ptr<InterestRateIndex>>& index) {
1422 return index.second->currency().code() == ccy;
1424
1425 DLOG(
"set up zero vol IrLgmData for currency '" <<
modelCcys_[i] <<
"'");
1426
1428 config->hValues() = {0.0};
1429 config->calibrateA() = false;
1431 config->aTimes() = std::vector<Real>();
1432 config->aValues() = {0.0};
1433 } else {
1435
1439 config->hValues() = {rev->second};
1440 config->calibrateA() = true;
1442 config->aTimes() = calibrationTimes;
1443 config->aValues() = std::vector<Real>(calibrationTimes.size() + 1, 0.0030);
1444 config->optionExpiries() = calibrationExpiries;
1445 config->optionTerms() = calibrationTerms;
1446 config->optionStrikes() =
1447 std::vector<std::string>(calibrationExpiries.size(), "ATM");
1448 }
1449 irConfigs.push_back(config);
1450 }
1451
1452
1454 QuantLib::ext::shared_ptr<InflationModelData> config;
1456
1457 config = QuantLib::ext::make_shared<InfDkData>(
1462 LgmReversionTransformation(), true);
1463 } else {
1464
1465 QuantLib::ext::shared_ptr<BaseStrike> calibrationStrike;
1468 calibrationStrike = QuantLib::ext::make_shared<AbsoluteStrike>(k->second.front());
1469 } else {
1470 calibrationStrike = QuantLib::ext::make_shared<AtmStrike>(QuantLib::DeltaVolQuote::AtmType::AtmFwd);
1471 }
1472 std::vector<QuantLib::ext::shared_ptr<CalibrationInstrument>> calInstr;
1473 for (auto const& d : calibrationDates)
1474 calInstr.push_back(
1475 QuantLib::ext::make_shared<CpiCapFloor>(QuantLib::CapFloor::Type::Floor, d, calibrationStrike));
1476 std::vector<CalibrationBasket> calBaskets(1, CalibrationBasket(calInstr));
1478
1482 false, "0.0050"));
1483 config = QuantLib::ext::make_shared<InfDkData>(
1488 LgmReversionTransformation(),
1489
1490 true);
1492
1493
1494
1495
1497 Size ccyIndex =
1500 ReversionParameter realRateRev = QuantLib::ext::static_pointer_cast<LgmData>(irConfigs[ccyIndex])->reversionParameter();
1501 VolatilityParameter realRateVol = QuantLib::ext::static_pointer_cast<LgmData>(irConfigs[ccyIndex])->volatilityParameter();
1502 realRateRev.setCalibrate(false);
1503 realRateVol.setCalibrate(false);
1504 Real realRateToNominalRateRatio =
parseReal(
1508 "ScriptedTrade::buildGaussianCam(): internal error, inflation index currency "
1509 <<
modelInfIndices_[i].second->currency().code() <<
" not found in model ccy list.");
1510 realRateVol.mult(realRateToNominalRateRatio);
1511 config = QuantLib::ext::make_shared<InfJyData>(
1513
1514 realRateRev, realRateVol,
1515
1517
1518 LgmReversionTransformation(), CalibrationConfiguration(),
1519
1520 true,
1521
1522 true,
1523
1524 realRateToNominalRateRatio);
1525 } else {
1526 QL_FAIL(
"invalid infModelType '" <<
infModelType_ <<
"', expected DK or JY");
1527 }
1528 }
1529 infConfigs.push_back(config);
1530 }
1531
1532
1533 for (Size i = 1; i <
modelCcys_.size(); ++i) {
1534 auto config = QuantLib::ext::make_shared<FxBsData>();
1537
1538
1539 bool haveFxIndex = false;
1542 haveFxIndex = true;
1543 }
1545 DLOG(
"set up zero vol FxBsData for currency '" <<
modelCcys_[i] <<
"'");
1546
1548 config->calibrateSigma() = false;
1550 config->sigmaTimes() = std::vector<Real>();
1551 config->sigmaValues() = {0.0};
1552 } else {
1554
1556 config->calibrateSigma() = true;
1558 config->sigmaTimes() = calibrationTimes;
1559 config->sigmaValues() = std::vector<Real>(calibrationTimes.size() + 1, 0.10);
1560 config->optionExpiries() = calibrationExpiries;
1561 config->optionStrikes() =
1562 std::vector<std::string>(calibrationExpiries.size(), "ATMF");
1563 }
1564 fxConfigs.push_back(config);
1565 }
1566
1567
1569 auto config = QuantLib::ext::make_shared<EqBsData>();
1571 config->eqName() = eq.eq()->name();
1573 DLOG(
"set up zero vol EqBsData for underlying " << eq.eq()->name());
1574
1576 config->calibrateSigma() = false;
1578 config->sigmaTimes() = std::vector<Real>();
1579 config->sigmaValues() = {0.0};
1580 } else {
1581 DLOG(
"set up EqBsData for underlying '" << eq.eq()->name() <<
"'");
1582
1584 config->calibrateSigma() = true;
1586 config->sigmaTimes() = calibrationTimes;
1587 config->sigmaValues() = std::vector<Real>(calibrationTimes.size() + 1, 0.10);
1588 config->optionExpiries() = calibrationExpiries;
1589 config->optionStrikes() =
1590 std::vector<std::string>(calibrationExpiries.size(), "ATMF");
1591 }
1592 eqConfigs.push_back(config);
1593 }
1594
1595
1596 std::vector<QuantLib::ext::shared_ptr<CrLgmData>> crLgmConfigs;
1597 std::vector<QuantLib::ext::shared_ptr<CrCirData>> crCirConfigs;
1598
1599
1601 auto config = QuantLib::ext::make_shared<CommoditySchwartzData>();
1603 config->name() = comm.commName();
1606 config->calibrateSigma() = false;
1608 config->sigmaValue() = 0.0;
1609 } else {
1611 config->calibrateSigma() = true;
1613 config->sigmaValue() = 0.10;
1614 config->optionExpiries() = calibrationExpiries;
1615 config->optionStrikes() =
1616 std::vector<std::string>(calibrationExpiries.size(), "ATMF");
1617 }
1618 comConfigs.push_back(config);
1619 }
1620
1623 auto discretization =
useCg_ ? CrossAssetModel::Discretization::Euler : CrossAssetModel::Discretization::Exact;
1624 auto camBuilder = QuantLib::ext::make_shared<CrossAssetModelBuilder>(
1626 QuantLib::ext::make_shared<CrossAssetModelData>(irConfigs, fxConfigs, eqConfigs, infConfigs, crLgmConfigs, crCirConfigs,
1628 discretization),
1629 configurationInCcy, configurationXois, configurationXois, configurationInCcy, configurationInCcy,
1631 SalvagingAlgorithm::Spectral, id);
1632
1633
1635 modelCG_ = QuantLib::ext::make_shared<GaussianCamCG>(
1638 camBuilder->model()->discretization() == CrossAssetModel::Discretization::Exact ? 0 :
timeStepsPerYear_,
1639 iborFallbackConfig, std::vector<Size>(), conditionalExpectationModelStates);
1640 } else {
1641 model_ = QuantLib::ext::make_shared<GaussianCam>(
1644 camBuilder->model()->discretization() == CrossAssetModel::Discretization::Exact ? 0 :
timeStepsPerYear_,
1645 iborFallbackConfig, std::vector<Size>(), conditionalExpectationModelStates);
1646 }
1647
1649}
@ Hagan
Parametrize LGM H(t) as H(t) = int_0^t h(s) ds with constant or piecewise h(s)
@ Hagan
Parametrize volatility as Hagan alpha(t)
CorrelationFactor parseCorrelationFactor(const string &name, const char separator)
std::pair< std::string, Period > convertIndexToCamCorrelationEntry(const std::string &i)