48#include <ql/cashflows/capflooredinflationcoupon.hpp>
49#include <ql/cashflows/indexedcashflow.hpp>
50#include <ql/cashflows/overnightindexedcoupon.hpp>
51#include <ql/errors.hpp>
52#include <ql/indexes/ibor/libor.hpp>
53#include <ql/instruments/creditdefaultswap.hpp>
54#include <ql/instruments/forwardrateagreement.hpp>
55#include <ql/instruments/makecapfloor.hpp>
56#include <ql/instruments/makeois.hpp>
57#include <ql/instruments/makevanillaswap.hpp>
58#include <ql/instruments/yearonyearinflationswap.hpp>
59#include <ql/instruments/zerocouponinflationswap.hpp>
60#include <ql/math/solvers1d/newtonsafe.hpp>
61#include <ql/pricingengines/capfloor/bacheliercapfloorengine.hpp>
62#include <ql/pricingengines/capfloor/blackcapfloorengine.hpp>
63#include <ql/pricingengines/credit/midpointcdsengine.hpp>
64#include <ql/pricingengines/swap/discountingswapengine.hpp>
65#include <ql/quotes/derivedquote.hpp>
66#include <ql/termstructures/yield/flatforward.hpp>
67#include <ql/termstructures/yield/oisratehelper.hpp>
70#include <boost/lexical_cast.hpp>
71#include <boost/numeric/ublas/operation.hpp>
72#include <boost/numeric/ublas/vector.hpp>
80using boost::numeric::ublas::element_div;
81using boost::numeric::ublas::element_prod;
88 const QuantLib::Date&
asof,
89 const QuantLib::ext::shared_ptr<ore::analytics::ScenarioSimMarketParameters>& simMarketParams,
91 const std::set<ore::analytics::RiskFactorKey::KeyType>& typesDisabled,
92 const std::set<ore::analytics::RiskFactorKey::KeyType>& parTypes,
93 const std::set<ore::analytics::RiskFactorKey>& relevantRiskFactors,
const bool continueOnError,
94 const string& marketConfiguration,
const QuantLib::ext::shared_ptr<Market>& simMarket)
const {
96 QL_REQUIRE(typesDisabled != parTypes,
"At least one par risk factor type must be enabled "
97 <<
"for a valid ParSensitivityAnalysis.");
105 bool dryRun = simMarket ==
nullptr;
107 Settings::instance().evaluationDate() =
asof;
110 LOG(
"Build par instruments...");
112 auto& parCaps_ = instruments.
parCaps_;
127 const QuantLib::ext::shared_ptr<Conventions>& conventions = InstrumentConventions::instance().conventions();
128 QL_REQUIRE(conventions !=
nullptr,
"conventions are empty");
133 LOG(
"ParSensitivityAnalysis: Discount curve par instruments");
135 string ccy = c.first;
136 QL_REQUIRE(simMarket || yieldCurvePillars_.find(ccy) == yieldCurvePillars_.end(),
137 "duplicate entry in yieldCurvePillars '" << ccy <<
"'");
139 *QuantLib::ext::dynamic_pointer_cast<SensitivityScenarioData::CurveShiftParData>(c.second);
140 LOG(
"ParSensitivityAnalysis: Discount curve ccy=" << ccy);
141 Size n_ten =
data.shiftTenors.size();
142 QL_REQUIRE(
data.parInstruments.size() == n_ten,
143 "number of tenors does not match number of discount curve par instruments, "
144 <<
data.parInstruments.size() <<
" vs. " << n_ten <<
" ccy=" << ccy
145 <<
", check sensitivity configuration.");
146 for (Size j = 0; j < n_ten; ++j) {
148 if (!dryRun && !relevantRiskFactors.empty() &&
149 relevantRiskFactors.find(key) == relevantRiskFactors.end())
151 Period term =
data.shiftTenors[j];
152 string instType =
data.parInstruments[j];
153 bool singleCurve =
data.parInstrumentSingleCurve;
154 string indexName =
"";
155 string yieldCurveName =
"";
156 string equityForecastCurveName =
"";
157 std::pair<QuantLib::ext::shared_ptr<Instrument>, Date> ret;
158 bool recognised =
true, skipped =
false;
160 map<string, string> conventionsMap =
data.parInstrumentConventions;
161 QL_REQUIRE(conventionsMap.find(instType) != conventionsMap.end(),
162 "conventions not found for ccy " << ccy <<
" and instrument type " << instType);
163 QuantLib::ext::shared_ptr<Convention> convention = conventions->get(conventionsMap[instType]);
164 QL_REQUIRE(convention !=
nullptr,
"convention is empty");
165 if (instType ==
"IRS")
166 ret =
makeSwap(simMarket, ccy, indexName, yieldCurveName, equityForecastCurveName, term,
167 convention, singleCurve, parHelperDependencies_[key],
169 else if (instType ==
"DEP")
170 ret =
makeDeposit(
asof, simMarket, ccy, indexName, yieldCurveName, equityForecastCurveName,
171 term, convention, marketConfiguration);
172 else if (instType ==
"FRA")
173 ret =
makeFRA(
asof, simMarket, ccy, indexName, yieldCurveName, equityForecastCurveName, term,
174 convention, marketConfiguration);
175 else if (instType ==
"OIS")
176 ret =
makeOIS(simMarket, ccy, indexName, yieldCurveName, equityForecastCurveName, term,
177 convention, singleCurve, parHelperDependencies_[key],
179 else if (instType ==
"XBS") {
180 string otherCurrency =
181 data.otherCurrency.empty() ? simMarketParams->baseCcy() :
data.otherCurrency;
184 marketConfiguration);
185 }
else if (instType ==
"FXF")
186 ret =
makeFxForward(simMarket, simMarketParams->baseCcy(), ccy, term, convention,
187 parHelperDependencies_[key], marketConfiguration);
188 else if (instType ==
"TBS")
189 ret =
makeTenorBasisSwap(
asof, simMarket, ccy,
"",
"",
"",
"", term, convention, singleCurve,
191 data.discountCurve, marketConfiguration);
194 }
catch (
const std::exception& e) {
196 if (continueOnError) {
198 "Skipping par instrument for discount curve " + ccy, e.what())
205 QL_FAIL(
"Instrument type " << instType <<
" for par sensitivity conversion not recognised");
207 parHelpers_[key] = ret.first;
209 yieldCurvePillars_[ccy].push_back((ret.second -
asof) * Days);
211 DLOG(
"Par instrument for discount curve, ccy " << ccy <<
" tenor " << j <<
", type " << instType
220 LOG(
"ParSensitivityAnalysis: Yield curve par instruments");
222 QL_REQUIRE(simMarketParams->yieldCurveNames().size() == simMarketParams->yieldCurveCurrencies().size(),
223 "vector size mismatch in sim market parameters yield curve names/currencies");
225 string curveName = y.first;
226 QL_REQUIRE(simMarket || yieldCurvePillars_.find(curveName) == yieldCurvePillars_.end(),
227 "duplicate entry in yieldCurvePillars '" << curveName <<
"'");
228 string equityForecastCurveName =
"";
230 for (Size j = 0; j < simMarketParams->yieldCurveNames().
size(); ++j) {
231 if (curveName == simMarketParams->yieldCurveNames()[j])
232 ccy = simMarketParams->yieldCurveCurrencies().at(curveName);
234 LOG(
"ParSensitivityAnalysis: yield curve name " << curveName);
235 QL_REQUIRE(ccy !=
"",
"yield curve currency not found for yield curve " << curveName);
237 *QuantLib::ext::static_pointer_cast<SensitivityScenarioData::CurveShiftParData>(y.second);
238 Size n_ten =
data.shiftTenors.size();
239 QL_REQUIRE(
data.parInstruments.size() == n_ten,
240 "number of tenors does not match number of yield curve par instruments");
241 for (Size j = 0; j < n_ten; ++j) {
243 if (!dryRun && !relevantRiskFactors.empty() &&
244 relevantRiskFactors.find(key) == relevantRiskFactors.end())
246 Period term =
data.shiftTenors[j];
247 string instType =
data.parInstruments[j];
248 bool singleCurve =
data.parInstrumentSingleCurve;
249 std::pair<QuantLib::ext::shared_ptr<Instrument>, Date> ret;
250 bool recognised =
true, skipped =
false;
252 map<string, string> conventionsMap =
data.parInstrumentConventions;
253 QL_REQUIRE(conventionsMap.find(instType) != conventionsMap.end(),
254 "conventions not found for ccy " << ccy <<
" and instrument type " << instType);
255 QuantLib::ext::shared_ptr<Convention> convention = conventions->get(conventionsMap[instType]);
257 if (instType ==
"IRS")
258 ret =
makeSwap(simMarket, ccy,
"", curveName, equityForecastCurveName, term, convention,
260 data.discountCurve, marketConfiguration);
261 else if (instType ==
"DEP")
262 ret =
makeDeposit(
asof, simMarket, ccy,
"", curveName, equityForecastCurveName, term,
263 convention, marketConfiguration);
264 else if (instType ==
"FRA")
265 ret =
makeFRA(
asof, simMarket, ccy,
"", curveName, equityForecastCurveName, term, convention,
266 marketConfiguration);
267 else if (instType ==
"OIS")
268 ret =
makeOIS(simMarket, ccy,
"", curveName, equityForecastCurveName, term, convention,
270 data.discountCurve, marketConfiguration);
271 else if (instType ==
"TBS")
273 singleCurve, parHelperDependencies_[key],
275 marketConfiguration);
276 else if (instType ==
"XBS") {
277 string otherCurrency =
278 data.otherCurrency.empty() ? simMarketParams->baseCcy() :
data.otherCurrency;
281 marketConfiguration);
284 }
catch (
const std::exception& e) {
286 if (continueOnError) {
288 "Skipping par instrument for " + curveName, e.what())
295 QL_FAIL(
"Instrument type " << instType <<
" for par sensitivity conversion unexpected");
297 parHelpers_[key] = ret.first;
299 yieldCurvePillars_[curveName].push_back((ret.second -
asof) * Days);
301 DLOG(
"Par instrument for yield curve, ccy " << ccy <<
" tenor " << j <<
", type " << instType
310 LOG(
"ParSensitivityAnalysis: Index curve par instruments");
313 string indexName = index.first;
314 QL_REQUIRE(simMarket || yieldCurvePillars_.find(indexName) == yieldCurvePillars_.end(),
315 "duplicate entry in yieldCurvePillars '" << indexName <<
"'");
317 *QuantLib::ext::static_pointer_cast<SensitivityScenarioData::CurveShiftParData>(index.second);
318 Size n_ten =
data.shiftTenors.size();
319 QL_REQUIRE(
data.parInstruments.size() == n_ten,
320 indexName <<
" number of tenors " << n_ten <<
"does not match number of index curve par instruments"
321 <<
data.parInstruments.size());
322 vector<string> tokens;
323 boost::split(tokens, indexName, boost::is_any_of(
"-"));
324 QL_REQUIRE(tokens.size() >= 2,
"index name " << indexName <<
" unexpected");
325 string ccy = tokens[0];
326 QL_REQUIRE(ccy.length() == 3,
"currency token not recognised");
327 for (Size j = 0; j < n_ten; ++j) {
329 if (!dryRun && !relevantRiskFactors.empty() &&
330 relevantRiskFactors.find(key) == relevantRiskFactors.end())
332 Period term =
data.shiftTenors[j];
333 string instType =
data.parInstruments[j];
334 bool singleCurve =
data.parInstrumentSingleCurve;
335 string yieldCurveName =
"";
336 string equityForecastCurveName =
"";
337 std::pair<QuantLib::ext::shared_ptr<Instrument>, Date> ret;
338 bool recognised =
true, skipped =
false;
340 map<string, string> conventionsMap =
data.parInstrumentConventions;
341 QL_REQUIRE(conventionsMap.find(instType) != conventionsMap.end(),
342 "conventions not found for ccy " << ccy <<
" and instrument type " << instType);
343 QuantLib::ext::shared_ptr<Convention> convention = conventions->get(conventionsMap[instType]);
345 if (instType ==
"IRS")
346 ret =
makeSwap(simMarket, ccy, indexName, yieldCurveName, equityForecastCurveName, term,
347 convention, singleCurve, parHelperDependencies_[key],
349 else if (instType ==
"DEP")
350 ret =
makeDeposit(
asof, simMarket, ccy, indexName, yieldCurveName, equityForecastCurveName,
351 term, convention, marketConfiguration);
352 else if (instType ==
"FRA")
353 ret =
makeFRA(
asof, simMarket, ccy, indexName, yieldCurveName, equityForecastCurveName, term,
354 convention, marketConfiguration);
355 else if (instType ==
"OIS")
356 ret =
makeOIS(simMarket, ccy, indexName, yieldCurveName, equityForecastCurveName, term,
357 convention, singleCurve, parHelperDependencies_[key],
359 else if (instType ==
"TBS")
360 ret =
makeTenorBasisSwap(
asof, simMarket, ccy,
"",
"",
"",
"", term, convention, singleCurve,
362 data.discountCurve, marketConfiguration);
365 }
catch (
const std::exception& e) {
367 if (continueOnError) {
369 "Skipping par instrument for index curve " + indexName,
377 QL_FAIL(
"Instrument type " << instType <<
" for par sensitivity conversion not recognised");
379 parHelpers_[key] = ret.first;
381 yieldCurvePillars_[indexName].push_back((ret.second -
asof) * Days);
383 DLOG(
"Par instrument for index " << indexName <<
" ccy " << ccy <<
" tenor " << j <<
" built.");
392 LOG(
"ParSensitivityAnalysis: Cap/Floor par instruments");
395 string key = c.first;
396 auto datap = QuantLib::ext::dynamic_pointer_cast<SensitivityScenarioData::CapFloorVolShiftParData>(c.second);
397 string expDiscountCurve = datap ? datap->discountCurve :
"";
399 string indexName =
data.indexName;
401 Handle<YieldTermStructure> yts;
402 Handle<OptionletVolatilityStructure> ovs;
403 Size n_strikes =
data.shiftStrikes.size();
404 Size n_expiries =
data.shiftExpiries.size();
407 bool isAtm =
data.shiftStrikes.size() == 1 &&
data.shiftStrikes[0] == 0.0 &&
data.isRelative;
409 for (Size j = 0; j < n_strikes; ++j) {
410 Real strike =
data.shiftStrikes[j];
411 for (Size k = 0; k < n_expiries; ++k) {
413 if (!dryRun && !relevantRiskFactors.empty() &&
414 relevantRiskFactors.find(rfkey) == relevantRiskFactors.end())
417 if (simMarket !=
nullptr) {
418 yts = expDiscountCurve.empty() ? simMarket->discountCurve(ccy, marketConfiguration)
419 : simMarket->iborIndex(expDiscountCurve, marketConfiguration)
420 ->forwardingTermStructure();
421 ovs = simMarket->capFloorVol(key, marketConfiguration);
423 Period term =
data.shiftExpiries[k];
424 auto tmp =
makeCapFloor(simMarket, ccy, indexName, term, strike, isAtm,
425 parHelperDependencies_[rfkey], expDiscountCurve, marketConfiguration);
426 parCaps_[rfkey] = tmp;
427 parCapsYts_[rfkey] = yts;
428 parCapsVts_[rfkey] = ovs;
430 capFloorPillars_[key].push_back(term);
431 DLOG(
"Par cap/floor for key " << rfkey <<
" strike " << j <<
" tenor " << k <<
" built.");
432 }
catch (
const std::exception& e) {
433 if (continueOnError) {
435 "Skipping par cap/floor for key " + key, e.what())
449 LOG(
"ParSensitivityAnalysis: CDS par instruments");
451 string name = c.first;
455 "creditCurveShiftData not found for " <<
name);
457 *QuantLib::ext::static_pointer_cast<SensitivityScenarioData::CurveShiftParData>(c.second);
458 Size n_expiries =
data.shiftTenors.size();
459 for (Size k = 0; k < n_expiries; ++k) {
460 string instType =
data.parInstruments[k];
462 if (!dryRun && !relevantRiskFactors.empty() &&
463 relevantRiskFactors.find(key) == relevantRiskFactors.end())
465 Period term =
data.shiftTenors[k];
466 std::pair<QuantLib::ext::shared_ptr<Instrument>, Date> ret;
467 bool skipped =
false;
469 map<string, string> conventionsMap =
data.parInstrumentConventions;
470 QL_REQUIRE(conventionsMap.find(instType) != conventionsMap.end(),
471 "conventions not found for name " <<
name <<
" and instrument type " << instType);
472 QuantLib::ext::shared_ptr<Convention> convention = conventions->get(conventionsMap[instType]);
474 ret =
makeCDS(simMarket,
name, ccy, term, convention, parHelperDependencies_[key],
475 data.discountCurve, marketConfiguration);
476 }
catch (
const std::exception& e) {
478 if (continueOnError) {
480 "Skipping par instrument for cds " +
name, e.what())
487 parHelpers_[key] = ret.first;
489 cdsPillars_[
name].push_back((ret.second -
asof) * Days);
491 DLOG(
"Par CDS for name " <<
name <<
" tenor " << k <<
" built.");
499 LOG(
"ParSensitivityAnalysis: ZCI curve par instruments");
502 string indexName = z.first;
504 *QuantLib::ext::static_pointer_cast<SensitivityScenarioData::CurveShiftParData>(z.second);
505 Size n_ten =
data.shiftTenors.size();
506 for (Size j = 0; j < n_ten; ++j) {
508 if (!dryRun && !relevantRiskFactors.empty() &&
509 relevantRiskFactors.find(key) == relevantRiskFactors.end())
511 Period term =
data.shiftTenors[j];
512 string instType =
data.parInstruments[j];
513 bool singleCurve =
data.parInstrumentSingleCurve;
515 map<string, string> conventionsMap =
data.parInstrumentConventions;
516 QL_REQUIRE(conventionsMap.find(instType) != conventionsMap.end(),
517 "conventions not found for zero inflation curve " << indexName <<
" and instrument type "
519 QuantLib::ext::shared_ptr<Convention> convention = conventions->get(conventionsMap[instType]);
523 parHelperDependencies_[key],
data.discountCurve, marketConfiguration);
524 auto helper = QuantLib::ext::dynamic_pointer_cast<ZeroCouponInflationSwap>(tmp);
525 QuantLib::ext::shared_ptr<IndexedCashFlow> lastCoupon =
526 QuantLib::ext::dynamic_pointer_cast<IndexedCashFlow>(
helper->inflationLeg().back());
527 Date latestRelevantDate = std::max(
helper->maturityDate(), lastCoupon->fixingDate());
528 zeroInflationPillars_[indexName].push_back((latestRelevantDate -
asof) * Days);
530 parHelpers_[key] = tmp;
531 DLOG(
"Par instrument for zero inflation index " << indexName <<
" tenor " << j <<
" built.");
532 }
catch (
const std::exception& e) {
533 if (continueOnError) {
535 "Skipping par instrument for zero inflation index " + indexName,
549 LOG(
"ParSensitivityAnalysis: YOYI curve par instruments");
551 string indexName = y.first;
553 *QuantLib::ext::static_pointer_cast<SensitivityScenarioData::CurveShiftParData>(y.second);
554 Size n_ten =
data.shiftTenors.size();
555 for (Size j = 0; j < n_ten; ++j) {
556 Period term =
data.shiftTenors[j];
557 string instType =
data.parInstruments[j];
558 bool singleCurve =
data.parInstrumentSingleCurve;
561 bool recognised =
true;
563 map<string, string> conventionsMap =
data.parInstrumentConventions;
564 QL_REQUIRE(conventionsMap.find(instType) != conventionsMap.end(),
565 "conventions not found for zero inflation curve " << indexName <<
" and instrument type "
567 QuantLib::ext::shared_ptr<Convention> convention = conventions->get(conventionsMap[instType]);
569 if (instType ==
"ZIS") {
572 parHelperDependencies_[key],
data.discountCurve, marketConfiguration);
573 auto helper = dynamic_pointer_cast<YearOnYearInflationSwap>(tmp);
575 QuantLib::ext::shared_ptr<YoYInflationCoupon> lastCoupon =
576 QuantLib::ext::dynamic_pointer_cast<YoYInflationCoupon>(
helper->yoyLeg().back());
577 Date latestRelevantDate = std::max(
helper->maturityDate(), lastCoupon->fixingDate());
579 parHelpers_[key] = tmp;
580 }
else if (instType ==
"YYS") {
583 parHelperDependencies_[key],
data.discountCurve, marketConfiguration);
584 auto helper = dynamic_pointer_cast<YearOnYearInflationSwap>(tmp);
586 QuantLib::ext::shared_ptr<YoYInflationCoupon> lastCoupon =
587 QuantLib::ext::dynamic_pointer_cast<YoYInflationCoupon>(
helper->yoyLeg().back());
588 Date latestRelevantDate = std::max(
helper->maturityDate(), lastCoupon->fixingDate());
590 parHelpers_[key] = tmp;
593 }
catch (
const std::exception& e) {
594 if (continueOnError) {
596 "Skipping par instrument for yoy index " + indexName, e.what())
603 QL_FAIL(
"Instrument type " << instType <<
" for par sensitivity conversion not recognised");
604 DLOG(
"Par instrument for yoy inflation index " << indexName <<
" tenor " << j <<
" built.");
612 LOG(
"ParSensitivityAnalysis: YOYI Cap/Floor par instruments");
614 string indexName = y.first;
616 *QuantLib::ext::static_pointer_cast<SensitivityScenarioData::CapFloorVolShiftParData>(y.second);
617 Size n_strikes =
data.shiftStrikes.size();
618 Size n_expiries =
data.shiftExpiries.size();
619 bool singleCurve =
data.parInstrumentSingleCurve;
620 for (Size j = 0; j < n_strikes; ++j) {
621 Real strike =
data.shiftStrikes[j];
622 pair<string, Size> key(indexName, j);
623 for (Size k = 0; k < n_expiries; ++k) {
627 bool recognised =
true;
630 instType =
data.parInstruments[j];
631 map<string, string> conventionsMap =
data.parInstrumentConventions;
632 QL_REQUIRE(conventionsMap.find(instType) != conventionsMap.end(),
633 "conventions not found for zero inflation curve "
634 << indexName <<
" and instrument type " << instType);
635 QuantLib::ext::shared_ptr<Convention> convention = conventions->get(conventionsMap[instType]);
636 Period term =
data.shiftExpiries[k];
637 if (instType ==
"ZIS") {
638 makeYoYCapFloor(instruments, simMarket, indexName, term, strike, convention, singleCurve,
639 true,
data.discountCurve, key, marketConfiguration);
640 }
else if (instType ==
"YYS") {
641 makeYoYCapFloor(instruments, simMarket, indexName, term, strike, convention, singleCurve,
642 false,
data.discountCurve, key, marketConfiguration);
646 yoyCapFloorPillars_[indexName].push_back(term);
647 }
catch (
const std::exception& e) {
648 if (continueOnError) {
650 "Par sensitivity conversion",
651 "Skipping par instrument for yoy cap floor index " + indexName, e.what())
658 QL_FAIL(
"Instrument type " << instType <<
" for par sensitivity conversion not recognised");
659 DLOG(
"Par yoy cap/floor for index " << indexName <<
" strike " << j <<
" tenor " << k <<
" built.");
665 LOG(
"Par instrument building done, got " << parHelpers_.size() + parCaps_.size() + parYoYCaps_.size()
670 const QuantLib::ext::shared_ptr<Market>& market,
string ccy,
string indexName,
string yieldCurveName,
671 string equityForecastCurveName, Period term,
const QuantLib::ext::shared_ptr<Convention>& convention,
bool singleCurve,
672 std::set<ore::analytics::RiskFactorKey>& parHelperDependencies_, std::set<std::string>& removeTodaysFixingIndices,
673 const string& expDiscountCurve,
const string& marketConfiguration)
const {
681 QuantLib::ext::shared_ptr<Conventions> conventions = InstrumentConventions::instance().conventions();
682 QuantLib::ext::shared_ptr<IRSwapConvention> conv = QuantLib::ext::dynamic_pointer_cast<IRSwapConvention>(convention);
683 QL_REQUIRE(conv,
"convention not recognised, expected IRSwapConvention");
684 string name = indexName !=
"" ? indexName : conv->indexName();
685 QuantLib::ext::shared_ptr<IborIndex> index;
686 Handle<YieldTermStructure> discountCurve;
687 if (market ==
nullptr) {
690 if (!expDiscountCurve.empty()) {
692 QuantLib::ext::shared_ptr<IborIndex> dummyIndex;
694 auto discountIndex = market->iborIndex(expDiscountCurve, marketConfiguration);
695 discountCurve = discountIndex->forwardingTermStructure();
697 discountCurve = market->yieldCurve(expDiscountCurve, marketConfiguration);
699 }
else if (ccy !=
"")
700 discountCurve = market->discountCurve(ccy, marketConfiguration);
701 else if (yieldCurveName !=
"")
702 discountCurve = market->yieldCurve(yieldCurveName, marketConfiguration);
703 else if (equityForecastCurveName !=
"")
704 discountCurve = market->equityForecastCurve(equityForecastCurveName, marketConfiguration);
706 index = *market->iborIndex(
name, marketConfiguration);
710 discountCurve = index->forwardingTermStructure();
711 else if (yieldCurveName !=
"") {
712 index = index->clone(market->yieldCurve(yieldCurveName, marketConfiguration));
713 discountCurve = market->yieldCurve(yieldCurveName, marketConfiguration);
714 }
else if (ccy !=
"")
715 index = index->clone(market->discountCurve(ccy, marketConfiguration));
716 else if (equityForecastCurveName !=
"") {
717 index = index->clone(market->equityForecastCurve(equityForecastCurveName, marketConfiguration));
718 discountCurve = market->equityForecastCurve(equityForecastCurveName, marketConfiguration);
720 QL_FAIL(
"Discount curve undetermined for Swap (ccy=" << ccy <<
")");
727 QuantLib::ext::shared_ptr<Swap>
helper;
728 Date latestRelevantDate;
730 auto bmaIndex = QuantLib::ext::dynamic_pointer_cast<QuantExt::BMAIndexWrapper>(index);
733 helper = QuantLib::ext::shared_ptr<FixedBMASwap>(
737 QuantLib::ext::shared_ptr<AverageBMACoupon> lastCoupon =
738 QuantLib::ext::dynamic_pointer_cast<AverageBMACoupon>(
helper->leg(1).back());
739 latestRelevantDate = std::max(
helper->maturityDate(), lastCoupon->fixingDates().end()[-2]);
740 }
else if (conv->hasSubPeriod()) {
741 removeTodaysFixingIndices.insert(index->name());
742 auto subPeriodSwap = QuantLib::ext::shared_ptr<SubPeriodsSwap>(
751 latestRelevantDate = subPeriodSwap->maturityDate();
752 QuantLib::ext::shared_ptr<FloatingRateCoupon> lastCoupon =
753 QuantLib::ext::dynamic_pointer_cast<FloatingRateCoupon>(subPeriodSwap->floatLeg().back());
755 if (IborCoupon::Settings::instance().usingAtParCoupons()) {
757 if (QuantLib::ext::dynamic_pointer_cast<QuantExt::SubPeriodsCoupon1>(lastCoupon)) {
758 Date fixingValueDate = index->valueDate(lastCoupon->fixingDate());
759 Date endValueDate = index->maturityDate(fixingValueDate);
760 latestRelevantDate = std::max(latestRelevantDate, endValueDate);
765 Date fixingValueDate = index->valueDate(lastCoupon->fixingDate());
766 Date endValueDate = index->maturityDate(fixingValueDate);
767 latestRelevantDate = std::max(latestRelevantDate, endValueDate);
770 removeTodaysFixingIndices.insert(index->name());
771 helper = QuantLib::ext::shared_ptr<VanillaSwap>(MakeVanillaSwap(term, index, 0.0, 0 * Days)
772 .withSettlementDays(index->fixingDays())
773 .withFixedLegDayCount(conv->fixedDayCounter())
774 .withFixedLegTenor(Period(conv->fixedFrequency()))
775 .withFixedLegConvention(conv->fixedConvention())
776 .withFixedLegTerminationDateConvention(conv->fixedConvention())
777 .withFixedLegCalendar(conv->fixedCalendar())
778 .withFloatingLegCalendar(conv->fixedCalendar()));
779 QuantLib::ext::shared_ptr<IborCoupon> lastCoupon = QuantLib::ext::dynamic_pointer_cast<IborCoupon>(
helper->leg(1).back());
780 latestRelevantDate = std::max(
helper->maturityDate(), lastCoupon->fixingEndDate());
784 QuantLib::ext::shared_ptr<PricingEngine> swapEngine = QuantLib::ext::make_shared<DiscountingSwapEngine>(discountCurve);
785 helper->setPricingEngine(swapEngine);
789 return std::pair<QuantLib::ext::shared_ptr<Instrument>, Date>(
helper, latestRelevantDate);
793 const QuantLib::Date&
asof,
const QuantLib::ext::shared_ptr<Market>& market,
string ccy,
string indexName,
794 string yieldCurveName,
string equityForecastCurveName, Period term,
const QuantLib::ext::shared_ptr<Convention>& convention,
795 const string& marketConfiguration)
const {
801 QuantLib::ext::shared_ptr<Conventions> conventions = InstrumentConventions::instance().conventions();
802 QuantLib::ext::shared_ptr<DepositConvention> conv = QuantLib::ext::dynamic_pointer_cast<DepositConvention>(convention);
803 QL_REQUIRE(conv,
"convention not recognised, expected DepositConvention");
804 QuantLib::ext::shared_ptr<IborIndex> index;
805 if (indexName ==
"" && conv->indexBased()) {
812 }
else if (indexName !=
"") {
813 if (market !=
nullptr) {
814 index = market->iborIndex(indexName, marketConfiguration).currentLink();
819 QuantLib::ext::shared_ptr<Deposit>
helper;
820 if (index !=
nullptr) {
821 helper = QuantLib::ext::make_shared<Deposit>(1.0, 0.0, term, index->fixingDays(), index->fixingCalendar(),
822 index->businessDayConvention(), index->endOfMonth(), index->dayCounter(),
823 asof,
true, 0 * Days);
825 QL_REQUIRE(!conv->indexBased(),
"expected non-index-based deposit convention");
826 helper = QuantLib::ext::make_shared<Deposit>(1.0, 0.0, term, conv->settlementDays(), conv->calendar(),
827 conv->convention(), conv->eom(), conv->dayCounter(),
asof,
true, 0 * Days);
829 RelinkableHandle<YieldTermStructure> engineYts;
830 QuantLib::ext::shared_ptr<PricingEngine> depositEngine = QuantLib::ext::make_shared<DepositEngine>(engineYts);
831 helper->setPricingEngine(depositEngine);
832 if (market !=
nullptr) {
834 engineYts.linkTo(*index->forwardingTermStructure());
835 else if (yieldCurveName !=
"")
836 engineYts.linkTo(*market->yieldCurve(yieldCurveName, marketConfiguration));
837 else if (equityForecastCurveName !=
"")
838 engineYts.linkTo(*market->equityForecastCurve(equityForecastCurveName, marketConfiguration));
840 engineYts.linkTo(*market->discountCurve(ccy, marketConfiguration));
842 QL_FAIL(
"Yield term structure not found for deposit (ccy=" << ccy <<
")");
845 Date latestRelevantDate =
helper->maturityDate();
846 return std::pair<QuantLib::ext::shared_ptr<Instrument>, Date>(
helper, latestRelevantDate);
850 const QuantLib::Date&
asof,
const QuantLib::ext::shared_ptr<Market>& market,
string ccy,
string indexName,
851 string yieldCurveName,
string equityForecastCurveName, Period term,
const QuantLib::ext::shared_ptr<Convention>& convention,
852 const string& marketConfiguration)
const {
856 QuantLib::ext::shared_ptr<Conventions> conventions = InstrumentConventions::instance().conventions();
857 QuantLib::ext::shared_ptr<FraConvention> conv = QuantLib::ext::dynamic_pointer_cast<FraConvention>(convention);
858 QL_REQUIRE(conv,
"convention not recognised, expected FraConvention");
859 string name = indexName !=
"" ? indexName : conv->indexName();
860 QuantLib::ext::shared_ptr<IborIndex> index;
861 if (market !=
nullptr) {
862 index = *market->iborIndex(
name, marketConfiguration);
863 if (indexName ==
"") {
864 if (yieldCurveName !=
"")
865 index = market->iborIndex(
name)->clone(market->yieldCurve(yieldCurveName, marketConfiguration));
866 else if (equityForecastCurveName !=
"")
867 index = market->iborIndex(
name)->clone(
868 market->equityForecastCurve(equityForecastCurveName, marketConfiguration));
870 index = market->iborIndex(
name)->clone(market->discountCurve(ccy, marketConfiguration));
872 QL_FAIL(
"index curve not identified for FRA (ccy=" << ccy <<
")");
877 QuantLib::ext::shared_ptr<IborIndex> fraConvIdx =
879 if (fraConvIdx->tenor() != index->tenor()) {
880 WLOG(
"FRA building - mismatch between input index (" << indexName <<
") and conventions (" << conv->indexName()
881 <<
") - using conventions");
883 QL_REQUIRE((term.units() == Months) || (term.units() == Years),
"term unit must be Months or Years");
884 QL_REQUIRE(fraConvIdx->tenor().units() == Months,
"index tenor unit must be Months (" << fraConvIdx->tenor() <<
")("
885 << term <<
")(" << indexName
886 <<
")(" <<
name <<
")");
887 QL_REQUIRE(term > fraConvIdx->tenor(),
"term must be larger than index tenor");
888 Period startTerm = term - fraConvIdx->tenor();
889 Calendar fraCal = fraConvIdx->fixingCalendar();
890 Date asofadj = fraCal.adjust(
asof);
891 Date todaySpot = fraConvIdx->valueDate(asofadj);
893 fraCal.advance(todaySpot, startTerm, fraConvIdx->businessDayConvention(), fraConvIdx->endOfMonth());
894 Date maturityDate = fraConvIdx->maturityDate(valueDate);
895 Handle<YieldTermStructure> ytsTmp;
896 if (market !=
nullptr) {
898 ytsTmp = market->discountCurve(ccy, marketConfiguration);
899 else if (yieldCurveName !=
"")
900 ytsTmp = market->yieldCurve(yieldCurveName, marketConfiguration);
901 else if (equityForecastCurveName !=
"")
902 ytsTmp = market->equityForecastCurve(equityForecastCurveName, marketConfiguration);
904 ytsTmp = index->forwardingTermStructure();
907 ytsTmp = Handle<YieldTermStructure>(QuantLib::ext::make_shared<FlatForward>(0, NullCalendar(), 0.00, Actual365Fixed()));
908 fraConvIdx = fraConvIdx->clone(ytsTmp);
911 QuantLib::ext::make_shared<QuantLib::ForwardRateAgreement>(fraConvIdx, valueDate, Position::Long, 0.0, 1.0, ytsTmp);
915 return std::pair<QuantLib::ext::shared_ptr<Instrument>, Date>(
helper, maturityDate);
919 const QuantLib::ext::shared_ptr<Market>& market,
string ccy,
string indexName,
string yieldCurveName,
920 string equityForecastCurveName, Period term,
const QuantLib::ext::shared_ptr<Convention>& convention,
bool singleCurve,
921 std::set<ore::analytics::RiskFactorKey>& parHelperDependencies_, std::set<std::string>& removeTodaysFixingIndices,
922 const std::string& expDiscountCurve,
const string& marketConfiguration)
const {
930 QuantLib::ext::shared_ptr<OisConvention> conv = QuantLib::ext::dynamic_pointer_cast<OisConvention>(convention);
931 QL_REQUIRE(conv,
"convention not recognised, expected OisConvention");
932 QuantLib::ext::shared_ptr<IborIndex> index =
parseIborIndex(conv->indexName());
933 if (market ==
nullptr) {
934 if (!expDiscountCurve.empty())
940 indexName !=
"" ? indexName : conv->indexName(), 0);
942 QuantLib::ext::shared_ptr<OvernightIndex> overnightIndexTmp = QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(index);
943 QL_REQUIRE(overnightIndexTmp,
944 "ParSensitivityAnalysis::makeOIS(): expected OIS index, got \"" << conv->indexName() <<
"\"");
946 Handle<YieldTermStructure> indexTs =
947 Handle<YieldTermStructure>(QuantLib::ext::make_shared<FlatForward>(0, NullCalendar(), 0.00, Actual365Fixed()));
948 if (market !=
nullptr) {
950 if (indexName !=
"") {
951 indexTs = market->iborIndex(indexName, marketConfiguration).currentLink()->forwardingTermStructure();
952 }
else if (yieldCurveName !=
"") {
953 indexTs = market->yieldCurve(yieldCurveName, marketConfiguration);
954 }
else if (equityForecastCurveName !=
"") {
955 indexTs = market->equityForecastCurve(equityForecastCurveName, marketConfiguration);
956 }
else if (ccy !=
"") {
957 indexTs = market->discountCurve(ccy, marketConfiguration);
959 QL_FAIL(
"Index curve not identified in ParSensitivityAnalysis::makeOIS");
962 indexTs = market->iborIndex(indexName !=
"" ? indexName : conv->indexName(), marketConfiguration)
964 ->forwardingTermStructure();
967 QuantLib::ext::shared_ptr<OvernightIndex> overnightIndex =
968 QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(overnightIndexTmp->clone(indexTs));
969 removeTodaysFixingIndices.insert(overnightIndex->name());
970 QuantLib::ext::shared_ptr<OvernightIndexedSwap>
helper =
971 MakeOIS(term, overnightIndex, Null<Rate>(), 0 * Days).withTelescopicValueDates(
true);
973 if (market !=
nullptr) {
974 RelinkableHandle<YieldTermStructure> engineYts;
977 engineYts.linkTo(*indexTs);
978 else if (yieldCurveName !=
"")
979 engineYts.linkTo(*market->yieldCurve(yieldCurveName, marketConfiguration));
980 else if (equityForecastCurveName !=
"")
981 engineYts.linkTo(*market->equityForecastCurve(equityForecastCurveName, marketConfiguration));
983 engineYts.linkTo(*market->discountCurve(ccy, marketConfiguration));
985 QL_FAIL(
"discount curve not identified in ParSensitivityAnalysis::makeOIS, single curve (ccy=" << ccy
988 if (!expDiscountCurve.empty()) {
990 auto discountIndex = market->iborIndex(expDiscountCurve, marketConfiguration);
991 engineYts.linkTo(*discountIndex->forwardingTermStructure());
992 }
else if (ccy !=
"")
993 engineYts.linkTo(*market->discountCurve(ccy, marketConfiguration));
994 else if (yieldCurveName !=
"")
995 engineYts.linkTo(*market->yieldCurve(yieldCurveName, marketConfiguration));
996 else if (equityForecastCurveName !=
"")
997 engineYts.linkTo(*market->equityForecastCurve(equityForecastCurveName, marketConfiguration));
999 QL_FAIL(
"discount curve not identified in ParSensitivityAnalysis::makeOIS, multi curve (ccy=" << ccy
1002 QuantLib::ext::shared_ptr<PricingEngine> swapEngine = QuantLib::ext::make_shared<DiscountingSwapEngine>(engineYts);
1003 helper->setPricingEngine(swapEngine);
1007 Date latestRelevantDate =
helper->maturityDate();
1008 return std::pair<QuantLib::ext::shared_ptr<Instrument>, Date>(
helper, latestRelevantDate);
1012 const QuantLib::Date&
asof,
const QuantLib::ext::shared_ptr<Market>& market,
string ccy,
string receiveIndexName,
1013 string payIndexName,
string yieldCurveName,
string equityForecastCurveName, Period term,
1014 const QuantLib::ext::shared_ptr<Convention>& convention,
const bool singleCurve,
1015 std::set<ore::analytics::RiskFactorKey>& parHelperDependencies_, std::set<std::string>& removeTodaysFixingIndices,
1016 const string& expDiscountCurve,
const string& marketConfiguration)
const {
1018 QuantLib::ext::shared_ptr<TenorBasisSwapConvention> conv =
1019 QuantLib::ext::dynamic_pointer_cast<TenorBasisSwapConvention>(convention);
1020 QL_REQUIRE(conv,
"convention not recognised, expected TenorBasisSwapConvention");
1021 Handle<YieldTermStructure> discountCurve, receiveIndexCurve, payIndexCurve;
1022 QuantLib::ext::shared_ptr<IborIndex> payIndex =
parseIborIndex(conv->payIndexName());
1023 QuantLib::ext::shared_ptr<IborIndex> receiveIndex =
parseIborIndex(conv->receiveIndexName());
1024 QuantLib::ext::shared_ptr<OvernightIndex> receiveIndexOn = QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(receiveIndex);
1025 QuantLib::ext::shared_ptr<OvernightIndex> payIndexOn = QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(payIndex);
1027 if (market !=
nullptr) {
1028 if (!expDiscountCurve.empty()) {
1030 auto discountIndex = market->iborIndex(expDiscountCurve, marketConfiguration);
1031 discountCurve = discountIndex->forwardingTermStructure();
1032 }
else if (ccy !=
"")
1033 discountCurve = market->discountCurve(ccy, marketConfiguration);
1034 else if (yieldCurveName !=
"")
1035 discountCurve = market->yieldCurve(yieldCurveName, marketConfiguration);
1036 else if (equityForecastCurveName !=
"")
1037 discountCurve = market->equityForecastCurve(equityForecastCurveName, marketConfiguration);
1039 QL_FAIL(
"tenor basis swap discount curve undetermined");
1042 receiveIndexCurve = discountCurve;
1044 receiveIndexCurve = market
1045 ->iborIndex(receiveIndexName !=
"" ? receiveIndexName : conv->receiveIndexName(),
1046 marketConfiguration)
1047 ->forwardingTermStructure();
1048 payIndexCurve = market->iborIndex(payIndexName !=
"" ? payIndexName : conv->payIndexName(), marketConfiguration)
1049 ->forwardingTermStructure();
1051 payIndex = payIndex->clone(payIndexCurve);
1052 receiveIndex = receiveIndex->clone(receiveIndexCurve);
1054 QuantLib::ext::shared_ptr<Libor> payIndexAsLibor = QuantLib::ext::dynamic_pointer_cast<Libor>(payIndex);
1055 QuantLib::ext::shared_ptr<Libor> receiveIndexAsLibor = QuantLib::ext::dynamic_pointer_cast<Libor>(receiveIndex);
1056 Calendar payIndexCalendar =
1057 payIndexAsLibor !=
nullptr ? payIndexAsLibor->jointCalendar() : payIndex->fixingCalendar();
1058 Calendar receiveIndexCalendar =
1059 receiveIndexAsLibor !=
nullptr ? receiveIndexAsLibor->jointCalendar() : receiveIndex->fixingCalendar();
1060 removeTodaysFixingIndices.insert(receiveIndex->name());
1061 removeTodaysFixingIndices.insert(payIndex->name());
1063 Date settlementDate = payIndexCalendar.advance(payIndexCalendar.adjust(
asof), payIndex->fixingDays() * Days);
1065 bool telescopicValueDates =
true;
1066 QuantLib::ext::shared_ptr<Swap>
helper = QuantLib::ext::make_shared<TenorBasisSwap>(
1067 settlementDate, 1.0, term, payIndex, 0.0, conv->payFrequency(), receiveIndex, 0.0, conv->receiveFrequency(),
1068 DateGeneration::Backward, conv->includeSpread(), conv->spreadOnRec(), conv->subPeriodsCouponType(),
1069 telescopicValueDates);
1071 QuantLib::ext::shared_ptr<IborCoupon> lastCoupon1 =
1072 QuantLib::ext::dynamic_pointer_cast<IborCoupon>(QuantLib::ext::static_pointer_cast<TenorBasisSwap>(
helper)->payLeg().back());
1074 QuantLib::ext::shared_ptr<IborCoupon> lastCoupon2 =
1075 QuantLib::ext::dynamic_pointer_cast<IborCoupon>(QuantLib::ext::static_pointer_cast<TenorBasisSwap>(
helper)->recLeg().back());
1076 if (lastCoupon2 !=
nullptr)
1077 maxDate2 = lastCoupon2->fixingEndDate();
1079 QuantLib::ext::shared_ptr<QuantExt::SubPeriodsCoupon1> lastCoupon2;
1080 if (conv->spreadOnRec())
1081 lastCoupon2 = QuantLib::ext::dynamic_pointer_cast<QuantExt::SubPeriodsCoupon1>(
1082 QuantLib::ext::static_pointer_cast<TenorBasisSwap>(
helper)->payLeg().back());
1084 lastCoupon2 = QuantLib::ext::dynamic_pointer_cast<QuantExt::SubPeriodsCoupon1>(
1085 QuantLib::ext::static_pointer_cast<TenorBasisSwap>(
helper)->recLeg().back());
1086 maxDate2 = receiveIndexCalendar.advance(lastCoupon2->valueDates().back(), conv->receiveFrequency());
1088 Date latestRelevantDate = std::max(
helper->maturityDate(), std::max(lastCoupon1->fixingEndDate(), maxDate2));
1090 if (market !=
nullptr) {
1091 QuantLib::ext::shared_ptr<PricingEngine> swapEngine = QuantLib::ext::make_shared<DiscountingSwapEngine>(discountCurve);
1092 helper->setPricingEngine(swapEngine);
1098 if (!expDiscountCurve.empty())
1105 return std::pair<QuantLib::ext::shared_ptr<Instrument>, Date>(
helper, latestRelevantDate);
1109 const QuantLib::ext::shared_ptr<Market>& market,
string ccy,
string indexName, Period term, Real strike,
bool isAtm,
1110 std::set<ore::analytics::RiskFactorKey>& parHelperDependencies_,
const std::string& expDiscountCurve,
1111 const string& marketConfiguration)
const {
1113 QuantLib::ext::shared_ptr<CapFloor> inst;
1114 auto conventions = InstrumentConventions::instance().conventions();
1118 QuantLib::ext::shared_ptr<IborIndex> index =
parseIborIndex(indexName);
1119 QL_REQUIRE(QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(index) ==
nullptr,
1120 "ParSensitivityAnalysis::makeCapFloor(): OIS indices are not yet supported for par conversion");
1121 inst = MakeCapFloor(CapFloor::Cap, term, index, 0.03);
1124 QuantLib::ext::shared_ptr<IborIndex> index = *market->iborIndex(indexName, marketConfiguration);
1125 QL_REQUIRE(QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(index) ==
nullptr,
1126 "ParSensitivityAnalysis::makeCapFloor(): OIS indices are not yet supported for par conversion");
1127 QL_REQUIRE(index,
"Index not found with name " << indexName);
1128 Handle<YieldTermStructure> discount;
1129 if (expDiscountCurve.empty())
1130 discount = market->discountCurve(ccy, marketConfiguration);
1132 discount = market->iborIndex(expDiscountCurve, marketConfiguration)->forwardingTermStructure();
1133 QL_REQUIRE(!discount.empty(),
"Discount curve not found for cap floor index " << indexName);
1137 inst = MakeCapFloor(CapFloor::Cap, term, index, 0.03);
1138 Rate atmRate = inst->atmRate(**discount);
1141 strike = strike == Null<Real>() ? atmRate : strike;
1142 CapFloor::Type type = strike >= atmRate ? CapFloor::Cap : CapFloor::Floor;
1146 inst = MakeCapFloor(type, term, index, atmRate);
1148 inst = MakeCapFloor(type, term, index, strike);
1150 Handle<OptionletVolatilityStructure> ovs = market->capFloorVol(indexName, marketConfiguration);
1151 QL_REQUIRE(!ovs.empty(),
"Optionlet volatility structure not found for index " << indexName);
1152 QL_REQUIRE(ovs->volatilityType() == ShiftedLognormal || ovs->volatilityType() == Normal,
1153 "Optionlet volatility type " << ovs->volatilityType() <<
" not covered");
1154 QuantLib::ext::shared_ptr<PricingEngine> engine;
1155 if (ovs->volatilityType() == ShiftedLognormal) {
1156 engine = QuantLib::ext::make_shared<BlackCapFloorEngine>(discount, ovs, ovs->displacement());
1158 engine = QuantLib::ext::make_shared<BachelierCapFloorEngine>(discount, ovs);
1160 inst->setPricingEngine(engine);
1169 QL_REQUIRE(inst,
"empty cap/floor par instrument pointer");
1174 const QuantLib::ext::shared_ptr<Market>& market,
string baseCcy,
string ccy, Period term,
1175 const QuantLib::ext::shared_ptr<Convention>& convention, std::set<ore::analytics::RiskFactorKey>& parHelperDependencies_,
1176 std::set<std::string>& removeTodaysFixingIndices,
const string& marketConfiguration)
const {
1178 auto conventions = InstrumentConventions::instance().conventions();
1179 QuantLib::ext::shared_ptr<CrossCcyBasisSwapConvention> conv =
1180 QuantLib::ext::dynamic_pointer_cast<CrossCcyBasisSwapConvention>(convention);
1181 QL_REQUIRE(conv,
"convention not recognised, expected CrossCcyBasisSwapConvention");
1182 QL_REQUIRE(baseCcy == conv->flatIndex()->currency().code() || baseCcy == conv->spreadIndex()->currency().code(),
1183 "base currency " << baseCcy <<
" not covered by convention " << conv->id());
1184 QL_REQUIRE(ccy == conv->flatIndex()->currency().code() || ccy == conv->spreadIndex()->currency().code(),
1185 "currency " << ccy <<
" not covered by convention " << conv->id());
1186 string baseIndexName, indexName;
1187 Period baseIndexTenor, indexTenor;
1188 if (baseCcy == conv->flatIndex()->currency().code()) {
1189 baseIndexName = conv->flatIndexName();
1190 baseIndexTenor = conv->flatTenor();
1191 indexName = conv->spreadIndexName();
1192 indexTenor = conv->spreadTenor();
1194 baseIndexName = conv->spreadIndexName();
1195 baseIndexTenor = conv->spreadTenor();
1196 indexName = conv->flatIndexName();
1197 indexTenor = conv->flatTenor();
1201 Handle<IborIndex> baseIndex, index;
1202 if (market !=
nullptr) {
1203 baseIndex = market->iborIndex(baseIndexName, marketConfiguration);
1204 index = market->iborIndex(indexName, marketConfiguration);
1209 Date today = Settings::instance().evaluationDate();
1212 today = conv->settlementCalendar().adjust(today);
1214 Date start = conv->settlementCalendar().advance(today, conv->settlementDays() * Days, conv->rollConvention());
1215 Date end = conv->settlementCalendar().advance(start, term, conv->rollConvention());
1216 Schedule baseSchedule = MakeSchedule()
1219 .withTenor(baseIndexTenor)
1220 .withCalendar(conv->settlementCalendar())
1221 .withConvention(conv->rollConvention())
1222 .endOfMonth(conv->eom());
1223 Schedule schedule = MakeSchedule()
1226 .withTenor(indexTenor)
1227 .withCalendar(conv->settlementCalendar())
1228 .withConvention(conv->rollConvention())
1229 .endOfMonth(conv->eom());
1230 Real baseNotional = 1.0;
1232 Handle<Quote> fxSpot =
1235 ? market->fxRate(ccy + baseCcy, marketConfiguration)
1236 : Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(1.0));
1237 Real notional = 1.0 / fxSpot->value();
1239 RelinkableHandle<YieldTermStructure> baseDiscountCurve;
1240 RelinkableHandle<YieldTermStructure> discountCurve;
1241 QuantLib::ext::shared_ptr<FxIndex> fxIndex =
1242 QuantLib::ext::make_shared<FxIndex>(
"dummy", conv->settlementDays(), currency, baseCurrency, conv->settlementCalendar(),
1243 fxSpot, discountCurve, baseDiscountCurve);
1244 auto m = [](Real x) {
return 1.0 / x; };
1245 QuantLib::ext::shared_ptr<FxIndex> reversedFxIndex = QuantLib::ext::make_shared<FxIndex>(
1246 "dummyRev", conv->settlementDays(), baseCurrency, currency, conv->settlementCalendar(),
1247 Handle<Quote>(QuantLib::ext::make_shared<DerivedQuote<
decltype(m)>>(fxSpot, m)), baseDiscountCurve, discountCurve);
1251 removeTodaysFixingIndices.insert(baseIndex->name());
1252 removeTodaysFixingIndices.insert(index->name());
1253 QuantLib::ext::shared_ptr<CrossCcySwap>
helper;
1254 bool telescopicValueDates =
true;
1256 if (baseCcy == conv->spreadIndex()->currency().code()) {
1257 if (conv->isResettable() && conv->flatIndexIsResettable()) {
1258 DLOG(
"create resettable xccy par instrument (1), convention " << conv->id());
1259 helper = QuantLib::ext::make_shared<CrossCcyBasisMtMResetSwap>(
1260 baseNotional, baseCurrency, baseSchedule, *baseIndex, 0.0,
1261 currency, schedule, *index, 0.0, reversedFxIndex,
true,
1262 conv->paymentLag(), conv->flatPaymentLag(), conv->includeSpread(), conv->lookback(), conv->fixingDays(),
1263 conv->rateCutoff(), conv->isAveraged(), conv->flatIncludeSpread(), conv->flatLookback(),
1264 conv->flatFixingDays(), conv->flatRateCutoff(), conv->flatIsAveraged(), telescopicValueDates,
1266 }
else if (conv->isResettable() && !conv->flatIndexIsResettable()) {
1267 DLOG(
"create resettable xccy par instrument (2), convention " << conv->id());
1268 helper = QuantLib::ext::make_shared<CrossCcyBasisMtMResetSwap>(
1269 notional, currency, schedule, *index, 0.0,
1270 baseCurrency, baseSchedule, *baseIndex, 0.0, fxIndex,
1272 conv->flatPaymentLag(), conv->paymentLag(), conv->flatIncludeSpread(), conv->flatLookback(),
1273 conv->flatFixingDays(), conv->flatRateCutoff(), conv->flatIsAveraged(), conv->includeSpread(),
1274 conv->lookback(), conv->fixingDays(), conv->rateCutoff(), conv->isAveraged(), telescopicValueDates,
1277 DLOG(
"create non-resettable xccy par instrument (3), convention " << conv->id());
1278 helper = QuantLib::ext::make_shared<CrossCcyBasisSwap>(
1279 baseNotional, baseCurrency, baseSchedule, *baseIndex, 0.0, 1.0,
1280 notional, currency, schedule, *index, 0.0, 1.0,
1281 conv->paymentLag(), conv->flatPaymentLag(), conv->includeSpread(), conv->lookback(), conv->fixingDays(),
1282 conv->rateCutoff(), conv->isAveraged(), conv->flatIncludeSpread(), conv->flatLookback(),
1283 conv->flatFixingDays(), conv->flatRateCutoff(), conv->flatIsAveraged(), telescopicValueDates);
1286 if (conv->isResettable() && conv->flatIndexIsResettable()) {
1287 DLOG(
"create resettable xccy par instrument (4), convention " << conv->id());
1289 helper = QuantLib::ext::make_shared<CrossCcyBasisMtMResetSwap>(
1290 notional, currency, schedule, *index, 0.0,
1291 baseCurrency, baseSchedule, *baseIndex, 0.0, fxIndex,
true,
1292 conv->paymentLag(), conv->flatPaymentLag(), conv->includeSpread(), conv->lookback(), conv->fixingDays(),
1293 conv->rateCutoff(), conv->isAveraged(), conv->flatIncludeSpread(), conv->flatLookback(),
1294 conv->flatFixingDays(), conv->flatRateCutoff(), conv->flatIsAveraged(), telescopicValueDates,
1296 }
else if (conv->isResettable() && !conv->flatIndexIsResettable()) {
1297 DLOG(
"create resettable xccy par instrument (5), convention " << conv->id());
1299 helper = QuantLib::ext::make_shared<CrossCcyBasisMtMResetSwap>(
1300 baseNotional, baseCurrency, baseSchedule, *baseIndex, 0.0,
1301 currency, schedule, *index, 0.0, reversedFxIndex,
1303 conv->flatPaymentLag(), conv->paymentLag(), conv->flatIncludeSpread(), conv->flatLookback(),
1304 conv->flatFixingDays(), conv->flatRateCutoff(), conv->flatIsAveraged(), conv->includeSpread(),
1305 conv->lookback(), conv->fixingDays(), conv->rateCutoff(), conv->isAveraged(), telescopicValueDates,
1308 DLOG(
"create non-resettable xccy par instrument (6), convention " << conv->id());
1309 helper = QuantLib::ext::make_shared<CrossCcyBasisSwap>(
1310 notional, currency, schedule, *index, 0.0, 1.0,
1311 baseNotional, baseCurrency, baseSchedule, *baseIndex, 0.0, 1.0,
1312 conv->paymentLag(), conv->flatPaymentLag(), conv->includeSpread(), conv->lookback(), conv->fixingDays(),
1313 conv->rateCutoff(), conv->isAveraged(), conv->flatIncludeSpread(), conv->flatLookback(),
1314 conv->flatFixingDays(), conv->flatRateCutoff(), conv->flatIsAveraged(), telescopicValueDates);
1318 bool isBaseDiscount =
true;
1319 bool isNonBaseDiscount =
true;
1320 if (market !=
nullptr) {
1321 baseDiscountCurve.linkTo(
xccyYieldCurve(market, baseCcy, isBaseDiscount, marketConfiguration).currentLink());
1322 discountCurve.linkTo(
xccyYieldCurve(market, ccy, isNonBaseDiscount, marketConfiguration).currentLink());
1323 QuantLib::ext::shared_ptr<PricingEngine> swapEngine =
1324 QuantLib::ext::make_shared<CrossCcySwapEngine>(baseCurrency, baseDiscountCurve, currency, discountCurve, fxSpot);
1325 helper->setPricingEngine(swapEngine);
1333 if (isNonBaseDiscount)
1342 Date latestRelevantDate =
helper->maturityDate();
1343 if (
auto i = QuantLib::ext::dynamic_pointer_cast<CrossCcyBasisSwap>(
helper)) {
1344 QuantLib::ext::shared_ptr<IborCoupon> lastCoupon0 =
1345 QuantLib::ext::dynamic_pointer_cast<IborCoupon>(
helper->leg(0)[
helper->leg(0).size() - 2]);
1346 QuantLib::ext::shared_ptr<IborCoupon> lastCoupon1 =
1347 QuantLib::ext::dynamic_pointer_cast<IborCoupon>(
helper->leg(1)[
helper->leg(1).size() - 2]);
1348 if (lastCoupon0 !=
nullptr)
1349 latestRelevantDate = std::max(latestRelevantDate, lastCoupon0->fixingEndDate());
1350 if (lastCoupon1 !=
nullptr)
1351 latestRelevantDate = std::max(latestRelevantDate, lastCoupon1->fixingEndDate());
1355 return std::pair<QuantLib::ext::shared_ptr<Instrument>, Date>(
helper, latestRelevantDate);
1358std::pair<QuantLib::ext::shared_ptr<Instrument>, Date>
1360 Period term,
const QuantLib::ext::shared_ptr<Convention>& convention,
1361 std::set<ore::analytics::RiskFactorKey>& parHelperDependencies_,
1362 const string& marketConfiguration)
const {
1364 QuantLib::ext::shared_ptr<FXConvention> conv = QuantLib::ext::dynamic_pointer_cast<FXConvention>(convention);
1365 QL_REQUIRE(conv,
"convention not recognised, expected FXConvention");
1366 QL_REQUIRE(baseCcy == conv->sourceCurrency().code() || baseCcy == conv->targetCurrency().code(),
1367 "base currency " << baseCcy <<
" not covered by convention " << conv->id());
1368 QL_REQUIRE(ccy == conv->sourceCurrency().code() || ccy == conv->targetCurrency().code(),
1369 "currency " << ccy <<
" not covered by convention " << conv->id());
1372 Date today = Settings::instance().evaluationDate();
1373 Date spot = conv->advanceCalendar().advance(today, conv->spotDays() * Days);
1374 Date
maturity = conv->advanceCalendar().advance(spot, term);
1375 Real baseNotional = 1.0;
1376 Handle<Quote> fxSpot =
1378 ? market->fxRate(ccy + baseCcy, marketConfiguration)
1379 : Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(1.0));
1380 Real notional = 1.0 / fxSpot->value();
1381 QuantLib::ext::shared_ptr<FxForward>
helper =
1382 QuantLib::ext::make_shared<FxForward>(baseNotional, baseCurrency, notional, currency,
maturity,
true);
1384 bool isBaseDiscount =
true;
1385 bool isNonBaseDiscount =
true;
1386 if (market !=
nullptr) {
1387 Handle<YieldTermStructure> baseDiscountCurve =
1388 xccyYieldCurve(market, baseCcy, isBaseDiscount, marketConfiguration);
1389 Handle<YieldTermStructure> discountCurve =
xccyYieldCurve(market, ccy, isNonBaseDiscount, marketConfiguration);
1390 QuantLib::ext::shared_ptr<PricingEngine> engine = QuantLib::ext::make_shared<DiscountingFxForwardEngine>(
1391 baseCurrency, baseDiscountCurve, currency, discountCurve, fxSpot);
1392 helper->setPricingEngine(engine);
1400 if (isNonBaseDiscount)
1407 return std::pair<QuantLib::ext::shared_ptr<Instrument>, Date>(
helper,
maturity);
1410std::pair<QuantLib::ext::shared_ptr<Instrument>, Date>
1412 const QuantLib::ext::shared_ptr<Convention>& convention,
1413 std::set<ore::analytics::RiskFactorKey>& parHelperDependencies_,
1414 const std::string& expDiscountCurve,
const string& marketConfiguration)
const {
1416 QuantLib::ext::shared_ptr<CdsConvention> conv = QuantLib::ext::dynamic_pointer_cast<CdsConvention>(convention);
1417 QL_REQUIRE(conv,
"convention not recognised, expected CdsConvention");
1429 if (market !=
nullptr) {
1430 Handle<YieldTermStructure> yts;
1431 if (!expDiscountCurve.empty()) {
1433 auto discountIndex = market->iborIndex(expDiscountCurve, marketConfiguration);
1434 yts = discountIndex->forwardingTermStructure();
1436 yts = market->discountCurve(ccy, marketConfiguration);
1439 Handle<DefaultProbabilityTermStructure> dpts = market->defaultCurve(
name, marketConfiguration)->curve();
1440 Handle<Quote> recovery = market->recoveryRate(
name, marketConfiguration);
1442 QuantLib::ext::shared_ptr<PricingEngine> cdsEngine =
1443 QuantLib::ext::make_shared<QuantExt::MidPointCdsEngine>(dpts, recovery->value(), yts);
1444 helper->setPricingEngine(cdsEngine);
1451 Date
maturity = conv->calendar().adjust(
helper->maturity(), conv->paymentConvention());
1453 return std::pair<QuantLib::ext::shared_ptr<Instrument>, Date>(
helper,
maturity);
1457 const QuantLib::ext::shared_ptr<Market>& market,
string indexName, Period term,
1458 const QuantLib::ext::shared_ptr<Convention>& convention,
bool singleCurve,
1459 std::set<ore::analytics::RiskFactorKey>& parHelperDependencies_,
const std::string& expDiscountCurve,
1460 const string& marketConfiguration)
const {
1462 QuantLib::ext::shared_ptr<InflationSwapConvention> conv = QuantLib::ext::dynamic_pointer_cast<InflationSwapConvention>(convention);
1463 QL_REQUIRE(conv,
"convention not recognised, expected InflationSwapConvention");
1464 string name = indexName !=
"" ? indexName : conv->indexName();
1465 QuantLib::ext::shared_ptr<ZeroInflationIndex> index = conv->index();
1466 Currency currency = index->currency();
1467 string ccy = currency.code();
1468 Handle<YieldTermStructure> discountCurve;
1469 if (market !=
nullptr) {
1471 index = *market->zeroInflationIndex(
name, marketConfiguration);
1474 if (!expDiscountCurve.empty()) {
1476 auto discountIndex = market->iborIndex(expDiscountCurve, marketConfiguration);
1477 discountCurve = discountIndex->forwardingTermStructure();
1480 discountCurve = market->discountCurve(ccy, marketConfiguration);
1485 Date start = Settings::instance().evaluationDate();
1487 Date end = start + term;
1488 QuantLib::ext::shared_ptr<ZeroCouponInflationSwap>
helper(
new ZeroCouponInflationSwap(
1489 ZeroCouponInflationSwap::Payer, 1.0, start, end, conv->infCalendar(), conv->infConvention(), conv->dayCounter(),
1490 0.0, index, conv->observationLag(), CPI::AsIndex));
1492 if (market !=
nullptr) {
1493 QuantLib::ext::shared_ptr<PricingEngine> swapEngine = QuantLib::ext::make_shared<DiscountingSwapEngine>(discountCurve);
1494 helper->setPricingEngine(swapEngine);
1504 const QuantLib::ext::shared_ptr<Market>& market,
string indexName, Period term,
1505 const QuantLib::ext::shared_ptr<Convention>& convention,
bool singleCurve,
bool fromZero,
1506 std::set<ore::analytics::RiskFactorKey>& parHelperDependencies_,
const std::string& expDiscountCurve,
1507 const string& marketConfiguration)
const {
1509 QuantLib::ext::shared_ptr<InflationSwapConvention> conv = QuantLib::ext::dynamic_pointer_cast<InflationSwapConvention>(convention);
1510 QL_REQUIRE(conv,
"convention not recognised, expected InflationSwapConvention");
1511 string name = indexName !=
"" ? indexName : conv->indexName();
1513 QuantLib::ext::shared_ptr<ZeroInflationIndex> zeroIndex = conv->index();
1514 QuantLib::ext::shared_ptr<YoYInflationIndex> index =
1515 QuantLib::ext::make_shared<QuantExt::YoYInflationIndexWrapper>(zeroIndex, conv->interpolated());
1518 Date start = Settings::instance().evaluationDate();
1520 Date end = start + term;
1521 Period tenor(1, Years);
1522 Schedule fixSchedule = MakeSchedule()
1526 .withCalendar(conv->fixCalendar())
1527 .withConvention(conv->fixConvention());
1528 Schedule yoySchedule = MakeSchedule()
1532 .withCalendar(conv->infCalendar())
1533 .withConvention(conv->infConvention());
1535 Currency currency = index->currency();
1536 string ccy = currency.code();
1537 Handle<YieldTermStructure> discountCurve;
1538 if (market !=
nullptr) {
1542 zeroIndex = *market->zeroInflationIndex(
name, marketConfiguration);
1543 index = QuantLib::ext::make_shared<QuantExt::YoYInflationIndexWrapper>(zeroIndex,
false);
1545 index = *market->yoyInflationIndex(
name, marketConfiguration);
1549 if (!expDiscountCurve.empty()) {
1551 auto discountIndex = market->iborIndex(expDiscountCurve, marketConfiguration);
1552 discountCurve = discountIndex->forwardingTermStructure();
1555 discountCurve = market->discountCurve(ccy, marketConfiguration);
1559 QuantLib::ext::shared_ptr<YearOnYearInflationSwap>
helper(
new YearOnYearInflationSwap(
1560 YearOnYearInflationSwap::Payer, 1.0, fixSchedule, 0.0, conv->dayCounter(), yoySchedule, index,
1561 conv->observationLag(), 0.0, conv->dayCounter(), conv->infCalendar()));
1563 QuantLib::ext::shared_ptr<InflationCouponPricer> yoyCpnPricer = QuantLib::ext::make_shared<YoYInflationCouponPricer>(discountCurve);
1564 for (
auto& c :
helper->yoyLeg()) {
1565 auto cpn = QuantLib::ext::dynamic_pointer_cast<YoYInflationCoupon>(c);
1566 QL_REQUIRE(cpn,
"yoy inflation coupon expected, could not cast");
1567 cpn->setPricer(yoyCpnPricer);
1575 if (market !=
nullptr) {
1576 QuantLib::ext::shared_ptr<PricingEngine> swapEngine = QuantLib::ext::make_shared<DiscountingSwapEngine>(discountCurve);
1577 helper->setPricingEngine(swapEngine);
1583 const QuantLib::ext::shared_ptr<Market>& market,
string indexName,
1584 Period term, Real strike,
1585 const QuantLib::ext::shared_ptr<Convention>& convention,
bool singleCurve,
1586 bool fromZero,
const std::string& expDiscountCurve,
1588 const string& marketConfiguration)
const {
1590 QuantLib::ext::shared_ptr<InflationSwapConvention> conv = QuantLib::ext::dynamic_pointer_cast<InflationSwapConvention>(convention);
1591 QL_REQUIRE(conv,
"convention not recognised, expected InflationSwapConvention");
1592 string name = indexName !=
"" ? indexName : conv->indexName();
1594 QuantLib::ext::shared_ptr<ZeroInflationIndex> zeroIndex = conv->index();
1595 QuantLib::ext::shared_ptr<YoYInflationIndex> index =
1596 QuantLib::ext::make_shared<QuantExt::YoYInflationIndexWrapper>(zeroIndex, conv->interpolated());
1598 Date start = Settings::instance().evaluationDate();
1599 Date end = start + term;
1600 Period tenor(1, Years);
1601 Schedule yoySchedule = MakeSchedule()
1605 .withCalendar(conv->infCalendar())
1606 .withConvention(conv->infConvention());
1608 Currency currency = index->currency();
1609 string ccy = currency.code();
1610 Handle<YieldTermStructure> discountCurve;
1611 if (market !=
nullptr) {
1615 zeroIndex = *market->zeroInflationIndex(
name, marketConfiguration);
1616 index = QuantLib::ext::make_shared<QuantExt::YoYInflationIndexWrapper>(zeroIndex, conv->interpolated());
1618 index = *market->yoyInflationIndex(
name, marketConfiguration);
1622 if (!expDiscountCurve.empty()) {
1624 auto discountIndex = market->iborIndex(expDiscountCurve, marketConfiguration);
1625 discountCurve = discountIndex->forwardingTermStructure();
1628 discountCurve = market->discountCurve(ccy, marketConfiguration);
1633 Leg yoyLeg =
yoyInflationLeg(yoySchedule, yoySchedule.calendar(), index, conv->observationLag())
1638 if (market ==
nullptr)
1641 auto ovs = market->yoyCapFloorVol(
name, marketConfiguration);
1642 QuantLib::ext::shared_ptr<PricingEngine> engine;
1643 if (ovs->volatilityType() == ShiftedLognormal) {
1645 engine = QuantLib::ext::make_shared<QuantExt::YoYInflationBlackCapFloorEngine>(index, ovs, discountCurve);
1648 QuantLib::ext::make_shared<QuantExt::YoYInflationUnitDisplacedBlackCapFloorEngine>(index, ovs, discountCurve);
1650 }
else if (ovs->volatilityType() == Normal) {
1651 engine = QuantLib::ext::make_shared<QuantExt::YoYInflationBachelierCapFloorEngine>(index, ovs, discountCurve);
1653 QL_FAIL(
"ParSensitivityAnalysis::makeYoYCapFloor(): volatility type " << ovs->volatilityType()
1654 <<
" not handled for index " <<
name);
1657 QuantLib::ext::shared_ptr<YoYInflationCapFloor> atmHelper = QuantLib::ext::make_shared<YoYInflationCapFloor>(
1658 YoYInflationCapFloor::Cap, yoyLeg, std::vector<Real>(yoyLeg.size(), strike));
1659 Rate atmRate = atmHelper->atmRate(**discountCurve);
1660 strike = strike == Null<Real>() ? atmRate : strike;
1661 YoYInflationCapFloor::Type type = strike >= atmRate ? YoYInflationCapFloor::Cap : YoYInflationCapFloor::Floor;
1662 auto helper = QuantLib::ext::make_shared<YoYInflationCapFloor>(type, yoyLeg, std::vector<Real>(yoyLeg.size(), strike));
1663 helper->setPricingEngine(engine);
MakeCreditDefaultSwap & withPaysAtDefaultTime(bool)
MakeCreditDefaultSwap & withCouponTenor(Period)
MakeCreditDefaultSwap & withNominal(Real)
MakeCreditDefaultSwap & withDayCounter(const DayCounter &)
MakeCreditDefaultSwap & withDateGenerationRule(DateGeneration::Rule rule)
MakeCreditDefaultSwap & withSettlesAccrual(bool)
MakeFixedBMASwap & withBMALegTenor(const Period &tenor)
MakeSubPeriodsSwap & withFixedLegTenor(const Period &t)
MakeSubPeriodsSwap & withSettlementDays(Natural settlementDays)
MakeSubPeriodsSwap & withFixedLegConvention(BusinessDayConvention bdc)
MakeSubPeriodsSwap & withSubCouponsType(const QuantExt::SubPeriodsCoupon1::Type &st)
MakeSubPeriodsSwap & withFixedLegDayCount(const DayCounter &dc)
MakeSubPeriodsSwap & withFixedLegCalendar(const Calendar &cal)
yoyInflationLeg & withRateCurve(const Handle< YieldTermStructure > &rateCurve)
yoyInflationLeg & withNotionals(Real notional)
yoyInflationLeg & withPaymentDayCounter(const DayCounter &)
std::pair< QuantLib::ext::shared_ptr< QuantLib::Instrument >, Date > makeSwap(const QuantLib::ext::shared_ptr< ore::data::Market > &market, std::string ccy, std::string indexName, std::string yieldCurveName, std::string equityForecastCurveName, QuantLib::Period term, const QuantLib::ext::shared_ptr< ore::data::Convention > &conventions, bool singleCurve, std::set< ore::analytics::RiskFactorKey > &parHelperDependencies, std::set< std::string > &removeTodaysFixingIndices, const std::string &expDiscountCurve="", const std::string &marketConfiguration=ore::data::Market::defaultConfiguration) const
Create Swap for implying par rate sensitivity from zero rate sensitivity.
QuantLib::ext::shared_ptr< QuantLib::CapFloor > makeCapFloor(const QuantLib::ext::shared_ptr< ore::data::Market > &market, std::string ccy, std::string indexName, QuantLib::Period term, double strike, bool generatePillar, std::set< ore::analytics::RiskFactorKey > &parHelperDependencies, const std::string &expDiscountCurve="", const std::string &marketConfiguration=ore::data::Market::defaultConfiguration) const
Create Cap/Floor QuantLib::Instrument for implying flat vol sensitivity from optionlet vol sensitivit...
std::pair< QuantLib::ext::shared_ptr< QuantLib::Instrument >, Date > makeTenorBasisSwap(const QuantLib::Date &asof, const QuantLib::ext::shared_ptr< ore::data::Market > &market, std::string ccy, std::string receiveIndexName, std::string payIndexName, std::string yieldCurveName, std::string equityForecastCurveName, QuantLib::Period term, const QuantLib::ext::shared_ptr< ore::data::Convention > &conventions, const bool singleCurve, std::set< ore::analytics::RiskFactorKey > &parHelperDependencies, std::set< std::string > &removeTodaysFixingIndices, const std::string &expDiscountCurve="", const std::string &marketConfiguration=ore::data::Market::defaultConfiguration) const
Create Basis Swap for implying par rate sensitivity from zero rate sensitivity.
std::pair< QuantLib::ext::shared_ptr< QuantLib::Instrument >, Date > makeCrossCcyBasisSwap(const QuantLib::ext::shared_ptr< ore::data::Market > &market, std::string baseCcy, std::string ccy, QuantLib::Period term, const QuantLib::ext::shared_ptr< ore::data::Convention > &conventions, std::set< ore::analytics::RiskFactorKey > &parHelperDependencies, std::set< std::string > &removeTodaysFixingIndices, const std::string &marketConfiguration=ore::data::Market::defaultConfiguration) const
Create Cross Ccy Basis Swap for implying par rate sensitivity from zero rate sensitivity.
void createParInstruments(ParSensitivityInstrumentBuilder::Instruments &instruments, const QuantLib::Date &asof, const QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarketParameters > &simMarketParams, const ore::analytics::SensitivityScenarioData &sensitivityData, const std::set< ore::analytics::RiskFactorKey::KeyType > &typesDisabled={}, const std::set< ore::analytics::RiskFactorKey::KeyType > &parTypes={}, const std::set< ore::analytics::RiskFactorKey > &relevantRiskFactors={}, const bool continueOnError=false, const std::string &marketConfiguration=ore::data::Market::defaultConfiguration, const QuantLib::ext::shared_ptr< ore::analytics::Market > &simMarket=nullptr) const
Create par QuantLib::Instruments.
void makeYoYCapFloor(ParSensitivityInstrumentBuilder::Instruments &instruments, const QuantLib::ext::shared_ptr< Market > &market, std::string indexName, QuantLib::Period term, double strike, const QuantLib::ext::shared_ptr< ore::data::Convention > &convention, bool singleCurve, bool fromZero, const std::string &expDiscountCurve, const ore::analytics::RiskFactorKey &key, const std::string &marketConfiguration=ore::data::Market::defaultConfiguration) const
Create YoY Cap/Floor for implying rate rate sensitivity from yoy optionlet vol sensitivity.
std::pair< QuantLib::ext::shared_ptr< QuantLib::Instrument >, Date > makeDeposit(const QuantLib::Date &asof, const QuantLib::ext::shared_ptr< ore::data::Market > &market, std::string ccy, std::string indexName, std::string yieldCurveName, std::string equityForecastCurveName, QuantLib::Period term, const QuantLib::ext::shared_ptr< ore::data::Convention > &conventions, const std::string &marketConfiguration=ore::data::Market::defaultConfiguration) const
Create Deposit for implying par rate sensitivity from zero rate sensitivity.
std::pair< QuantLib::ext::shared_ptr< QuantLib::Instrument >, Date > makeFRA(const QuantLib::Date &asof, const QuantLib::ext::shared_ptr< ore::data::Market > &market, std::string ccy, std::string indexName, std::string yieldCurveName, std::string equityForecastCurveName, QuantLib::Period term, const QuantLib::ext::shared_ptr< ore::data::Convention > &conventions, const std::string &marketConfiguration=ore::data::Market::defaultConfiguration) const
Create FRA for implying par rate sensitivity from zero rate sensitivity.
std::pair< QuantLib::ext::shared_ptr< QuantLib::Instrument >, Date > makeOIS(const QuantLib::ext::shared_ptr< ore::data::Market > &market, std::string ccy, std::string indexName, std::string yieldCurveName, std::string equityForecastCurveName, QuantLib::Period term, const QuantLib::ext::shared_ptr< ore::data::Convention > &conventions, bool singleCurve, std::set< ore::analytics::RiskFactorKey > &parHelperDependencies, std::set< std::string > &removeTodaysFixingIndices, const std::string &expDiscountCurve="", const std::string &marketConfiguration=ore::data::Market::defaultConfiguration) const
Create OIS Swap for implying par rate sensitivity from zero rate sensitivity.
QuantLib::ext::shared_ptr< QuantLib::Instrument > makeYoyInflationSwap(const QuantLib::ext::shared_ptr< ore::data::Market > &market, std::string indexName, QuantLib::Period term, const QuantLib::ext::shared_ptr< ore::data::Convention > &conventions, bool singleCurve, bool fromZero, std::set< ore::analytics::RiskFactorKey > &parHelperDependencies, const std::string &expDiscountCurve="", const std::string &marketConfiguration=ore::data::Market::defaultConfiguration) const
Create YoY Swap for implying par rate sensitivity from yoy rate sensitivity.
std::pair< QuantLib::ext::shared_ptr< QuantLib::Instrument >, Date > makeFxForward(const QuantLib::ext::shared_ptr< ore::data::Market > &market, std::string baseCcy, std::string ccy, QuantLib::Period term, const QuantLib::ext::shared_ptr< ore::data::Convention > &conventions, std::set< ore::analytics::RiskFactorKey > &parHelperDependencies, const std::string &marketConfiguration=ore::data::Market::defaultConfiguration) const
Create FX Forwrad for implying par rate sensitivity from zero rate sensitivity.
std::pair< QuantLib::ext::shared_ptr< QuantLib::Instrument >, Date > makeCDS(const QuantLib::ext::shared_ptr< ore::data::Market > &market, std::string name, std::string ccy, QuantLib::Period term, const QuantLib::ext::shared_ptr< ore::data::Convention > &conventions, std::set< ore::analytics::RiskFactorKey > &parHelperDependencies, const std::string &expDiscountCurve="", const std::string &marketConfiguration=ore::data::Market::defaultConfiguration) const
Create CDS for implying par rate sensitivity from Hazard Rate sensitivity.
QuantLib::ext::shared_ptr< QuantLib::Instrument > makeZeroInflationSwap(const QuantLib::ext::shared_ptr< ore::data::Market > &market, std::string indexName, QuantLib::Period term, const QuantLib::ext::shared_ptr< ore::data::Convention > &conventions, bool singleCurve, std::set< ore::analytics::RiskFactorKey > &parHelperDependencies, const std::string &expDiscountCurve="", const std::string &marketConfiguration=ore::data::Market::defaultConfiguration) const
Create Zero Swap for implying par rate sensitivity from zero rate sensitivity.
Data types stored in the scenario class.
@ YoYInflationCapFloorVolatility
Description of sensitivity shift scenarios.
const map< string, QuantLib::ext::shared_ptr< CapFloorVolShiftData > > & yoyInflationCapFloorVolShiftData() const
const map< string, QuantLib::ext::shared_ptr< CurveShiftData > > & indexCurveShiftData() const
const map< string, QuantLib::ext::shared_ptr< CapFloorVolShiftData > > & capFloorVolShiftData() const
const map< string, string > & creditCcys() const
const map< string, QuantLib::ext::shared_ptr< CurveShiftData > > & discountCurveShiftData() const
const map< string, QuantLib::ext::shared_ptr< CurveShiftData > > & zeroInflationCurveShiftData() const
const map< string, QuantLib::ext::shared_ptr< CurveShiftData > > & creditCurveShiftData() const
const map< string, QuantLib::ext::shared_ptr< CurveShiftData > > & yoyInflationCurveShiftData() const
const map< string, QuantLib::ext::shared_ptr< CurveShiftData > > & yieldCurveShiftData() const
QuantLib::ext::shared_ptr< IborIndex > parseIborIndex(const string &s, const Handle< YieldTermStructure > &h=Handle< YieldTermStructure >())
bool isOvernightIndex(const std::string &indexName)
bool tryParseIborIndex(const string &s, QuantLib::ext::shared_ptr< IborIndex > &index)
Currency parseCurrency(const string &s)
A cube implementation that stores the cube in memory.
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
Handle< YieldTermStructure > xccyYieldCurve(const QuantLib::ext::shared_ptr< Market > &market, const string &ccyCode, const string &configuration)
QuantLib::Date getInflationSwapStart(const Date &asof, const InflationSwapConvention &convention)
Size size(const ValueType &v)
std::string to_string(const LocationInfo &l)
Singleton class to hold global Observation Mode.
QuantLib::BootstrapHelper< QuantLib::OptionletVolatilityStructure > helper
A class to hold the parametrisation for building sensitivity scenarios.
factory classes for simple scenarios
std::map< ore::analytics::RiskFactorKey, QuantLib::Handle< QuantExt::YoYOptionletVolatilitySurface > > parYoYCapsVts_
std::map< std::string, std::vector< QuantLib::Period > > zeroInflationPillars_
std::set< std::string > removeTodaysFixingIndices_
std::map< ore::analytics::RiskFactorKey, QuantLib::Handle< QuantLib::YieldTermStructure > > parYoYCapsYts_
par helpers: YoY cap / floors
std::map< ore::analytics::RiskFactorKey, QuantLib::ext::shared_ptr< QuantLib::Instrument > > parHelpers_
par helpers (all except cap/floors)
std::map< ore::analytics::RiskFactorKey, std::set< ore::analytics::RiskFactorKey > > parHelperDependencies_
list of (raw) risk factors on which a par helper depends
std::map< std::string, std::vector< QuantLib::Period > > yieldCurvePillars_
par QuantLib::Instrument pillars
std::map< ore::analytics::RiskFactorKey, QuantLib::Handle< QuantLib::YieldTermStructure > > parCapsYts_
std::map< ore::analytics::RiskFactorKey, QuantLib::ext::shared_ptr< QuantLib::CapFloor > > parCaps_
par helpers: IR cap / floors
std::map< ore::analytics::RiskFactorKey, QuantLib::Handle< QuantLib::OptionletVolatilityStructure > > parCapsVts_
std::map< ore::analytics::RiskFactorKey, QuantLib::ext::shared_ptr< QuantLib::YoYInflationCapFloor > > parYoYCaps_
std::map< ore::analytics::RiskFactorKey, QuantLib::Handle< QuantLib::YoYInflationIndex > > parYoYCapsIndex_
std::map< std::string, std::vector< QuantLib::Period > > yoyCapFloorPillars_
std::map< std::string, std::vector< QuantLib::Period > > capFloorPillars_
std::map< std::string, std::vector< QuantLib::Period > > cdsPillars_
std::map< std::string, std::vector< QuantLib::Period > > yoyInflationPillars_
Structured analytics error.