Skip to content

Commit 40975b9

Browse files
committed
Merge branch 'update20240321' into 'master'
Update20240321 See merge request qs/ore-github!39
2 parents 08bc5c0 + 28b522e commit 40975b9

File tree

14 files changed

+290
-94
lines changed

14 files changed

+290
-94
lines changed
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
#TradeId,TradeType,Maturity,MaturityTime,NPV,NpvCurrency,NPV(Base),BaseCurrency,Notional,NotionalCurrency,Notional(Base),NettingSet,CounterParty
22
BermSwp,ScriptedTrade,2036-03-03,20.073770,51640.311738,EUR,51640.311738,EUR,#N/A,#N/A,#N/A,CPTY_A,CPTY_A
3-
LPISwp,ScriptedTrade,2035-02-01,18.989303,62979.404029,GBP,78301.934721,EUR,#N/A,#N/A,#N/A,CPTY_B,CPTY_B
3+
LPISwp,ScriptedTrade,2035-02-01,18.989303,53833.516084,GBP,66930.904274,EUR,#N/A,#N/A,#N/A,CPTY_B,CPTY_B

Examples/Example_54/Input/pricingengine.xml

+7-1
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,17 @@
88
<Parameter name="EnforceBaseCcy">false</Parameter>
99
<Parameter name="GridCoarsening">3M(1W),1Y(1M),5Y(3M),10Y(1Y),50Y(5Y)</Parameter>
1010
<Parameter name="IrReversion_EUR">0.01</Parameter>
11-
<Parameter name="IrReversion_GBP">0.01</Parameter>
11+
<Parameter name="IrReversion_GBP">0.015</Parameter>
1212
<Parameter name="FullDynamicFx">true</Parameter>
1313
<Parameter name="FullDynamicIr">true</Parameter>
1414
<!-- DK or JY -->
1515
<Parameter name="InfModelType">JY</Parameter>
16+
<!-- explicit overwrite of cam correlations -->
17+
<Parameter name="Correlation_IR:GBP_INF:UKRPI:0">0.8</Parameter>
18+
<Parameter name="Correlation_IR:GBP_INF:UKRPI:1">0.6</Parameter>
19+
<Parameter name="Correlation_INF:UKRPI:0_INF:UKRPI:1">0.3</Parameter>
20+
<!-- real to nominal rate vol ratio in jy model -->
21+
<Parameter name="InfJyRealToNominalVolRatio">0.6</Parameter>
1622
</ModelParameters>
1723
<Engine>Generic</Engine>
1824
<EngineParameters>

Examples/Example_54/run.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@
55
sys.path.append('../')
66
from ore_examples_helper import OreExample
77

8-
samples1=os.environ["OVERWRITE_SCENARIOGENERATOR_SAMPLES"]
9-
print("samples1 =", samples1)
10-
os.environ["OVERWRITE_SCENARIOGENERATOR_SAMPLES"]=""
11-
samples2=os.environ["OVERWRITE_SCENARIOGENERATOR_SAMPLES"]
12-
print("samples2 =", samples2)
8+
if "OVERWRITE_SCENARIOGENERATOR_SAMPLES" in os.environ:
9+
backupSamples = os.environ["OVERWRITE_SCENARIOGENERATOR_SAMPLES"]
10+
os.environ["OVERWRITE_SCENARIOGENERATOR_SAMPLES"] = ""
1311

1412
oreex = OreExample(sys.argv[1] if len(sys.argv)>1 else False)
1513

@@ -41,4 +39,5 @@
4139
oreex.decorate_plot(title="Example Scripting / AMC - DIM Evolution for LPI Swap (sticky date mpor mode)")
4240
oreex.save_plot_to_file()
4341

44-
os.environ["OVERWRITE_SCENARIOGENERATOR_SAMPLES"]=samples1
42+
if "OVERWRITE_SCENARIOGENERATOR_SAMPLES" in os.environ:
43+
os.environ["OVERWRITE_SCENARIOGENERATOR_SAMPLES"] = backupSamples

OREData/ored/model/crossassetmodelbuilder.cpp

+45
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,35 @@ void CrossAssetModelBuilder::resetModelParams(const CrossAssetModel::AssetType t
162162
}
163163
}
164164

