Skip to content

Commit 3e95c4b

Browse files
pcaspersjenkins
authored andcommitted
QPR-12491 allow for sabr parameter term structures in curve config
1 parent 6bad20b commit 3e95c4b

10 files changed

Lines changed: 249 additions & 70 deletions

File tree

Lines changed: 1 addition & 1 deletion
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
2-
Cap_USD_SOFR,Swap,2025-03-21,1.003324,0.000931,USD,0.000931,USD,100000000.00,USD,100000000.00,DUMMY_NS,DUMMY_CP
2+
Cap_USD_SOFR,Swap,2025-03-21,1.003324,290.635657,USD,290.635657,USD,100000000.00,USD,100000000.00,DUMMY_NS,DUMMY_CP
33
Swaption_USD_SOFR,Swaption,2046-01-12,21.817022,250911.447904,USD,250911.447904,USD,100000000.00,USD,100000000.00,DUMMY_NS,DUMMY_CP

Examples/Example_60/Input/curveconfig.xml

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,29 @@
5555
<IsFixed>false</IsFixed>
5656
</Parameter>
5757
</Parameters>
58+
<!-- alternatively, the parameters can be specified for each optionlet, e.g.: -->
59+
<!-- <Parameters> -->
60+
<!-- <Parameter> -->
61+
<!-- <Name>alpha</Name> -->
62+
<!-- <InitialValue>0.0050,0.0060,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050</InitialValue> -->
63+
<!-- <IsFixed>true</IsFixed> -->
64+
<!-- </Parameter> -->
65+
<!-- <Parameter> -->
66+
<!-- <Name>beta</Name> -->
67+
<!-- <InitialValue>0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.1</InitialValue> -->
68+
<!-- <IsFixed>true</IsFixed> -->
69+
<!-- </Parameter> -->
70+
<!-- <Parameter> -->
71+
<!-- <Name>nu</Name> -->
72+
<!-- <InitialValue>0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.20,0.30</InitialValue> -->
73+
<!-- <IsFixed>true</IsFixed> -->
74+
<!-- </Parameter> -->
75+
<!-- <Parameter> -->
76+
<!-- <Name>rho</Name> -->
77+
<!-- <InitialValue>0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.9,0.0,0.0</InitialValue> -->
78+
<!-- <IsFixed>true</IsFixed> -->
79+
<!-- </Parameter> -->
80+
<!-- </Parameters> -->
5881
<Calibration>
5982
<MaxCalibrationAttempts>10</MaxCalibrationAttempts>
6083
<ExitEarlyErrorThreshold>0.005</ExitEarlyErrorThreshold>
@@ -116,6 +139,109 @@
116139
<IsFixed>false</IsFixed>
117140
</Parameter>
118141
</Parameters>
142+
<!-- alternatively the parameters can be specified per option tenor (row) and swap tenor (col), e.g.: -->
143+
<!-- <Parameters> -->
144+
<!-- <Parameter> -->
145+
<!-- <Name>alpha</Name> -->
146+
<!-- <InitialValue> -->
147+
<!-- 0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0070, -->
148+
<!-- 0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050, -->
149+
<!-- 0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050, -->
150+
<!-- 0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050, -->
151+
<!-- 0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050, -->
152+
<!-- 0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050, -->
153+
<!-- 0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050, -->
154+
<!-- 0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050, -->
155+
<!-- 0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050, -->
156+
<!-- 0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050, -->
157+
<!-- 0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050, -->
158+
<!-- 0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050, -->
159+
<!-- 0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050, -->
160+
<!-- 0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050, -->
161+
<!-- 0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050, -->
162+
<!-- 0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050, -->
163+
<!-- 0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050, -->
164+
<!-- 0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050, -->
165+
<!-- 0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050,0.0050 -->
166+
<!-- </InitialValue> -->
167+
<!-- <IsFixed>true</IsFixed> -->
168+
<!-- </Parameter> -->
169+
<!-- <Parameter> -->
170+
<!-- <Name>beta</Name> -->
171+
<!-- <InitialValue> -->
172+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
173+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
174+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
175+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
176+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
177+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
178+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
179+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
180+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
181+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
182+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
183+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
184+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
185+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
186+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
187+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
188+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
189+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
190+
<!-- 0.8,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -->
191+
<!-- </InitialValue> -->
192+
<!-- <IsFixed>true</IsFixed> -->
193+
<!-- </Parameter> -->
194+
<!-- <Parameter> -->
195+
<!-- <Name>nu</Name> -->
196+
<!-- <InitialValue> -->
197+
<!-- 0.20,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30, -->
198+
<!-- 0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30, -->
199+
<!-- 0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30, -->
200+
<!-- 0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30, -->
201+
<!-- 0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30, -->
202+
<!-- 0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30, -->
203+
<!-- 0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30, -->
204+
<!-- 0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30, -->
205+
<!-- 0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30, -->
206+
<!-- 0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30, -->
207+
<!-- 0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30, -->
208+
<!-- 0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30, -->
209+
<!-- 0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30, -->
210+
<!-- 0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30, -->
211+
<!-- 0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30, -->
212+
<!-- 0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30, -->
213+
<!-- 0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30, -->
214+
<!-- 0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30, -->
215+
<!-- 0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30,0.30 -->
216+
<!-- </InitialValue> -->
217+
<!-- <IsFixed>true</IsFixed> -->
218+
<!-- </Parameter> -->
219+
<!-- <Parameter> -->
220+
<!-- <Name>rho</Name> -->
221+
<!-- <InitialValue> -->
222+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
223+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
224+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
225+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
226+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
227+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
228+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
229+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
230+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
231+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
232+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
233+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
234+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
235+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
236+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
237+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
238+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
239+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, -->
240+
<!-- 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-0.99 -->
241+
<!-- </InitialValue> -->
242+
<!-- <IsFixed>true</IsFixed> -->
243+
<!-- </Parameter> -->
244+
<!-- </Parameters> -->
119245
<Calibration>
120246
<MaxCalibrationAttempts>10</MaxCalibrationAttempts>
121247
<ExitEarlyErrorThreshold>0.005</ExitEarlyErrorThreshold>

