1919#include < ored/model/lgmbuilder.hpp>
2020#include < ored/portfolio/builders/swaption.hpp>
2121#include < ored/utilities/dategrid.hpp>
22+ #include < ored/utilities/marketdata.hpp>
2223#include < ored/utilities/parsers.hpp>
2324#include < ored/utilities/to_string.hpp>
2425
2829#include < qle/pricingengines/numericlgmmultilegoptionengine.hpp>
2930
3031#include < ql/methods/montecarlo/lsmbasissystem.hpp>
32+ #include < ql/termstructures/yield/zerospreadedtermstructure.hpp>
3133
3234#include < set>
3335
@@ -61,14 +63,18 @@ boost::shared_ptr<PricingEngine> buildMcEngine(
6163namespace ore {
6264namespace data {
6365
64- boost::shared_ptr<PricingEngine> EuropeanSwaptionEngineBuilder::engineImpl (const string& id, const string& key,
65- const std::vector<Date>& dates,
66- const Date& maturity,
67- const std::vector<Real>& strikes,
68- const bool isAmerican) {
66+ boost::shared_ptr<PricingEngine>
67+ EuropeanSwaptionEngineBuilder::engineImpl (const string& id, const string& key, const std::vector<Date>& dates,
68+ const Date& maturity, const std::vector<Real>& strikes, const bool isAmerican,
69+ const std::string& discountCurve, const std::string& securitySpread) {
6970 boost::shared_ptr<IborIndex> index;
7071 string ccyCode = tryParseIborIndex (key, index) ? index->currency ().code () : key;
71- Handle<YieldTermStructure> yts = market_->discountCurve (ccyCode, configuration (MarketContext::pricing));
72+ Handle<YieldTermStructure> yts =
73+ discountCurve.empty () ? market_->discountCurve (ccyCode, configuration (MarketContext::pricing))
74+ : indexOrYieldCurve (market_, discountCurve, configuration (MarketContext::pricing));
75+ if (!securitySpread.empty ())
76+ yts = Handle<YieldTermStructure>(boost::make_shared<ZeroSpreadedTermStructure>(
77+ yts, market_->securitySpread (securitySpread, configuration (MarketContext::pricing))));
7278 Handle<SwaptionVolatilityStructure> svts = market_->swaptionVol (key, configuration (MarketContext::pricing));
7379 return boost::make_shared<BlackMultiLegOptionEngine>(yts, svts);
7480}
@@ -225,11 +231,10 @@ boost::shared_ptr<QuantExt::LGM> LGMSwaptionEngineBuilder::model(const string& i
225231 return model;
226232}
227233
228- boost::shared_ptr<PricingEngine> LGMGridSwaptionEngineBuilder::engineImpl (const string& id, const string& key,
229- const std::vector<Date>& expiries,
230- const Date& maturity,
231- const std::vector<Real>& strikes,
232- const bool isAmerican) {
234+ boost::shared_ptr<PricingEngine>
235+ LGMGridSwaptionEngineBuilder::engineImpl (const string& id, const string& key, const std::vector<Date>& expiries,
236+ const Date& maturity, const std::vector<Real>& strikes, const bool isAmerican,
237+ const std::string& discountCurve, const std::string& securitySpread) {
233238 DLOG (" Building LGM Grid Bermudan/American Swaption engine for trade " << id);
234239
235240 boost::shared_ptr<QuantExt::LGM> lgm = model (id, key, expiries, maturity, strikes, isAmerican);
@@ -244,14 +249,20 @@ boost::shared_ptr<PricingEngine> LGMGridSwaptionEngineBuilder::engineImpl(const
244249 DLOG (" Build engine (configuration " << configuration (MarketContext::pricing) << " )" );
245250 boost::shared_ptr<IborIndex> index;
246251 std::string ccy = tryParseIborIndex (key, index) ? index->currency ().code () : key;
252+ Handle<YieldTermStructure> yts =
253+ discountCurve.empty () ? market_->discountCurve (ccy, configuration (MarketContext::pricing))
254+ : indexOrYieldCurve (market_, discountCurve, configuration (MarketContext::pricing));
255+ if (!securitySpread.empty ())
256+ yts = Handle<YieldTermStructure>(boost::make_shared<ZeroSpreadedTermStructure>(
257+ yts, market_->securitySpread (securitySpread, configuration (MarketContext::pricing))));
247258 return boost::make_shared<QuantExt::NumericLgmMultiLegOptionEngine>(
248- lgm, sy, ny, sx, nx, market_->discountCurve (ccy, configuration (MarketContext::pricing)),
249- isAmerican ? parseInteger (modelParameter (" ExerciseTimeStepsPerYear" )) : 0 );
259+ lgm, sy, ny, sx, nx, yts, isAmerican ? parseInteger (modelParameter (" ExerciseTimeStepsPerYear" )) : 0 );
250260}
251261
252262boost::shared_ptr<PricingEngine>
253263LGMFDSwaptionEngineBuilder::engineImpl (const string& id, const string& key, const std::vector<Date>& expiries,
254- const Date& maturity, const std::vector<Real>& strikes, const bool isAmerican) {
264+ const Date& maturity, const std::vector<Real>& strikes, const bool isAmerican,
265+ const std::string& discountCurve, const std::string& securitySpread) {
255266 DLOG (" Building LGM FD Bermudan/American Swaption engine for trade " << id);
256267
257268 boost::shared_ptr<QuantExt::LGM> lgm = model (id, key, expiries, maturity, strikes, isAmerican);
@@ -267,15 +278,21 @@ LGMFDSwaptionEngineBuilder::engineImpl(const string& id, const string& key, cons
267278 DLOG (" Build engine (configuration " << configuration (MarketContext::pricing) << " )" );
268279 boost::shared_ptr<IborIndex> index;
269280 std::string ccy = tryParseIborIndex (key, index) ? index->currency ().code () : key;
281+ Handle<YieldTermStructure> yts =
282+ discountCurve.empty () ? market_->discountCurve (ccy, configuration (MarketContext::pricing))
283+ : indexOrYieldCurve (market_, discountCurve, configuration (MarketContext::pricing));
284+ if (!securitySpread.empty ())
285+ yts = Handle<YieldTermStructure>(boost::make_shared<ZeroSpreadedTermStructure>(
286+ yts, market_->securitySpread (securitySpread, configuration (MarketContext::pricing))));
270287 return boost::make_shared<QuantExt::NumericLgmMultiLegOptionEngine>(
271- lgm, maxTime, scheme, stateGridPoints, timeStepsPerYear, mesherEpsilon,
272- market_->discountCurve (ccy, configuration (MarketContext::pricing)),
288+ lgm, maxTime, scheme, stateGridPoints, timeStepsPerYear, mesherEpsilon, yts,
273289 isAmerican ? parseInteger (modelParameter (" ExerciseTimeStepsPerYear" )) : 0 );
274290}
275291
276292boost::shared_ptr<PricingEngine>
277293LGMMCSwaptionEngineBuilder::engineImpl (const string& id, const string& key, const std::vector<Date>& expiries,
278- const Date& maturity, const std::vector<Real>& strikes, const bool isAmerican) {
294+ const Date& maturity, const std::vector<Real>& strikes, const bool isAmerican,
295+ const std::string& discountCurve, const std::string& securitySpread) {
279296 DLOG (" Building MC Bermudan/American Swaption engine for trade " << id);
280297
281298 auto lgm = model (id, key, expiries, maturity, strikes, isAmerican);
@@ -284,15 +301,21 @@ LGMMCSwaptionEngineBuilder::engineImpl(const string& id, const string& key, cons
284301 DLOG (" Build engine (configuration " << configuration (MarketContext::pricing) << " )" );
285302 boost::shared_ptr<IborIndex> index;
286303 std::string ccy = tryParseIborIndex (key, index) ? index->currency ().code () : key;
287- auto discountCurve = market_->discountCurve (ccy, configuration (MarketContext::pricing));
304+ Handle<YieldTermStructure> yts =
305+ discountCurve.empty () ? market_->discountCurve (ccy, configuration (MarketContext::pricing))
306+ : indexOrYieldCurve (market_, discountCurve, configuration (MarketContext::pricing));
307+ if (!securitySpread.empty ())
308+ yts = Handle<YieldTermStructure>(boost::make_shared<ZeroSpreadedTermStructure>(
309+ yts, market_->securitySpread (securitySpread, configuration (MarketContext::pricing))));
288310 return buildMcEngine ([this ](const std::string& p, const std::vector<std::string>& q, const bool m,
289311 const std::string& d) { return this ->engineParameter (p, q, m, d); },
290- lgm, discountCurve , std::vector<Date>(), std::vector<Size>());
312+ lgm, yts , std::vector<Date>(), std::vector<Size>());
291313} // LgmMc engineImpl()
292314
293315boost::shared_ptr<PricingEngine>
294316LGMAmcSwaptionEngineBuilder::engineImpl (const string& id, const string& key, const std::vector<Date>& expiries,
295- const Date& maturity, const std::vector<Real>& strikes, const bool isAmerican) {
317+ const Date& maturity, const std::vector<Real>& strikes, const bool isAmerican,
318+ const std::string& discountCurve, const std::string& securitySpread) {
296319 boost::shared_ptr<IborIndex> index;
297320 std::string ccy = tryParseIborIndex (key, index) ? index->currency ().code () : key;
298321 Currency curr = parseCurrency (ccy);
@@ -306,11 +329,15 @@ LGMAmcSwaptionEngineBuilder::engineImpl(const string& id, const string& key, con
306329
307330 // Build engine
308331 DLOG (" Build engine (configuration " << configuration (MarketContext::pricing) << " )" );
309- // we assume that the given cam has pricing discount curves attached already
310- Handle<YieldTermStructure> discountCurve;
332+ Handle<YieldTermStructure> yts =
333+ discountCurve.empty () ? market_->discountCurve (ccy, configuration (MarketContext::pricing))
334+ : indexOrYieldCurve (market_, discountCurve, configuration (MarketContext::pricing));
335+ if (!securitySpread.empty ())
336+ yts = Handle<YieldTermStructure>(boost::make_shared<ZeroSpreadedTermStructure>(
337+ yts, market_->securitySpread (securitySpread, configuration (MarketContext::pricing))));
311338 return buildMcEngine ([this ](const std::string& p, const std::vector<std::string>& q, const bool m,
312339 const std::string& d) { return this ->engineParameter (p, q, m, d); },
313- lgm, discountCurve , simulationDates_, modelIndex);
340+ lgm, yts , simulationDates_, modelIndex);
314341} // LgmCam engineImpl
315342
316343} // namespace data
0 commit comments