Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Functions
simulationmeasures.cpp File Reference
#include <boost/test/unit_test.hpp>
#include <orea/scenario/crossassetmodelscenariogenerator.hpp>
#include <orea/scenario/lgmscenariogenerator.hpp>
#include <orea/scenario/scenariogeneratorbuilder.hpp>
#include <orea/scenario/scenariosimmarket.hpp>
#include <orea/scenario/simplescenario.hpp>
#include <orea/scenario/simplescenariofactory.hpp>
#include <ored/marketdata/market.hpp>
#include <ored/marketdata/marketimpl.hpp>
#include <ored/model/calibrationinstruments/cpicapfloor.hpp>
#include <ored/model/crossassetmodelbuilder.hpp>
#include <ored/model/irlgmdata.hpp>
#include <ored/portfolio/builders/swap.hpp>
#include <ored/portfolio/swap.hpp>
#include <ored/utilities/log.hpp>
#include <ored/utilities/to_string.hpp>
#include <oret/toplevelfixture.hpp>
#include <test/oreatoplevelfixture.hpp>
#include <qle/instruments/fxforward.hpp>
#include <qle/models/crossassetmodel.hpp>
#include <qle/models/fxbspiecewiseconstantparametrization.hpp>
#include <qle/models/irlgm1fpiecewiseconstantparametrization.hpp>
#include <qle/models/lgm.hpp>
#include <qle/pricingengines/analyticcclgmfxoptionengine.hpp>
#include <qle/pricingengines/analyticdkcpicapfloorengine.hpp>
#include <qle/pricingengines/analyticlgmswaptionengine.hpp>
#include <qle/pricingengines/discountingfxforwardengine.hpp>
#include <qle/pricingengines/discountingswapenginemulticurve.hpp>
#include <ql/cashflows/simplecashflow.hpp>
#include <ql/currencies/america.hpp>
#include <ql/currencies/europe.hpp>
#include <ql/indexes/ibor/all.hpp>
#include <ql/indexes/swap/euriborswap.hpp>
#include <ql/indexes/swap/usdliborswap.hpp>
#include <ql/instruments/cpicapfloor.hpp>
#include <ql/instruments/makeswaption.hpp>
#include <ql/instruments/makevanillaswap.hpp>
#include <ql/math/statistics/incrementalstatistics.hpp>
#include <ql/pricingengines/vanilla/analyticeuropeanengine.hpp>
#include <ql/quotes/simplequote.hpp>
#include <ql/termstructures/volatility/equityfx/blackconstantvol.hpp>
#include <ql/termstructures/volatility/swaption/swaptionconstantvol.hpp>
#include <ql/termstructures/yield/flatforward.hpp>
#include <ql/time/calendars/target.hpp>
#include <ql/time/daycounters/actual360.hpp>
#include <ql/time/daycounters/thirty360.hpp>
#include "testmarket.hpp"
#include <boost/timer/timer.hpp>

Go to the source code of this file.

Functions

void test_measure (std::string measureName, Real shiftHorizon, std::string discName)
 
 BOOST_AUTO_TEST_CASE (testLgmExact)
 
 BOOST_AUTO_TEST_CASE (testFwdExact)
 
 BOOST_AUTO_TEST_CASE (testBaExact)
 
 BOOST_AUTO_TEST_CASE (testBaEuler)
 

Function Documentation

◆ test_measure()

void test_measure ( std::string  measureName,
Real  shiftHorizon,
std::string  discName 
)

Definition at line 204 of file simulationmeasures.cpp.