165+
void CrossAssetModelBuilder::copyModelParams(const CrossAssetModel::AssetType t0, const Size param0, const Size index0,
166+
const Size i0, const CrossAssetModel::AssetType t1, const Size param1,
167+
const Size index1, const Size i1, const Real mult) const {
168+
auto mp0 = model_->MoveParameter(t0, param0, index0, i0);
169+
auto mp1 = model_->MoveParameter(t1, param1, index1, i1);
170+
auto s0 = 0, s1 = 0;
171+
for (Size i = 0; i < mp0.size(); ++i)
172+
if (mp0[i])
173+
s0++;
174+
for (Size i = 0; i < mp1.size(); ++i)
175+
if (mp1[i])
176+
s1++;
177+
QL_REQUIRE(s0 == s1, "CrossAssetModelBuilder::copyModelParams(): source range size ("
178+
<< s0 << ") does not match target range size (" << s1 << ") when copying (" << t0 << ", "
179+
<< param0 << "," << index0 << "," << i0 << ") -> (" << t0 << ", " << param0 << ","
180+
<< index0 << "," << i0 << ")");
181+
std::vector<Real> sourceValues(s0);
182+
for (Size idx0 = 0, count = 0; idx0 < mp0.size(); ++idx0) {
183+
if (!mp0[idx0]) {
184+
sourceValues[count++] = params_[idx0];
185+
}
186+
}
187+
for (Size idx1 = 0, count = 0; idx1 < mp1.size(); ++idx1) {
188+
if (!mp1[idx1]) {
189+
model_->setParam(idx1, sourceValues[count++] * mult);
190+
}
191+
}
192+
}
193+
165194
void CrossAssetModelBuilder::buildModel() const {
166195

167196
LOG("Start building CrossAssetModel");
@@ -842,6 +871,15 @@ void CrossAssetModelBuilder::calibrateInflation(const InfJyData& data, Size mode
842871
// Calibration configuration.
843872
const auto& cc = data.calibrationConfiguration();
844873

874+
// if we link the real rate params to the nominal rate params, we copy them over now (ir calibration is done at this point)
875+
if(data.linkRealRateParamsToNominalRateParams()) {
876+
Size irIdx = model_->ccyIndex(model_->infjy(modelIdx)->currency());
877+
copyModelParams(CrossAssetModel::AssetType::IR, 0, irIdx, Null<Size>(), CrossAssetModel::AssetType::INF, 0,
878+
modelIdx, Null<Size>(), data.linkedRealRateVolatilityScaling());
879+
copyModelParams(CrossAssetModel::AssetType::IR, 1, irIdx, Null<Size>(), CrossAssetModel::AssetType::INF, 1,
880+
modelIdx, Null<Size>(), 1.0);
881+
}
882+
845883
if (data.calibrationType() == CalibrationType::BestFit) {
846884

847885
// If calibration type is BestFit, do a global optimisation on the parameters that need to be calibrated.
@@ -937,6 +975,13 @@ void CrossAssetModelBuilder::calibrateInflation(const InfJyData& data, Size mode
937975
}
938976

939977
// Log the calibration details.
978+
TLOG("INF (JY) " << data.index() << " model parameters after calibration:");
979+
TLOG("Real rate vol times : " << inflationParam->parameterTimes(0));
980+
TLOG("Real rate vol values : " << inflationParam->parameterValues(0));
981+
TLOG("Real rate rev times : " << inflationParam->parameterTimes(1));
982+
TLOG("Real rate rev values : " << inflationParam->parameterValues(1));
983+
TLOG("R/N conversion times : " << inflationParam->parameterTimes(2));
984+
TLOG("R/N conversion values : " << inflationParam->parameterValues(2));
940985
DLOG("INF (JY) " << data.index() << " calibration errors:");
941986
inflationCalibrationErrors_[modelIdx] = getCalibrationError(allHelpers);
942987
if (data.calibrationType() == CalibrationType::Bootstrap) {

OREData/ored/model/crossassetmodelbuilder.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ class CrossAssetModelBuilder : public QuantExt::ModelBuilder {
111111
void performCalculations() const override;
112112
void buildModel() const;
113113
void resetModelParams(const CrossAssetModel::AssetType t, const Size param, const Size index, const Size i) const;
114+
void copyModelParams(const CrossAssetModel::AssetType t0, const Size param0, const Size index0, const Size i0,
115+
const CrossAssetModel::AssetType t1, const Size param1, const Size index1, const Size i1,
116+
const Real mult) const;
114117

115118
mutable std::vector<std::vector<boost::shared_ptr<BlackCalibrationHelper>>> swaptionBaskets_;
116119
mutable std::vector<std::vector<boost::shared_ptr<BlackCalibrationHelper>>> fxOptionBaskets_;

OREData/ored/model/inflation/infjydata.cpp

+29-17
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,18 @@ namespace data {
2929

3030
InfJyData::InfJyData() {}
3131

32-
InfJyData::InfJyData(CalibrationType calibrationType,
33-
const vector<CalibrationBasket>& calibrationBaskets,
34-
const std::string& currency,
35-
const std::string& index,
36-
const ReversionParameter& realRateReversion,
37-
const VolatilityParameter& realRateVolatility,
38-
const VolatilityParameter& indexVolatility,
39-
const LgmReversionTransformation& reversionTransformation,
40-
const CalibrationConfiguration& calibrationConfiguration,
41-
const bool ignoreDuplicateCalibrationExpiryTimes)
32+
InfJyData::InfJyData(CalibrationType calibrationType, const vector<CalibrationBasket>& calibrationBaskets,
33+
const std::string& currency, const std::string& index, const ReversionParameter& realRateReversion,
34+
const VolatilityParameter& realRateVolatility, const VolatilityParameter& indexVolatility,
35+
const LgmReversionTransformation& reversionTransformation,
36+
const CalibrationConfiguration& calibrationConfiguration,
37+
const bool ignoreDuplicateCalibrationExpiryTimes, const bool linkRealToNominalRateParams,
38+
const Real linkedRealRateVolatilityScaling)
4239
: InflationModelData(calibrationType, calibrationBaskets, currency, index, ignoreDuplicateCalibrationExpiryTimes),
43-
realRateReversion_(realRateReversion),
44-
realRateVolatility_(realRateVolatility),
45-
indexVolatility_(indexVolatility),
46-
reversionTransformation_(reversionTransformation),
47-
calibrationConfiguration_(calibrationConfiguration) {}
40+
realRateReversion_(realRateReversion), realRateVolatility_(realRateVolatility), indexVolatility_(indexVolatility),
41+
reversionTransformation_(reversionTransformation), calibrationConfiguration_(calibrationConfiguration),
42+
linkRealToNominalRateParams_(linkRealToNominalRateParams),
43+
linkedRealRateVolatilityScaling_(linkedRealRateVolatilityScaling) {}
4844

4945
const ReversionParameter& InfJyData::realRateReversion() const {
5046
return realRateReversion_;
@@ -66,6 +62,10 @@ const CalibrationConfiguration& InfJyData::calibrationConfiguration() const {
6662
return calibrationConfiguration_;
6763
}
6864

65+
bool InfJyData::linkRealRateParamsToNominalRateParams() const { return linkRealToNominalRateParams_; }
66+
67+
Real InfJyData::linkedRealRateVolatilityScaling() const { return linkedRealRateVolatilityScaling_; }
68+
6969
void InfJyData::fromXML(XMLNode* node) {
7070

7171
// Check the node is not null and that name is LGM or DodgsonKainth. LGM is for backward compatibility.
@@ -88,9 +88,16 @@ void InfJyData::fromXML(XMLNode* node) {
8888
indexVolatility_.fromXML(XMLUtils::getChildNode(idxNode, "Volatility"));
8989

9090
// Get the calibration configuration
91-
XMLNode* ccNode = XMLUtils::getChildNode(node, "CalibrationConfiguration");
92-
if (ccNode)
91+
if (XMLNode* ccNode = XMLUtils::getChildNode(node, "CalibrationConfiguration"))
9392
calibrationConfiguration_.fromXML(ccNode);
93+
94+
// Get the link to nominal param fields
95+
linkRealToNominalRateParams_ =
96+
parseBool(XMLUtils::getChildValue(node, "LinkRealToNominalRateParams", false, "false"));
97+
if (linkRealToNominalRateParams_) {
98+
linkedRealRateVolatilityScaling_ =
99+
parseReal(XMLUtils::getChildValue(node, "LinkedRealRateVolatilityScaling", false, "1.0"));
100+
}
94101
}
95102

96103
XMLNode* InfJyData::toXML(XMLDocument& doc) {
@@ -110,6 +117,11 @@ XMLNode* InfJyData::toXML(XMLDocument& doc) {
110117

111118
XMLUtils::appendNode(node, calibrationConfiguration_.toXML(doc));
112119

120+
if (linkRealToNominalRateParams_) {
121+
XMLUtils::addChild(doc, node, "LinkRealToNominalRateParams", linkRealToNominalRateParams_);
122+
XMLUtils::addChild(doc, node, "LinkedRealRateVolatilityScaling", linkedRealRateVolatilityScaling_);
123+
}
124+
113125
return node;
114126
}
115127

OREData/ored/model/inflation/infjydata.hpp

+16-10
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,18 @@ class InfJyData : public InflationModelData {
4848
InfJyData();
4949

5050
//! Detailed constructor
51-
InfJyData(CalibrationType calibrationType,
52-
const std::vector<CalibrationBasket>& calibrationBaskets,
53-
const std::string& currency,
54-
const std::string& index,
55-
const ReversionParameter& realRateReversion,
56-
const VolatilityParameter& realRateVolatility,
57-
const VolatilityParameter& indexVolatility,
58-
const LgmReversionTransformation& reversionTransformation = LgmReversionTransformation(),
59-
const CalibrationConfiguration& calibrationConfiguration = CalibrationConfiguration(),
60-
const bool ignoreDuplicateCalibrationExpiryTimes = false);
51+
/* Note: If linkRealRateToNominalRateParams == true, the realRateVolatility and realRateReversion should be set to
52+
the nominal rate parameters and the calibrate flag in these new parameters should be set to false. Also, the
53+
scaling linkRealRateVolatilityScaling should have been applied to the new parameters. All this is not automatic
54+
neither cheked in this class (lack of info on the nominal parameters, but required to ensure a calibration of the
55+
jy model as part of the cam to work consistently. */
56+
InfJyData(CalibrationType calibrationType, const std::vector<CalibrationBasket>& calibrationBaskets,
57+
const std::string& currency, const std::string& index, const ReversionParameter& realRateReversion,
58+
const VolatilityParameter& realRateVolatility, const VolatilityParameter& indexVolatility,
59+
const LgmReversionTransformation& reversionTransformation = LgmReversionTransformation(),
60+
const CalibrationConfiguration& calibrationConfiguration = CalibrationConfiguration(),
61+
const bool ignoreDuplicateCalibrationExpiryTimes = false, const bool linkRealToNominalRateParams = false,
62+
const Real linkedRealRateVolatilityScaling = 1.0);
6163

6264
//! \name Inspectors
6365
//@{
@@ -66,6 +68,8 @@ class InfJyData : public InflationModelData {
6668
const VolatilityParameter& indexVolatility() const;
6769
const LgmReversionTransformation& reversionTransformation() const;
6870
const CalibrationConfiguration& calibrationConfiguration() const;
71+
bool linkRealRateParamsToNominalRateParams() const;
72+
Real linkedRealRateVolatilityScaling() const;
6973
//@}
7074

7175
//! \name Serialisation
@@ -80,6 +84,8 @@ class InfJyData : public InflationModelData {
8084
VolatilityParameter indexVolatility_;
8185
LgmReversionTransformation reversionTransformation_;
8286
CalibrationConfiguration calibrationConfiguration_;
87+
bool linkRealToNominalRateParams_;
88+
Real linkedRealRateVolatilityScaling_;
8389
};
8490

8591
}

OREData/ored/model/lgmdata.cpp

+12-8
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*/
1818

1919
#include <ored/model/lgmdata.hpp>
20+
#include <ored/model/modelparameter.hpp>
2021
#include <ored/utilities/correlationmatrix.hpp>
2122
#include <ored/utilities/log.hpp>
2223
#include <ored/utilities/parsers.hpp>
@@ -212,19 +213,22 @@ XMLNode* LgmData::toXML(XMLDocument& doc) {
212213
return lgmNode;
213214
}
214215

215-
LgmReversionTransformation::LgmReversionTransformation()
216-
: horizon_(0.0), scaling_(1.0) {}
216+
ReversionParameter LgmData::reversionParameter() const {
217+
return ReversionParameter(revType_, calibrateH_, hType_, hTimes_, hValues_);
218+
}
219+
220+
VolatilityParameter LgmData::volatilityParameter() const {
221+
return VolatilityParameter(volType_, calibrateA_, aType_, aTimes_, aValues_);
222+
}
223+
224+
LgmReversionTransformation::LgmReversionTransformation() : horizon_(0.0), scaling_(1.0) {}
217225

218226
LgmReversionTransformation::LgmReversionTransformation(Time horizon, Real scaling)
219227
: horizon_(horizon), scaling_(scaling) {}
220228

221-
Time LgmReversionTransformation::horizon() const {
222-
return horizon_;
223-
}
229+
Time LgmReversionTransformation::horizon() const { return horizon_; }
224230

225-
Real LgmReversionTransformation::scaling() const {
226-
return scaling_;
227-
}
231+
Real LgmReversionTransformation::scaling() const { return scaling_; }
228232

229233
void LgmReversionTransformation::fromXML(XMLNode* node) {
230234
XMLUtils::checkNode(node, "ParameterTransformation");

OREData/ored/model/lgmdata.hpp

+11-6
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ namespace ore {
3939
namespace data {
4040
using namespace QuantLib;
4141

42+
class VolatilityParameter;
43+
class ReversionParameter;
44+
4245
//! Linear Gauss Markov Model Parameters
4346
/*!
4447
This class contains the description of a Linear Gauss Markov interest rate model
@@ -111,9 +114,11 @@ class LgmData : public IrModelData {
111114
std::vector<Real>& aValues() { return aValues_; }
112115
Real& shiftHorizon() { return shiftHorizon_; }
113116
Real& scaling() { return scaling_; }
114-
std::vector<std::string>& optionExpiries() { return optionExpiries_; }
115-
std::vector<std::string>& optionTerms() { return optionTerms_; }
116-
std::vector<std::string>& optionStrikes() { return optionStrikes_; }
117+
std::vector<std::string>& optionExpiries() const { return optionExpiries_; }
118+
std::vector<std::string>& optionTerms() const { return optionTerms_; }
119+
std::vector<std::string>& optionStrikes() const { return optionStrikes_; }
120+
ReversionParameter reversionParameter() const;
121+
VolatilityParameter volatilityParameter() const;
117122
//@}
118123

119124
//! \name Operators
@@ -134,9 +139,9 @@ class LgmData : public IrModelData {
134139
std::vector<Time> aTimes_;
135140
std::vector<Real> aValues_;
136141
Real shiftHorizon_, scaling_;
137-
std::vector<std::string> optionExpiries_;
138-
std::vector<std::string> optionTerms_;
139-
std::vector<std::string> optionStrikes_;
142+
mutable std::vector<std::string> optionExpiries_;
143+
mutable std::vector<std::string> optionTerms_;
144+
mutable std::vector<std::string> optionStrikes_;
140145
};
141146

142147
//! Enum parsers used in CrossAssetModelBuilder's fromXML

OREData/ored/model/modelparameter.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ const vector<Real>& ModelParameter::values() const {
5656
return values_;
5757
}
5858

59+
void ModelParameter::mult(const Real f) {
60+
std::transform(values_.begin(), values_.end(), values_.begin(), [&f](const Real v) { return f * v; });
61+
}
62+
63+
void ModelParameter::setCalibrate(const bool b) { calibrate_ = b; }
64+
5965
void ModelParameter::fromXML(XMLNode* node) {
6066
calibrate_ = XMLUtils::getChildValueAsBool(node, "Calibrate", true);
6167
type_ = parseParamType(XMLUtils::getChildValue(node, "ParamType", true));

OREData/ored/model/modelparameter.hpp

+7
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ class ModelParameter : public XMLSerializable {
5454
const std::vector<QuantLib::Real>& values() const;
5555
//@}
5656

57+
//! \name Setters / Modifiers
58+
59+
//@{
60+
void mult(const Real f);
61+
void setCalibrate(const bool b);
62+
//@}
63+
5764
//! \name Serialisation
5865
//@{
5966
void fromXML(XMLNode* node) override;

0 commit comments

Comments
 (0)