OREData/ored/configuration/parametricsmileconfiguration.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ namespace data {
2727
void ParametricSmileConfiguration::Parameter::fromXML(XMLNode* node) {
2828
XMLUtils::checkNode(node, "Parameter");
2929
name = XMLUtils::getChildValue(node, "Name", true);
30-
initialValue = parseReal(XMLUtils::getChildValue(node, "InitialValue", true));
30+
initialValue = parseListOfValues<Real>(XMLUtils::getChildValue(node, "InitialValue", true), parseReal);
3131
isFixed = parseBool(XMLUtils::getChildValue(node, "IsFixed", true));
3232
}
3333

OREData/ored/configuration/parametricsmileconfiguration.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class ParametricSmileConfiguration : public XMLSerializable {
4040
ore::data::XMLNode* toXML(ore::data::XMLDocument& doc) const override;
4141

4242
std::string name;
43-
double initialValue = 0.0;
43+
std::vector<double> initialValue = {0.0};
4444
bool isFixed = false;
4545
};
4646

OREData/ored/marketdata/capfloorvolcurve.cpp

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ void CapFloorVolCurve::termOptSurface(const Date& asof, CapFloorVolatilityCurveC
329329
Size dontThrowSteps = config.bootstrapConfig().dontThrowSteps();
330330

331331
// Get configuration values for parametric smile
332-
std::vector<std::pair<Real,bool>> initialModelParameters;
332+
std::vector<std::vector<std::pair<Real, bool>>> initialModelParameters;
333333
Size maxCalibrationAttempts = 10;
334334
Real exitEarlyErrorThreshold = 0.005;
335335
Real maxAcceptableError = 0.05;
@@ -338,10 +338,19 @@ void CapFloorVolCurve::termOptSurface(const Date& asof, CapFloorVolatilityCurveC
338338
auto beta = config.parametricSmileConfiguration()->parameter("beta");
339339
auto nu = config.parametricSmileConfiguration()->parameter("nu");
340340
auto rho = config.parametricSmileConfiguration()->parameter("rho");
341-
initialModelParameters.push_back(std::make_pair(alpha.initialValue, alpha.isFixed));
342-
initialModelParameters.push_back(std::make_pair(beta.initialValue, beta.isFixed));
343-
initialModelParameters.push_back(std::make_pair(nu.initialValue, nu.isFixed));
344-
initialModelParameters.push_back(std::make_pair(rho.initialValue, rho.isFixed));
341+
QL_REQUIRE(alpha.initialValue.size() == beta.initialValue.size() &&
342+
alpha.initialValue.size() == nu.initialValue.size() &&
343+
alpha.initialValue.size() == rho.initialValue.size(),
344+
"CapFloorVolCurve: parametric smile config: alpha size ("
345+
<< alpha.initialValue.size() << ") beta size (" << beta.initialValue.size() << ") nu size ("
346+
<< nu.initialValue.size() << ") rho size (" << rho.initialValue.size() << ") must match");
347+
for (Size i = 0; i < alpha.initialValue.size(); ++i) {
348+
initialModelParameters.push_back(std::vector<std::pair<Real, bool>>());
349+
initialModelParameters.back().push_back(std::make_pair(alpha.initialValue[i], alpha.isFixed));
350+
initialModelParameters.back().push_back(std::make_pair(beta.initialValue[i], beta.isFixed));
351+
initialModelParameters.back().push_back(std::make_pair(nu.initialValue[i], nu.isFixed));
352+
initialModelParameters.back().push_back(std::make_pair(rho.initialValue[i], rho.isFixed));
353+
}
345354
maxCalibrationAttempts = config.parametricSmileConfiguration()->calibration().maxCalibrationAttempts;
346355
exitEarlyErrorThreshold = config.parametricSmileConfiguration()->calibration().exitEarlyErrorThreshold;
347356
maxAcceptableError = config.parametricSmileConfiguration()->calibration().maxAcceptableError;
@@ -795,7 +804,7 @@ void CapFloorVolCurve::optOptSurface(const QuantLib::Date& asof, CapFloorVolatil
795804
QL_REQUIRE(config.optionalQuotes() == false, "Optional quotes for optionlet volatilities are not supported.");
796805

797806
// Get configuration values for parametric smile
798-
std::vector<std::pair<Real,bool>> initialModelParameters;
807+
std::vector<std::vector<std::pair<Real,bool>>> initialModelParameters;
799808
Size maxCalibrationAttempts = 10;
800809
Real exitEarlyErrorThreshold = 0.005;
801810
Real maxAcceptableError = 0.05;
@@ -804,10 +813,19 @@ void CapFloorVolCurve::optOptSurface(const QuantLib::Date& asof, CapFloorVolatil
804813
auto beta = config.parametricSmileConfiguration()->parameter("beta");
805814
auto nu = config.parametricSmileConfiguration()->parameter("nu");
806815
auto rho = config.parametricSmileConfiguration()->parameter("rho");
807-
initialModelParameters.push_back(std::make_pair(alpha.initialValue, alpha.isFixed));
808-
initialModelParameters.push_back(std::make_pair(beta.initialValue, beta.isFixed));
809-
initialModelParameters.push_back(std::make_pair(nu.initialValue, nu.isFixed));
810-
initialModelParameters.push_back(std::make_pair(rho.initialValue, rho.isFixed));
816+
QL_REQUIRE(alpha.initialValue.size() == beta.initialValue.size() &&
817+
alpha.initialValue.size() == nu.initialValue.size() &&
818+
alpha.initialValue.size() == rho.initialValue.size(),
819+
"CapFloorVolCurve: parametric smile config: alpha size ("
820+
<< alpha.initialValue.size() << ") beta size (" << beta.initialValue.size() << ") nu size ("
821+
<< nu.initialValue.size() << ") rho size (" << rho.initialValue.size() << ") must match");
822+
for (Size i = 0; i < alpha.initialValue.size(); ++i) {
823+
initialModelParameters.push_back(std::vector<std::pair<Real, bool>>());
824+
initialModelParameters.back().push_back(std::make_pair(alpha.initialValue[i], alpha.isFixed));
825+
initialModelParameters.back().push_back(std::make_pair(beta.initialValue[i], beta.isFixed));
826+
initialModelParameters.back().push_back(std::make_pair(nu.initialValue[i], nu.isFixed));
827+
initialModelParameters.back().push_back(std::make_pair(rho.initialValue[i], rho.isFixed));
828+
}
811829
maxCalibrationAttempts = config.parametricSmileConfiguration()->calibration().maxCalibrationAttempts;
812830
exitEarlyErrorThreshold = config.parametricSmileConfiguration()->calibration().exitEarlyErrorThreshold;
813831
maxAcceptableError = config.parametricSmileConfiguration()->calibration().maxAcceptableError;
@@ -1657,21 +1675,21 @@ void CapFloorVolCurve::buildCalibrationInfo(const Date& asof, const CurveConfigu
16571675

16581676
if (p) {
16591677
DLOG("SABR parameters:");
1660-
DLOG("alpha:");
1678+
DLOG("alpha (pls ignore second row, this is present for technical reasons):");
16611679
DLOGGERSTREAM(p->alpha());
1662-
DLOG("beta:");
1680+
DLOG("beta (pls ignore second row, this is present for technical reasons):");
16631681
DLOGGERSTREAM(p->beta());
1664-
DLOG("nu:");
1682+
DLOG("nu (pls ignore second row, this is present for technical reasons):");
16651683
DLOGGERSTREAM(p->nu());
1666-
DLOG("rho:");
1684+
DLOG("rho (pls ignore second row, this is present for technical reasons):");
16671685
DLOGGERSTREAM(p->rho());
1668-
DLOG("lognormal shift:");
1686+
DLOG("lognormal shift (pls ignore second row, this is present for technical reasons):");
16691687
DLOGGERSTREAM(p->lognormalShift());
16701688
DLOG("calibration attempts:");
16711689
DLOGGERSTREAM(p->numberOfCalibrationAttempts());
16721690
DLOG("calibration error:");
16731691
DLOGGERSTREAM(p->calibrationError());
1674-
DLOG("isInterpolated:");
1692+
DLOG("isInterpolated (1 means calibration failed and point is interpolated):");
16751693
DLOGGERSTREAM(p->isInterpolated());
16761694
}
16771695

0 commit comments

Comments
 (0)