204 {
205
206 BOOST_TEST_MESSAGE("Testing market simulation, measure " << measureName << ", horizon " << shiftHorizon
207 << ", discretization " << discName);
208
209 TestData d(measureName, shiftHorizon);
210
211 // Simulation date grid
212 Date today = d.referenceDate;
213 std::vector<Period> tenorGrid;
214 if (discName == "exact")
215 tenorGrid = {1 * Years, 2 * Years, 3 * Years, 5 * Years, 7 * Years, 10 * Years};
216 else {
217 for (Size i = 1; i <= 60; ++i)
218 tenorGrid.push_back(i * 2 * Months);
219 }
220 QuantLib::ext::shared_ptr<DateGrid> grid = QuantLib::ext::make_shared<DateGrid>(tenorGrid);
221
222 // Model
223 QuantLib::ext::shared_ptr<QuantExt::CrossAssetModel> model = discName == "exact" ? d.ccLgmExact : d.ccLgmEuler;
224
225 // Simulation market parameters, we just need the yield curve structure here
226 QuantLib::ext::shared_ptr<ScenarioSimMarketParameters> simMarketConfig(new ScenarioSimMarketParameters);
227 simMarketConfig->setYieldCurveTenors("", {3 * Months, 6 * Months, 1 * Years, 2 * Years, 3 * Years, 4 * Years,
228 5 * Years, 7 * Years, 10 * Years, 12 * Years});
229 simMarketConfig->setSimulateFXVols(false);
230 simMarketConfig->setSimulateEquityVols(false);
231
232 simMarketConfig->baseCcy() = "EUR";
233 simMarketConfig->setDiscountCurveNames({"EUR", "USD", "GBP"});
234 simMarketConfig->setIndices({"EUR-EURIBOR-6M", "USD-LIBOR-3M", "GBP-LIBOR-6M"});
235 simMarketConfig->interpolation() = "LogLinear";
236 simMarketConfig->setSwapVolExpiries("", {6 * Months, 1 * Years, 2 * Years, 3 * Years, 5 * Years, 10 * Years});
237 simMarketConfig->setSwapVolTerms("", {1 * Years, 2 * Years, 3 * Years, 5 * Years, 7 * Years, 10 * Years});
238 simMarketConfig->setFxCcyPairs({"USDEUR", "GBPEUR"});
239
240 QuantLib::ext::shared_ptr<ScenarioGeneratorData> sgd(new ScenarioGeneratorData);
241 sgd->sequenceType() = Sobol;
242 sgd->seed() = 42;
243 sgd->setGrid(grid);
244
246 QuantLib::ext::shared_ptr<ScenarioFactory> sf = QuantLib::ext::make_shared<SimpleScenarioFactory>(true);
247 QuantLib::ext::shared_ptr<ScenarioGenerator> sg = sgb.build(model, sf, simMarketConfig, today, d.market);
248
249 convs();
250 auto simMarket = QuantLib::ext::make_shared<ScenarioSimMarket>(d.market, simMarketConfig);
251 simMarket->scenarioGenerator() = sg;
252
253 // Basic Martingale tests
254 Size samples = 5000;
255 Real eur = 0.0, usd = 0.0, gbp = 0.0, eur2 = 0.0, usd2 = 0.0, gbp2 = 0.0;
256 Real eur3 = 0.0, usd3 = 0.0, gbp3 = 0.0;
257 int horizon = 10;
258
259 Date d1 = grid->dates().back();
260 Date d2 = d1 + horizon * Years;
261 Real relTolerance = 0.01;
262 Real eurExpected = d.market->discountCurve("EUR")->discount(d2);
263 Real eurExpected2 = d.market->discountCurve("EUR")->discount(d1);
264 Real gbpExpected = d.market->fxRate("GBPEUR")->value() * d.market->discountCurve("GBP")->discount(d2);
265 Real gbpExpected2 = d.market->fxRate("GBPEUR")->value() * d.market->discountCurve("GBP")->discount(d1);
266 Real usdExpected = d.market->fxRate("USDEUR")->value() * d.market->discountCurve("USD")->discount(d2);
267 Real usdExpected2 = d.market->fxRate("USDEUR")->value() * d.market->discountCurve("USD")->discount(d1);
268
269 cpu_timer timer, timer2;
270 BOOST_TEST_MESSAGE("running " << samples << " samples simulation over " << grid->dates().size() << " time steps");
271 for (Size i = 0; i < samples; i++) {
272 for (Date d : grid->dates()) {
273 timer.resume();
274 simMarket->update(d);
275 timer.stop();
276 if (d == grid->dates().back()) {
277 Real numeraire = simMarket->numeraire();
278 Real usdeurFX = simMarket->fxRate("USDEUR")->value();
279 Real gbpeurFX = simMarket->fxRate("GBPEUR")->value();
280 Real eurDiscount = simMarket->discountCurve("EUR")->discount(1.0 * horizon);
281 Real gbpDiscount = simMarket->discountCurve("GBP")->discount(1.0 * horizon);
282 ;
283 Real usdDiscount = simMarket->discountCurve("USD")->discount(1.0 * horizon);
284 ;
285 Real eurIndex =
286 simMarket->iborIndex("EUR-EURIBOR-6M")->forwardingTermStructure()->discount(1.0 * horizon);
287 Real gbpIndex =
288 simMarket->iborIndex("GBP-LIBOR-6M")->forwardingTermStructure()->discount(1.0 * horizon);
289 ;
290 Real usdIndex =
291 simMarket->iborIndex("USD-LIBOR-3M")->forwardingTermStructure()->discount(1.0 * horizon);
292 ;
293 eur += eurDiscount / numeraire;
294 gbp += gbpDiscount * gbpeurFX / numeraire;
295 usd += usdDiscount * usdeurFX / numeraire;
296 eur2 += 1.0 / numeraire;
297 gbp2 += gbpeurFX / numeraire;
298 usd2 += usdeurFX / numeraire;
299 eur3 += eurIndex / numeraire;
300 gbp3 += gbpIndex * gbpeurFX / numeraire;
301 usd3 += usdIndex * usdeurFX / numeraire;
302 }
303 }
304 }
305
306 timer2.stop();
307
308 eur /= samples;
309 gbp /= samples;
310 usd /= samples;
311 eur2 /= samples;
312 gbp2 /= samples;
313 usd2 /= samples;
314 eur3 /= samples;
315 gbp3 /= samples;
316 usd3 /= samples;
317
318 Real eurDiff = fabs(eur - eurExpected) / eurExpected;
319 BOOST_CHECK_MESSAGE(eurDiff < relTolerance, "EUR 20Y Discount mismatch: " << eur << " vs " << eurExpected);
320
321 Real gbpDiff = fabs(gbp - gbpExpected) / gbpExpected;
322 BOOST_CHECK_MESSAGE(gbpDiff < relTolerance,
323 "GBP 20Y Discount mismatch: " << gbp << " vs " << gbpExpected << " (" << gbpDiff << ")");
324
325 Real usdDiff = fabs(usd - usdExpected) / usdExpected;
326 BOOST_CHECK_MESSAGE(usdDiff < relTolerance, "USD 20Y Discount mismatch: " << usd << " vs " << usdExpected);
327
328 Real eur3Diff = fabs(eur3 - eurExpected) / eurExpected;
329 BOOST_CHECK_MESSAGE(eur3Diff < relTolerance, "EUR 20Y Index Discount mismatch: " << eur3 << " vs " << eurExpected);
330
331 Real gbp3Diff = fabs(gbp3 - gbpExpected) / gbpExpected;
332 BOOST_CHECK_MESSAGE(gbp3Diff < relTolerance, "GBP 20Y Index Discount mismatch: " << gbp3 << " vs " << gbpExpected);
333
334 Real usd3Diff = fabs(usd3 - usdExpected) / usdExpected;
335 BOOST_CHECK_MESSAGE(usd3Diff < relTolerance, "USD 20Y Index Discount mismatch: " << usd3 << " vs " << usdExpected);
336
337 Real eur2Diff = fabs(eur2 - eurExpected2) / eurExpected2;
338 BOOST_CHECK_MESSAGE(eur2Diff < relTolerance, "EUR 10Y Discount mismatch: " << eur2 << " vs " << eurExpected2);
339
340 Real gbp2Diff = fabs(gbp2 - gbpExpected2) / gbpExpected2;
341 BOOST_CHECK_MESSAGE(gbp2Diff < relTolerance, "GBP 10Y Discount mismatch: " << gbp2 << " vs " << gbpExpected2);
342
343 Real usd2Diff = fabs(usd2 - usdExpected2) / usdExpected2;
344 BOOST_CHECK_MESSAGE(usd2Diff < relTolerance, "USD 10Y Discount mismatch: " << usd2 << " vs " << usdExpected2);
345
346 BOOST_TEST_MESSAGE("CrossAssetModel via ScenarioSimMarket");
347 BOOST_TEST_MESSAGE("EUR " << QuantLib::io::iso_date(d2) << " Discount: " << eur << " vs " << eurExpected
348 << " (" << eurDiff << ")");
349 BOOST_TEST_MESSAGE("GBP " << QuantLib::io::iso_date(d2) << " Discount in EUR: " << gbp << " vs " << gbpExpected
350 << " (" << gbpDiff << ")");
351 BOOST_TEST_MESSAGE("USD " << QuantLib::io::iso_date(d2) << " Discount in EUR: " << usd << " vs " << usdExpected
352 << " (" << usdDiff << ")");
353 BOOST_TEST_MESSAGE("EUR " << QuantLib::io::iso_date(d1) << " Discount: " << eur2 << " vs " << eurExpected2
354 << " (" << eur2Diff << ")");
355 BOOST_TEST_MESSAGE("GBP " << QuantLib::io::iso_date(d1) << " Discount in EUR: " << gbp2 << " vs " << gbpExpected2
356 << " (" << gbp2Diff << ")");
357 BOOST_TEST_MESSAGE("USD " << QuantLib::io::iso_date(d1) << " Discount in EUR: " << usd2 << " vs " << usdExpected2
358 << " (" << usd2Diff << ")");
359 BOOST_TEST_MESSAGE("Simulation time " << timer.format(default_places, "%w") << ", total "
360 << timer2.format(default_places, "%w"));
361}
Sobol
QuantLib::ext::shared_ptr< data::Conventions > convs()
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BOOST_AUTO_TEST_CASE() [1/4]

BOOST_AUTO_TEST_CASE ( testLgmExact  )

Definition at line 363 of file simulationmeasures.cpp.

363{ test_measure("LGM", 0.0, "exact"); }
void test_measure(std::string measureName, Real shiftHorizon, std::string discName)
+ Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [2/4]

BOOST_AUTO_TEST_CASE ( testFwdExact  )

Definition at line 367 of file simulationmeasures.cpp.

367{ test_measure("LGM", 30.0, "exact"); }
+ Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [3/4]

BOOST_AUTO_TEST_CASE ( testBaExact  )

Definition at line 371 of file simulationmeasures.cpp.

371{ test_measure("BA", 0.0, "exact"); }
+ Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [4/4]

BOOST_AUTO_TEST_CASE ( testBaEuler  )

Definition at line 373 of file simulationmeasures.cpp.

373{ test_measure("BA", 0.0, "euler"); }
+ Here is the call graph for this function: