Skip to content

Commit e2508b7

Browse files
author
jenkins
committed
git subrepo pull (merge) ore
subrepo: subdir: "ore" merged: "be37222c1e" upstream: origin: "git@gitlab.acadiasoft.net:qs/ore.git" branch: "master" commit: "989545210c" git-subrepo: version: "0.4.6" origin: "https://github.com/ingydotnet/git-subrepo" commit: "73a0129"
2 parents 044ae6e + 9895452 commit e2508b7

9 files changed

Lines changed: 136 additions & 70 deletions

File tree

Docs/UserGuide/parameterisation/pricingengines.tex

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,8 @@ \subsubsection{Product Type: EuropeanSwaption}
355355
\item VolatilityType: Hagan, HullWhite
356356
\item ShiftHorizon: Shift horizon for LGM model as fraction of deal maturity
357357
\item Tolerance: Error tolerance for calibration
358+
\item FloatSpreadMapping: mapping of float spreads in analytic swaption pricing for model calibration: proRata,
359+
nextCoupon, simple, optional, defaults to proRata.
358360
\item sy, sx: Number of covered standard deviations (notation as in Hagan's paper)
359361
\item ny, nx: Number of grid points for numerical integration (notation as in Hagan's paper)
360362
\item SensitivityTemplate [optional]: the sensitivity template to use
@@ -374,6 +376,7 @@ \subsubsection{Product Type: EuropeanSwaption}
374376
<Parameter name="VolatilityType">Hagan</Parameter>
375377
<Parameter name="ShiftHorizon">0.5</Parameter>
376378
<Parameter name="Tolerance">0.20</Parameter>
379+
<Parameter name="FloatSpreadMapping">proRata</Parameter>
377380
</ModelParameters>
378381
<Engine>Grid</Engine>
379382
<EngineParameters>

Docs/UserGuide/userguide.tex

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5204,6 +5204,7 @@ \subsubsection{Model}\label{sec:sim_model}
52045204
<ShiftHorizon>0.0</ShiftHorizon>
52055205
<Scaling>1.0</Scaling>
52065206
</ParameterTransformation>
5207+
<FloatSpreadMapping>proRata</FloatSpreadMapping>
52075208
</LGM>
52085209
<LGM ccy="EUR">
52095210
<!-- ... -->
@@ -5241,6 +5242,8 @@ \subsubsection{Model}\label{sec:sim_model}
52415242
\item {\tt ParameterTransformation: } LGM model prices are invariant under scaling and shift transformations
52425243
\cite{Lichters} with advantages for numerical convergence of results in long term simulations. These transformations can
52435244
be chosen here. Default settings are shiftHorizon 0 (time in years) and scaling factor 1.
5245+
\item {\tt FloatSpreadMapping: } mapping of float spreads in analytic swaption pricing for model calibration: proRata,
5246+
nextCoupon, simple, optional, defaults to proRata.
52445247
\end{itemize}
52455248

52465249
The reason for having to specify one more {\tt Volatility/InitialValue} entries than {\tt Volatility/TimeGrid} entries (and at least one more calibration option than {\tt Volatility/TimeGrid} entries) is the fact that the intervals defined by the {\tt Volatility/TimeGrid} entries are spanning from $[0,t_1],[t_1,t_2]\ldots[t_n,\infty]$, which results in $n+1$ intervals.

OREData/ored/model/lgmbuilder.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,8 @@ void LgmBuilder::performCalculations() const {
346346
}
347347

348348
for (Size j = 0; j < swaptionBasket_.size(); j++) {
349-
auto engine = QuantLib::ext::make_shared<QuantExt::AnalyticLgmSwaptionEngine>(model_, calibrationDiscountCurve_);
349+
auto engine = QuantLib::ext::make_shared<QuantExt::AnalyticLgmSwaptionEngine>(model_, calibrationDiscountCurve_,
350+
data_->floatSpreadMapping());
350351
engine->enableCache(!data_->calibrateH(), !data_->calibrateA());
351352
swaptionBasket_[j]->setPricingEngine(engine);
352353
// necessary if notifications are disabled (observation mode = Disable)

OREData/ored/model/lgmdata.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,29 @@ std::ostream& operator<<(std::ostream& oss, const LgmData::VolatilityType& type)
9797
return oss;
9898
}
9999

100+
QuantExt::AnalyticLgmSwaptionEngine::FloatSpreadMapping parseFloatSpreadMapping(const string& s) {
101+
if (boost::algorithm::to_upper_copy(s) == "NEXTCOUPON")
102+
return QuantExt::AnalyticLgmSwaptionEngine::nextCoupon;
103+
else if (boost::algorithm::to_upper_copy(s) == "PRORATA")
104+
return QuantExt::AnalyticLgmSwaptionEngine::proRata;
105+
else if (boost::algorithm::to_upper_copy(s) == "SIMPLE")
106+
return QuantExt::AnalyticLgmSwaptionEngine::simple;
107+
else
108+
QL_FAIL("FloatSpreadMapping '" << s << "' not recognized");
109+
}
110+
111+
std::ostream& operator<<(std::ostream& oss, const QuantExt::AnalyticLgmSwaptionEngine::FloatSpreadMapping& m) {
112+
if (m == QuantExt::AnalyticLgmSwaptionEngine::nextCoupon)
113+
oss << "NEXTCOUPON";
114+
else if (m == QuantExt::AnalyticLgmSwaptionEngine::proRata)
115+
oss << "PRORATA";
116+
else if (m == QuantExt::AnalyticLgmSwaptionEngine::simple)
117+
oss << "SIMPLE";
118+
else
119+
QL_FAIL("FloatSpreadMapping type not covered");
120+
return oss;
121+
}
122+
100123
void LgmData::clear() {
101124
optionExpiries_.clear();
102125
optionTerms_.clear();
@@ -117,7 +140,6 @@ void LgmData::reset() {
117140
aValues_ = {0.01};
118141
shiftHorizon_ = 0.0;
119142
scaling_ = 1.0;
120-
121143
}
122144

123145
void LgmData::fromXML(XMLNode* node) {
@@ -174,6 +196,9 @@ void LgmData::fromXML(XMLNode* node) {
174196
scaling_ = 1.0;
175197
}
176198

199+
floatSpreadMapping_ =
200+
parseFloatSpreadMapping(XMLUtils::getChildValue(node, "FloatSpreadMapping", false, "proRata"));
201+
177202
IrModelData::fromXML(node);
178203

179204
LOG("LgmData done");
@@ -210,6 +235,8 @@ XMLNode* LgmData::toXML(XMLDocument& doc) const {
210235
XMLUtils::addChild(doc, parameterTransformationNode, "ShiftHorizon", shiftHorizon_);
211236
XMLUtils::addChild(doc, parameterTransformationNode, "Scaling", scaling_);
212237

238+
XMLUtils::addChild(doc, lgmNode, "FloatSpreadMapping", ore::data::to_string(floatSpreadMapping_));
239+
213240
return lgmNode;
214241
}
215242

OREData/ored/model/lgmdata.hpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <ql/types.hpp>
3030

3131
#include <qle/models/lgm.hpp>
32+
#include <qle/pricingengines/analyticlgmswaptionengine.hpp>
3233

3334
#include <ored/configuration/conventions.hpp>
3435
#include <ored/marketdata/market.hpp>
@@ -82,11 +83,13 @@ class LgmData : public IrModelData {
8283
ParamType aType, std::vector<Time> aTimes, std::vector<Real> aValues, Real shiftHorizon = 0.0,
8384
Real scaling = 1.0, std::vector<std::string> optionExpiries = std::vector<std::string>(),
8485
std::vector<std::string> optionTerms = std::vector<std::string>(),
85-
std::vector<std::string> optionStrikes = std::vector<std::string>())
86-
: IrModelData("LGM", qualifier, calibrationType), revType_(revType), volType_(volType),
87-
calibrateH_(calibrateH), hType_(hType), hTimes_(hTimes), hValues_(hValues), calibrateA_(calibrateA),
88-
aType_(aType), aTimes_(aTimes), aValues_(aValues), shiftHorizon_(shiftHorizon), scaling_(scaling),
89-
optionExpiries_(optionExpiries), optionTerms_(optionTerms), optionStrikes_(optionStrikes) {}
86+
std::vector<std::string> optionStrikes = std::vector<std::string>(),
87+
const QuantExt::AnalyticLgmSwaptionEngine::FloatSpreadMapping inputFloatSpreadMapping =
88+
QuantExt::AnalyticLgmSwaptionEngine::proRata)
89+
: IrModelData("LGM", qualifier, calibrationType), revType_(revType), volType_(volType), calibrateH_(calibrateH),
90+
hType_(hType), hTimes_(hTimes), hValues_(hValues), calibrateA_(calibrateA), aType_(aType), aTimes_(aTimes),
91+
aValues_(aValues), shiftHorizon_(shiftHorizon), scaling_(scaling), optionExpiries_(optionExpiries),
92+
optionTerms_(optionTerms), optionStrikes_(optionStrikes), floatSpreadMapping_(inputFloatSpreadMapping) {}
9093

9194
//! Clear list of calibration instruments
9295
void clear() override;
@@ -114,6 +117,7 @@ class LgmData : public IrModelData {
114117
std::vector<Real>& aValues() { return aValues_; }
115118
Real& shiftHorizon() { return shiftHorizon_; }
116119
Real& scaling() { return scaling_; }
120+
QuantExt::AnalyticLgmSwaptionEngine::FloatSpreadMapping& floatSpreadMapping() { return floatSpreadMapping_; }
117121
std::vector<std::string>& optionExpiries() const { return optionExpiries_; }
118122
std::vector<std::string>& optionTerms() const { return optionTerms_; }
119123
std::vector<std::string>& optionStrikes() const { return optionStrikes_; }
@@ -142,15 +146,19 @@ class LgmData : public IrModelData {
142146
mutable std::vector<std::string> optionExpiries_;
143147
mutable std::vector<std::string> optionTerms_;
144148
mutable std::vector<std::string> optionStrikes_;
149+
QuantExt::AnalyticLgmSwaptionEngine::FloatSpreadMapping floatSpreadMapping_ =
150+
QuantExt::AnalyticLgmSwaptionEngine::proRata;
145151
};
146152

147-
//! Enum parsers used in CrossAssetModelBuilder's fromXML
153+
//! Enum parsers
148154
LgmData::ReversionType parseReversionType(const string& s);
149155
LgmData::VolatilityType parseVolatilityType(const string& s);
156+
QuantExt::AnalyticLgmSwaptionEngine::FloatSpreadMapping parseFloatSpreadMapping(const string& s);
150157

151-
//! Enum to string used in CrossAssetModelBuilder's toXML
158+
//! Enum to string
152159
std::ostream& operator<<(std::ostream& oss, const LgmData::ReversionType& type);
153160
std::ostream& operator<<(std::ostream& oss, const LgmData::VolatilityType& type);
161+
std::ostream& operator<<(std::ostream& oss, const QuantExt::AnalyticLgmSwaptionEngine::FloatSpreadMapping& m);
154162

155163
/*! LGM reversion transformation.
156164

OREData/ored/portfolio/builders/scriptedtrade.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1477,11 +1477,15 @@ void ScriptedTradeEngineBuilder::buildGaussianCam(const std::string& id, const I
14771477
std::vector<CalibrationBasket> calBaskets(1, CalibrationBasket(calInstr));
14781478
if (infModelType_ == "DK") {
14791479
// build DK config
1480+
std::string infName = IndexInfo(modelInfIndices_[i].first).infName();
1481+
Real vol = parseReal(modelParameter("InfDkVolatility",
1482+
{resolvedProductTag_ + "_" + infName, infName, resolvedProductTag_},
1483+
false, "0.0050"));
14801484
config = QuantLib::ext::make_shared<InfDkData>(
14811485
CalibrationType::Bootstrap, calBaskets, modelInfIndices_[i].second->currency().code(),
14821486
IndexInfo(modelInfIndices_[i].first).infName(),
14831487
ReversionParameter(LgmData::ReversionType::Hagan, true, ParamType::Piecewise, {}, {0.60}),
1484-
VolatilityParameter(LgmData::VolatilityType::Hagan, false, ParamType::Piecewise, {}, {0.0050}),
1488+
VolatilityParameter(LgmData::VolatilityType::Hagan, false, ParamType::Piecewise, {}, {vol}),
14851489
LgmReversionTransformation(),
14861490
// ignore duplicate expiry times among calibration instruments
14871491
true);

OREData/ored/portfolio/builders/swaption.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ QuantLib::ext::shared_ptr<QuantExt::LGM> LGMSwaptionEngineBuilder::model(const s
104104
bool continueOnCalibrationError = globalParameters_.count("ContinueOnCalibrationError") > 0 &&
105105
parseBool(globalParameters_.at("ContinueOnCalibrationError"));
106106

107+
auto floatSpreadMapping = parseFloatSpreadMapping(modelParameter("FloatSpreadMapping", {}, false, "proRata"));
108+
107109
auto data = QuantLib::ext::make_shared<IrLgmData>();
108110

109111
// check for allowed calibration / bermudan strategy settings
@@ -138,6 +140,7 @@ QuantLib::ext::shared_ptr<QuantExt::LGM> LGMSwaptionEngineBuilder::model(const s
138140
data->volatilityType() = volatilityType;
139141
data->calibrationType() = calibration;
140142
data->shiftHorizon() = shiftHorizon;
143+
data->floatSpreadMapping() = floatSpreadMapping;
141144

142145
std::vector<Date> effExpiries;
143146
std::vector<Real> effStrikes;

0 commit comments

Comments
 (0)