38 bool operator()(
const Currency& c1,
const Currency& c2)
const {
return c1.code() < c2.code(); }
43 std::string sc = s +
"_" + c;
53 QL_FAIL(
"did not find model parameter " << s <<
" (when looking for ccy " << c <<
")");
58 const string&
id,
const std::vector<Date>& exDates,
const Date& maturityDate,
59 const std::vector<Currency>& currencies,
const std::vector<Date>& fixingDates,
60 const std::vector<QuantLib::ext::shared_ptr<QuantLib::InterestRateIndex>>& indexes) {
62 DLOG(
"Building multi leg option engine for trade " <<
id <<
"...");
64 QL_REQUIRE(!currencies.empty(),
"CamMcMultiLegOptionEngineBuilder: no currencies given");
65 QL_REQUIRE(fixingDates.size() == indexes.size(),
"CamMcMultiLegOptionEngineBuilder: fixing dates size ("
66 << fixingDates.size() <<
") must match indexes size ("
67 << indexes.size() <<
")");
69 std::vector<Handle<YieldTermStructure>> discountCurves;
72 std::vector<std::pair<CalibrationType, CalibrationStrategy>> validCalPairs = {
79 "CamMcMultiLegOptionEngineBuilder: invalid FxCalibration (" <<
fxCalibration <<
")");
81 QL_REQUIRE(std::find(validCalPairs.begin(), validCalPairs.end(),
82 std::make_pair(
irCalibration, irCalibrationStrategy)) != validCalPairs.end(),
83 "Calibration (" <<
irCalibration <<
") and CalibrationStrategy (" << irCalibrationStrategy
84 <<
") are not allowed in this combination");
90 Real shiftHorizon = 0.5;
94 Date today = Settings::instance().evaluationDate();
95 shiftHorizon = ActualActual(ActualActual::ISDA).yearFraction(today, maturityDate) * shiftHorizon;
99 vector<string> swaptionExStr, swaptionTermStr, swaptionStrikesStr, fxStrikesStr;
100 map<Currency, string, CcyComp> swaptionTermCcyStr;
102 DLOG(
"Building calibration basket from exercise dates");
103 for (Size i = 0; i < exDates.size(); ++i) {
106 swaptionStrikesStr.push_back(
"ATM");
107 fxStrikesStr.push_back(
"ATMF");
108 DLOG(
"added exercsie " << swaptionExStr.back() <<
", term " << swaptionTermStr.back() <<
", strike "
109 << swaptionStrikesStr.back());
112 DLOG(
"Building calibration basket from underlying fixing dates");
114 std::vector<Date> allFixingDates(fixingDates.begin(), fixingDates.end());
115 std::sort(allFixingDates.begin(), allFixingDates.end());
116 auto it = std::unique(allFixingDates.begin(), allFixingDates.end());
117 allFixingDates.resize(it - allFixingDates.begin());
118 for (
auto const& d : allFixingDates) {
120 swaptionTermStr.push_back(
"1Y");
121 swaptionStrikesStr.push_back(
"ATM");
122 fxStrikesStr.push_back(
"ATMF");
123 DLOG(
"added exercise " << swaptionExStr.back() <<
", term tbd, strike " << swaptionStrikesStr.back());
126 for (
auto const& i : indexes) {
127 if (swaptionTermCcyStr.find(i->currency()) == swaptionTermCcyStr.end())
131 for (
auto const& k : swaptionTermCcyStr) {
132 DLOG(
"added term " << k.second <<
" for ccy " << k.first.code());
137 QL_FAIL(
"IR Calibration Strategy " << irCalibrationStrategy
138 <<
" not supported by CamMcMultiLegOptionEngineBuilder");
143 std::vector<QuantLib::ext::shared_ptr<IrModelData>> irData;
144 for (Size i = 0; i < currencies.size(); ++i) {
145 DLOG(
"IR component #" << i <<
" (" << currencies[i].code() <<
")");
150 vector<Real> volTimes =
151 parseListOfValues<Real>(
getCcyValue(
"IrVolatilityTimes", currencies[i].code(),
false), &
parseReal);
152 QL_REQUIRE(vols.size() == volTimes.size() + 1,
"there must be n+1 volatilities ("
153 << vols.size() <<
") for n volatility times ("
154 << volTimes.size() <<
"), for ccy " << currencies[i]);
157 auto lgmData = QuantLib::ext::make_shared<IrLgmData>();
159 lgmData->ccy() = currencies[i].code();
160 lgmData->calibrateH() =
false;
162 lgmData->hValues() = {rev};
163 lgmData->reversionType() = reversionType;
164 lgmData->calibrateA() =
false;
166 lgmData->aValues() = vols;
167 lgmData->aTimes() = volTimes;
170 lgmData->shiftHorizon() = i == 0 ? shiftHorizon : 0.0;
171 lgmData->optionExpiries() = swaptionExStr;
173 if (swaptionTermCcyStr.find(currencies[i]) != swaptionTermCcyStr.end())
174 lgmData->optionTerms() =
175 std::vector<std::string>(swaptionTermStr.size(), swaptionTermCcyStr.at(currencies[i]));
177 lgmData->optionTerms() = swaptionTermStr;
178 lgmData->optionStrikes() = swaptionStrikesStr;
180 irData.push_back(lgmData);
185 std::vector<QuantLib::ext::shared_ptr<FxBsData>> fxData;
186 for (Size i = 1; i < currencies.size(); ++i) {
187 string ccyPair = currencies[i].code() + currencies.front().code();
188 DLOG(
"FX component # " << (i - 1) <<
" (" << ccyPair <<
")");
189 auto bsData = QuantLib::ext::make_shared<FxBsData>();
190 vector<Real> vols = parseListOfValues<Real>(
getCcyValue(
"FxVolatility", ccyPair,
true), &
parseReal);
191 vector<Real> volTimes =
192 parseListOfValues<Real>(
getCcyValue(
"FxVolatilityTimes", currencies[i].code(),
false), &
parseReal);
193 QL_REQUIRE(vols.size() == volTimes.size() + 1,
"there must be n+1 FX volatilities ("
194 << vols.size() <<
") for n volatility times ("
195 << volTimes.size() <<
"), for pair " << ccyPair);
197 std::vector<string> fxExStr(swaptionExStr);
201 while (n < fxExStr.size() &&
parseDate(fxExStr[n]) <= fxvol->maxDate())
204 fxStrikesStr.resize(n);
206 bsData->domesticCcy() = currencies.front().code();
207 bsData->foreignCcy() = currencies[i].code();
211 bsData->sigmaTimes() = volTimes;
212 bsData->sigmaValues() = vols;
213 bsData->optionExpiries() = fxExStr;
214 bsData->optionStrikes() = fxStrikesStr;
215 fxData.push_back(bsData);
220 DLOG(
"Setting correlations (IR-IR, IR-FX, FX-FX)");
221 map<CorrelationKey, Handle<Quote>> corr;
223 if (p.first.substr(0, 5) ==
"Corr_") {
224 std::vector<std::string> tokens;
225 boost::split(tokens, p.first, boost::is_any_of(
"_"));
226 QL_REQUIRE(tokens.size() == 3,
"CamMcMultiLegOptionEngineBuilder: invalid correlation key "
227 << p.first <<
" expected 'Corr_Key1_Key2'");
230 corr[std::make_pair(f_1, f_2)] = Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(
parseReal(p.second)));
231 DLOG(
"added correlation " << tokens[1] <<
" " << tokens[2] <<
" " << p.second);
238 bool continueOnCalibrationError =
globalParameters_.count(
"ContinueOnCalibrationError") > 0 &&
244 auto builder = QuantLib::ext::make_shared<CrossAssetModelBuilder>(
245 market_, QuantLib::ext::make_shared<CrossAssetModelData>(irData, fxData, corr, tolerance), configurationInCcy,
246 configurationXois, configurationXois, configurationInCcy, configurationInCcy, configurationXois, !calibrate,
247 continueOnCalibrationError,
"", SalvagingAlgorithm::Spectral,
id);
253 auto engine = QuantLib::ext::make_shared<McMultiLegOptionEngine>(
261 std::vector<Size>());
267 const string&
id,
const std::vector<Date>& exDates,
const Date& maturityDate,
268 const std::vector<Currency>& currencies,
const std::vector<Date>& fixingDates,
269 const std::vector<QuantLib::ext::shared_ptr<QuantLib::InterestRateIndex>>& indexes) {
272 for (
auto const& c : currencies) {
273 ccysStr += c.code() +
"_";
276 DLOG(
"Building multi leg option engine for ccys " << ccysStr <<
" (from externally given CAM)");
278 QL_REQUIRE(!currencies.empty(),
"CamMcMultiLegOptionEngineBuilder: no currencies given");
279 QL_REQUIRE(fixingDates.size() == indexes.size(),
"CamMcMultiLegOptionEngineBuilder: fixing dates size ("
280 << fixingDates.size() <<
") must match indexes size ("
281 << indexes.size() <<
")");
283 std::vector<Size> externalModelIndices;
284 std::vector<Handle<YieldTermStructure>> discountCurves;
285 std::vector<Size> cIdx;
286 std::vector<QuantLib::ext::shared_ptr<IrModel>> lgm;
287 std::vector<QuantLib::ext::shared_ptr<FxBsParametrization>> fx;
291 bool needBaseCcy = currencies.size() > 1;
296 for (Size i = 0; i <
cam_->components(CrossAssetModel::AssetType::IR); ++i) {
297 if ((i == 0 && needBaseCcy) ||
298 std::find(currencies.begin(), currencies.end(),
cam_->irlgm1f(i)->currency()) != currencies.end()) {
299 lgm.push_back(
cam_->lgm(i));
300 externalModelIndices.push_back(
cam_->pIdx(CrossAssetModel::AssetType::IR, i));
301 cIdx.push_back(
cam_->cIdx(CrossAssetModel::AssetType::IR, i));
303 fx.push_back(
cam_->fxbs(i - 1));
304 externalModelIndices.push_back(
cam_->pIdx(CrossAssetModel::AssetType::FX, i - 1));
305 cIdx.push_back(
cam_->cIdx(CrossAssetModel::AssetType::FX, i - 1));
310 std::sort(externalModelIndices.begin(), externalModelIndices.end());
311 std::sort(cIdx.begin(), cIdx.end());
314 Matrix corr(cIdx.size(), cIdx.size(), 1.0);
315 for (Size i = 0; i < cIdx.size(); ++i) {
316 for (Size j = 0; j < i; ++j) {
317 corr(i, j) = corr(j, i) =
cam_->correlation()(cIdx[i], cIdx[j]);
321 Handle<CrossAssetModel>
model(QuantLib::ext::make_shared<CrossAssetModel>(lgm, fx, corr));
327 auto engine = QuantLib::ext::make_shared<McMultiLegOptionEngine>(
multi leg option engine builder
const std::vector< Date > simulationDates_
const QuantLib::ext::shared_ptr< QuantExt::CrossAssetModel > cam_
QuantLib::ext::shared_ptr< PricingEngine > engineImpl(const string &id, const std::vector< Date > &exDates, const Date &maturityDate, const std::vector< Currency > ¤cies, const std::vector< Date > &fixingDates, const std::vector< QuantLib::ext::shared_ptr< QuantLib::InterestRateIndex > > &indexes) override
std::string getCcyValue(const std::string &s, const std::string &c, const bool mandatory)
QuantLib::ext::shared_ptr< PricingEngine > engineImpl(const string &id, const std::vector< Date > &exDates, const Date &maturityDate, const std::vector< Currency > ¤cies, const std::vector< Date > &fixingDates, const std::vector< QuantLib::ext::shared_ptr< QuantLib::InterestRateIndex > > &indexes) override
QuantLib::ext::shared_ptr< Market > market_
const string & engine() const
Return the engine name.
const string & model() const
Return the model name.
std::string engineParameter(const std::string &p, const std::vector< std::string > &qualifiers={}, const bool mandatory=true, const std::string &defaultValue="") const
const string & configuration(const MarketContext &key)
Return a configuration (or the default one if key not found)
set< std::pair< string, QuantLib::ext::shared_ptr< QuantExt::ModelBuilder > > > modelBuilders_
std::map< std::string, std::string > globalParameters_
map< string, string > modelParameters_
Build a cross asset model.
FX component data for the cross asset model.
SequenceType parseSequenceType(const std::string &s)
Convert string to sequence type.
QuantLib::LsmBasisSystem::PolynomialType parsePolynomType(const std::string &s)
Convert text to QuantLib::LsmBasisSystem::PolynomialType.
Date parseDate(const string &s)
Convert std::string to QuantLib::Date.
bool parseBool(const string &s)
Convert text to bool.
SobolRsg::DirectionIntegers parseSobolRsgDirectionIntegers(const std::string &s)
Convert text to QuantLib::SobolRsg::DirectionIntegers.
Real parseRealOrNull(const string &s)
Convert text to Real, empty string to Null<Real>()
QuantExt::McMultiLegBaseEngine::RegressorModel parseRegressorModel(const std::string &s)
Convert text to QuantExt::McMultiLegBaseEngine::RegressorModel.
Real parseReal(const string &s)
Convert text to Real.
SobolBrownianGenerator::Ordering parseSobolBrownianGeneratorOrdering(const std::string &s)
Convert text to QuantLib::SobolBrownianGenerator::Ordering.
Integer parseInteger(const string &s)
Convert text to QuantLib::Integer.
IR component data for the cross asset model.
Linear Gauss Markov model data.
Classes and functions for log message handling.
#define DLOG(text)
Logging Macro (Level = Debug)
CorrelationFactor parseCorrelationFactor(const string &name, const char separator)
CalibrationType parseCalibrationType(const string &s)
Convert calibration type string into enumerated class value.
CalibrationStrategy parseCalibrationStrategy(const string &s)
Convert calibration strategy string into enumerated class value.
VolatilityType volatilityType(CapFloorVolatilityCurveConfig::VolatilityType type)
Imply QuantLib::VolatilityType from CapFloorVolatilityCurveConfig::VolatilityType.
std::string to_string(const LocationInfo &l)
LgmData::ReversionType parseReversionType(const string &s)
Enum parsers.
LgmData::VolatilityType parseVolatilityType(const string &s)
Serializable Credit Default Swap.
string conversion utilities