Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Functions
crossassetmodelparametrizations.cpp File Reference
#include "utilities.hpp"
#include "toplevelfixture.hpp"
#include <boost/test/unit_test.hpp>
#include <ql/currencies/america.hpp>
#include <ql/currencies/europe.hpp>
#include <ql/math/array.hpp>
#include <ql/math/comparison.hpp>
#include <ql/quotes/simplequote.hpp>
#include <ql/termstructures/yield/flatforward.hpp>
#include <ql/time/calendars/nullcalendar.hpp>
#include <qle/models/cdsoptionhelper.hpp>
#include <qle/models/cpicapfloorhelper.hpp>
#include <qle/models/crlgm1fparametrization.hpp>
#include <qle/models/crossassetanalytics.hpp>
#include <qle/models/crossassetanalyticsbase.hpp>
#include <qle/models/crossassetmodel.hpp>
#include <qle/models/crossassetmodelimpliedeqvoltermstructure.hpp>
#include <qle/models/crossassetmodelimpliedfxvoltermstructure.hpp>
#include <qle/models/dkimpliedyoyinflationtermstructure.hpp>
#include <qle/models/dkimpliedzeroinflationtermstructure.hpp>
#include <qle/models/eqbsconstantparametrization.hpp>
#include <qle/models/eqbsparametrization.hpp>
#include <qle/models/eqbspiecewiseconstantparametrization.hpp>
#include <qle/models/fxbsconstantparametrization.hpp>
#include <qle/models/fxbsparametrization.hpp>
#include <qle/models/fxbspiecewiseconstantparametrization.hpp>
#include <qle/models/fxeqoptionhelper.hpp>
#include <qle/models/gaussian1dcrossassetadaptor.hpp>
#include <qle/models/infdkparametrization.hpp>
#include <qle/models/irlgm1fconstantparametrization.hpp>
#include <qle/models/irlgm1fparametrization.hpp>
#include <qle/models/irlgm1fpiecewiseconstanthullwhiteadaptor.hpp>
#include <qle/models/irlgm1fpiecewiseconstantparametrization.hpp>
#include <qle/models/irlgm1fpiecewiselinearparametrization.hpp>
#include <qle/models/lgm.hpp>
#include <qle/models/lgmimplieddefaulttermstructure.hpp>
#include <qle/models/lgmimpliedyieldtermstructure.hpp>
#include <qle/models/linkablecalibratedmodel.hpp>
#include <qle/models/parametrization.hpp>
#include <qle/models/piecewiseconstanthelper.hpp>
#include <qle/models/pseudoparameter.hpp>
#include <boost/make_shared.hpp>

Go to the source code of this file.

Functions

 BOOST_AUTO_TEST_CASE (testParametrizationBaseClasses)
 
 BOOST_AUTO_TEST_CASE (testIrLgm1fParametrizations)
 
 BOOST_AUTO_TEST_CASE (testFxBsParametrizations)
 

Function Documentation

◆ BOOST_AUTO_TEST_CASE() [1/3]

BOOST_AUTO_TEST_CASE ( testParametrizationBaseClasses  )

Definition at line 92 of file crossassetmodelparametrizations.cpp.

