85#include <ql/instruments/makecapfloor.hpp>
86#include <ql/math/interpolations/loginterpolation.hpp>
87#include <ql/termstructures/credit/interpolatedsurvivalprobabilitycurve.hpp>
88#include <ql/termstructures/defaulttermstructure.hpp>
89#include <ql/termstructures/volatility/capfloor/capfloortermvolatilitystructure.hpp>
90#include <ql/termstructures/volatility/capfloor/capfloortermvolsurface.hpp>
91#include <ql/termstructures/volatility/equityfx/blackvariancecurve.hpp>
92#include <ql/termstructures/volatility/equityfx/blackvoltermstructure.hpp>
93#include <ql/termstructures/volatility/optionlet/strippedoptionlet.hpp>
94#include <ql/termstructures/volatility/optionlet/strippedoptionletadapter.hpp>
95#include <ql/termstructures/volatility/swaption/swaptionconstantvol.hpp>
96#include <ql/termstructures/volatility/swaption/swaptionvolcube.hpp>
97#include <ql/termstructures/volatility/swaption/swaptionvolmatrix.hpp>
98#include <ql/termstructures/volatility/swaption/swaptionvolstructure.hpp>
99#include <ql/termstructures/yield/discountcurve.hpp>
100#include <ql/time/calendars/target.hpp>
101#include <ql/time/calendars/weekendsonly.hpp>
102#include <ql/time/daycounters/actual365fixed.hpp>
103#include <ql/time/daycounters/actualactual.hpp>
104#include <ql/quotes/compositequote.hpp>
105#include <ql/quotes/derivedquote.hpp>
107#include <boost/algorithm/string.hpp>
108#include <boost/timer/timer.hpp>
118void processException(
bool continueOnError,
const std::exception& e,
const std::string& curveId =
"",
120 const bool simDataWritten =
false) {
126 std::string message =
"skipping this object in scenario sim market";
127 if (!curve.empty()) {
128 message +=
" (scenario data was ";
131 message +=
"written for this object.)";
133 if (continueOnError) {
134 std::string exceptionMessage = e.what();
137 if (boost::starts_with(exceptionMessage,
"did not find object ")) {
138 ALOG(
"CurveID: " << curve <<
": " << message <<
": " << exceptionMessage);
143 QL_FAIL(
"Object with CurveID '" << curve <<
"' failed to build in scenario sim market: " << e.what());
153 if (y == ore::data::YieldCurveType::Discount) {
155 }
else if (y == ore::data::YieldCurveType::Yield) {
157 }
else if (y == ore::data::YieldCurveType::EquityDividend) {
160 QL_FAIL(
"yieldCurveType not supported");
167 return ore::data::YieldCurveType::Discount;
169 return ore::data::YieldCurveType::Yield;
171 return ore::data::YieldCurveType::EquityDividend;
173 QL_FAIL(
"RiskFactorKey::KeyType not supported");
186 QL_FAIL(
"Decay mode \"" << s <<
"\" not recognized");
190void checkDayCounterConsistency(
const std::string& curveId,
const DayCounter& initCurveDayCounter,
191 const DayCounter& simCurveDayCounter) {
192 if (initCurveDayCounter != simCurveDayCounter) {
193 std::string initDcName = initCurveDayCounter.empty() ?
"(empty)" : initCurveDayCounter.name();
194 std::string ssmDcName = simCurveDayCounter.empty() ?
"(empty)" : simCurveDayCounter.name();
195 ALOG(
"inconsistent day counters: when using spreaded curves in scenario sim market, the init curve day counter"
197 initDcName +
") should be equal to the ssm day counter (" + ssmDcName +
198 "), continuing anyway, please consider fixing this in either the initial market or ssm "
203QuantLib::ext::shared_ptr<YieldTermStructure>
204makeYieldCurve(
const std::string& curveId,
const bool spreaded,
const Handle<YieldTermStructure>& initMarketTs,
205 const std::vector<Real>& yieldCurveTimes,
const std::vector<Handle<Quote>>& quotes,
const DayCounter& dc,
206 const Calendar& cal,
const std::string& interpolation,
const std::string& extrapolation) {
208 return QuantLib::ext::shared_ptr<YieldTermStructure>(QuantLib::ext::make_shared<QuantExt::InterpolatedDiscountCurve>(
209 yieldCurveTimes, quotes, 0, cal, dc,
210 interpolation ==
"LogLinear" ? QuantExt::InterpolatedDiscountCurve::Interpolation::logLinear
211 : QuantExt::InterpolatedDiscountCurve::Interpolation::linearZero,
212 extrapolation ==
"FlatZero" ? QuantExt::InterpolatedDiscountCurve::Extrapolation::flatZero
213 : QuantExt::InterpolatedDiscountCurve::Extrapolation::flatFwd));
216 checkDayCounterConsistency(curveId, initMarketTs->dayCounter(), dc);
217 return QuantLib::ext::make_shared<QuantExt::SpreadedDiscountCurve>(
218 initMarketTs, yieldCurveTimes, quotes,
219 interpolation ==
"LogLinear" ? QuantExt::SpreadedDiscountCurve::Interpolation::logLinear
220 : QuantExt::SpreadedDiscountCurve::Interpolation::linearZero,
221 extrapolation ==
"FlatZero" ? SpreadedDiscountCurve::Extrapolation::flatZero
222 : SpreadedDiscountCurve::Extrapolation::flatFwd);
224 auto idc = QuantLib::ext::make_shared<QuantExt::InterpolatedDiscountCurve2>(
225 yieldCurveTimes, quotes, dc,
226 interpolation ==
"LogLinear" ? QuantExt::InterpolatedDiscountCurve2::Interpolation::logLinear
227 : QuantExt::InterpolatedDiscountCurve2::Interpolation::linearZero,
228 extrapolation ==
"FlatZero" ? InterpolatedDiscountCurve2::Extrapolation::flatZero
229 : InterpolatedDiscountCurve2::Extrapolation::flatFwd);
230 idc->setAdjustReferenceDate(
false);
239 std::map<RiskFactorKey, Real>& absoluteSimDataTmp,
241 const std::vector<std::vector<Real>>& coordinates) {
242 simData_.insert(simDataTmp.begin(), simDataTmp.end());
243 absoluteSimData_.insert(absoluteSimDataTmp.begin(), absoluteSimDataTmp.end());
246 absoluteSimDataTmp.clear();
251 bool& simDataWritten,
bool simulate,
bool spreaded) {
252 Handle<YieldTermStructure> wrapper = (
riskFactorYieldCurve(rf) == ore::data::YieldCurveType::Discount)
253 ? initMarket->discountCurve(key, configuration)
255 QL_REQUIRE(!wrapper.empty(),
"yield curve not provided for " << key);
256 QL_REQUIRE(tenors.front() > 0 * Days,
"yield curve tenors must not include t=0");
260 DayCounter dc = wrapper->dayCounter();
261 vector<Time> yieldCurveTimes(1, 0.0);
262 vector<Date> yieldCurveDates(1,
asof_);
263 for (
auto& tenor : tenors) {
264 yieldCurveTimes.push_back(dc.yearFraction(
asof_,
asof_ + tenor));
265 yieldCurveDates.push_back(
asof_ + tenor);
268 vector<Handle<Quote>> quotes;
269 QuantLib::ext::shared_ptr<SimpleQuote> q(
new SimpleQuote(1.0));
270 quotes.push_back(Handle<Quote>(q));
271 vector<Real> discounts(yieldCurveTimes.size());
272 std::map<RiskFactorKey, QuantLib::ext::shared_ptr<SimpleQuote>> simDataTmp;
273 std::map<RiskFactorKey, Real> absoluteSimDataTmp;
274 for (Size i = 0; i < yieldCurveTimes.size() - 1; i++) {
275 Real val = wrapper->discount(yieldCurveDates[i + 1]);
276 DLOG(
"ScenarioSimMarket yield curve " << rf <<
" " << key <<
" discount[" << i <<
"]=" << val);
277 QuantLib::ext::shared_ptr<SimpleQuote> q(
new SimpleQuote(spreaded ? 1.0 : val));
279 quotes.push_back(qh);
283 simDataTmp.emplace(std::piecewise_construct, std::forward_as_tuple(rf, key, i), std::forward_as_tuple(q));
286 absoluteSimDataTmp.emplace(std::piecewise_construct, std::forward_as_tuple(rf, key, i),
287 std::forward_as_tuple(val));
293 {std::vector<Real>(std::next(yieldCurveTimes.begin(), 1), yieldCurveTimes.end())});
294 simDataWritten =
true;
296 QuantLib::ext::shared_ptr<YieldTermStructure>
yieldCurve =
297 makeYieldCurve(key, spreaded, wrapper, yieldCurveTimes, quotes, dc, TARGET(),
parameters_->interpolation(),
301 if (wrapper->allowsExtrapolation())
302 ych->enableExtrapolation();
307 const QuantLib::ext::shared_ptr<ScenarioSimMarketParameters>& parameters,
310 const bool useSpreadedTermStructures,
const bool cacheSimData,
312 const bool handlePseudoCurrencies,
313 const QuantLib::ext::shared_ptr<Scenario>& offSetScenario)
315 configuration,
curveConfigs, todaysMarketParams, continueOnError, useSpreadedTermStructures,
316 cacheSimData, allowPartialScenarios, iborFallbackConfig, handlePseudoCurrencies,
320 const QuantLib::ext::shared_ptr<Market>& initMarket,
const QuantLib::ext::shared_ptr<ScenarioSimMarketParameters>& parameters,
321 const QuantLib::ext::shared_ptr<FixingManager>& fixingManager,
const std::string& configuration,
323 const bool continueOnError,
const bool useSpreadedTermStructures,
const bool cacheSimData,
324 const bool allowPartialScenarios,
const IborFallbackConfig& iborFallbackConfig,
const bool handlePseudoCurrencies,
const QuantLib::ext::shared_ptr<Scenario>& offSetScenario)
325 :
SimMarket(handlePseudoCurrencies), parameters_(parameters), fixingManager_(fixingManager),
326 filter_(
QuantLib::ext::make_shared<
ScenarioFilter>()), useSpreadedTermStructures_(useSpreadedTermStructures),
327 cacheSimData_(cacheSimData), allowPartialScenarios_(allowPartialScenarios),
328 iborFallbackConfig_(iborFallbackConfig), offsetScenario_(offSetScenario) {
330 LOG(
"building ScenarioSimMarket...");
331 asof_ = initMarket->asofDate();
332 DLOG(
"AsOf " << QuantLib::io::iso_date(
asof_));
336 "ScenarioSimMarket: Interpolation (" <<
parameters_->interpolation()
337 <<
") must be set to 'LogLinear' or 'LinearZero'");
339 "ScenarioSimMarket: YieldCurves / Extrapolation ('" <<
parameters_->extrapolation()
340 <<
"') must be set to 'FlatZero' or 'FlatFwd'");
341 QL_REQUIRE(
parameters_->defaultCurveExtrapolation() ==
"FlatZero" ||
342 parameters_->defaultCurveExtrapolation() ==
"FlatFwd",
343 "ScenarioSimMarket: DefaultCurves / Extrapolation ('" <<
parameters_->extrapolation()
344 <<
"') must be set to 'FlatZero' or 'FlatFwd'");
346 for (
const auto& param : parameters->parameters()) {
350 std::map<RiskFactorKey, QuantLib::ext::shared_ptr<SimpleQuote>> simDataTmp;
351 std::map<RiskFactorKey, Real> absoluteSimDataTmp;
353 boost::timer::cpu_timer timer;
355 switch (param.first) {
357 std::map<std::string, Handle<Quote>> fxQuotes;
358 for (
const auto&
name : param.second.second) {
359 bool simDataWritten =
false;
362 DLOG(
"adding " <<
name <<
" FX rates");
363 Real v = initMarket->fxSpot(
name, configuration)->value();
366 auto m = [v](Real x) {
return x * v; };
367 fxQuotes[
name] = Handle<Quote>(
368 QuantLib::ext::make_shared<DerivedQuote<
decltype(m)>>(Handle<Quote>(q), m));
370 fxQuotes[
name] = Handle<Quote>(q);
373 if (param.second.first) {
374 simDataTmp.emplace(std::piecewise_construct, std::forward_as_tuple(param.first,
name),
375 std::forward_as_tuple(q));
377 absoluteSimDataTmp.emplace(std::piecewise_construct,
378 std::forward_as_tuple(param.first,
name),
379 std::forward_as_tuple(v));
383 simDataWritten =
true;
384 }
catch (
const std::exception& e) {
385 processException(continueOnError, e,
name, param.first, simDataWritten);
388 fx_ = QuantLib::ext::make_shared<FXTriangulation>(fxQuotes);
394 for (
const auto&
name : param.second.second) {
395 bool simDataWritten =
false;
397 DLOG(
"building " <<
name <<
" yield curve..");
398 vector<Period> tenors = parameters->yieldCurveTenors(
name);
399 addYieldCurve(initMarket, configuration, param.first,
name, tenors, simDataWritten,
401 DLOG(
"building " <<
name <<
" yield curve done");
402 }
catch (
const std::exception& e) {
403 processException(continueOnError, e,
name, param.first, simDataWritten);
411 std::vector<std::string> indices;
412 for (
auto const& i : param.second.second) {
415 isOn = QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(*initMarket->iborIndex(i, configuration)) !=
420 indices.insert(indices.begin(), i);
422 indices.push_back(i);
425 for (
const auto&
name : indices) {
426 bool simDataWritten =
false;
428 DLOG(
"building " <<
name <<
" index curve");
429 std::vector<string> indexTokens;
430 split(indexTokens,
name, boost::is_any_of(
"-"));
431 Handle<IborIndex> index;
432 if (indexTokens[1] ==
"GENERIC") {
435 index = Handle<IborIndex>(
438 index = initMarket->iborIndex(
name, configuration);
440 QL_REQUIRE(!index.empty(),
"index object for " <<
name <<
" not provided");
441 Handle<YieldTermStructure> wrapperIndex = index->forwardingTermStructure();
442 QL_REQUIRE(!wrapperIndex.empty(),
"no termstructure for index " <<
name);
443 vector<string> keys(parameters->yieldCurveTenors(
name).size());
445 DayCounter dc = wrapperIndex->dayCounter();
446 vector<Time> yieldCurveTimes(1, 0.0);
447 vector<Date> yieldCurveDates(1,
asof_);
448 QL_REQUIRE(parameters->yieldCurveTenors(
name).front() > 0 * Days,
449 "yield curve tenors must not include t=0");
450 for (
auto& tenor : parameters->yieldCurveTenors(
name)) {
451 yieldCurveTimes.push_back(dc.yearFraction(
asof_,
asof_ + tenor));
452 yieldCurveDates.push_back(
asof_ + tenor);
456 vector<Handle<Quote>> quotes;
457 QuantLib::ext::shared_ptr<SimpleQuote> q(
new SimpleQuote(1.0));
458 quotes.push_back(Handle<Quote>(q));
460 for (Size i = 0; i < yieldCurveTimes.size() - 1; i++) {
461 Real val = wrapperIndex->discount(yieldCurveDates[i + 1]);
464 quotes.push_back(qh);
466 simDataTmp.emplace(std::piecewise_construct, std::forward_as_tuple(param.first,
name, i),
467 std::forward_as_tuple(q));
469 absoluteSimDataTmp.emplace(std::piecewise_construct,
470 std::forward_as_tuple(param.first,
name, i),
471 std::forward_as_tuple(val));
474 DLOG(
"ScenarioSimMarket index curve " <<
name <<
" discount[" << i <<
"]=" << val);
478 {std::vector<Real>(std::next(yieldCurveTimes.begin(), 1), yieldCurveTimes.end())});
479 simDataWritten =
true;
481 QuantLib::ext::shared_ptr<YieldTermStructure> indexCurve = makeYieldCurve(
485 Handle<YieldTermStructure> ich(indexCurve);
486 if (wrapperIndex->allowsExtrapolation())
487 ich->enableExtrapolation();
489 QuantLib::ext::shared_ptr<IborIndex> i = index->clone(ich);
495 "Could not build ibor fallback index '"
496 <<
name <<
"', because rfr index '" << fallbackData.rfrIndex
497 <<
"' is not present in scenario sim market, is the rfr index in the "
498 "scenario sim market parameters?");
499 auto rfrInd = QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(*f->second);
500 QL_REQUIRE(rfrInd !=
nullptr,
502 << fallbackData.rfrIndex
503 <<
"' to overnight index when building the ibor fallback index '" <<
name
505 if (
auto original = QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(i))
506 i = QuantLib::ext::make_shared<QuantExt::FallbackOvernightIndex>(
507 original, rfrInd, fallbackData.spread, fallbackData.switchDate,
510 i = QuantLib::ext::make_shared<QuantExt::FallbackIborIndex>(
511 i, rfrInd, fallbackData.spread, fallbackData.switchDate,
513 DLOG(
"built ibor fall back index '"
514 <<
name <<
"' with rfr index '" << fallbackData.rfrIndex <<
"', spread "
515 << fallbackData.spread <<
", use rfr curve in scen sim market: " << std::boolalpha
520 DLOG(
"building " <<
name <<
" index curve done");
521 }
catch (
const std::exception& e) {
522 processException(continueOnError, e,
name, param.first, simDataWritten);
529 for (
const auto&
name : param.second.second) {
530 bool simDataWritten =
false;
533 DLOG(
"adding " <<
name <<
" equity spot...");
534 Real spotVal = initMarket->equitySpot(
name, configuration)->value();
537 auto m = [spotVal](Real x) {
return x * spotVal; };
540 Handle<Quote>(QuantLib::ext::make_shared<DerivedQuote<
decltype(m)>>(
541 Handle<Quote>(q), m))));
546 simDataTmp.emplace(std::piecewise_construct, std::forward_as_tuple(param.first,
name),
547 std::forward_as_tuple(q));
549 absoluteSimDataTmp.emplace(std::piecewise_construct,
550 std::forward_as_tuple(param.first,
name),
551 std::forward_as_tuple(spotVal));
554 simDataWritten =
true;
555 DLOG(
"adding " <<
name <<
" equity spot done");
556 }
catch (
const std::exception& e) {
557 processException(continueOnError, e,
name, param.first, simDataWritten);
563 for (
const auto&
name : param.second.second) {
564 bool simDataWritten =
false;
566 DLOG(
"building " <<
name <<
" equity dividend yield curve..");
567 vector<Period> tenors = parameters->equityDividendTenors(
name);
568 addYieldCurve(initMarket, configuration, param.first,
name, tenors, simDataWritten,
570 DLOG(
"building " <<
name <<
" equity dividend yield curve done");
574 string forecastCurve;
578 string forecastName = eqVolConfig->forecastingCurve();
579 string eqCcy = eqVolConfig->currency();
582 forecastCurve = ycspec.
name();
583 TLOG(
"Got forecast curve '" << forecastCurve <<
"' from equity curve config for " <<
name);
587 Handle<YieldTermStructure> forecastTs =
589 Handle<EquityIndex2> curve = initMarket->equityCurve(
name, configuration);
593 if (forecastTs.empty()) {
594 string ccy = curve->currency().code();
595 TLOG(
"Falling back on the discount curve for currency '"
596 << ccy <<
"' for equity forecast curve '" <<
name <<
"'");
599 QuantLib::ext::shared_ptr<EquityIndex2> ei(
601 yieldCurve(YieldCurveType::EquityDividend,
name, configuration)));
602 Handle<EquityIndex2> eh(ei);
604 }
catch (
const std::exception& e) {
605 processException(continueOnError, e,
name, param.first, simDataWritten);
611 for (
const auto&
name : param.second.second) {
614 DLOG(
"Adding security spread " <<
name <<
" from configuration " << configuration);
615 Real v = initMarket->securitySpread(
name, configuration)->value();
618 auto m = [v](Real x) {
return x + v; };
621 Handle<Quote>(QuantLib::ext::make_shared<DerivedQuote<
decltype(m)>>(
622 Handle<Quote>(q), m))));
627 if (param.second.first) {
628 simDataTmp.emplace(std::piecewise_construct, std::forward_as_tuple(param.first,
name),
629 std::forward_as_tuple(q));
631 absoluteSimDataTmp.emplace(std::piecewise_construct,
632 std::forward_as_tuple(param.first,
name),
633 std::forward_as_tuple(v));
638 }
catch (
const std::exception& e) {
639 DLOG(
"skipping this object: " << e.what());
643 DLOG(
"Adding security recovery rate " <<
name <<
" from configuration " << configuration);
644 Real v = initMarket->recoveryRate(
name, configuration)->value();
647 auto m = [v](Real x) {
return x * v; };
650 Handle<Quote>(QuantLib::ext::make_shared<DerivedQuote<
decltype(m)>>(
651 Handle<Quote>(q), m))));
659 if (parameters->simulateRecoveryRates()) {
660 simDataTmp.emplace(std::piecewise_construct,
662 std::forward_as_tuple(q));
664 absoluteSimDataTmp.emplace(std::piecewise_construct,
665 std::forward_as_tuple(param.first,
name),
666 std::forward_as_tuple(v));
670 }
catch (
const std::exception& e) {
671 DLOG(
"skipping this object: " << e.what());
678 for (
const auto&
name : param.second.second) {
679 bool simDataWritten =
false;
682 RelinkableHandle<SwaptionVolatilityStructure> wrapper;
683 vector<Period> optionTenors, underlyingTenors;
684 vector<Real> strikeSpreads;
686 bool isCube, isAtm, simulateAtmOnly;
688 DLOG(
"building " <<
name <<
" swaption volatility curve...");
689 wrapper.linkTo(*initMarket->swaptionVol(
name, configuration));
692 isCube = parameters->swapVolIsCube(
name);
693 optionTenors = parameters->swapVolExpiries(
name);
694 underlyingTenors = parameters->swapVolTerms(
name);
695 strikeSpreads = parameters->swapVolStrikeSpreads(
name);
696 simulateAtmOnly = parameters->simulateSwapVolATMOnly();
698 DLOG(
"building " <<
name <<
" yield volatility curve...");
699 wrapper.linkTo(*initMarket->yieldVol(
name, configuration));
701 optionTenors = parameters->yieldVolExpiries();
702 underlyingTenors = parameters->yieldVolTerms();
703 strikeSpreads = {0.0};
704 simulateAtmOnly =
true;
706 DLOG(
"Initial market " <<
name <<
" yield volatility type = " << wrapper->volatilityType());
709 isAtm = QuantLib::ext::dynamic_pointer_cast<SwaptionVolatilityMatrix>(*wrapper) !=
nullptr ||
710 QuantLib::ext::dynamic_pointer_cast<ConstantSwaptionVolatility>(*wrapper) !=
nullptr;
712 Handle<SwaptionVolatilityStructure> svp;
713 if (param.second.first) {
714 LOG(
"Simulating yield vols for ccy " <<
name);
715 DLOG(
"YieldVol T0 source is atm : " << (isAtm ?
"True" :
"False"));
716 DLOG(
"YieldVol ssm target is cube : " << (isCube ?
"True" :
"False"));
717 DLOG(
"YieldVol simulate atm only : " << (simulateAtmOnly ?
"True" :
"False"));
718 if (simulateAtmOnly) {
719 QL_REQUIRE(strikeSpreads.size() == 1 &&
close_enough(strikeSpreads[0], 0),
720 "for atmOnly strikeSpreads must be {0.0}");
722 QuantLib::ext::shared_ptr<QuantLib::SwaptionVolatilityCube> cube;
723 if (isCube && !isAtm) {
724 QuantLib::ext::shared_ptr<SwaptionVolCubeWithATM> tmp =
725 QuantLib::ext::dynamic_pointer_cast<SwaptionVolCubeWithATM>(*wrapper);
726 QL_REQUIRE(tmp,
"swaption cube missing");
729 vector<vector<Handle<Quote>>> quotes, atmQuotes;
730 quotes.resize(optionTenors.size() * underlyingTenors.size(),
731 vector<Handle<Quote>>(strikeSpreads.size(), Handle<Quote>()));
732 atmQuotes.resize(optionTenors.size(),
733 std::vector<Handle<Quote>>(underlyingTenors.size(), Handle<Quote>()));
734 vector<vector<Real>> shift(optionTenors.size(), vector<Real>(underlyingTenors.size(), 0.0));
735 Size atmSlice = std::find_if(strikeSpreads.begin(), strikeSpreads.end(),
736 [](
const Real s) { return close_enough(s, 0.0); }) -
737 strikeSpreads.begin();
738 QL_REQUIRE(atmSlice < strikeSpreads.size(),
739 "could not find atm slice (strikeSpreads do not contain 0.0)");
749 bool convertToNormal = wrapper->volatilityType() != Normal &&
752 DLOG(
"T0 ts is normal : " << (wrapper->volatilityType() == Normal ?
"True"
754 DLOG(
"Have swaption vol : "
756 DLOG(
"Will convert to normal vol : " << (convertToNormal ?
"True" :
"False"));
760 if (convertToNormal) {
762 Handle<SwapIndex> shortSwapIndex =
765 *shortSwapIndex, Normal);
768 for (Size k = 0; k < strikeSpreads.size(); ++k) {
769 for (Size i = 0; i < optionTenors.size(); ++i) {
770 for (Size j = 0; j < underlyingTenors.size(); ++j) {
771 Real strike = Null<Real>();
772 if (!simulateAtmOnly && cube)
773 strike = cube->atmStrike(optionTenors[i], underlyingTenors[j]) +
776 if (convertToNormal) {
779 vol = converter->
convert(wrapper->optionDateFromTenor(optionTenors[i]),
780 underlyingTenors[j], strikeSpreads[k],
781 wrapper->dayCounter(), Normal);
784 wrapper->volatility(optionTenors[i], underlyingTenors[j], strike,
true);
786 QuantLib::ext::shared_ptr<SimpleQuote> q(
789 Size index = i * underlyingTenors.size() * strikeSpreads.size() +
790 j * strikeSpreads.size() + k;
792 simDataTmp.emplace(std::piecewise_construct,
793 std::forward_as_tuple(param.first,
name, index),
794 std::forward_as_tuple(q));
796 absoluteSimDataTmp.emplace(std::piecewise_construct,
797 std::forward_as_tuple(param.first,
name, index),
798 std::forward_as_tuple(vol));
800 auto tmp = Handle<Quote>(q);
801 quotes[i * underlyingTenors.size() + j][k] = tmp;
803 atmQuotes[i][j] = tmp;
805 !convertToNormal && wrapper->volatilityType() == ShiftedLognormal
806 ? wrapper->shift(optionTenors[i], underlyingTenors[j])
808 DLOG(
"AtmVol at " << optionTenors.at(i) <<
"/" << underlyingTenors.at(j)
809 <<
" is " << vol <<
", shift is " << shift[i][j]
810 <<
", (name,index) = (" <<
name <<
"," << index <<
")");
812 DLOG(
"SmileVol at " << optionTenors.at(i) <<
"/" << underlyingTenors.at(j)
813 <<
"/" << strikeSpreads.at(k) <<
" is " << vol
814 <<
", (name,index) = (" <<
name <<
"," << index <<
")");
820 std::vector<std::vector<Real>> coordinates(3);
821 for (Size i = 0; i < optionTenors.size(); ++i) {
822 coordinates[0].push_back(
823 wrapper->timeFromReference(wrapper->optionDateFromTenor(optionTenors[i])));
825 for (Size j = 0; j < underlyingTenors.size(); ++j) {
826 coordinates[1].push_back(wrapper->swapLength(underlyingTenors[j]));
828 for (Size k = 0; k < strikeSpreads.size(); ++k) {
829 coordinates[2].push_back(strikeSpreads[k]);
832 writeSimData(simDataTmp, absoluteSimDataTmp, param.first,
name, coordinates);
833 simDataWritten =
true;
834 bool flatExtrapolation =
true;
835 VolatilityType volType = convertToNormal ? Normal : wrapper->volatilityType();
836 DayCounter dc = wrapper->dayCounter();
839 bool stickyStrike =
parameters_->swapVolSmileDynamics(
name) ==
"StickyStrike";
840 QuantLib::ext::shared_ptr<SwapIndex>
swapIndex, shortSwapIndex;
841 QuantLib::ext::shared_ptr<SwapIndex> simSwapIndex, simShortSwapIndex;
847 simShortSwapIndex = *this->
swapIndex(shortSwapIndexBase, configuration);
849 if (simSwapIndex ==
nullptr || simShortSwapIndex ==
nullptr)
857 Handle<SwaptionVolatilityStructure>(QuantLib::ext::make_shared<SpreadedSwaptionVolatility>(
858 wrapper, optionTenors, underlyingTenors, strikeSpreads, quotes,
swapIndex,
859 shortSwapIndex, simSwapIndex, simShortSwapIndex, !stickyStrike));
861 Handle<SwaptionVolatilityStructure> atm;
862 atm = Handle<SwaptionVolatilityStructure>(QuantLib::ext::make_shared<SwaptionVolatilityMatrix>(
863 wrapper->calendar(), wrapper->businessDayConvention(), optionTenors,
864 underlyingTenors, atmQuotes, dc, flatExtrapolation, volType, shift));
865 atm->enableExtrapolation();
866 if (simulateAtmOnly) {
876 svp = Handle<SwaptionVolatilityStructure>(
877 QuantLib::ext::make_shared<SwaptionVolatilityConstantSpread>(atm, wrapper));
882 atm, optionTenors, underlyingTenors, strikeSpreads, quotes,
885 flatExtrapolation,
false));
886 tmp->setAdjustReferenceDate(
false);
887 svp = Handle<SwaptionVolatilityStructure>(
888 QuantLib::ext::make_shared<SwaptionVolCubeWithATM>(tmp));
895 string decayModeString = parameters->swapVolDecayMode();
897 DLOG(
"Dynamic (" << wrapper->volatilityType() <<
") yield vols (" << decayModeString
898 <<
") for qualifier " <<
name);
900 QL_REQUIRE(!QuantLib::ext::dynamic_pointer_cast<ProxySwaptionVolatility>(*wrapper),
901 "DynamicSwaptionVolatilityMatrix does not support ProxySwaptionVolatility surface");
903 QuantLib::ext::shared_ptr<SwaptionVolatilityStructure> atmSlice;
907 auto c = QuantLib::ext::dynamic_pointer_cast<SwaptionVolCubeWithATM>(*wrapper);
908 QL_REQUIRE(c,
"internal error - expected swaption cube to be SwaptionVolCubeWithATM.");
909 atmSlice = *c->cube()->atmVol();
913 WLOG(
"Only ATM slice is considered from init market's cube");
914 QuantLib::ext::shared_ptr<QuantLib::SwaptionVolatilityStructure> svolp =
915 QuantLib::ext::make_shared<QuantExt::DynamicSwaptionVolatilityMatrix>(
916 atmSlice, 0, NullCalendar(), decayMode);
917 svp = Handle<SwaptionVolatilityStructure>(svolp);
919 svp->setAdjustReferenceDate(
false);
920 svp->enableExtrapolation();
922 DLOG(
"Simulation market " <<
name <<
" yield volatility type = " << svp->volatilityType());
933 }
catch (
const std::exception& e) {
934 processException(continueOnError, e,
name, param.first, simDataWritten);
940 for (
const auto&
name : param.second.second) {
941 bool simDataWritten =
false;
943 LOG(
"building " <<
name <<
" cap/floor volatility curve...");
944 Handle<OptionletVolatilityStructure> wrapper = initMarket->capFloorVol(
name, configuration);
945 auto [iborIndexName, rateComputationPeriod] =
946 initMarket->capFloorVolIndexBase(
name, configuration);
947 QuantLib::ext::shared_ptr<IborIndex>
iborIndex =
950 LOG(
"Initial market cap/floor volatility type = " << wrapper->volatilityType());
952 Handle<OptionletVolatilityStructure> hCapletVol;
955 if (param.second.first) {
956 LOG(
"Simulating Cap/Floor Optionlet vols for key " <<
name);
960 Natural settleDays = 0;
962 Calendar iborCalendar;
963 Size onSettlementDays = 0;
966 QuantLib::ext::shared_ptr<CapFloorVolatilityCurveConfig> config;
977 settleDays = config->settleDays();
978 onSettlementDays = config->onCapSettlementDays();
983 iborCalendar =
iborIndex->fixingCalendar();
984 isOis = QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(
iborIndex) !=
nullptr;
987 vector<Period> optionTenors = parameters->capFloorVolExpiries(
name);
988 vector<Date> optionDates(optionTenors.size());
990 vector<Real>
strikes = parameters->capFloorVolStrikes(
name);
995 parameters->capFloorVolIsAtm(
name),
998 <<
" is empty in simulation parameters so expected its ATM flag to be true");
1003 vector<vector<Handle<Quote>>> quotes(
1004 optionTenors.size(), vector<Handle<Quote>>(
strikes.size(), Handle<Quote>()));
1006 DLOG(
"cap floor use adjusted option pillars = " << std::boolalpha <<
parameters_->capFloorVolAdjustOptionletPillars());
1007 DLOG(
"have ibor index = " << std::boolalpha << (
iborIndex !=
nullptr));
1009 Rate atmStrike = Null<Rate>();
1010 for (Size i = 0; i < optionTenors.size(); ++i) {
1019 CapFloor::Cap, optionTenors[i],
1020 QuantLib::ext::dynamic_pointer_cast<QuantLib::OvernightIndex>(
iborIndex),
1021 rateComputationPeriod, 0.0)
1024 if (capFloor.empty()) {
1025 optionDates[i] =
asof_ + 1;
1027 auto lastCoupon = QuantLib::ext::dynamic_pointer_cast<
1029 QL_REQUIRE(lastCoupon,
"SSM internal error, could not cast to "
1030 "CappedFlooredOvernightIndexedCoupon "
1031 "when building optionlet vol for '"
1035 std::max(
asof_ + 1, lastCoupon->underlying()->fixingDates().front());
1038 QuantLib::ext::shared_ptr<CapFloor> capFloor =
1039 MakeCapFloor(CapFloor::Cap, optionTenors[i],
iborIndex, 0.0, 0 * Days);
1040 if (capFloor->floatingLeg().empty()) {
1041 optionDates[i] =
asof_ + 1;
1044 std::max(
asof_ + 1, capFloor->lastFloatingRateCoupon()->fixingDate());
1047 QL_REQUIRE(i == 0 || optionDates[i] > optionDates[i - 1],
1048 "SSM: got non-increasing option dates "
1049 << optionDates[i - 1] <<
", " << optionDates[i] <<
" for tenors "
1050 << optionTenors[i - 1] <<
", " << optionTenors[i] <<
" for index "
1054 optionDates[i] = wrapper->optionDateFromTenor(optionTenors[i]);
1055 if (iborCalendar != Calendar()) {
1057 optionDates[i] = iborCalendar.adjust(optionDates[i]);
1061 DLOG(
"Option [tenor, date] pair is [" << optionTenors[i] <<
", "
1062 << io::iso_date(optionDates[i]) <<
"]");
1067 "SSM: Expected ibor index for key "
1068 <<
name <<
" from the key or a curve config for a ccy");
1069 auto t0_iborIndex = *initMarket->iborIndex(
1070 IndexNameTranslator::instance().oreName(
iborIndex->name()), configuration);
1072 QL_REQUIRE(!isOis,
"SSM: capFloorVolUseCapATM not supported for OIS indices ("
1073 << t0_iborIndex->name() <<
")");
1074 QuantLib::ext::shared_ptr<CapFloor> cap =
1075 MakeCapFloor(CapFloor::Cap, optionTenors[i], t0_iborIndex, 0.0, 0 * Days);
1076 atmStrike = cap->atmRate(**initMarket->discountCurve(
name, configuration));
1081 QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(t0_iborIndex),
1082 rateComputationPeriod, 0.0)
1085 if (capFloor.empty()) {
1086 atmStrike = t0_iborIndex->fixing(optionDates[i]);
1089 QuantLib::ext::dynamic_pointer_cast<CappedFlooredOvernightIndexedCoupon>(
1091 QL_REQUIRE(lastCoupon,
"SSM internal error, could not cast to "
1092 "CappedFlooredOvernightIndexedCoupon "
1093 "when building optionlet vol for '"
1094 <<
name <<
"', index=" << t0_iborIndex->name());
1095 atmStrike = lastCoupon->underlying()->rate();
1098 atmStrike = t0_iborIndex->fixing(optionDates[i]);
1103 for (Size j = 0; j <
strikes.size(); ++j) {
1104 Real strike = isAtm ? atmStrike :
strikes[j];
1106 wrapper->volatility(optionDates[i], strike,
true);
1107 DLOG(
"Vol at [date, strike] pair [" << optionDates[i] <<
", " << std::fixed
1108 << std::setprecision(4) << strike <<
"] is "
1109 << std::setprecision(12) << vol);
1110 QuantLib::ext::shared_ptr<SimpleQuote> q =
1112 Size index = i *
strikes.size() + j;
1113 simDataTmp.emplace(std::piecewise_construct,
1114 std::forward_as_tuple(param.first,
name, index),
1115 std::forward_as_tuple(q));
1117 absoluteSimDataTmp.emplace(std::piecewise_construct,
1118 std::forward_as_tuple(param.first,
name, index),
1119 std::forward_as_tuple(vol));
1121 quotes[i][j] = Handle<Quote>(q);
1125 std::vector<std::vector<Real>> coordinates(2);
1126 for(Size i=0;i<optionTenors.size();++i) {
1127 coordinates[0].push_back(
1128 wrapper->timeFromReference(wrapper->optionDateFromTenor(optionTenors[i])));
1130 for(Size j=0;j<
strikes.size();++j) {
1131 coordinates[1].push_back(isAtm ? atmStrike :
strikes[j]);
1134 writeSimData(simDataTmp, absoluteSimDataTmp, param.first,
name, coordinates);
1135 simDataWritten =
true;
1137 DayCounter dc = wrapper->dayCounter();
1140 hCapletVol = Handle<OptionletVolatilityStructure>(
1141 QuantLib::ext::make_shared<QuantExt::SpreadedOptionletVolatility2>(wrapper, optionDates,
1146 QuantLib::ext::shared_ptr<StrippedOptionlet> optionlet = QuantLib::ext::make_shared<StrippedOptionlet>(
1147 settleDays, wrapper->calendar(), wrapper->businessDayConvention(),
iborIndex,
1148 optionDates,
strikes, quotes, dc, wrapper->volatilityType(),
1149 wrapper->displacement());
1151 hCapletVol = Handle<OptionletVolatilityStructure>(
1156 string decayModeString = parameters->capFloorVolDecayMode();
1159 QL_REQUIRE(!QuantLib::ext::dynamic_pointer_cast<ProxyOptionletVolatility>(*wrapper),
1160 "DynamicOptionletVolatilityStructure does not support ProxyOptionletVolatility surface.");
1162 QuantLib::ext::shared_ptr<OptionletVolatilityStructure> capletVol =
1163 QuantLib::ext::make_shared<DynamicOptionletVolatilityStructure>(*wrapper, 0, NullCalendar(),
1165 hCapletVol = Handle<OptionletVolatilityStructure>(capletVol);
1167 hCapletVol->setAdjustReferenceDate(
false);
1168 hCapletVol->enableExtrapolation();
1171 std::forward_as_tuple(hCapletVol));
1174 std::forward_as_tuple(std::make_pair(iborIndexName, rateComputationPeriod)));
1176 LOG(
"Simulation market cap/floor volatility type = " << hCapletVol->volatilityType());
1177 }
catch (
const std::exception& e) {
1178 processException(continueOnError, e,
name, param.first, simDataWritten);
1184 for (
const auto&
name : param.second.second) {
1185 bool simDataWritten =
false;
1187 LOG(
"building " <<
name <<
" default curve..");
1188 auto wrapper = initMarket->defaultCurve(
name, configuration);
1189 vector<Handle<Quote>> quotes;
1191 QL_REQUIRE(parameters->defaultTenors(
name).front() > 0 * Days,
1192 "default curve tenors must not include t=0");
1194 vector<Date> dates(1,
asof_);
1195 vector<Real> times(1, 0.0);
1197 DayCounter dc = wrapper->curve()->dayCounter();
1199 for (Size i = 0; i < parameters->defaultTenors(
name).
size(); i++) {
1200 dates.push_back(
asof_ + parameters->defaultTenors(
name)[i]);
1201 times.push_back(dc.yearFraction(
asof_, dates.back()));
1204 QuantLib::ext::shared_ptr<SimpleQuote> q(
new SimpleQuote(1.0));
1205 quotes.push_back(Handle<Quote>(q));
1206 for (Size i = 0; i < dates.size() - 1; i++) {
1207 Probability prob = wrapper->curve()->survivalProbability(dates[i + 1],
true);
1208 QuantLib::ext::shared_ptr<SimpleQuote> q =
1211 if (param.second.first) {
1212 simDataTmp.emplace(std::piecewise_construct,
1213 std::forward_as_tuple(param.first,
name, i),
1214 std::forward_as_tuple(q));
1215 DLOG(
"ScenarioSimMarket default curve " <<
name <<
" survival[" << i <<
"]=" << prob);
1217 absoluteSimDataTmp.emplace(std::piecewise_construct,
1218 std::forward_as_tuple(param.first,
name, i),
1219 std::forward_as_tuple(prob));
1222 Handle<Quote> qh(q);
1223 quotes.push_back(qh);
1226 {std::vector<Real>(std::next(times.begin(), 1), times.end())});
1227 simDataWritten =
true;
1231 defaultCurve = Handle<DefaultProbabilityTermStructure>(
1232 QuantLib::ext::make_shared<QuantExt::SpreadedSurvivalProbabilityTermStructure>(
1233 wrapper->curve(), times, quotes,
1234 parameters->defaultCurveExtrapolation() ==
"FlatZero"
1235 ? QuantExt::SpreadedSurvivalProbabilityTermStructure::Extrapolation::flatZero
1236 : QuantExt::SpreadedSurvivalProbabilityTermStructure::Extrapolation::flatFwd));
1238 defaultCurve = Handle<DefaultProbabilityTermStructure>(
1240 dates, quotes, dc, cal, std::vector<Handle<Quote>>(), std::vector<Date>(),
1242 parameters->defaultCurveExtrapolation() ==
"FlatZero"
1250 Handle<CreditCurve>(QuantLib::ext::make_shared<CreditCurve>(
1251 defaultCurve, wrapper->rateCurve(), wrapper->recovery(), wrapper->refData()))));
1252 }
catch (
const std::exception& e) {
1253 processException(continueOnError, e,
name, param.first, simDataWritten);
1259 for (
const auto&
name : param.second.second) {
1260 bool simDataWritten =
false;
1262 DLOG(
"Adding security recovery rate " <<
name <<
" from configuration " << configuration);
1263 Real v = initMarket->recoveryRate(
name, configuration)->value();
1266 auto m = [v](Real x) {
return x * v; };
1269 Handle<Quote>(QuantLib::ext::make_shared<DerivedQuote<
decltype(m)>>(
1270 Handle<Quote>(q), m))));
1276 if (param.second.first) {
1277 simDataTmp.emplace(std::piecewise_construct,
1279 std::forward_as_tuple(q));
1281 absoluteSimDataTmp.emplace(
1282 std::piecewise_construct,
1284 std::forward_as_tuple(v));
1288 simDataWritten =
true;
1291 }
catch (
const std::exception& e) {
1292 processException(continueOnError, e,
name, param.first, simDataWritten);
1298 for (
const auto&
name : param.second.second) {
1299 bool simDataWritten =
false;
1301 LOG(
"building " <<
name <<
" cds vols..");
1302 Handle<QuantExt::CreditVolCurve> wrapper = initMarket->cdsVol(
name, configuration);
1303 Handle<QuantExt::CreditVolCurve> cvh;
1304 bool stickyStrike =
parameters_->cdsVolSmileDynamics(
name) ==
"StickyStrike";
1305 if (param.second.first) {
1306 LOG(
"Simulating CDS Vols for " <<
name);
1307 vector<Handle<Quote>> quotes;
1308 vector<Volatility> vols;
1310 vector<Date> expiryDates;
1311 DayCounter dc = wrapper->dayCounter();
1312 for (Size i = 0; i < parameters->cdsVolExpiries().
size(); i++) {
1313 Date date =
asof_ + parameters->cdsVolExpiries()[i];
1314 expiryDates.push_back(date);
1316 Volatility vol = wrapper->volatility(date, 5.0, Null<Real>(), wrapper->type());
1317 vols.push_back(vol);
1318 times.push_back(dc.yearFraction(
asof_, date));
1319 QuantLib::ext::shared_ptr<SimpleQuote> q =
1321 if (parameters->simulateCdsVols()) {
1322 simDataTmp.emplace(std::piecewise_construct,
1323 std::forward_as_tuple(param.first,
name, i),
1324 std::forward_as_tuple(q));
1326 absoluteSimDataTmp.emplace(std::piecewise_construct,
1327 std::forward_as_tuple(param.first,
name, i),
1328 std::forward_as_tuple(vol));
1331 quotes.emplace_back(q);
1334 simDataWritten =
true;
1337 std::vector<Handle<Quote>> spreads;
1339 for (
size_t i = 0; i < quotes.size(); i++) {
1340 Handle<Quote> atmVol(QuantLib::ext::make_shared<SimpleQuote>(quotes[i]->
value()));
1341 Handle<Quote> quote(QuantLib::ext::make_shared <
1342 CompositeQuote<std::minus<double>>>(quotes[i], atmVol,
1343 std::minus<double>()));
1344 spreads.push_back(quote);
1349 std::vector<QuantLib::Period> simTerms;
1350 std::vector<Handle<CreditCurve>> simTermCurves;
1354 simTerms = cc->terms();
1355 for (
auto const& c : cc->termCurves())
1359 simTerms = wrapper->terms();
1360 for (
auto const& t : simTerms) {
1364 cvh = Handle<CreditVolCurve>(QuantLib::ext::make_shared<SpreadedCreditVolCurve>(
1365 wrapper, expiryDates, spreads, !stickyStrike, simTerms, simTermCurves));
1368 cvh = Handle<CreditVolCurve>(QuantLib::ext::make_shared<CreditVolCurveWrapper>(
1369 Handle<BlackVolTermStructure>(QuantLib::ext::make_shared<BlackVarianceCurve3>(
1370 0, NullCalendar(), wrapper->businessDayConvention(), dc, times, quotes,
1374 string decayModeString = parameters->cdsVolDecayMode();
1375 LOG(
"Deterministic CDS Vols with decay mode " << decayModeString <<
" for " <<
name);
1379 cvh = Handle<CreditVolCurve>(
1380 QuantLib::ext::make_shared<CreditVolCurveWrapper>(Handle<BlackVolTermStructure>(
1382 Handle<BlackVolTermStructure>(
1383 QuantLib::ext::make_shared<BlackVolFromCreditVolWrapper>(wrapper, 5.0)),
1384 0, NullCalendar(), decayMode,
1387 cvh->setAdjustReferenceDate(
false);
1388 if (wrapper->allowsExtrapolation())
1389 cvh->enableExtrapolation();
1391 }
catch (
const std::exception& e) {
1392 processException(continueOnError, e,
name, param.first, simDataWritten);
1398 for (
const auto&
name : param.second.second) {
1399 bool simDataWritten =
false;
1401 Handle<BlackVolTermStructure> wrapper = initMarket->fxVol(
name, configuration);
1403 QL_REQUIRE(
name.length() == 6,
"invalid ccy pair length");
1404 string forCcy =
name.substr(0, 3);
1405 string domCcy =
name.substr(3, 3);
1410 string domesticTsId;
1413 foreignTsId = fxVolConfig->fxForeignYieldCurveID();
1414 TLOG(
"Got foreign term structure '" << foreignTsId
1415 <<
"' from FX volatility curve config for " <<
name);
1416 domesticTsId = fxVolConfig->fxDomesticYieldCurveID();
1417 TLOG(
"Got domestic term structure '" << domesticTsId
1418 <<
"' from FX volatility curve config for " <<
name);
1420 Handle<BlackVolTermStructure> fvh;
1422 bool stickyStrike =
parameters_->fxVolSmileDynamics(
name) ==
"StickyStrike";
1424 if (param.second.first) {
1425 LOG(
"Simulating FX Vols for " <<
name);
1426 auto& expiries = parameters->fxVolExpiries(
name);
1427 Size m = expiries.size();
1428 Calendar cal = wrapper->calendar();
1430 cal = NullCalendar();
1432 DayCounter dc = wrapper->dayCounter();
1433 vector<vector<Handle<Quote>>> quotes;
1434 vector<Time> times(m);
1435 vector<Date> dates(m);
1438 Handle<YieldTermStructure> initForTS =
1439 getYieldCurve(foreignTsId, todaysMarketParams, configuration, initMarket);
1440 TLOG(
"Foreign term structure '" << foreignTsId <<
"' from t_0 market is "
1441 << (initForTS.empty() ?
"empty" :
"not empty"));
1442 Handle<YieldTermStructure> initDomTS =
1443 getYieldCurve(domesticTsId, todaysMarketParams, configuration, initMarket);
1444 TLOG(
"Domestic term structure '" << domesticTsId <<
"' from t_0 market is "
1445 << (initDomTS.empty() ?
"empty" :
"not empty"));
1448 if (initForTS.empty() || initDomTS.empty()) {
1449 TLOG(
"Falling back on the discount curves for " << forCcy <<
" and " << domCcy
1450 <<
" from t_0 market");
1451 initForTS = initMarket->discountCurve(forCcy, configuration);
1452 initDomTS = initMarket->discountCurve(domCcy, configuration);
1456 Handle<YieldTermStructure> forTS =
1458 TLOG(
"Foreign term structure '" << foreignTsId <<
"' from sim market is "
1459 << (forTS.empty() ?
"empty" :
"not empty"));
1460 Handle<YieldTermStructure> domTS =
1462 TLOG(
"Domestic term structure '" << domesticTsId <<
"' from sim market is "
1463 << (domTS.empty() ?
"empty" :
"not empty"));
1466 if (forTS.empty() || domTS.empty()) {
1467 TLOG(
"Falling back on the discount curves for " << forCcy <<
" and " << domCcy
1468 <<
" from sim market");
1473 for (Size k = 0; k < m; k++) {
1474 dates[k] =
asof_ + expiries[k];
1475 times[k] = wrapper->timeFromReference(dates[k]);
1478 QuantLib::ext::shared_ptr<BlackVolTermStructure> fxVolCurve;
1479 if (parameters->fxVolIsSurface(
name)) {
1481 strikes = parameters->fxUseMoneyness(
name) ? parameters->fxVolMoneyness(
name)
1482 : parameters->fxVolStdDevs(
name);
1484 quotes.resize(n, vector<Handle<Quote>>(m, Handle<Quote>()));
1487 bool flatExtrapolation =
true;
1490 if (parameters->fxUseMoneyness(
name)) {
1491 for (Size j = 0; j < m; j++) {
1492 for (Size i = 0; i < n; i++) {
1495 Real k = spot->value() * mon * initForTS->discount(dates[j]) /
1496 initDomTS->discount(dates[j]);
1497 Size idx = i * m + j;
1499 Volatility vol = wrapper->blackVol(dates[j], k,
true);
1500 QuantLib::ext::shared_ptr<SimpleQuote> q(
1502 simDataTmp.emplace(std::piecewise_construct,
1503 std::forward_as_tuple(param.first,
name, idx),
1504 std::forward_as_tuple(q));
1506 absoluteSimDataTmp.emplace(
1507 std::piecewise_construct,
1508 std::forward_as_tuple(param.first,
name, idx),
1509 std::forward_as_tuple(q->value()));
1511 quotes[i][j] = Handle<Quote>(q);
1514 writeSimData(simDataTmp, absoluteSimDataTmp, param.first,
name, {strikes, times});
1515 simDataWritten =
true;
1518 fxVolCurve = QuantLib::ext::make_shared<SpreadedBlackVolatilitySurfaceMoneynessForward>(
1519 Handle<BlackVolTermStructure>(wrapper), spot, times,
1520 parameters->fxVolMoneyness(
name), quotes,
1521 Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(spot->value())), initForTS,
1522 initDomTS, forTS, domTS, stickyStrike);
1524 fxVolCurve = QuantLib::ext::make_shared<BlackVarianceSurfaceMoneynessForward>(
1525 cal, spot, times, parameters->fxVolMoneyness(
name), quotes, dc, forTS,
1526 domTS, stickyStrike, flatExtrapolation);
1531 vector<Real> atmVols;
1532 for (Size i = 0; i < m; i++) {
1533 Real k = spot->value() * initForTS->discount(dates[i]) / initDomTS->discount(dates[i]);
1535 atmVols.push_back(wrapper->blackVol(dates[i], k));
1536 DLOG(
"on date " << dates[i] <<
": fwd = " << fwds.back()
1537 <<
", atmVol = " << atmVols.back());
1541 Interpolation forwardCurve =
1542 Linear().interpolate(times.begin(), times.end(), fwds.begin());
1543 Interpolation atmVolCurve =
1544 Linear().interpolate(times.begin(), times.end(), atmVols.begin());
1547 vector<vector<Handle<Quote>>> absQuotes(n,
1548 vector<Handle<Quote>>(m, Handle<Quote>()));
1550 parameters->fxVolStdDevs(
name),
1551 forwardCurve, atmVolCurve);
1553 for (Size i = 0; i < n; ++i)
1554 for (Size j = 0; j < m; ++j)
1555 quotes[i][j] = Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(0.0));
1561 for (Size i = 0; i < m; i++) {
1562 for (Size j = 0; j < n; j++) {
1563 Size idx = j * m + i;
1564 QuantLib::ext::shared_ptr<Quote> q = quotes[j][i].currentLink();
1565 QuantLib::ext::shared_ptr<SimpleQuote> sq =
1566 QuantLib::ext::dynamic_pointer_cast<SimpleQuote>(q);
1567 simDataTmp.emplace(std::piecewise_construct,
1568 std::forward_as_tuple(param.first,
name, idx),
1569 std::forward_as_tuple(sq));
1571 absoluteSimDataTmp.emplace(
1572 std::piecewise_construct,
1573 std::forward_as_tuple(param.first,
name, idx),
1574 std::forward_as_tuple(absQuotes[j][i]->value()));
1578 writeSimData(simDataTmp, absoluteSimDataTmp, param.first,
name, {strikes, times});
1579 simDataWritten =
true;
1584 if (parameters->fxUseMoneyness(
name)) {
1587 fxVolCurve = QuantLib::ext::make_shared<SpreadedBlackVolatilitySurfaceStdDevs>(
1588 Handle<BlackVolTermStructure>(wrapper), spot, times,
1589 parameters->fxVolStdDevs(
name), quotes,
1590 Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(spot->value())),
1591 initForTS, initDomTS, forTS, domTS, stickyStrike);
1593 fxVolCurve = QuantLib::ext::make_shared<BlackVarianceSurfaceStdDevs>(
1594 cal, spot, times, parameters->fxVolStdDevs(
name), quotes, dc,
1595 fxInd.currentLink(), stickyStrike, flatExtrapolation);
1600 quotes.resize(1, vector<Handle<Quote>>(m, Handle<Quote>()));
1602 for (Size j = 0; j < m; j++) {
1606 spot->value() * initForTS->discount(dates[j]) / initDomTS->discount(dates[j]);
1607 Volatility vol = wrapper->blackVol(dates[j], f);
1608 QuantLib::ext::shared_ptr<SimpleQuote> q(
1610 simDataTmp.emplace(std::piecewise_construct,
1611 std::forward_as_tuple(param.first,
name, idx),
1612 std::forward_as_tuple(q));
1614 absoluteSimDataTmp.emplace(std::piecewise_construct,
1615 std::forward_as_tuple(param.first,
name, idx),
1616 std::forward_as_tuple(vol));
1618 quotes[0][j] = Handle<Quote>(q);
1622 simDataWritten =
true;
1627 fxVolCurve = QuantLib::ext::make_shared<SpreadedBlackVolatilityCurve>(
1628 Handle<BlackVolTermStructure>(wrapper), times, quotes[0],
1629 !parameters->simulateFxVolATMOnly());
1631 LOG(
"ATM FX Vols (BlackVarianceCurve3) for " <<
name);
1632 QuantLib::ext::shared_ptr<BlackVolTermStructure> atmCurve;
1633 atmCurve = QuantLib::ext::make_shared<BlackVarianceCurve3>(
1634 0, NullCalendar(), wrapper->businessDayConvention(), dc, times, quotes[0],
false);
1637 if (parameters->simulateFxVolATMOnly()) {
1638 LOG(
"Simulating FX Vols (FXVolatilityConstantSpread) for " <<
name);
1639 fxVolCurve = QuantLib::ext::make_shared<BlackVolatilityConstantSpread>(
1640 Handle<BlackVolTermStructure>(atmCurve), wrapper);
1642 fxVolCurve = atmCurve;
1646 fvh = Handle<BlackVolTermStructure>(fxVolCurve);
1649 string decayModeString = parameters->fxVolDecayMode();
1650 LOG(
"Deterministic FX Vols with decay mode " << decayModeString <<
" for " <<
name);
1657 fvh = Handle<BlackVolTermStructure>(
1659 wrapper, 0, NullCalendar(), decayMode,
1663 fvh->setAdjustReferenceDate(
false);
1664 fvh->enableExtrapolation();
1668 QL_REQUIRE(
name.size() == 6,
"Invalid Ccy pair " <<
name);
1669 string reverse =
name.substr(3) +
name.substr(0, 3);
1670 Handle<QuantLib::BlackVolTermStructure> ifvh(
1671 QuantLib::ext::make_shared<BlackInvertedVolTermStructure>(fvh));
1672 ifvh->enableExtrapolation();
1674 }
catch (
const std::exception& e) {
1675 processException(continueOnError, e,
name, param.first, simDataWritten);
1681 for (
const auto&
name : param.second.second) {
1682 bool simDataWritten =
false;
1684 Handle<BlackVolTermStructure> wrapper = initMarket->equityVol(
name, configuration);
1685 Handle<BlackVolTermStructure> evh;
1687 bool stickyStrike =
parameters_->equityVolSmileDynamics(
name) ==
"StickyStrike";
1688 if (param.second.first) {
1690 Handle<Quote> spot = eqCurve->equitySpot();
1691 auto expiries = parameters->equityVolExpiries(
name);
1693 Size m = expiries.size();
1694 vector<vector<Handle<Quote>>> quotes;
1695 vector<Time> times(m);
1696 vector<Date> dates(m);
1700 if (cfg->calendar().empty())
1705 if (cal.empty() || cal == NullCalendar()) {
1707 cal = eqCurve->fixingCalendar();
1709 DayCounter dc = wrapper->dayCounter();
1711 for (Size k = 0; k < m; k++) {
1712 dates[k] = cal.advance(
asof_, expiries[k]);
1713 times[k] = dc.yearFraction(
asof_, dates[k]);
1716 QuantLib::ext::shared_ptr<BlackVolTermStructure> eqVolCurve;
1718 if (parameters->equityVolIsSurface(
name)) {
1721 ? parameters->equityVolMoneyness(
name)
1722 : parameters->equityVolStandardDevs(
name);
1724 quotes.resize(n, vector<Handle<Quote>>(m, Handle<Quote>()));
1726 if (parameters->equityUseMoneyness(
name)) {
1727 for (Size j = 0; j < m; j++) {
1728 for (Size i = 0; i < n; i++) {
1731 Real k = eqCurve->forecastFixing(dates[j]) * mon;
1732 Size idx = i * m + j;
1733 Volatility vol = wrapper->blackVol(dates[j], k);
1734 QuantLib::ext::shared_ptr<SimpleQuote> q(
1736 simDataTmp.emplace(std::piecewise_construct,
1737 std::forward_as_tuple(param.first,
name, idx),
1738 std::forward_as_tuple(q));
1740 absoluteSimDataTmp.emplace(
1741 std::piecewise_construct,
1742 std::forward_as_tuple(param.first,
name, idx),
1743 std::forward_as_tuple(vol));
1745 quotes[i][j] = Handle<Quote>(q);
1748 writeSimData(simDataTmp, absoluteSimDataTmp, param.first,
name, {strikes, times});
1749 simDataWritten =
true;
1750 LOG(
"Simulating EQ Vols (BlackVarianceSurfaceMoneyness) for " <<
name);
1753 eqVolCurve = QuantLib::ext::make_shared<SpreadedBlackVolatilitySurfaceMoneynessForward>(
1754 Handle<BlackVolTermStructure>(wrapper), spot, times,
1755 parameters->equityVolMoneyness(
name), quotes,
1756 Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(spot->value())),
1757 initMarket->equityCurve(
name, configuration)->equityDividendCurve(),
1758 initMarket->equityCurve(
name, configuration)->equityForecastCurve(),
1759 eqCurve->equityDividendCurve(), eqCurve->equityForecastCurve(),
1763 eqVolCurve = QuantLib::ext::make_shared<BlackVarianceSurfaceMoneynessSpot>(
1764 cal, spot, times, parameters->equityVolMoneyness(
name), quotes, dc,
1767 eqVolCurve->enableExtrapolation();
1772 vector<Real> atmVols;
1773 for (Size i = 0; i < expiries.size(); i++) {
1774 auto eqForward = eqCurve->forecastFixing(dates[i]);
1775 fwds.push_back(eqForward);
1776 atmVols.push_back(wrapper->blackVol(dates[i], eqForward));
1777 DLOG(
"on date " << dates[i] <<
": fwd = " << fwds.back()
1778 <<
", atmVol = " << atmVols.back());
1782 Interpolation forwardCurve =
1783 Linear().interpolate(times.begin(), times.end(), fwds.begin());
1784 Interpolation atmVolCurve =
1785 Linear().interpolate(times.begin(), times.end(), atmVols.begin());
1788 vector<vector<Handle<Quote>>> absQuotes(n,
1789 vector<Handle<Quote>>(m, Handle<Quote>()));
1791 forwardCurve, atmVolCurve);
1793 for (Size i = 0; i < n; ++i)
1794 for (Size j = 0; j < m; ++j)
1795 quotes[i][j] = Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(0.0));
1801 for (Size i = 0; i < m; i++) {
1802 for (Size j = 0; j < n; j++) {
1803 Size idx = j * m + i;
1804 QuantLib::ext::shared_ptr<Quote> q = quotes[j][i].currentLink();
1805 QuantLib::ext::shared_ptr<SimpleQuote> sq =
1806 QuantLib::ext::dynamic_pointer_cast<SimpleQuote>(q);
1807 QL_REQUIRE(sq,
"Quote is not a SimpleQuote");
1808 simDataTmp.emplace(std::piecewise_construct,
1809 std::forward_as_tuple(param.first,
name, idx),
1810 std::forward_as_tuple(sq));
1812 absoluteSimDataTmp.emplace(
1813 std::piecewise_construct,
1814 std::forward_as_tuple(param.first,
name, idx),
1815 std::forward_as_tuple(absQuotes[j][i]->value()));
1819 writeSimData(simDataTmp, absoluteSimDataTmp, param.first,
name, {strikes, times});
1820 simDataWritten =
true;
1821 bool flatExtrapolation =
true;
1823 eqVolCurve = QuantLib::ext::make_shared<SpreadedBlackVolatilitySurfaceStdDevs>(
1824 Handle<BlackVolTermStructure>(wrapper), spot, times,
1825 parameters->equityVolStandardDevs(
name), quotes,
1826 Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(spot->value())),
1827 initMarket->equityCurve(
name, configuration)->equityDividendCurve(),
1828 initMarket->equityCurve(
name, configuration)->equityForecastCurve(),
1829 eqCurve->equityDividendCurve(), eqCurve->equityForecastCurve(),
1832 eqVolCurve = QuantLib::ext::make_shared<BlackVarianceSurfaceStdDevs>(
1833 cal, spot, times, parameters->equityVolStandardDevs(
name), quotes, dc,
1834 eqCurve.currentLink(), stickyStrike, flatExtrapolation);
1838 quotes.resize(1, vector<Handle<Quote>>(m, Handle<Quote>()));
1840 for (Size j = 0; j < m; j++) {
1843 auto eqForward = eqCurve->fixing(dates[j]);
1844 Volatility vol = wrapper->blackVol(dates[j], eqForward);
1845 QuantLib::ext::shared_ptr<SimpleQuote> q(
1847 simDataTmp.emplace(std::piecewise_construct,
1848 std::forward_as_tuple(param.first,
name, idx),
1849 std::forward_as_tuple(q));
1851 absoluteSimDataTmp.emplace(std::piecewise_construct,
1852 std::forward_as_tuple(param.first,
name, idx),
1853 std::forward_as_tuple(vol));
1855 quotes[0][j] = Handle<Quote>(q);
1859 simDataWritten =
true;
1864 eqVolCurve = QuantLib::ext::make_shared<SpreadedBlackVolatilityCurve>(
1865 Handle<BlackVolTermStructure>(wrapper), times, quotes[0],
1866 !parameters->simulateEquityVolATMOnly());
1868 LOG(
"ATM EQ Vols (BlackVarianceCurve3) for " <<
name);
1869 QuantLib::ext::shared_ptr<BlackVolTermStructure> atmCurve;
1870 atmCurve = QuantLib::ext::make_shared<BlackVarianceCurve3>(0, NullCalendar(),
1871 wrapper->businessDayConvention(),
1872 dc, times, quotes[0],
false);
1875 if (parameters->simulateEquityVolATMOnly()) {
1876 LOG(
"Simulating EQ Vols (EquityVolatilityConstantSpread) for " <<
name);
1877 eqVolCurve = QuantLib::ext::make_shared<BlackVolatilityConstantSpread>(
1878 Handle<BlackVolTermStructure>(atmCurve), wrapper);
1880 eqVolCurve = atmCurve;
1884 evh = Handle<BlackVolTermStructure>(eqVolCurve);
1887 string decayModeString = parameters->equityVolDecayMode();
1888 DLOG(
"Deterministic EQ Vols with decay mode " << decayModeString <<
" for " <<
name);
1895 evh = Handle<BlackVolTermStructure>(
1897 wrapper, 0, NullCalendar(), decayMode,
1901 evh->setAdjustReferenceDate(
false);
1902 if (wrapper->allowsExtrapolation())
1903 evh->enableExtrapolation();
1905 DLOG(
"EQ volatility curve built for " <<
name);
1906 }
catch (
const std::exception& e) {
1907 processException(continueOnError, e,
name, param.first, simDataWritten);
1913 for (
const auto&
name : param.second.second) {
1914 bool simDataWritten =
false;
1916 Handle<QuantExt::BaseCorrelationTermStructure> wrapper =
1917 initMarket->baseCorrelation(
name, configuration);
1918 if (!param.second.first)
1921 std::vector<Real> times;
1922 Size nd = parameters->baseCorrelationDetachmentPoints().size();
1923 Size nt = parameters->baseCorrelationTerms().size();
1924 vector<vector<Handle<Quote>>> quotes(nd, vector<Handle<Quote>>(nt));
1925 vector<Period> terms(nt);
1926 vector<double> detachmentPoints(nd);
1927 for (Size i = 0; i < nd; ++i) {
1928 Real lossLevel = parameters->baseCorrelationDetachmentPoints()[i];
1929 detachmentPoints[i] = lossLevel;
1930 for (Size j = 0; j < nt; ++j) {
1931 Period term = parameters->baseCorrelationTerms()[j];
1934 times.push_back(wrapper->timeFromReference(
asof_ + term));
1935 Real bc = wrapper->correlation(
asof_ + term, lossLevel,
true);
1936 QuantLib::ext::shared_ptr<SimpleQuote> q =
1938 simDataTmp.emplace(std::piecewise_construct,
1939 std::forward_as_tuple(param.first,
name, i * nt + j),
1940 std::forward_as_tuple(q));
1942 absoluteSimDataTmp.emplace(std::piecewise_construct,
1943 std::forward_as_tuple(param.first,
name, i * nt + j),
1944 std::forward_as_tuple(bc));
1946 quotes[i][j] = Handle<Quote>(q);
1951 simDataTmp, absoluteSimDataTmp, param.first,
name,
1952 {parameters->baseCorrelationDetachmentPoints(), times});
1953 simDataWritten =
true;
1957 terms.push_back(terms[0] + 1 * terms[0].units());
1958 for (Size i = 0; i < nd; ++i)
1959 quotes[i].push_back(quotes[i][0]);
1963 quotes.push_back(vector<Handle<Quote>>(terms.size()));
1964 for (Size j = 0; j < terms.size(); ++j)
1965 quotes[1][j] = quotes[0][j];
1967 if (detachmentPoints[0] < 1.0 && !QuantLib::close_enough(detachmentPoints[0], 1.0)) {
1968 detachmentPoints.push_back(1.0);
1970 detachmentPoints.insert(detachmentPoints.begin(), 0.01);
1974 QuantLib::ext::shared_ptr<QuantExt::BaseCorrelationTermStructure> bcp;
1976 bcp = QuantLib::ext::make_shared<QuantExt::SpreadedBaseCorrelationCurve>(
1977 wrapper, terms, detachmentPoints, quotes);
1978 bcp->enableExtrapolation(wrapper->allowsExtrapolation());
1980 DayCounter dc = wrapper->dayCounter();
1981 bcp = QuantLib::ext::make_shared<InterpolatedBaseCorrelationTermStructure<Bilinear>>(
1982 wrapper->settlementDays(), wrapper->calendar(), wrapper->businessDayConvention(),
1983 terms, detachmentPoints, quotes, dc);
1985 bcp->enableExtrapolation(wrapper->allowsExtrapolation());
1987 bcp->setAdjustReferenceDate(
false);
1988 Handle<QuantExt::BaseCorrelationTermStructure> bch(bcp);
1991 DLOG(
"Base correlations built for " <<
name);
1992 }
catch (
const std::exception& e) {
1993 processException(continueOnError, e,
name, param.first, simDataWritten);
1999 for (
const auto&
name : param.second.second) {
2000 bool simDataWritten =
false;
2002 DLOG(
"adding " <<
name <<
" base CPI price");
2004 initMarket->zeroInflationIndex(
name, configuration);
2009 QuantLib::ext::shared_ptr<InflationIndex> inflationIndex =
2012 auto q = QuantLib::ext::make_shared<SimpleQuote>(baseCPI);
2014 auto m = [baseCPI](Real x) {
return x * baseCPI; };
2015 Handle<InflationIndexObserver> inflObserver(
2016 QuantLib::ext::make_shared<InflationIndexObserver>(
2019 QuantLib::ext::make_shared<DerivedQuote<
decltype(m)>>(Handle<Quote>(q), m)),
2023 Handle<InflationIndexObserver> inflObserver(
2024 QuantLib::ext::make_shared<InflationIndexObserver>(inflationIndex, Handle<Quote>(q),
2028 simDataTmp.emplace(std::piecewise_construct, std::forward_as_tuple(param.first,
name),
2029 std::forward_as_tuple(q));
2031 absoluteSimDataTmp.emplace(std::piecewise_construct,
2032 std::forward_as_tuple(param.first,
name),
2033 std::forward_as_tuple(baseCPI));
2036 simDataWritten =
true;
2037 }
catch (
const std::exception& e) {
2038 processException(continueOnError, e,
name, param.first, simDataWritten);
2044 for (
const auto&
name : param.second.second) {
2045 bool simDataWritten =
false;
2047 LOG(
"building " <<
name <<
" zero inflation curve");
2049 Handle<ZeroInflationIndex> inflationIndex = initMarket->zeroInflationIndex(
name, configuration);
2050 Handle<ZeroInflationTermStructure> inflationTs = inflationIndex->zeroInflationTermStructure();
2051 vector<string> keys(parameters->zeroInflationTenors(
name).size());
2053 Date date0 =
asof_ - inflationTs->observationLag();
2054 DayCounter dc = inflationTs->dayCounter();
2055 vector<Date> quoteDates;
2056 vector<Time> zeroCurveTimes(
2057 1, -dc.yearFraction(inflationPeriod(date0, inflationTs->frequency()).first,
asof_));
2058 vector<Handle<Quote>> quotes;
2059 QL_REQUIRE(parameters->zeroInflationTenors(
name).front() > 0 * Days,
2060 "zero inflation tenors must not include t=0");
2062 for (
auto& tenor : parameters->zeroInflationTenors(
name)) {
2063 Date inflDate = inflationPeriod(date0 + tenor, inflationTs->frequency()).first;
2064 zeroCurveTimes.push_back(dc.yearFraction(
asof_, inflDate));
2065 quoteDates.push_back(
asof_ + tenor);
2068 for (Size i = 1; i < zeroCurveTimes.size(); i++) {
2069 Real rate = inflationTs->zeroRate(quoteDates[i - 1]);
2070 if (inflationTs->hasSeasonality()) {
2071 Date
fixingDate = quoteDates[i - 1] - inflationTs->observationLag();
2072 rate = inflationTs->seasonality()->deseasonalisedZeroRate(
fixingDate,
2073 rate, *inflationTs.currentLink());
2079 quotes.push_back(Handle<Quote>(q));
2081 quotes.push_back(Handle<Quote>(q));
2082 simDataTmp.emplace(std::piecewise_construct,
2083 std::forward_as_tuple(param.first,
name, i - 1),
2084 std::forward_as_tuple(q));
2086 absoluteSimDataTmp.emplace(std::piecewise_construct,
2087 std::forward_as_tuple(param.first,
name, i - 1),
2088 std::forward_as_tuple(rate));
2089 DLOG(
"ScenarioSimMarket zero inflation curve " <<
name <<
" zeroRate[" << i
2094 {std::vector<Real>(std::next(zeroCurveTimes.begin(), 1), zeroCurveTimes.end())});
2095 simDataWritten =
true;
2098 QuantLib::ext::shared_ptr<ZeroInflationTermStructure> zeroCurve;
2101 QuantLib::ext::make_shared<SpreadedZeroInflationCurve>(inflationTs, zeroCurveTimes, quotes);
2103 zeroCurve = QuantLib::ext::make_shared<ZeroInflationCurveObserverMoving<Linear>>(
2104 0, inflationIndex->fixingCalendar(), dc, inflationTs->observationLag(),
2105 inflationTs->frequency(),
false, zeroCurveTimes, quotes,
2106 inflationTs->seasonality());
2109 Handle<ZeroInflationTermStructure> its(zeroCurve);
2110 its->setAdjustReferenceDate(
false);
2111 its->enableExtrapolation();
2112 QuantLib::ext::shared_ptr<ZeroInflationIndex> i =
2114 Handle<ZeroInflationIndex> zh(i);
2117 LOG(
"building " <<
name <<
" zero inflation curve done");
2118 }
catch (
const std::exception& e) {
2119 processException(continueOnError, e,
name, param.first, simDataWritten);
2125 for (
const auto&
name : param.second.second) {
2126 bool simDataWritten =
false;
2128 LOG(
"building " <<
name <<
" zero inflation cap/floor volatility curve...");
2129 Handle<QuantLib::CPIVolatilitySurface> wrapper =
2130 initMarket->cpiInflationCapFloorVolatilitySurface(
name, configuration);
2132 initMarket->zeroInflationIndex(
name, configuration);
2136 Handle<QuantLib::CPIVolatilitySurface> hCpiVol;
2139 if (param.second.first) {
2140 LOG(
"Simulating zero inflation cap/floor vols for index name " <<
name);
2142 DayCounter dc = wrapper->dayCounter();
2143 vector<Period> optionTenors = parameters->zeroInflationCapFloorVolExpiries(
name);
2144 vector<Date> optionDates(optionTenors.size());
2145 vector<Real>
strikes = parameters->zeroInflationCapFloorVolStrikes(
name);
2146 vector<vector<Handle<Quote>>> quotes(
2147 optionTenors.size(), vector<Handle<Quote>>(
strikes.size(), Handle<Quote>()));
2148 for (Size i = 0; i < optionTenors.size(); ++i) {
2149 optionDates[i] = wrapper->optionDateFromTenor(optionTenors[i]);
2150 for (Size j = 0; j <
strikes.size(); ++j) {
2152 wrapper->volatility(optionTenors[i],
strikes[j], wrapper->observationLag(),
2153 wrapper->allowsExtrapolation());
2155 Size index = i *
strikes.size() + j;
2156 simDataTmp.emplace(std::piecewise_construct,
2157 std::forward_as_tuple(param.first,
name, index),
2158 std::forward_as_tuple(q));
2160 absoluteSimDataTmp.emplace(std::piecewise_construct,
2161 std::forward_as_tuple(param.first,
name, index),
2162 std::forward_as_tuple(vol));
2164 quotes[i][j] = Handle<Quote>(q);
2168 std::vector<std::vector<Real>> coordinates(2);
2169 for (Size i = 0; i < optionTenors.size(); ++i) {
2170 coordinates[0].push_back(
2171 wrapper->timeFromReference(wrapper->optionDateFromTenor(optionTenors[i])));
2173 for (Size j = 0; j <
strikes.size(); ++j) {
2174 coordinates[1].push_back(
strikes[j]);
2177 writeSimData(simDataTmp, absoluteSimDataTmp, param.first,
name, coordinates);
2178 simDataWritten =
true;
2183 auto surface = QuantLib::ext::dynamic_pointer_cast<QuantExt::CPIVolatilitySurface>(wrapper.currentLink());
2185 "Internal error, todays market should build QuantExt::CPIVolatiltiySurface "
2186 "instead of QuantLib::CPIVolatilitySurface");
2187 hCpiVol = Handle<QuantLib::CPIVolatilitySurface>(
2188 QuantLib::ext::make_shared<SpreadedCPIVolatilitySurface>(
2189 Handle<QuantExt::CPIVolatilitySurface>(surface), optionDates,
strikes, quotes));
2192 QuantLib::ext::dynamic_pointer_cast<QuantExt::CPIVolatilitySurface>(wrapper.currentLink());
2194 "Internal error, todays market should build QuantExt::CPIVolatiltiySurface "
2195 "instead of QuantLib::CPIVolatilitySurface");
2196 hCpiVol = Handle<QuantLib::CPIVolatilitySurface>(
2199 wrapper->settlementDays(), wrapper->calendar(),
2200 wrapper->businessDayConvention(), wrapper->dayCounter(),
2201 wrapper->observationLag(), surface->capFloorStartDate(), Bilinear(),
2202 surface->volatilityType(), surface->displacement()));
2214 hCpiVol->setAdjustReferenceDate(
false);
2215 if (wrapper->allowsExtrapolation())
2216 hCpiVol->enableExtrapolation();
2219 std::forward_as_tuple(hCpiVol));
2221 }
catch (
const std::exception& e) {
2222 processException(continueOnError, e,
name, param.first, simDataWritten);
2228 for (
const auto&
name : param.second.second) {
2229 bool simDataWritten =
false;
2232 initMarket->yoyInflationIndex(
name, configuration);
2233 Handle<YoYInflationTermStructure> yoyInflationTs =
2235 vector<string> keys(parameters->yoyInflationTenors(
name).size());
2237 Date date0 =
asof_ - yoyInflationTs->observationLag();
2238 DayCounter dc = yoyInflationTs->dayCounter();
2239 vector<Date> quoteDates;
2240 vector<Time> yoyCurveTimes(
2241 1, -dc.yearFraction(inflationPeriod(date0, yoyInflationTs->frequency()).first,
asof_));
2242 vector<Handle<Quote>> quotes;
2243 QL_REQUIRE(parameters->yoyInflationTenors(
name).front() > 0 * Days,
2244 "zero inflation tenors must not include t=0");
2246 for (
auto& tenor : parameters->yoyInflationTenors(
name)) {
2247 Date inflDate = inflationPeriod(date0 + tenor, yoyInflationTs->frequency()).first;
2248 yoyCurveTimes.push_back(dc.yearFraction(
asof_, inflDate));
2249 quoteDates.push_back(
asof_ + tenor);
2252 for (Size i = 1; i < yoyCurveTimes.size(); i++) {
2253 Real rate = yoyInflationTs->yoyRate(quoteDates[i - 1]);
2258 quotes.push_back(Handle<Quote>(q));
2260 quotes.push_back(Handle<Quote>(q));
2261 simDataTmp.emplace(std::piecewise_construct,
2262 std::forward_as_tuple(param.first,
name, i - 1),
2263 std::forward_as_tuple(q));
2265 absoluteSimDataTmp.emplace(std::piecewise_construct,
2266 std::forward_as_tuple(param.first,
name, i - 1),
2267 std::forward_as_tuple(rate));
2268 DLOG(
"ScenarioSimMarket yoy inflation curve " <<
name <<
" yoyRate[" << i <<
"]=" << rate);
2272 {std::vector<Real>(std::next(yoyCurveTimes.begin(), 1), yoyCurveTimes.end())});
2273 simDataWritten =
true;
2275 QuantLib::ext::shared_ptr<YoYInflationTermStructure> yoyCurve;
2280 QuantLib::ext::make_shared<SpreadedYoYInflationCurve>(yoyInflationTs, yoyCurveTimes, quotes);
2282 yoyCurve = QuantLib::ext::make_shared<YoYInflationCurveObserverMoving<Linear>>(
2285 quotes, yoyInflationTs->seasonality());
2287 yoyCurve->setAdjustReferenceDate(
false);
2288 Handle<YoYInflationTermStructure> its(yoyCurve);
2289 its->enableExtrapolation();
2291 Handle<YoYInflationIndex> zh(i);
2293 }
catch (
const std::exception& e) {
2294 processException(continueOnError, e,
name, param.first, simDataWritten);
2300 for (
const auto&
name : param.second.second) {
2301 bool simDataWritten =
false;
2303 LOG(
"building " <<
name <<
" yoy inflation cap/floor volatility curve...");
2304 Handle<QuantExt::YoYOptionletVolatilitySurface> wrapper =
2305 initMarket->yoyCapFloorVol(
name, configuration);
2306 LOG(
"Initial market "
2307 <<
name <<
" yoy inflation cap/floor volatility type = " << wrapper->volatilityType());
2308 Handle<QuantExt::YoYOptionletVolatilitySurface> hYoYCapletVol;
2311 if (param.second.first) {
2312 LOG(
"Simulating yoy inflation optionlet vols for index name " <<
name);
2313 vector<Period> optionTenors = parameters->yoyInflationCapFloorVolExpiries(
name);
2314 vector<Date> optionDates(optionTenors.size());
2315 vector<Real>
strikes = parameters->yoyInflationCapFloorVolStrikes(
name);
2316 vector<vector<Handle<Quote>>> quotes(
2317 optionTenors.size(), vector<Handle<Quote>>(
strikes.size(), Handle<Quote>()));
2318 for (Size i = 0; i < optionTenors.size(); ++i) {
2319 optionDates[i] = wrapper->optionDateFromTenor(optionTenors[i]);
2320 for (Size j = 0; j <
strikes.size(); ++j) {
2322 wrapper->volatility(optionTenors[i],
strikes[j], wrapper->observationLag(),
2323 wrapper->allowsExtrapolation());
2324 QuantLib::ext::shared_ptr<SimpleQuote> q(
2326 Size index = i *
strikes.size() + j;
2327 simDataTmp.emplace(std::piecewise_construct,
2328 std::forward_as_tuple(param.first,
name, index),
2329 std::forward_as_tuple(q));
2331 absoluteSimDataTmp.emplace(std::piecewise_construct,
2332 std::forward_as_tuple(param.first,
name, index),
2333 std::forward_as_tuple(vol));
2335 quotes[i][j] = Handle<Quote>(q);
2336 TLOG(
"ScenarioSimMarket yoy cf vol " <<
name <<
" tenor #" << i <<
" strike #" << j
2341 std::vector<std::vector<Real>> coordinates(2);
2342 for (Size i = 0; i < optionTenors.size(); ++i) {
2343 coordinates[0].push_back(
2344 wrapper->timeFromReference(wrapper->optionDateFromTenor(optionTenors[i])));
2346 for (Size j = 0; j <
strikes.size(); ++j) {
2347 coordinates[1].push_back(
strikes[j]);
2350 writeSimData(simDataTmp, absoluteSimDataTmp, param.first,
name, coordinates);
2351 simDataWritten =
true;
2353 DayCounter dc = wrapper->dayCounter();
2355 QuantLib::ext::shared_ptr<QuantExt::YoYOptionletVolatilitySurface> yoyoptionletvolsurface;
2357 yoyoptionletvolsurface = QuantLib::ext::make_shared<QuantExt::SpreadedYoYVolatilitySurface>(
2358 wrapper, optionDates,
strikes, quotes);
2360 yoyoptionletvolsurface = QuantLib::ext::make_shared<StrippedYoYInflationOptionletVol>(
2361 0, wrapper->calendar(), wrapper->businessDayConvention(), dc,
2362 wrapper->observationLag(), wrapper->frequency(), wrapper->indexIsInterpolated(),
2363 optionDates,
strikes, quotes, wrapper->volatilityType(), wrapper->displacement());
2365 hYoYCapletVol = Handle<QuantExt::YoYOptionletVolatilitySurface>(yoyoptionletvolsurface);
2367 string decayModeString = parameters->yoyInflationCapFloorVolDecayMode();
2369 QuantLib::ext::shared_ptr<QuantExt::DynamicYoYOptionletVolatilitySurface> yoyCapletVol =
2370 QuantLib::ext::make_shared<QuantExt::DynamicYoYOptionletVolatilitySurface>(*wrapper, decayMode);
2371 hYoYCapletVol = Handle<QuantExt::YoYOptionletVolatilitySurface>(yoyCapletVol);
2373 hYoYCapletVol->setAdjustReferenceDate(
false);
2374 if (wrapper->allowsExtrapolation())
2375 hYoYCapletVol->enableExtrapolation();
2378 std::forward_as_tuple(hYoYCapletVol));
2379 LOG(
"Simulation market yoy inflation cap/floor volatility type = "
2380 << hYoYCapletVol->volatilityType());
2381 }
catch (
const std::exception& e) {
2382 processException(continueOnError, e,
name, param.first, simDataWritten);
2389 std::vector<std::string> curveNames;
2390 std::vector<std::string> basisCurves;
2391 for (
const auto&
name : param.second.second) {
2393 Handle<PriceTermStructure> initialCommodityCurve =
2394 initMarket->commodityPriceCurve(
name, configuration);
2395 QuantLib::ext::shared_ptr<CommodityBasisPriceTermStructure> basisCurve =
2396 QuantLib::ext::dynamic_pointer_cast<QuantExt::CommodityBasisPriceTermStructure>(
2397 initialCommodityCurve.currentLink());
2398 if (basisCurve !=
nullptr) {
2399 basisCurves.push_back(
name);
2401 curveNames.push_back(
name);
2404 curveNames.push_back(
name);
2407 curveNames.insert(curveNames.end(), basisCurves.begin(), basisCurves.end());
2409 for (
const auto&
name : curveNames) {
2411 bool simDataWritten =
false;
2413 LOG(
"building commodity curve for " <<
name);
2416 Handle<PriceTermStructure> initialCommodityCurve =
2417 initMarket->commodityPriceCurve(
name, configuration);
2419 bool allowsExtrapolation = initialCommodityCurve->allowsExtrapolation();
2423 vector<Period> simulationTenors = parameters->commodityCurveTenors(
name);
2424 DayCounter commodityCurveDayCounter = initialCommodityCurve->dayCounter();
2425 if (simulationTenors.empty()) {
2426 DLOG(
"simulation tenors are empty, use "
2427 << initialCommodityCurve->pillarDates().size()
2428 <<
" pillar dates from T0 curve to build ssm curve.");
2429 simulationTenors.reserve(initialCommodityCurve->pillarDates().size());
2430 for (
const Date& d : initialCommodityCurve->pillarDates()) {
2431 QL_REQUIRE(d >=
asof_,
"Commodity curve pillar date (" << io::iso_date(d)
2432 <<
") must be after as of ("
2433 << io::iso_date(
asof_) <<
").");
2434 simulationTenors.push_back(Period(d -
asof_, Days));
2439 parameters->setCommodityCurveTenors(
name, simulationTenors);
2441 DLOG(
"using " << simulationTenors.size() <<
" simulation tenors.");
2445 vector<Handle<Quote>> quotes(simulationTenors.size());
2447 for (Size i = 0; i < simulationTenors.size(); i++) {
2448 Date d =
asof_ + simulationTenors[i];
2449 Real price = initialCommodityCurve->price(d, allowsExtrapolation);
2450 times.push_back(initialCommodityCurve->timeFromReference(d));
2451 TLOG(
"Commodity curve: price at " << io::iso_date(d) <<
" is " << price);
2453 QuantLib::ext::shared_ptr<SimpleQuote> quote = QuantLib::ext::make_shared<SimpleQuote>(
2455 quotes[i] = Handle<Quote>(quote);
2458 if (param.second.first) {
2459 simDataTmp.emplace(piecewise_construct, forward_as_tuple(param.first,
name, i),
2460 forward_as_tuple(quote));
2462 absoluteSimDataTmp.emplace(piecewise_construct,
2463 forward_as_tuple(param.first,
name, i),
2464 forward_as_tuple(price));
2469 simDataWritten =
true;
2470 QuantLib::ext::shared_ptr<PriceTermStructure> priceCurve;
2473 vector<Real> simulationTimes;
2474 for (
auto const& t : simulationTenors) {
2475 simulationTimes.push_back(commodityCurveDayCounter.yearFraction(
asof_,
asof_ + t));
2477 if (simulationTimes.front() != 0.0) {
2478 simulationTimes.insert(simulationTimes.begin(), 0.0);
2479 quotes.insert(quotes.begin(), quotes.front());
2483 priceCurve = QuantLib::ext::make_shared<SpreadedPriceTermStructure>(initialCommodityCurve,
2484 simulationTimes, quotes);
2486 priceCurve= QuantLib::ext::make_shared<InterpolatedPriceCurve<LinearFlat>>(
2487 simulationTenors, quotes, commodityCurveDayCounter, initialCommodityCurve->currency());
2490 auto orgBasisCurve =
2491 QuantLib::ext::dynamic_pointer_cast<QuantExt::CommodityBasisPriceTermStructure>(
2492 initialCommodityCurve.currentLink());
2494 Handle<PriceTermStructure> pts;
2495 if (orgBasisCurve ==
nullptr) {
2496 pts = Handle<PriceTermStructure>(priceCurve);
2501 "Internal error in scenariosimmarket: couldn't find underlying base curve '"
2502 << orgBasisCurve->baseIndex()->underlyingName()
2503 <<
"' while building commodity basis curve '" <<
name <<
"'");
2504 pts = Handle<PriceTermStructure>(QuantLib::ext::make_shared<CommodityBasisPriceCurveWrapper>(
2505 orgBasisCurve, baseIndex->second.currentLink(), priceCurve));
2508 pts->setAdjustReferenceDate(
false);
2509 pts->enableExtrapolation(allowsExtrapolation);
2514 forward_as_tuple(commIdx));
2515 }
catch (
const std::exception& e) {
2516 processException(continueOnError, e,
name, param.first, simDataWritten);
2522 for (
const auto&
name : param.second.second) {
2523 bool simDataWritten =
false;
2525 LOG(
"building commodity volatility for " <<
name);
2528 Handle<BlackVolTermStructure> baseVol = initMarket->commodityVolatility(
name, configuration);
2530 Handle<BlackVolTermStructure> newVol;
2531 bool stickyStrike =
parameters_->commodityVolSmileDynamics(
name) ==
"StickyStrike";
2532 if (param.second.first) {
2535 vector<Real> moneyness = parameters->commodityVolMoneyness(
name);
2536 QL_REQUIRE(!moneyness.empty(),
"Commodity volatility moneyness for "
2537 <<
name <<
" should have at least one element.");
2538 sort(moneyness.begin(), moneyness.end());
2539 auto mIt = unique(moneyness.begin(), moneyness.end(),
2540 [](
const Real& x,
const Real& y) { return close(x, y); });
2541 QL_REQUIRE(mIt == moneyness.end(),
2542 "Commodity volatility moneyness values for " <<
name <<
" should be unique.");
2544 vector<Period> expiries = parameters->commodityVolExpiries(
name);
2545 QL_REQUIRE(!expiries.empty(),
"Commodity volatility expiries for "
2546 <<
name <<
" should have at least one element.");
2547 sort(expiries.begin(), expiries.end());
2548 auto eIt = unique(expiries.begin(), expiries.end());
2549 QL_REQUIRE(eIt == expiries.end(),
2550 "Commodity volatility expiries for " <<
name <<
" should be unique.");
2561 bool isSurface = moneyness.size() > 1;
2562 Handle<YieldTermStructure> yts;
2563 Handle<YieldTermStructure> priceYts;
2567 vector<Date> dates{
asof_};
2568 vector<Real> dfs{1.0};
2570 auto discCurve =
discountCurve(priceCurve->currency().code(), configuration);
2571 for (
const auto& expiry : expiries) {
2572 auto d =
asof_ + expiry;
2576 dfs.push_back(discCurve->discount(d,
true));
2579 auto ytsPtr = QuantLib::ext::make_shared<DiscountCurve>(dates, dfs, discCurve->dayCounter());
2580 ytsPtr->enableExtrapolation();
2581 yts = Handle<YieldTermStructure>(ytsPtr);
2582 priceYts = Handle<YieldTermStructure>(
2583 QuantLib::ext::make_shared<PriceTermStructureAdapter>(priceCurve, ytsPtr));
2584 priceYts->enableExtrapolation();
2588 using QuoteRow = vector<Handle<Quote>>;
2589 using QuoteMatrix = vector<QuoteRow>;
2590 QuoteMatrix quotes(moneyness.size(), QuoteRow(expiries.size()));
2593 vector<Date> expiryDates(expiries.size());
2594 vector<Time> expiryTimes(expiries.size());
2595 vector<Real> forwards(expiries.size());
2598 DayCounter dayCounter = baseVol->dayCounter();
2599 for (Size j = 0; j < expiries.size(); ++j) {
2600 Date d =
asof_ + expiries[j];
2602 expiryTimes[j] = dayCounter.yearFraction(
asof_, d);
2603 forwards[j] = priceCurve->price(d);
2608 for (Size i = 0; i < moneyness.size(); ++i) {
2609 for (Size j = 0; j < expiries.size(); ++j) {
2610 Real strike = moneyness[i] * forwards[j];
2611 auto vol = baseVol->blackVol(expiryDates[j], strike);
2614 simDataTmp.emplace(piecewise_construct, forward_as_tuple(param.first,
name, index),
2615 forward_as_tuple(quote));
2617 absoluteSimDataTmp.emplace(piecewise_construct,
2618 forward_as_tuple(param.first,
name, index),
2619 forward_as_tuple(vol));
2621 quotes[i][j] = Handle<Quote>(quote);
2626 writeSimData(simDataTmp, absoluteSimDataTmp, param.first,
name, {moneyness, expiryTimes});
2627 simDataWritten =
true;
2631 DLOG(
"Ssm comm vol for " <<
name <<
" uses BlackVarianceCurve3.");
2634 Handle<BlackVolTermStructure>(QuantLib::ext::make_shared<SpreadedBlackVolatilityCurve>(
2635 Handle<BlackVolTermStructure>(baseVol), expiryTimes, quotes[0],
true));
2637 newVol = Handle<BlackVolTermStructure>(QuantLib::ext::make_shared<BlackVarianceCurve3>(
2638 0, NullCalendar(), baseVol->businessDayConvention(), dayCounter, expiryTimes,
2642 DLOG(
"Ssm comm vol for " <<
name <<
" uses BlackVarianceSurfaceMoneynessSpot.");
2644 bool flatExtrapMoneyness =
true;
2645 Handle<Quote> spot(QuantLib::ext::make_shared<SimpleQuote>(priceCurve->price(0)));
2648 Handle<YieldTermStructure> initMarketYts =
2649 initMarket->discountCurve(priceCurve->currency().code(), configuration);
2650 Handle<QuantExt::PriceTermStructure> priceCurve =
2651 initMarket->commodityPriceCurve(
name, configuration);
2652 Handle<YieldTermStructure> initMarketPriceYts(
2653 QuantLib::ext::make_shared<PriceTermStructureAdapter>(*priceCurve, *initMarketYts));
2655 newVol = Handle<BlackVolTermStructure>(
2656 QuantLib::ext::make_shared<SpreadedBlackVolatilitySurfaceMoneynessForward>(
2657 Handle<BlackVolTermStructure>(baseVol), spot, expiryTimes, moneyness,
2658 quotes, Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(spot->value())),
2659 initMarketPriceYts, initMarketYts, priceYts, yts, stickyStrike));
2661 newVol = Handle<BlackVolTermStructure>(
2662 QuantLib::ext::make_shared<BlackVarianceSurfaceMoneynessForward>(
2663 baseVol->calendar(), spot, expiryTimes, moneyness, quotes, dayCounter,
2664 priceYts, yts, stickyStrike, flatExtrapMoneyness));
2669 string decayModeString = parameters->commodityVolDecayMode();
2670 DLOG(
"Deterministic commodity volatilities with decay mode " << decayModeString <<
" for "
2675 newVol = Handle<BlackVolTermStructure>(
2677 baseVol, 0, NullCalendar(), decayMode,
2681 newVol->setAdjustReferenceDate(
false);
2682 newVol->enableExtrapolation(baseVol->allowsExtrapolation());
2685 forward_as_tuple(newVol));
2687 DLOG(
"Commodity volatility curve built for " <<
name);
2688 }
catch (
const std::exception& e) {
2689 processException(continueOnError, e,
name, param.first, simDataWritten);
2695 for (
const auto&
name : param.second.second) {
2696 bool simDataWritten =
false;
2698 LOG(
"Adding correlations for " <<
name <<
" from configuration " << configuration);
2701 QL_REQUIRE(tokens.size() == 2,
"not a valid correlation pair: " <<
name);
2702 pair<string, string> pair = std::make_pair(tokens[0], tokens[1]);
2704 QuantLib::ext::shared_ptr<QuantExt::CorrelationTermStructure> corr;
2705 Handle<QuantExt::CorrelationTermStructure> baseCorr =
2706 initMarket->correlationCurve(pair.first, pair.second, configuration);
2708 Handle<QuantExt::CorrelationTermStructure> ch;
2709 if (param.second.first) {
2710 Size n = parameters->correlationStrikes().size();
2711 Size m = parameters->correlationExpiries().size();
2712 vector<vector<Handle<Quote>>> quotes(n, vector<Handle<Quote>>(m, Handle<Quote>()));
2713 vector<Time> times(m);
2714 Calendar cal = baseCorr->calendar();
2715 DayCounter dc = baseCorr->dayCounter();
2717 for (Size i = 0; i < n; i++) {
2718 Real strike = parameters->correlationStrikes()[i];
2720 for (Size j = 0; j < m; j++) {
2722 Size idx = i * m + j;
2723 times[j] = dc.yearFraction(
asof_,
asof_ + parameters->correlationExpiries()[j]);
2725 baseCorr->correlation(
asof_ + parameters->correlationExpiries()[j], strike);
2726 QuantLib::ext::shared_ptr<SimpleQuote> q(
2729 std::piecewise_construct,
2731 std::forward_as_tuple(q));
2733 absoluteSimDataTmp.emplace(
2734 std::piecewise_construct,
2736 std::forward_as_tuple(correlation));
2738 quotes[i][j] = Handle<Quote>(q);
2743 {parameters->correlationStrikes(), times});
2744 simDataWritten =
true;
2746 if (n == 1 && m == 1) {
2748 ch = Handle<QuantExt::CorrelationTermStructure>(
2749 QuantLib::ext::make_shared<QuantExt::SpreadedCorrelationCurve>(baseCorr, times,
2752 ch = Handle<QuantExt::CorrelationTermStructure>(QuantLib::ext::make_shared<FlatCorrelation>(
2753 baseCorr->settlementDays(), cal, quotes[0][0], dc));
2755 }
else if (n == 1) {
2757 ch = Handle<QuantExt::CorrelationTermStructure>(
2758 QuantLib::ext::make_shared<QuantExt::SpreadedCorrelationCurve>(baseCorr, times,
2761 ch = Handle<QuantExt::CorrelationTermStructure>(
2766 QL_FAIL(
"only atm or flat correlation termstructures currently supported");
2769 ch->enableExtrapolation(baseCorr->allowsExtrapolation());
2771 ch = Handle<QuantExt::CorrelationTermStructure>(*baseCorr);
2774 ch->setAdjustReferenceDate(
false);
2776 }
catch (
const std::exception& e) {
2777 processException(continueOnError, e,
name, param.first, simDataWritten);
2783 for (
const auto&
name : param.second.second) {
2784 bool simDataWritten =
false;
2786 DLOG(
"Adding cpr " <<
name <<
" from configuration " << configuration);
2787 Real v = initMarket->cpr(
name, configuration)->value();
2790 auto m = [v](Real x) {
return x + v; };
2792 Handle<Quote>(QuantLib::ext::make_shared<DerivedQuote<
decltype(m)>>(
2793 Handle<Quote>(q), m))));
2798 if (param.second.first) {
2799 simDataTmp.emplace(std::piecewise_construct, std::forward_as_tuple(param.first,
name),
2800 std::forward_as_tuple(q));
2802 absoluteSimDataTmp.emplace(std::piecewise_construct,
2803 std::forward_as_tuple(param.first,
name),
2804 std::forward_as_tuple(v));
2808 simDataWritten =
true;
2809 }
catch (
const std::exception& e) {
2810 processException(continueOnError, e,
name, param.first, simDataWritten);
2824 WLOG(
"RiskFactorKey None not yet implemented");
2828 if (!param.second.second.empty()) {
2829 LOG(
"built " << std::left << std::setw(25) << param.first << std::right << std::setw(10)
2830 << param.second.second.size() << std::setprecision(3) << std::setw(15)
2831 <<
static_cast<double>(timer.elapsed().wall) / 1E6 <<
" ms");
2834 }
catch (
const std::exception& e) {
2836 ore::data::StructuredMessage::Group::Curve, e.what(),
2837 {{
"exceptionType",
"ScenarioSimMarket top level catch - this should never happen, "
2838 "contact dev. Results are likely wrong or incomplete."}})
2840 processException(continueOnError, e);
2845 DLOG(
"building swap indices...");
2846 for (
const auto& it : parameters->swapIndices()) {
2847 addSwapIndexToSsm(it.first, continueOnError);
2850 if (offsetScenario_ !=
nullptr && offsetScenario_->isAbsolute() && !useSpreadedTermStructures_) {
2851 auto recastedScenario =
recastScenario(offsetScenario_, offsetScenario_->coordinates(), coordinatesData_);
2852 QL_REQUIRE(recastedScenario !=
nullptr,
"ScenarioSimMarke: Offset Scenario couldn't applied");
2853 for (
auto& [key, quote] : simData_) {
2854 if (recastedScenario->has(key)) {
2855 quote->setValue(recastedScenario->get(key));
2857 QL_FAIL(
"ScenarioSimMarket: Offset Scenario doesnt contain key "
2859 <<
". Internal error, possibly an internal error in the recastScenario method, contact dev.");
2862 }
else if (offsetScenario_ !=
nullptr && offsetScenario_->isAbsolute() && useSpreadedTermStructures_) {
2863 auto recastedScenario =
recastScenario(offsetScenario_, offsetScenario_->coordinates(), coordinatesData_);
2864 QL_REQUIRE(recastedScenario !=
nullptr,
"ScenarioSimMarke: Offset Scenario couldn't applied");
2865 for (
auto& [key, data] : simData_) {
2866 if (recastedScenario->has(key)) {
2868 data->setValue(shift);
2869 absoluteSimData_[key] = recastedScenario->get(key);
2871 QL_FAIL(
"ScenarioSimMarket: Offset Scenario doesnt contain key "
2873 <<
". Internal error, possibly an internal error in the recastScenario method, contact dev.");
2876 }
else if (offsetScenario_ !=
nullptr && !offsetScenario_->isAbsolute() && !useSpreadedTermStructures_) {
2877 auto recastedScenario =
recastScenario(offsetScenario_, offsetScenario_->coordinates(), coordinatesData_);
2878 QL_REQUIRE(recastedScenario !=
nullptr,
"ScenarioSimMarke: Offset Scenario couldn't applied");
2879 for (
auto& [key, quote] : simData_) {
2880 if (recastedScenario->has(key)) {
2883 QL_FAIL(
"ScenarioSimMarket: Offset Scenario doesnt contain key "
2885 <<
". Internal error, possibly an internal error in the recastScenario method, contact dev.");
2888 }
else if (offsetScenario_ !=
nullptr && !offsetScenario_->isAbsolute() && useSpreadedTermStructures_) {
2889 auto recastedScenario =
recastScenario(offsetScenario_, offsetScenario_->coordinates(), coordinatesData_);
2890 QL_REQUIRE(recastedScenario !=
nullptr,
"ScenarioSimMarke: Offset Scenario couldn't applied");
2891 for (
auto& [key, quote] : simData_) {
2892 if (recastedScenario->has(key)) {
2893 quote->setValue(recastedScenario->get(key));
2894 absoluteSimData_[key] =
2897 QL_FAIL(
"ScenarioSimMarket: Offset Scenario doesnt contain key "
2899 <<
". Internal error, possibly an internal error in the recastScenario method, contact dev.");
2904 LOG(
"building base scenario");
2905 auto tmp = QuantLib::ext::make_shared<SimpleScenario>(initMarket->asofDate(),
"BASE", 1.0);
2906 if (!useSpreadedTermStructures_) {
2907 for (
auto const& data : simData_) {
2908 tmp->add(
data.first,
data.second->value());
2910 tmp->setAbsolute(
true);
2911 for (
auto const& [type, name, coordinates] : coordinatesData_) {
2912 tmp->setCoordinates(type, name, coordinates);
2914 baseScenarioAbsolute_ = baseScenario_ = tmp;
2916 auto tmpAbs = QuantLib::ext::make_shared<SimpleScenario>(initMarket->asofDate(),
"BASE", 1.0);
2917 for (
auto const& data : simData_) {
2918 tmp->add(
data.first,
data.second->value());
2920 for (
auto const& data : absoluteSimData_) {
2921 tmpAbs->add(
data.first,
data.second);
2923 tmp->setAbsolute(
false);
2924 tmpAbs->setAbsolute(
true);
2925 for (
auto const& [type, name, coordinates] : coordinatesData_) {
2926 tmp->setCoordinates(type, name, coordinates);
2927 tmpAbs->setCoordinates(type, name, coordinates);
2929 baseScenario_ = tmp;
2930 baseScenarioAbsolute_ = tmpAbs;
2932 LOG(
"building base scenario done");
2935bool ScenarioSimMarket::addSwapIndexToSsm(
const std::string& indexName,
const bool continueOnError) {
2936 auto dsc = parameters_->swapIndices().find(indexName);
2937 if (dsc == parameters_->swapIndices().end()) {
2940 DLOG(
"Adding swap index " << indexName <<
" with discounting index " << dsc->second);
2943 DLOG(
"Adding swap index " << indexName <<
" done.");
2945 }
catch (
const std::exception& e) {
2946 processException(continueOnError, e, indexName);
2951void ScenarioSimMarket::reset() {
2952 auto filterBackup = filter_;
2954 filter_ = QuantLib::ext::make_shared<ScenarioFilter>();
2956 Settings::instance().evaluationDate() = baseScenario_->asof();
2958 numeraire_ = baseScenario_->getNumeraire();
2959 label_ = baseScenario_->label();
2961 cachedSimData_.clear();
2962 cachedSimDataActive_.clear();
2964 applyScenario(baseScenario_);
2966 diffToBaseKeys_.clear();
2968 if (ObservationMode::instance().mode() == ObservationMode::Mode::Unregister) {
2969 QuantLib::ext::shared_ptr<QuantLib::Observable> obs = QuantLib::Settings::instance().evaluationDate();
2970 obs->notifyObservers();
2973 fixingManager_->reset();
2975 filter_ = filterBackup;
2978void ScenarioSimMarket::applyScenario(
const QuantLib::ext::shared_ptr<Scenario>& scenario) {
2980 currentScenario_ = scenario;
2984 auto deltaScenario = QuantLib::ext::dynamic_pointer_cast<DeltaScenario>(scenario);
2989 if (deltaScenario !=
nullptr) {
2990 for (
auto const& key : diffToBaseKeys_) {
2991 auto it = simData_.find(key);
2992 if (it != simData_.end()) {
2993 it->second->setValue(baseScenario_->get(key));
2996 diffToBaseKeys_.clear();
2997 auto delta = deltaScenario->delta();
2998 bool missingPoint =
false;
2999 for (
auto const& key : delta->keys()) {
3000 auto it = simData_.find(key);
3001 if (it == simData_.end()) {
3002 ALOG(
"simulation data point missing for key " << key);
3003 missingPoint =
true;
3005 if (filter_->allow(key)) {
3006 it->second->setValue(delta->get(key));
3007 diffToBaseKeys_.insert(key);
3011 QL_REQUIRE(!missingPoint,
"simulation data points missing from scenario, exit.");
3019 if (cacheSimData_) {
3020 if (
auto s = QuantLib::ext::dynamic_pointer_cast<SimpleScenario>(scenario)) {
3024 if (cachedSimData_.empty() || s->keysHash() != cachedSimDataKeysHash_) {
3025 cachedSimData_.clear();
3026 cachedSimDataKeysHash_ = s->keysHash();
3028 for (
auto const& key : s->keys()) {
3029 auto it = simData_.find(key);
3030 if (it == simData_.end()) {
3031 WLOG(
"simulation data point missing for key " << key);
3032 cachedSimData_.push_back(QuantLib::ext::shared_ptr<SimpleQuote>());
3033 cachedSimDataActive_.push_back(
false);
3036 cachedSimData_.push_back(it->second);
3037 cachedSimDataActive_.push_back(filter_->allow(key));
3040 if (
count != simData_.size() && !allowPartialScenarios_) {
3041 ALOG(
"mismatch between scenario and sim data size, " <<
count <<
" vs " << simData_.size());
3042 for (
auto it : simData_) {
3043 if (!scenario->has(it.first))
3044 WLOG(
"Key " << it.first <<
" missing in scenario");
3046 QL_FAIL(
"mismatch between scenario and sim data size, exit.");
3053 for (
auto const& q : s->data()) {
3054 if (cachedSimDataActive_[i])
3055 cachedSimData_[i]->setValue(q);
3065 const vector<RiskFactorKey>& keys = scenario->keys();
3068 for (
const auto& key : keys) {
3074 auto it = simData_.find(key);
3075 if (it == simData_.end()) {
3076 WLOG(
"simulation data point missing for key " << key);
3078 if (filter_->allow(key)) {
3079 it->second->setValue(scenario->get(key));
3085 if (
count != simData_.size() && !allowPartialScenarios_) {
3086 ALOG(
"mismatch between scenario and sim data size, " <<
count <<
" vs " << simData_.size());
3087 for (
auto it : simData_) {
3088 if (!scenario->has(it.first))
3089 ALOG(
"Key " << it.first <<
" missing in scenario");
3091 QL_FAIL(
"mismatch between scenario and sim data size, exit.");
3095void ScenarioSimMarket::preUpdate() {
3097 if (om == ObservationMode::Mode::Disable)
3098 ObservableSettings::instance().disableUpdates(
false);
3099 else if (om == ObservationMode::Mode::Defer)
3100 ObservableSettings::instance().disableUpdates(
true);
3103void ScenarioSimMarket::updateDate(
const Date& d) {
3105 if (d != Settings::instance().evaluationDate())
3106 Settings::instance().evaluationDate() = d;
3107 else if (om == ObservationMode::Mode::Unregister) {
3114 QuantLib::ext::shared_ptr<QuantLib::Observable> obs = QuantLib::Settings::instance().evaluationDate();
3115 obs->notifyObservers();
3119void ScenarioSimMarket::updateScenario(
const Date& d) {
3120 QL_REQUIRE(scenarioGenerator_ !=
nullptr,
"ScenarioSimMarket::update: no scenario generator set");
3121 auto scenario = scenarioGenerator_->next(d);
3122 QL_REQUIRE(scenario->asof() == d,
3123 "Invalid Scenario date " << scenario->asof() <<
", expected " << d);
3124 numeraire_ = scenario->getNumeraire();
3125 label_ = scenario->label();
3126 applyScenario(scenario);
3129void ScenarioSimMarket::postUpdate(
const Date& d,
bool withFixings) {
3133 if (om == ObservationMode::Mode::Disable) {
3135 ObservableSettings::instance().enableUpdates();
3136 }
else if (om == ObservationMode::Mode::Defer) {
3137 ObservableSettings::instance().enableUpdates();
3142 fixingManager_->update(d);
3145void ScenarioSimMarket::updateAsd(
const Date& d) {
3148 for (
auto i : parameters_->additionalScenarioDataIndices()) {
3149 QuantLib::ext::shared_ptr<QuantLib::Index> index;
3151 index = *iborIndex(i);
3155 index = *swapIndex(i);
3158 QL_REQUIRE(index !=
nullptr,
"ScenarioSimMarket::update() index " << i <<
" not found in sim market");
3159 if (
auto fb = QuantLib::ext::dynamic_pointer_cast<FallbackIborIndex>(index)) {
3161 index = fb->rfrIndex();
3163 asd_->set(index->fixing(index->fixingCalendar().adjust(d)), AggregationScenarioDataType::IndexFixing, i);
3166 for (
auto c : parameters_->additionalScenarioDataCcys()) {
3167 if (c != parameters_->baseCcy())
3168 asd_->set(fxSpot(c + parameters_->baseCcy())->value(), AggregationScenarioDataType::FXSpot, c);
3171 for (Size i = 0; i < parameters_->additionalScenarioDataNumberOfCreditStates(); ++i) {
3172 RiskFactorKey key(RiskFactorKey::KeyType::CreditState, std::to_string(i));
3173 QL_REQUIRE(currentScenario_->has(key),
"scenario does not have key " << key);
3174 asd_->set(currentScenario_->get(key), AggregationScenarioDataType::CreditState, std::to_string(i));
3177 for (
const auto& n : parameters_->additionalScenarioDataSurvivalWeights()) {
3178 RiskFactorKey key(RiskFactorKey::KeyType::SurvivalWeight, n);
3179 QL_REQUIRE(currentScenario_->has(key),
"scenario does not have key " << key);
3180 asd_->set(currentScenario_->get(key), AggregationScenarioDataType::SurvivalWeight, n);
3181 RiskFactorKey rrKey(RiskFactorKey::KeyType::RecoveryRate, n);
3182 QL_REQUIRE(currentScenario_->has(rrKey),
"scenario does not have key " << key);
3183 asd_->set(currentScenario_->get(rrKey), AggregationScenarioDataType::RecoveryRate, n);
3186 asd_->set(numeraire_, AggregationScenarioDataType::Numeraire);
3193 return std::find(nonSimulatedFactors_.begin(), nonSimulatedFactors_.end(), factor) == nonSimulatedFactors_.end();
3196Handle<YieldTermStructure> ScenarioSimMarket::getYieldCurve(
const string& yieldSpecId,
3198 const string& configuration,
3199 const QuantLib::ext::shared_ptr<Market>& market)
const {
3202 if (yieldSpecId.empty())
3203 return Handle<YieldTermStructure>();
3208 for (
const auto& indexMapping : todaysMarketParams.
mapping(MarketObject::IndexCurve, configuration)) {
3209 if (indexMapping.second == yieldSpecId) {
3211 return market->iborIndex(indexMapping.first, configuration)->forwardingTermStructure();
3213 return iborIndex(indexMapping.first, configuration)->forwardingTermStructure();
3221 for (
const auto& yieldMapping : todaysMarketParams.
mapping(MarketObject::YieldCurve, configuration)) {
3222 if (yieldMapping.second == yieldSpecId) {
3224 return market->yieldCurve(yieldMapping.first, configuration);
3226 return yieldCurve(yieldMapping.first, configuration);
3233 if (todaysMarketParams.
hasMarketObject(MarketObject::DiscountCurve)) {
3234 for (
const auto& discountMapping : todaysMarketParams.
mapping(MarketObject::DiscountCurve, configuration)) {
3235 if (discountMapping.second == yieldSpecId) {
3237 return market->discountCurve(discountMapping.first, configuration);
3239 return discountCurve(discountMapping.first, configuration);
3250 return Handle<YieldTermStructure>();
static void populateVolMatrix(const QuantLib::Handle< QuantLib::BlackVolTermStructure > &termStructre, std::vector< std::vector< Handle< QuantLib::Quote > > > "esToPopulate, const std::vector< Real > ×, const std::vector< Real > &stdDevPoints, const QuantLib::Interpolation &forwardCurve, const QuantLib::Interpolation atmVolCurve)
MakeOISCapFloor & withSettlementDays(Natural settlementDays)
MakeOISCapFloor & withTelescopicValueDates(bool telescopicValueDates)
boost::shared_ptr< SwaptionVolatilityStructure > convert() const
Data types stored in the scenario class.
KeyType
Risk Factor types.
@ YoYInflationCapFloorVolatility
@ ZeroInflationCapFloorVolatility
A scenario filter can exclude certain key from updating the scenario.
Simulation Market updated with discrete scenarios.
std::map< RiskFactorKey, QuantLib::ext::shared_ptr< SimpleQuote > > simData_
bool addSwapIndexToSsm(const std::string &indexName, const bool continueOnError)
QuantLib::Handle< QuantLib::YieldTermStructure > getYieldCurve(const std::string &yieldSpecId, const ore::data::TodaysMarketParameters &todaysMarketParams, const std::string &configuration, const QuantLib::ext::shared_ptr< ore::data::Market > &market=nullptr) const
bool useSpreadedTermStructures_
const QuantLib::ext::shared_ptr< ScenarioSimMarketParameters > parameters_
void addYieldCurve(const QuantLib::ext::shared_ptr< Market > &initMarket, const std::string &configuration, const RiskFactorKey::KeyType rf, const string &key, const vector< Period > &tenors, bool &simDataWritten, bool simulate=true, bool spreaded=false)
ScenarioSimMarket(const bool handlePseudoCurrencies)
Constructor.
std::set< std::tuple< RiskFactorKey::KeyType, std::string, std::vector< std::vector< Real > > > > coordinatesData_
IborFallbackConfig iborFallbackConfig_
std::map< RiskFactorKey, Real > absoluteSimData_
void writeSimData(std::map< RiskFactorKey, QuantLib::ext::shared_ptr< SimpleQuote > > &simDataTmp, std::map< RiskFactorKey, Real > &absoluteSimDataTmp, const RiskFactorKey::KeyType keyType, const std::string &name, const std::vector< std::vector< Real > > &coordinates)
const FallbackData & fallbackData(const string &iborIndex) const
bool useRfrCurveInSimulationMarket() const
bool isIndexReplaced(const string &iborIndex, const QuantLib::Date &asof=QuantLib::Date::maxDate()) const
Handle< Quote > fxSpot(const string &ccypair, const string &configuration=Market::defaultConfiguration) const
QuantLib::Handle< QuantExt::FxIndex > fxIndex(const string &fxIndex, const string &configuration=Market::defaultConfiguration) const
static const string defaultConfiguration
Handle< YieldTermStructure > discountCurve(const string &ccy, const string &configuration=Market::defaultConfiguration) const
map< pair< string, string >, Handle< OptionletVolatilityStructure > > capFloorCurves_
string shortSwapIndexBase(const string &key, const string &configuration=Market::defaultConfiguration) const override
string swapIndexBase(const string &key, const string &configuration=Market::defaultConfiguration) const override
virtual Handle< ZeroInflationIndex > zeroInflationIndex(const string &indexName, const string &configuration=Market::defaultConfiguration) const override
Handle< QuantExt::EquityIndex2 > equityCurve(const string &eqName, const string &configuration=Market::defaultConfiguration) const override
map< tuple< string, string, string >, Handle< QuantExt::CorrelationTermStructure > > correlationCurves_
map< pair< string, string >, QuantLib::Handle< QuantExt::EquityIndex2 > > equityCurves_
map< pair< string, string >, Handle< CPIVolatilitySurface > > cpiInflationCapFloorVolatilitySurfaces_
map< pair< string, string >, Handle< QuantExt::InflationIndexObserver > > baseCpis_
map< pair< string, string >, Handle< BlackVolTermStructure > > fxVols_
QuantLib::ext::shared_ptr< FXTriangulation > fx_
map< tuple< string, YieldCurveType, string >, Handle< YieldTermStructure > > yieldCurves_
map< pair< string, string >, QuantLib::Handle< QuantExt::CommodityIndex > > commodityIndices_
map< pair< string, string >, Handle< QuantExt::CreditCurve > > defaultCurves_
map< pair< string, string >, Handle< IborIndex > > iborIndices_
map< pair< string, string >, Handle< YoYOptionletVolatilitySurface > > yoyCapFloorVolSurfaces_
Handle< QuantExt::CreditCurve > defaultCurve(const string &, const string &configuration=Market::defaultConfiguration) const override
map< pair< string, string >, Handle< YoYInflationIndex > > yoyInflationIndices_
map< pair< string, string >, Handle< QuantExt::CreditVolCurve > > cdsVols_
map< pair< string, string >, Handle< Quote > > equitySpots_
map< pair< string, string >, Handle< QuantLib::SwaptionVolatilityStructure > > swaptionCurves_
map< pair< string, string >, Handle< QuantExt::BaseCorrelationTermStructure > > baseCorrelations_
map< pair< string, string >, Handle< Quote > > cprs_
map< pair< string, string >, Handle< Quote > > recoveryRates_
QuantLib::Handle< QuantExt::PriceTermStructure > commodityPriceCurve(const string &commodityName, const string &configuration=Market::defaultConfiguration) const override
Handle< Quote > equitySpot(const string &eqName, const string &configuration=Market::defaultConfiguration) const override
map< pair< string, string >, Handle< ZeroInflationIndex > > zeroInflationIndices_
Handle< SwapIndex > swapIndex(const string &indexName, const string &configuration=Market::defaultConfiguration) const override
map< pair< string, string >, pair< string, string > > swaptionIndexBases_
map< pair< string, string >, Handle< BlackVolTermStructure > > equityVols_
virtual Handle< YoYInflationIndex > yoyInflationIndex(const string &indexName, const string &configuration=Market::defaultConfiguration) const override
map< pair< string, string >, Handle< QuantLib::SwaptionVolatilityStructure > > yieldVolCurves_
map< pair< string, string >, Handle< Quote > > securitySpreads_
Handle< YieldTermStructure > yieldCurve(const YieldCurveType &type, const string &ccy, const string &configuration=Market::defaultConfiguration) const override
Handle< IborIndex > iborIndex(const string &indexName, const string &configuration=Market::defaultConfiguration) const override
map< pair< string, string >, QuantLib::Handle< QuantLib::BlackVolTermStructure > > commodityVols_
map< pair< string, string >, std::pair< string, QuantLib::Period > > capFloorIndexBase_
bool hasConfiguration(const string &configuration) const
const map< string, string > & mapping(const MarketObject o, const string &configuration) const
bool hasMarketObject(const MarketObject &o) const
SafeStack< ValueType > value
QuantLib::ext::shared_ptr< CurveSpec > parseCurveSpec(const string &s)
QuantLib::ext::shared_ptr< ZeroInflationIndex > parseZeroInflationIndex(const string &s, const Handle< ZeroInflationTermStructure > &h=Handle< ZeroInflationTermStructure >())
Calendar parseCalendar(const string &s)
QuantLib::ext::shared_ptr< IborIndex > parseIborIndex(const string &s, const Handle< YieldTermStructure > &h=Handle< YieldTermStructure >())
QuantLib::Date fixingDate(const QuantLib::Date &d, const QuantLib::Period obsLag, const QuantLib::Frequency freq, bool interpolated)
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
RandomVariable log(RandomVariable x)
Real getDifferenceScenario(const RiskFactorKey::KeyType keyType, const Real v1, const Real v2)
RiskFactorKey::KeyType yieldCurveRiskFactor(const ore::data::YieldCurveType y)
Map a yield curve type to a risk factor key type.
QuantLib::ext::shared_ptr< Scenario > recastScenario(const QuantLib::ext::shared_ptr< Scenario > &scenario, const std::map< std::pair< RiskFactorKey::KeyType, std::string >, std::vector< std::vector< Real > > > &oldCoordinates, const std::map< std::pair< RiskFactorKey::KeyType, std::string >, std::vector< std::vector< Real > > > &newCoordinates)
Real addDifferenceToScenario(const RiskFactorKey::KeyType keyType, const Real v, const Real d)
ore::data::YieldCurveType riskFactorYieldCurve(const RiskFactorKey::KeyType rf)
std::vector< std::string > getCorrelationTokens(const std::string &name)
Size size(const ValueType &v)
std::string to_string(const LocationInfo &l)
QuantLib::ext::shared_ptr< QuantExt::CommodityIndex > parseCommodityIndex(const string &name, bool hasPrefix, const Handle< PriceTermStructure > &ts, const Calendar &cal, const bool enforceFutureIndex)
Singleton class to hold global Observation Mode.
A Market class that can be updated by Scenarios.
Scenario utility functions.
vector< string > curveConfigs