27#include <qle/pricingengines/blackmultilegoptionengine.hpp>
31#include <ql/methods/montecarlo/lsmbasissystem.hpp>
32#include <ql/termstructures/yield/zerospreadedtermstructure.hpp>
42QuantLib::ext::shared_ptr<PricingEngine> buildMcEngine(
43 const std::function<
string(
string,
const std::vector<std::string>&,
const bool,
const string&)>& engineParameter,
44 const QuantLib::ext::shared_ptr<LGM>& lgm,
const Handle<YieldTermStructure>& discountCurve,
45 const std::vector<Date>& simulationDates,
const std::vector<Size>& externalModelIndices) {
47 return QuantLib::ext::make_shared<QuantExt::McMultiLegOptionEngine>(
48 lgm,
parseSequenceType(engineParameter(
"Training.Sequence", {},
false,
"SobolBrownianBridge")),
49 parseSequenceType(engineParameter(
"Pricing.Sequence", {},
false,
"SobolBrownianBridge")),
50 parseInteger(engineParameter(
"Training.Samples", {},
true, std::string())),
51 parseInteger(engineParameter(
"Pricing.Samples", {},
false,
"0")),
52 parseInteger(engineParameter(
"Training.Seed", {},
true, std::string())),
53 parseInteger(engineParameter(
"Pricing.Seed", {},
false,
"42")),
54 parseInteger(engineParameter(
"Training.BasisFunctionOrder", {},
true, std::string())),
55 parsePolynomType(engineParameter(
"Training.BasisFunction", {},
true, std::string())),
58 simulationDates, externalModelIndices,
parseBool(engineParameter(
"MinObsDate", {},
false,
"true")),
60 parseRealOrNull(engineParameter(
"RegressionVarianceCutoff", {},
false, std::string())));
67QuantLib::ext::shared_ptr<PricingEngine>
69 const Date&
maturity,
const std::vector<Real>& strikes,
const bool isAmerican,
70 const std::string& discountCurve,
const std::string& securitySpread) {
71 QuantLib::ext::shared_ptr<IborIndex> index;
73 Handle<YieldTermStructure> yts =
76 if (!securitySpread.empty())
77 yts = Handle<YieldTermStructure>(QuantLib::ext::make_shared<ZeroSpreadedTermStructure>(
80 return QuantLib::ext::make_shared<BlackMultiLegOptionEngine>(yts, svts);
84 const std::vector<Date>& expiries,
85 const Date&
maturity,
const std::vector<Real>& strikes,
86 const bool isAmerican) {
87 QuantLib::ext::shared_ptr<IborIndex> index;
90 DLOG(
"Get model data");
94 std::string referenceCalibrationGrid =
modelParameter(
"ReferenceCalibrationGrid", {}, isAmerican,
"");
98 QL_REQUIRE(sigma.size() == sigmaTimes.size() + 1,
"there must be n+1 volatilities (" << sigma.size()
99 <<
") for n volatility times ("
100 << sigmaTimes.size() <<
")");
104 bool continueOnCalibrationError =
globalParameters_.count(
"ContinueOnCalibrationError") > 0 &&
109 auto data = QuantLib::ext::make_shared<IrLgmData>();
112 std::vector<std::pair<CalibrationType, CalibrationStrategy>> validCalPairs = {
119 QL_REQUIRE(std::find(validCalPairs.begin(), validCalPairs.end(),
120 std::make_pair(calibration, calibrationStrategy)) != validCalPairs.end(),
121 "Calibration (" << calibration <<
") and CalibrationStrategy (" << calibrationStrategy
122 <<
") are not allowed in this combination");
126 Date today = Settings::instance().evaluationDate();
127 shiftHorizon = ActualActual(ActualActual::ISDA).yearFraction(today,
maturity) * shiftHorizon;
131 data->qualifier() = key;
132 data->calibrateH() =
false;
134 data->hValues() = {lambda};
135 data->reversionType() = reversionType;
136 data->calibrateA() =
false;
138 data->aValues() = sigma;
139 data->aTimes() = sigmaTimes;
141 data->calibrationType() = calibration;
142 data->shiftHorizon() = shiftHorizon;
143 data->floatSpreadMapping() = floatSpreadMapping;
145 std::vector<Date> effExpiries;
146 std::vector<Real> effStrikes;
148 effExpiries = expiries;
151 QL_REQUIRE(expiries.size() == 2 &&
strikes.size() == 2,
152 "LGMBermudanAmericanSwaptionEngineBuilder::model(): expected 2 expiries and strikes for exercise "
153 "style 'American', got "
154 << expiries.size() <<
" expiries and " <<
strikes.size() <<
" strikes.");
156 DateGrid grid(referenceCalibrationGrid);
157 std::copy_if(grid.
dates().begin(), grid.
dates().end(), std::back_inserter(effExpiries),
158 [&expiries](
const Date& d) { return d >= expiries[0] && d < expiries[1]; });
160 effStrikes.resize(effExpiries.size(), Null<Real>());
162 Real t0 = Actual365Fixed().yearFraction(today, expiries[0]);
163 Real t1 = Actual365Fixed().yearFraction(today, expiries[1]);
164 for (Size i = 0; i < effExpiries.size(); ++i) {
165 Real t = Actual365Fixed().yearFraction(today, effExpiries[i]);
173 DLOG(
"Build LgmData for co-terminal specification");
174 vector<string> expiryDates, termDates;
175 for (Size i = 0; i < effExpiries.size(); ++i) {
176 expiryDates.push_back(
to_string(effExpiries[i]));
179 data->optionExpiries() = expiryDates;
180 data->optionTerms() = termDates;
181 data->optionStrikes().resize(expiryDates.size(),
"ATM");
183 for (Size i = 0; i < effExpiries.size(); ++i) {
184 if (effStrikes[i] != Null<Real>())
185 data->optionStrikes()[i] = std::to_string(effStrikes[i]);
189 DLOG(
"Calibrate piecewise alpha");
191 data->calibrateH() =
false;
193 data->hValues() = {lambda};
194 data->calibrateA() =
true;
196 data->aValues() = {sigma};
198 DLOG(
"Calibrate constant sigma");
200 data->calibrateH() =
false;
202 data->hValues() = {lambda};
203 data->calibrateA() =
true;
205 data->aValues() = {sigma};
207 QL_FAIL(
"choice of calibration type invalid");
210 bool generateAdditionalResults =
false;
213 generateAdditionalResults =
parseBool(p->second);
217 DLOG(
"Build LGM model");
218 QuantLib::ext::shared_ptr<LgmBuilder> calib = QuantLib::ext::make_shared<LgmBuilder>(
220 referenceCalibrationGrid, generateAdditionalResults,
id);
223 QuantLib::ext::shared_ptr<QuantExt::LGM>
model;
226 model = calib->model();
228 DLOG(
"Skip calibration of model based on global parameters");
230 model = calib->model();
238QuantLib::ext::shared_ptr<PricingEngine>
240 const Date&
maturity,
const std::vector<Real>& strikes,
const bool isAmerican,
241 const std::string& discountCurve,
const std::string& securitySpread) {
242 DLOG(
"Building LGM Grid Bermudan/American Swaption engine for trade " <<
id);
244 QuantLib::ext::shared_ptr<QuantExt::LGM> lgm =
model(
id, key, expiries,
maturity,
strikes, isAmerican);
246 DLOG(
"Get engine data");
254 QuantLib::ext::shared_ptr<IborIndex> index;
255 std::string ccy =
tryParseIborIndex(key, index) ? index->currency().code() : key;
256 Handle<YieldTermStructure> yts =
259 if (!securitySpread.empty())
260 yts = Handle<YieldTermStructure>(QuantLib::ext::make_shared<ZeroSpreadedTermStructure>(
262 return QuantLib::ext::make_shared<QuantExt::NumericLgmMultiLegOptionEngine>(
266QuantLib::ext::shared_ptr<PricingEngine>
268 const Date&
maturity,
const std::vector<Real>& strikes,
const bool isAmerican,
269 const std::string& discountCurve,
const std::string& securitySpread) {
270 DLOG(
"Building LGM FD Bermudan/American Swaption engine for trade " <<
id);
272 QuantLib::ext::shared_ptr<QuantExt::LGM> lgm =
model(
id, key, expiries,
maturity,
strikes, isAmerican);
274 DLOG(
"Get engine data");
280 Real maxTime = lgm->termStructure()->timeFromReference(
maturity);
283 QuantLib::ext::shared_ptr<IborIndex> index;
284 std::string ccy =
tryParseIborIndex(key, index) ? index->currency().code() : key;
285 Handle<YieldTermStructure> yts =
288 if (!securitySpread.empty())
289 yts = Handle<YieldTermStructure>(QuantLib::ext::make_shared<ZeroSpreadedTermStructure>(
291 return QuantLib::ext::make_shared<QuantExt::NumericLgmMultiLegOptionEngine>(
292 lgm, maxTime, scheme, stateGridPoints, timeStepsPerYear, mesherEpsilon, yts,
296QuantLib::ext::shared_ptr<PricingEngine>
298 const Date&
maturity,
const std::vector<Real>& strikes,
const bool isAmerican,
299 const std::string& discountCurve,
const std::string& securitySpread) {
300 DLOG(
"Building MC Bermudan/American Swaption engine for trade " <<
id);
306 QuantLib::ext::shared_ptr<IborIndex> index;
307 std::string ccy =
tryParseIborIndex(key, index) ? index->currency().code() : key;
308 Handle<YieldTermStructure> yts =
311 if (!securitySpread.empty())
312 yts = Handle<YieldTermStructure>(QuantLib::ext::make_shared<ZeroSpreadedTermStructure>(
314 return buildMcEngine([
this](
const std::string& p,
const std::vector<std::string>& q,
const bool m,
316 lgm, yts, std::vector<Date>(), std::vector<Size>());
319QuantLib::ext::shared_ptr<PricingEngine>
321 const Date&
maturity,
const std::vector<Real>& strikes,
const bool isAmerican,
322 const std::string& discountCurve,
const std::string& securitySpread) {
323 QuantLib::ext::shared_ptr<IborIndex> index;
324 std::string ccy =
tryParseIborIndex(key, index) ? index->currency().code() : key;
326 DLOG(
"Building AMC Bermudan/American Swaption engine for key " << key <<
", ccy " << ccy
327 <<
" (from externally given CAM)");
329 QL_REQUIRE(
cam_ !=
nullptr,
"LgmCamBermudanAmericanSwaptionEngineBuilder::engineImpl: cam is null");
330 Size currIdx =
cam_->ccyIndex(curr);
331 auto lgm =
cam_->lgm(currIdx);
332 std::vector<Size> modelIndex(1,
cam_->pIdx(CrossAssetModel::AssetType::IR, currIdx));
336 Handle<YieldTermStructure> yts =
339 if (!securitySpread.empty())
340 yts = Handle<YieldTermStructure>(QuantLib::ext::make_shared<ZeroSpreadedTermStructure>(
342 return buildMcEngine([
this](
const std::string& p,
const std::vector<std::string>& q,
const bool m,
const std::vector< QuantLib::Date > & dates() const
QuantLib::ext::shared_ptr< Market > market_
const string & model() const
Return the model name.
std::string modelParameter(const std::string &p, const std::vector< std::string > &qualifiers={}, const bool mandatory=true, const std::string &defaultValue="") const
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_
QuantLib::ext::shared_ptr< PricingEngine > engineImpl(const string &id, const string &key, const std::vector< Date > &dates, const Date &maturity, const std::vector< Real > &strikes, const bool isAmerican, const std::string &discountCurve, const std::string &securitySpread) override
const std::vector< Date > simulationDates_
const QuantLib::ext::shared_ptr< QuantExt::CrossAssetModel > cam_
QuantLib::ext::shared_ptr< PricingEngine > engineImpl(const string &id, const string &key, const std::vector< Date > &dates, const Date &maturity, const std::vector< Real > &strikes, const bool isAmerican, const std::string &discountCurve, const std::string &securitySpread) override
QuantLib::ext::shared_ptr< PricingEngine > engineImpl(const string &id, const string &key, const std::vector< Date > &dates, const Date &maturity, const std::vector< Real > &strikes, const bool isAmerican, const std::string &discountCurve, const std::string &securitySpread) override
QuantLib::ext::shared_ptr< PricingEngine > engineImpl(const string &id, const string &key, const std::vector< Date > &dates, const Date &maturity, const std::vector< Real > &strikes, const bool isAmerican, const std::string &discountCurve, const std::string &securitySpread) override
QuantLib::ext::shared_ptr< PricingEngine > engineImpl(const string &id, const string &key, const std::vector< Date > &dates, const Date &maturity, const std::vector< Real > &strikes, const bool isAmerican, const std::string &discountCurve, const std::string &securitySpread) override
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.
bool tryParseIborIndex(const string &s, QuantLib::ext::shared_ptr< IborIndex > &index)
Try to convert std::string to QuantLib::IborIndex.
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
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.
FdmSchemeDesc parseFdmSchemeDesc(const std::string &s)
Convert string to fdm scheme desc.
Integer parseInteger(const string &s)
Convert text to QuantLib::Integer.
#define DLOG(text)
Logging Macro (Level = Debug)
market data related utilties
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.
Handle< YieldTermStructure > indexOrYieldCurve(const QuantLib::ext::shared_ptr< Market > &market, const std::string &name, const std::string &configuration)
std::string to_string(const LocationInfo &l)
LgmData::ReversionType parseReversionType(const string &s)
Enum parsers.
QuantExt::AnalyticLgmSwaptionEngine::FloatSpreadMapping parseFloatSpreadMapping(const string &s)
LgmData::VolatilityType parseVolatilityType(const string &s)
Serializable Credit Default Swap.
Map text representations to QuantLib/QuantExt types.
string conversion utilities