92 {
93
94 BOOST_TEST_MESSAGE("Testing CrossAssetModel parametrizations (base classes)...");
95
96 // base class
97
98 Parametrization p1((EURCurrency()));
99
100 if (p1.parameterTimes(42) != Array()) {
101 BOOST_ERROR("empty parametrization should have empty times "
102 "array, it has size "
103 << p1.parameterTimes(42).size() << " though");
104 }
105
106 if (p1.parameterValues(42) != Array()) {
107 BOOST_ERROR("empty parametrization should have empty values "
108 "array, it has size "
109 << p1.parameterValues(42).size() << " though");
110 }
111
112 if (p1.parameter(42)->params().size() != 0) {
113 BOOST_ERROR("empty parametrization should have empty parameter "
114 "array, it has size "
115 << p1.parameter(42)->params().size() << " though");
116 }
117
118 // piecewise constant helpers
119
120 // the helpers expect raw values in the sense of parameter transformation
121 // which we generate here hard coded (kind of white box testing, since
122 // the helper classes are never used directly in client code)
123 Array noTimes;
124 PiecewiseConstantHelper1 helper11(noTimes);
125 helper11.p()->setParam(0, std::sqrt(3.0));
126 check("helper11.y", 0.0, helper11.y(0.0), 3.0);
127 check("helper11.y", 1.0, helper11.y(1.0), 3.0);
128 check("helper11.y", 3.0, helper11.y(3.0), 3.0);
129 check("helper11.int_y_sqr", 0.0, helper11.int_y_sqr(0.0), 0.0);
130 check("helper11.int_y_sqr", 1.0, helper11.int_y_sqr(1.0), 9.0);
131 check("helper11.int_y_sqr", 3.0, helper11.int_y_sqr(3.0), 27.0);
132
133 PiecewiseConstantHelper2 helper21(noTimes);
134 helper21.p()->setParam(0, 3.0);
135 check("helper21.y", 0.0, helper21.y(0.0), 3.0);
136 check("helper21.y", 1.0, helper21.y(1.0), 3.0);
137 check("helper21.y", 3.0, helper21.y(3.0), 3.0);
138 check("helper21.exp_m_int_y", 0.0, helper21.exp_m_int_y(0.0), 1.0);
139 check("helper21.exp_m_int_y", 1.0, helper21.exp_m_int_y(1.0), std::exp(-3.0));
140 check("helper21.exp_m_int_y", 3.0, helper21.exp_m_int_y(3.0), std::exp(-9.0));
141 check("helper21.int_exp_m_int_y", 0.0, helper21.int_exp_m_int_y(0.0), 0.0);
142 check("helper21.int_exp_m_int_y", 1.0, helper21.int_exp_m_int_y(1.0), (1.0 - std::exp(-3.0)) / 3.0);
143 check("helper21.int_exp_m_int_y", 3.0, helper21.int_exp_m_int_y(3.0), (1.0 - std::exp(-9.0)) / 3.0);
144
145 // the helper type 3 is close to type 2, so we only do the easiest
146 // tests here, in the irlgm1f Hull White adaptor tests below the
147 // other tests will be implicit though
148 PiecewiseConstantHelper3 helper31(noTimes, noTimes);
149 helper31.p1()->setParam(0, std::sqrt(3.0));
150 helper31.p2()->setParam(0, 2.0);
151 // helper 3 requires an update()
152 helper31.update();
153 check("helper31.y1", 0.0, helper31.y1(0.0), 3.0);
154 check("helper31.y1", 1.0, helper31.y1(1.0), 3.0);
155 check("helper31.y1", 3.0, helper31.y1(3.0), 3.0);
156 check("helper31.y2", 0.0, helper31.y2(0.0), 2.0);
157 check("helper31.y2", 1.0, helper31.y2(1.0), 2.0);
158 check("helper31.y2", 3.0, helper31.y2(3.0), 2.0);
159 check("helper31.int_y1_sqr_int_exp_2_int_y2", 0.0, helper31.int_y1_sqr_exp_2_int_y2(0.0), 0.0);
160 check("helper31.int_y1_sqr_int_exp_2_int_y2", 1.0, helper31.int_y1_sqr_exp_2_int_y2(1.0),
161 9.0 / 4.0 * (std::exp(2.0 * 2.0 * 1.0) - 1.0));
162 check("helper31.int_y1_sqr_int_exp_2_int_y2", 3.0, helper31.int_y1_sqr_exp_2_int_y2(3.0),
163 9.0 / 4.0 * (std::exp(2.0 * 2.0 * 3.0) - 1.0));
164
165 // test union set of times
166 Array times1(2);
167 Array times2(3);
168 times1[0] = 0.1;
169 times1[1] = 0.5;
170 times2[0] = 0.2;
171 times2[1] = 0.5;
172 times2[2] = 1.0;
173 PiecewiseConstantHelper3 helper32(times1, times2);
174 helper32.p1()->setParam(0, 0.0);
175 helper32.p1()->setParam(1, 0.0);
176 helper32.p1()->setParam(2, 0.0);
177 helper32.p2()->setParam(0, 0.0);
178 helper32.p2()->setParam(1, 0.0);
179 helper32.p2()->setParam(2, 0.0);
180 helper32.p2()->setParam(3, 0.0);
181 helper32.update();
182 Array exTu(4);
183 exTu[0] = 0.1;
184 exTu[1] = 0.2;
185 exTu[2] = 0.5;
186 exTu[3] = 1.0;
187 if (helper32.tUnion() != exTu)
188 BOOST_ERROR("helper32 expected tUnion array " << exTu << ", but is " << helper32.tUnion());
189
190 PiecewiseConstantHelper2 helper22(noTimes);
191 helper22.p()->setParam(0, 0.0);
192 check("helper22.y", 0.0, helper22.y(0.0), 0.0);
193 check("helper22.y", 1.0, helper22.y(1.0), 0.0);
194 check("helper22.y", 3.0, helper22.y(3.0), 0.0);
195 check("helper22.exp_m_int_y", 0.0, helper22.exp_m_int_y(0.0), 1.0);
196 check("helper22.exp_m_int_y", 1.0, helper22.exp_m_int_y(1.0), 1.0);
197 check("helper22.exp_m_int_y", 3.0, helper22.exp_m_int_y(3.0), 1.0);
198 check("helper22.int_exp_m_int_y", 0.0, helper22.int_exp_m_int_y(0.0), 0.0);
199 check("helper22.int_exp_m_int_y", 1.0, helper22.int_exp_m_int_y(1.0), 1.0);
200 check("helper22.int_exp_m_int_y", 3.0, helper22.int_exp_m_int_y(3.0), 3.0);
201
202 Array times(3), values(4), sqrt_values(4);
203 times[0] = 1.0;
204 times[1] = 2.0;
205 times[2] = 3.0;
206 values[0] = 1.0;
207 values[1] = 2.0;
208 values[2] = 0.0;
209 values[3] = 3.0;
210 sqrt_values[0] = std::sqrt(1.0);
211 sqrt_values[1] = std::sqrt(2.0);
212 sqrt_values[2] = std::sqrt(0.0);
213 sqrt_values[3] = std::sqrt(3.0);
214 PiecewiseConstantHelper1 helper12(times);
215 helper12.p()->setParam(0, sqrt_values[0]);
216 helper12.p()->setParam(1, sqrt_values[1]);
217 helper12.p()->setParam(2, sqrt_values[2]);
218 helper12.p()->setParam(3, sqrt_values[3]);
219 helper12.update();
220 check("helper12.y", 0.0, helper12.y(0.0), 1.0);
221 check("helper12.y", 0.5, helper12.y(0.5), 1.0);
222 check("helper12.y", 1.0, helper12.y(1.0), 2.0);
223 check("helper12.y", 2.2, helper12.y(2.2), 0.0);
224 check("helper12.y", 3.0 - 1.0E-8, helper12.y(3.0 - 1.0E-8), 0.0);
225 check("helper12.y", 3.0, helper12.y(3.0), 3.0);
226 check("helper12.y", 5.0, helper12.y(5.0), 3.0);
227 check("helper12.int_y_sqr", 0.0, helper12.int_y_sqr(0.0), 0.0);
228 check("helper12.int_y_sqr", 0.5, helper12.int_y_sqr(0.5), 0.5);
229 check("helper12.int_y_sqr", 1.0, helper12.int_y_sqr(1.0), 1.0);
230 check("helper12.int_y_sqr", 1.2, helper12.int_y_sqr(1.2), 1.0 + 4.0 * 0.2);
231 check("helper12.int_y_sqr", 2.0, helper12.int_y_sqr(2.0), 1.0 + 4.0);
232 check("helper12.int_y_sqr", 2.1, helper12.int_y_sqr(2.1), 1.0 + 4.0);
233 check("helper12.int_y_sqr", 2.5, helper12.int_y_sqr(2.5), 1.0 + 4.0);
234 check("helper12.int_y_sqr", 2.9, helper12.int_y_sqr(2.9), 1.0 + 4.0);
235 check("helper12.int_y_sqr", 3.0, helper12.int_y_sqr(3.0), 1.0 + 4.0);
236 check("helper12.int_y_sqr", 5.0, helper12.int_y_sqr(5.0), 1.0 + 4.0 + 9.0 * 2.0);
237
238 PiecewiseConstantHelper2 helper23(times);
239 helper23.p()->setParam(0, values[0]);
240 helper23.p()->setParam(1, values[1]);
241 helper23.p()->setParam(2, values[2]);
242 helper23.p()->setParam(3, values[3]);
243 helper23.update();
244 check("helper23.y", 0.0, helper23.y(0.0), 1.0);
245 check("helper23.y", 0.5, helper23.y(0.5), 1.0);
246 check("helper23.y", 1.0, helper23.y(1.0), 2.0);
247 check("helper23.y", 2.2, helper23.y(2.2), 0.0);
248 check("helper23.y", 3.0 - 1.0E-8, helper23.y(3.0 - 1.0E-8), 0.0);
249 check("helper23.y", 3.0, helper23.y(3.0), 3.0);
250 check("helper23.y", 5.0, helper23.y(5.0), 3.0);
251 check("helper23.exp_m_int_y", 0.0, helper23.exp_m_int_y(0.0), 1.0);
252 check("helper23.exp_m_int_y", 0.5, helper23.exp_m_int_y(0.5), std::exp(-0.5));
253 check("helper23.exp_m_int_y", 1.0, helper23.exp_m_int_y(1.0), std::exp(-1.0));
254 check("helper23.exp_m_int_y", 1.5, helper23.exp_m_int_y(1.5), std::exp(-2.0));
255 check("helper23.exp_m_int_y", 2.0, helper23.exp_m_int_y(2.0), std::exp(-3.0));
256 check("helper23.exp_m_int_y", 2.1, helper23.exp_m_int_y(2.1), std::exp(-3.0));
257 check("helper23.exp_m_int_y", 2.5, helper23.exp_m_int_y(2.5), std::exp(-3.0));
258 check("helper23.exp_m_int_y", 2.9, helper23.exp_m_int_y(2.9), std::exp(-3.0));
259 check("helper23.exp_m_int_y", 3.0, helper23.exp_m_int_y(3.0), std::exp(-3.0));
260 check("helper23.exp_m_int_y", 5.0, helper23.exp_m_int_y(5.0), std::exp(-3.0 - 6.0));
261
262 check("helper23.int_exp_m_int_y", 0.0, helper23.int_exp_m_int_y(0.0), 0.0);
263 Real h = 1.0E-5, x0 = 0.0, sum = 0.0;
264 while (x0 < 5.0) {
265 sum += h * helper23.exp_m_int_y(x0 + h / 2.0);
266 x0 += h;
267 check2("helper23.int_exp_m_int_y2", x0, helper23.int_exp_m_int_y(x0), sum, 1.0E-10);
268 }
269
270 // check update after value change
271
272 helper12.p()->setParam(0, std::sqrt(0.5));
273 helper12.p()->setParam(1, std::sqrt(1.0));
274 helper23.p()->setParam(0, 0.5);
275 helper23.p()->setParam(1, 1.0);
276 helper12.update();
277 helper23.update();
278 check("update helper12.y", 1.0, helper12.y(1.0), 1.0);
279 check("update helper12.int_y_sqr", 2.0, helper12.int_y_sqr(2.0), 0.5 * 0.5 + 1.0 * 1.0);
280 check("update helper23.y", 1.0, helper23.y(1.0), 1.0);
281 check("update helper23.exp_m_int_y", 2.0, helper23.exp_m_int_y(2.0), std::exp(-0.5 - 1.0));
282
283 // check dates based constructor
284
285 Handle<YieldTermStructure> yts(QuantLib::ext::make_shared<FlatForward>(0, NullCalendar(), 0.0, Actual365Fixed()));
286 std::vector<Date> dates;
287 dates.push_back(yts->referenceDate() + 100);
288 dates.push_back(yts->referenceDate() + 200);
289 dates.push_back(yts->referenceDate() + 250);
290 dates.push_back(yts->referenceDate() + 2385);
291 PiecewiseConstantHelper1 helper1x(dates, yts);
292
293 check("time from date helper1x", 0.0, helper1x.t()[0], yts->timeFromReference(dates[0]));
294 check("time from date helper1x", 0.0, helper1x.t()[1], yts->timeFromReference(dates[1]));
295 check("time from date helper1x", 0.0, helper1x.t()[2], yts->timeFromReference(dates[2]));
296 check("time from date helper1x", 0.0, helper1x.t()[3], yts->timeFromReference(dates[3]));
297}
Real sum(const Cash &c, const Cash &d)
Definition: bondbasket.cpp:107
+ Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [2/3]

BOOST_AUTO_TEST_CASE ( testIrLgm1fParametrizations  )

Definition at line 299 of file crossassetmodelparametrizations.cpp.

299 {
300
301 BOOST_TEST_MESSAGE("Testing CrossAssetModel parametrizations (irlgm1f)...");
302
303 // test generic inspectors of irlgm1f parametrization
304
305 class IrLgm1fTmpParametrization : public IrLgm1fParametrization {
306 public:
307 IrLgm1fTmpParametrization(const Currency& currency, const Handle<YieldTermStructure>& termStructure)
308 : IrLgm1fParametrization(currency, termStructure) {}
309 Handle<YieldTermStructure> termStructure() const { return Handle<YieldTermStructure>(); }
310 // do not use this parametrization at home
311 Real zeta(const Time t) const override { return sin(t); }
312 Real H(const Time t) const override { return t * t * t; }
313 } irlgm1f_1((EURCurrency()), Handle<YieldTermStructure>());
314
315 // check numerical differentiation scheme (in particular near zero)
316 // of the irlgm1f parametrization
317
318 Real h = 1.0E-6, h2 = 1.0E-4;
319
320 check("irlgm1f_1.alpha", 0.0, irlgm1f_1.alpha(0.0), std::sqrt((irlgm1f_1.zeta(h) - irlgm1f_1.zeta(0.0)) / h));
321 check("irlgm1f_1.alpha", 0.3E-8, irlgm1f_1.alpha(0.3E-8), std::sqrt((irlgm1f_1.zeta(h) - irlgm1f_1.zeta(0.0)) / h));
322 check("irlgm1f_1.alpha", 1.0, irlgm1f_1.alpha(1.0),
323 std::sqrt((irlgm1f_1.zeta(1.0 + h / 2.0) - irlgm1f_1.zeta(1.0 - h / 2.0)) / h));
324
325 check("irlgm1f_1.Hprime", 0.0, irlgm1f_1.Hprime(0.0), (irlgm1f_1.H(h) - irlgm1f_1.H(0.0)) / h);
326 check("irlgm1f_1.Hprime", 0.3E-8, irlgm1f_1.Hprime(0.3E-8), (irlgm1f_1.H(h) - irlgm1f_1.H(0.0)) / h);
327 check("irlgm1f_1.Hprime", 1.0, irlgm1f_1.Hprime(1.0),
328 (irlgm1f_1.H(1.0 + h / 2.0) - irlgm1f_1.H(1.0 - h / 2.0)) / h);
329
330 check("irlgm1f_1.Hprime2", 0.0, irlgm1f_1.Hprime2(0.0),
331 (irlgm1f_1.H(2.0 * h2) - 2.0 * irlgm1f_1.H(h2) + irlgm1f_1.H(0.0)) / (h2 * h2));
332 check("irlgm1f_1.Hprime2", 0.3E-4, irlgm1f_1.Hprime2(0.3E-4),
333 (irlgm1f_1.H(2.0 * h2) - 2.0 * irlgm1f_1.H(h2) + irlgm1f_1.H(0.0)) / (h2 * h2));
334 check("irlgm1f_1.Hprime2", 1.0, irlgm1f_1.Hprime2(1.0),
335 (irlgm1f_1.H(1.0 + h2) - 2.0 * irlgm1f_1.H(1.0) + irlgm1f_1.H(1.0 - h2)) / (h2 * h2));
336
337 check("irlgm1f_1.hullWhiteSigma", 1.5, irlgm1f_1.hullWhiteSigma(1.5), irlgm1f_1.Hprime(1.5) * irlgm1f_1.alpha(1.5));
338 check("irlgm1f_1.kappa", 1.5, irlgm1f_1.kappa(1.5), -irlgm1f_1.Hprime2(1.5) / irlgm1f_1.Hprime(1.5));
339
340 // check the irlgm1f parametrizations
341
342 Handle<YieldTermStructure> flatYts(QuantLib::ext::make_shared<FlatForward>(0, NullCalendar(), 0.02, Actual365Fixed()));
343
344 IrLgm1fConstantParametrization irlgm1f_2(EURCurrency(), flatYts, 0.01, 0.01);
345 IrLgm1fConstantParametrization irlgm1f_3(EURCurrency(), flatYts, 0.01, 0.00);
346
347 Array alphaTimes(99), kappaTimes(99), alpha(100), kappa(100), sigma(100);
348 for (Size i = 0; i < 100; ++i) {
349 if (i < 99) {
350 alphaTimes[i] = static_cast<Real>(i + 1);
351 kappaTimes[i] = alphaTimes[i];
352 }
353 // 0.0000 to 0.099
354 alpha[i] = sigma[i] = static_cast<Real>(i) * 0.0010;
355 // -0.05 to 0.049
356 kappa[i] = (static_cast<Real>(i) - 50.0) * 0.001;
357 }
358
359 IrLgm1fPiecewiseConstantParametrization irlgm1f_4(EURCurrency(), flatYts, alphaTimes, alpha, kappaTimes, kappa);
360
361 // alpha and kappa times are identical
362 IrLgm1fPiecewiseConstantHullWhiteAdaptor irlgm1f_5(EURCurrency(), flatYts, alphaTimes, sigma, alphaTimes, kappa);
363
364 Real t = 0.0, step = 1.0E-3;
365 while (t < 100.0) {
366
367 // check irlgm1f parametrization (piecewise constant and constant)
368 // for consistency with sqrt(zeta') = alpha and -H'' / H' = kappa
369
370 // as well, check the Hull White adaptor by checking
371 // sqrt(zeta') H' = sigma, -H'' / H' = kappa
372
373 Real zetaPrime2, zetaPrime3, zetaPrime4, zetaPrime5;
374 Real Hprime2, Hprime3, Hprime4, Hprime5;
375 Real Hprimeprime2, Hprimeprime3, Hprimeprime4, Hprimeprime5;
376 if (t < h / 2.0) {
377 zetaPrime2 = (irlgm1f_2.zeta(t + h) - irlgm1f_2.zeta(t)) / h;
378 zetaPrime3 = (irlgm1f_3.zeta(t + h) - irlgm1f_3.zeta(t)) / h;
379 zetaPrime4 = (irlgm1f_4.zeta(t + h) - irlgm1f_4.zeta(t)) / h;
380 zetaPrime5 = (irlgm1f_5.zeta(t + h) - irlgm1f_5.zeta(t)) / h;
381 Hprime2 = (irlgm1f_2.H(t + h) - irlgm1f_2.H(t)) / h;
382 Hprime3 = (irlgm1f_3.H(t + h) - irlgm1f_3.H(t)) / h;
383 Hprime4 = (irlgm1f_4.H(t + h) - irlgm1f_4.H(t)) / h;
384 Hprime5 = (irlgm1f_5.H(t + h) - irlgm1f_5.H(t)) / h;
385 } else {
386 zetaPrime2 = (irlgm1f_2.zeta(t + h / 2.0) - irlgm1f_2.zeta(t - h / 2.0)) / h;
387 zetaPrime3 = (irlgm1f_3.zeta(t + h / 2.0) - irlgm1f_3.zeta(t - h / 2.0)) / h;
388 zetaPrime4 = (irlgm1f_4.zeta(t + h / 2.0) - irlgm1f_4.zeta(t - h / 2.0)) / h;
389 zetaPrime5 = (irlgm1f_5.zeta(t + h / 2.0) - irlgm1f_5.zeta(t - h / 2.0)) / h;
390 Hprime2 = (irlgm1f_2.H(t + h / 2.0) - irlgm1f_2.H(t - h / 2.0)) / h;
391 Hprime3 = (irlgm1f_3.H(t + h / 2.0) - irlgm1f_3.H(t - h / 2.0)) / h;
392 Hprime4 = (irlgm1f_4.H(t + h / 2.0) - irlgm1f_4.H(t - h / 2.0)) / h;
393 Hprime5 = (irlgm1f_5.H(t + h / 2.0) - irlgm1f_5.H(t - h / 2.0)) / h;
394 }
395 if (t < h2) {
396 Hprimeprime2 = (irlgm1f_2.H(2.0 * h2) - 2.0 * irlgm1f_2.H(h2) + irlgm1f_2.H(0.0)) / (h2 * h2);
397 Hprimeprime3 = (irlgm1f_3.H(2.0 * h2) - 2.0 * irlgm1f_3.H(h2) + irlgm1f_3.H(0.0)) / (h2 * h2);
398 Hprimeprime4 = (irlgm1f_4.H(2.0 * h2) - 2.0 * irlgm1f_4.H(h2) + irlgm1f_4.H(0.0)) / (h2 * h2);
399 Hprimeprime5 = (irlgm1f_5.H(2.0 * h2) - 2.0 * irlgm1f_5.H(h2) + irlgm1f_5.H(0.0)) / (h2 * h2);
400 } else {
401 Hprimeprime2 = (irlgm1f_2.H(t + h2) - 2.0 * irlgm1f_2.H(t) + irlgm1f_2.H(t - h2)) / (h2 * h2);
402 Hprimeprime3 = (irlgm1f_3.H(t + h2) - 2.0 * irlgm1f_3.H(t) + irlgm1f_3.H(t - h2)) / (h2 * h2);
403 Hprimeprime4 = (irlgm1f_4.H(t + h2) - 2.0 * irlgm1f_4.H(t) + irlgm1f_4.H(t - h2)) / (h2 * h2);
404 Hprimeprime5 = (irlgm1f_5.H(t + h2) - 2.0 * irlgm1f_5.H(t) + irlgm1f_5.H(t - h2)) / (h2 * h2);
405 }
406 check2("sqrt(d/dt irlgm1f_2.zeta)", t, sqrt(zetaPrime2), 0.01, 1.0E-7);
407 check2("sqrt(d/dt irlgm1f_3.zeta)", t, sqrt(zetaPrime3), 0.01, 1.0E-7);
408 if (std::fabs(t - static_cast<int>(t + 0.5)) > h) {
409 // we can not expect this test to work when the numerical
410 // differentiation is going over a grid point where
411 // alpha (or sigma) jumps
412 check2("sqrt(d/dt irlgm1f_4.zeta)", t, sqrt(zetaPrime4), QL_PIECEWISE_FUNCTION(alphaTimes, alpha, t),
413 1.0E-7);
414 check2("sqrt(d/dt irlgm1f_5.zeta)*H'", t, sqrt(zetaPrime5) * Hprime5,
415 QL_PIECEWISE_FUNCTION(alphaTimes, sigma, t), 1.0E-6);
416 }
417 check2("irlgm1f_2.(-H''/H')", t, -Hprimeprime2 / Hprime2, 0.01, 2.0E-5);
418 check2("irlgm1f_3.(-H''/H')", t, -Hprimeprime3 / Hprime3, 0.00, 2.0E-5);
419 if (std::fabs(t - static_cast<int>(t + 0.5)) > h2) {
420 // same as above, we avoid to test the grid points
421 check2("irlgm1f_4.(-H''/H')", t, -Hprimeprime4 / Hprime4, QL_PIECEWISE_FUNCTION(kappaTimes, kappa, t),
422 5.0E-5);
423 check2("irlgm1f_5.(-H''/H')", t, -Hprimeprime5 / Hprime5, QL_PIECEWISE_FUNCTION(alphaTimes, kappa, t),
424 5.0E-5);
425 }
426
427 // check the remaining inspectors
428
429 check("irlgm1f_2.alpha", t, irlgm1f_2.alpha(t), 0.01);
430 check("irlgm1f_3.alpha", t, irlgm1f_3.alpha(t), 0.01);
431 check("irlgm1f_4.alpha", t, irlgm1f_4.alpha(t), QL_PIECEWISE_FUNCTION(alphaTimes, alpha, t));
432 check("irlgm1f_5.hullWhiteSigma", t, irlgm1f_5.hullWhiteSigma(t), QL_PIECEWISE_FUNCTION(alphaTimes, sigma, t));
433
434 check("irlgm1f_2.kappa", t, irlgm1f_2.kappa(t), 0.01);
435 check("irlgm1f_3.kappa", t, irlgm1f_3.kappa(t), 0.00);
436 check("irlgm1f_4.kappa", t, irlgm1f_4.kappa(t), QL_PIECEWISE_FUNCTION(kappaTimes, kappa, t));
437 check("irlgm1f_5.kappa", t, irlgm1f_5.kappa(t), QL_PIECEWISE_FUNCTION(alphaTimes, kappa, t));
438
439 check2("irlgm1f_2.Hprime", t, irlgm1f_2.Hprime(t), Hprime2, 1.0E-6);
440 check2("irlgm1f_3.Hprime", t, irlgm1f_3.Hprime(t), Hprime3, 1.0E-6);
441 if (std::fabs(t - static_cast<int>(t + 0.5)) > h) {
442 // same as above, we avoid to test the grid points
443 check2("irlgm1f_4.Hprime", t, irlgm1f_4.Hprime(t), Hprime4, 1.0E-6);
444 check2("irlgm1f_5.Hprime", t, irlgm1f_5.Hprime(t), Hprime5, 1.0E-6);
445 check2("irlgm1f_5.alpha", t, irlgm1f_5.alpha(t),
446 QL_PIECEWISE_FUNCTION(alphaTimes, sigma, t) / irlgm1f_5.Hprime(t), 1.0E-6);
447 }
448
449 check2("irlgm1f_2.Hprime2", t, irlgm1f_2.Hprime2(t), Hprimeprime2, 2.0E-5);
450 check2("irlgm1f_3.Hprime2", t, irlgm1f_3.Hprime2(t), Hprimeprime3, 2.0E-5);
451 if (std::fabs(t - static_cast<int>(t + 0.5)) > h) {
452 // same as above, we avoid to test the grid points
453 check2("irlgm1f_4.Hprime2", t, irlgm1f_4.Hprime2(t), Hprimeprime4, 2.0E-3);
454 check2("irlgm1f_5.Hprime2", t, irlgm1f_5.Hprime2(t), Hprimeprime5, 2.0E-3);
455 }
456
457 check2("irlgm1f_2.hullWhiteSigma", t, irlgm1f_2.hullWhiteSigma(t), 0.01 * Hprime2, 1.0E-7);
458 check2("irlgm1f_3.hullWhiteSigma", t, irlgm1f_3.hullWhiteSigma(t), 0.01 * Hprime3, 1.0E-7);
459 check2("irlgm1f_4.hullWhiteSigma", t, irlgm1f_4.hullWhiteSigma(t),
460 QL_PIECEWISE_FUNCTION(alphaTimes, alpha, t) * Hprime4, 1.0E-7);
461 // irlgm1f_5.alpha check is above if you should have wondered ...
462
463 t += step;
464 }
465}
virtual Real H(const Time t) const =0
const Handle< TS > termStructure() const
virtual Real zeta(const Time t) const =0
RandomVariable sqrt(RandomVariable x)
RandomVariable sin(RandomVariable x)
+ Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [3/3]

BOOST_AUTO_TEST_CASE ( testFxBsParametrizations  )

Definition at line 467 of file crossassetmodelparametrizations.cpp.

467 {
468
469 BOOST_TEST_MESSAGE("Testing CrossAssetModel parametrizations (fxbs)...");
470
471 FxBsConstantParametrization fxbs_0(USDCurrency(), Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(1.10)), 0.10);
472
473 check("fxbs_0.variance", 0.0, fxbs_0.variance(0.0), 0.0);
474 check("fxbs_0.variance", 1.0, fxbs_0.variance(1.0), 0.01 * 1.0);
475 check("fxbs_0.variance", 2.0, fxbs_0.variance(2.0), 0.01 * 2.0);
476 check("fxbs_0.variance", 3.0, fxbs_0.variance(3.0), 0.01 * 3.0);
477 check("fxbs_0.stdDeviation", 0.0, fxbs_0.stdDeviation(0.0), 0.0);
478 check("fxbs_0.stdDeviation", 1.0, fxbs_0.stdDeviation(1.0), std::sqrt(0.01 * 1.0));
479 check("fxbs_0.stdDeviation", 2.0, fxbs_0.stdDeviation(2.0), std::sqrt(0.01 * 2.0));
480 check("fxbs_0.stdDeviation", 3.0, fxbs_0.stdDeviation(3.0), std::sqrt(0.01 * 3.0));
481 check("fxbs_0.sigma", 0.0, fxbs_0.sigma(0.0), 0.10);
482 check("fxbs_0.sigma", 1.0, fxbs_0.sigma(1.0), 0.10);
483 check("fxbs_0.sigma", 2.0, fxbs_0.sigma(2.0), 0.10);
484 check("fxbs_0.sigma", 3.0, fxbs_0.sigma(3.0), 0.10);
485
486 Array times(3), sigma(4);
487 times[0] = 1.0;
488 times[1] = 2.0;
489 times[2] = 3.0;
490 sigma[0] = 0.10;
491 sigma[1] = 0.20;
492 sigma[2] = 0.0;
493 sigma[3] = 0.15;
494
495 FxBsPiecewiseConstantParametrization fxbs_1(USDCurrency(), Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(1.10)),
496 times, sigma);
497
498 check("fxbs_1.variance", 0.0, fxbs_1.variance(0.0), 0.0);
499 check("fxbs_1.variance", 0.5, fxbs_1.variance(0.5), 0.10 * 0.10 * 0.5);
500 check("fxbs_1.variance", 1.0, fxbs_1.variance(1.0), 0.10 * 0.10);
501 check("fxbs_1.variance", 1.5, fxbs_1.variance(1.5), 0.10 * 0.10 + 0.20 * 0.20 * 0.5);
502 check("fxbs_1.variance", 2.0, fxbs_1.variance(2.0), 0.10 * 0.10 + 0.20 * 0.20);
503 check("fxbs_1.variance", 2.2, fxbs_1.variance(2.2), 0.10 * 0.10 + 0.20 * 0.20);
504 check("fxbs_1.variance", 3.0, fxbs_1.variance(3.0), 0.10 * 0.10 + 0.20 * 0.20);
505 check("fxbs_1.variance", 5.0, fxbs_1.variance(5.0), 0.10 * 0.10 + 0.20 * 0.20 + 2 * 0.15 * 0.15);
506
507 check("fxbs_1.stdDeviation", 0.0, fxbs_1.stdDeviation(0.0), std::sqrt(0.0));
508 check("fxbs_1.stdDeviation", 0.5, fxbs_1.stdDeviation(0.5), std::sqrt(0.10 * 0.10 * 0.5));
509 check("fxbs_1.stdDeviation", 1.0, fxbs_1.stdDeviation(1.0), std::sqrt(0.10 * 0.10));
510 check("fxbs_1.stdDeviation", 1.5, fxbs_1.stdDeviation(1.5), std::sqrt(0.10 * 0.10 + 0.20 * 0.20 * 0.5));
511 check("fxbs_1.stdDeviation", 2.0, fxbs_1.stdDeviation(2.0), std::sqrt(0.10 * 0.10 + 0.20 * 0.20));
512 check("fxbs_1.stdDeviation", 2.2, fxbs_1.stdDeviation(2.2), std::sqrt(0.10 * 0.10 + 0.20 * 0.20));
513 check("fxbs_1.stdDeviation", 3.0, fxbs_1.stdDeviation(3.0), std::sqrt(0.10 * 0.10 + 0.20 * 0.20));
514 check("fxbs_1.stdDeviation", 5.0, fxbs_1.stdDeviation(5.0), std::sqrt(0.10 * 0.10 + 0.20 * 0.20 + 2 * 0.15 * 0.15));
515
516 check("fxb2_1.sigma", 0.0, fxbs_1.sigma(0.0), 0.10);
517 check("fxb2_1.sigma", 0.5, fxbs_1.sigma(0.5), 0.10);
518 check("fxb2_1.sigma", 1.0, fxbs_1.sigma(1.0), 0.20);
519 check("fxb2_1.sigma", 2.0, fxbs_1.sigma(2.0), 0.00);
520 check("fxb2_1.sigma", 3.0, fxbs_1.sigma(3.0), 0.15);
521 check("fxb2_1.sigma", 5.0, fxbs_1.sigma(5.0), 0.15);
522}
+ Here is the call graph for this function: