Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
scenariosimmarket.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2016 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
19#include <boost/test/unit_test.hpp>
26#include <oret/toplevelfixture.hpp>
27#include <ql/termstructures/credit/flathazardrate.hpp>
28#include <ql/termstructures/volatility/capfloor/constantcapfloortermvol.hpp>
29#include <ql/termstructures/volatility/equityfx/blackconstantvol.hpp>
30#include <ql/termstructures/volatility/swaption/swaptionconstantvol.hpp>
31#include <ql/termstructures/yield/flatforward.hpp>
32#include <ql/time/daycounters/actualactual.hpp>
34
35#include "testmarket.hpp"
36
37#include <ql/indexes/ibor/all.hpp>
38
39using namespace QuantLib;
40using namespace QuantExt;
41using namespace boost::unit_test_framework;
42using namespace std;
43using namespace ore;
44using namespace ore::data;
45
47
48namespace {
49
50QuantLib::ext::shared_ptr<data::Conventions> convs() {
51 QuantLib::ext::shared_ptr<Conventions> conventions = InstrumentConventions::instance().conventions();
52 conventions->clear();
53
54 QuantLib::ext::shared_ptr<data::Convention> swapIndexConv(
55 new data::SwapIndexConvention("EUR-CMS-2Y", "EUR-6M-SWAP-CONVENTIONS"));
56 conventions->add(swapIndexConv);
57
58 QuantLib::ext::shared_ptr<data::Convention> swapConv(
59 new data::IRSwapConvention("EUR-6M-SWAP-CONVENTIONS", "TARGET", "Annual", "MF", "30/360", "EUR-EURIBOR-6M"));
60 conventions->add(swapConv);
61
62 return conventions;
63}
64
65QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> scenarioParameters() {
66 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> parameters(new analytics::ScenarioSimMarketParameters());
67 parameters->baseCcy() = "EUR";
68 parameters->setDiscountCurveNames({"EUR", "USD"});
69 parameters->setYieldCurveTenors("", {6 * Months, 1 * Years, 2 * Years});
70 parameters->setIndices({"EUR-EURIBOR-6M", "USD-LIBOR-6M"});
71 parameters->interpolation() = "LogLinear";
72 parameters->extrapolation() = "FlatFwd";
73
74 parameters->setSwapVolTerms("", {6 * Months, 1 * Years});
75 parameters->setSwapVolExpiries("", {1 * Years, 2 * Years});
76 parameters->setSwapVolKeys({"EUR", "USD"});
77 parameters->swapVolDecayMode() = "ForwardVariance";
78
79 parameters->setDefaultNames({"dc2"});
80 parameters->setDefaultTenors("", {6 * Months, 8 * Months, 1 * Years, 2 * Years});
81
82 parameters->setSimulateFXVols(false);
83 parameters->setFxVolExpiries("", vector<Period>{2 * Years, 3 * Years, 4 * Years});
84 parameters->setFxVolDecayMode(string("ConstantVariance"));
85 parameters->setSimulateEquityVols(false);
86
87 parameters->setFxVolCcyPairs({"USDEUR"});
88
89 parameters->setFxCcyPairs({"USDEUR"});
90
91 parameters->setZeroInflationIndices({"EUHICPXT"});
92 parameters->setZeroInflationTenors("", {6 * Months, 1 * Years, 2 * Years});
93
94 parameters->setSimulateCorrelations(false);
95 parameters->correlationExpiries() = {1 * Years, 2 * Years};
96 parameters->setCorrelationPairs({"EUR-CMS-10Y:EUR-CMS-1Y", "USD-CMS-10Y:USD-CMS-1Y"});
97 return parameters;
98}
99} // namespace
100
101void testFxSpot(QuantLib::ext::shared_ptr<ore::data::Market>& initMarket,
102 QuantLib::ext::shared_ptr<ore::analytics::ScenarioSimMarket>& simMarket,
103 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters>& parameters) {
104
105 for (const auto& ccy : parameters->ccys()) {
106 if (ccy != parameters->baseCcy()) {
107 string ccyPair(parameters->baseCcy() + ccy);
108 string ccyReverse(ccy + parameters->baseCcy());
109
110 Handle<Quote> fx_sim = simMarket->fxSpot(ccyPair);
111 Handle<Quote> fx_init = initMarket->fxSpot(ccyPair);
112 if (fx_sim.empty())
113 BOOST_FAIL("fx_sim handle is empty");
114 if (fx_init.empty())
115 BOOST_FAIL("fx_init handle is empty");
116
117 BOOST_CHECK_CLOSE(fx_init->value(), fx_sim->value(), 1e-12);
118
119 fx_sim = simMarket->fxSpot(ccyReverse);
120 fx_init = initMarket->fxSpot(ccyReverse);
121 if (fx_sim.empty())
122 BOOST_FAIL("fx_sim handle is empty");
123 if (fx_init.empty())
124 BOOST_FAIL("fx_init handle is empty");
125
126 BOOST_CHECK_CLOSE(fx_init->value(), fx_sim->value(), 1e-12);
127 }
128 }
129}
130
131void testDiscountCurve(QuantLib::ext::shared_ptr<ore::data::Market>& initMarket,
132 QuantLib::ext::shared_ptr<ore::analytics::ScenarioSimMarket>& simMarket,
133 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters>& parameters) {
134
135 for (const auto& ccy : parameters->ccys()) {
136 Handle<YieldTermStructure> simCurve = simMarket->discountCurve(ccy);
137 Handle<YieldTermStructure> initCurve = initMarket->discountCurve(ccy);
138
139 BOOST_CHECK_CLOSE(simCurve->discount(0.5), initCurve->discount(0.5), 1e-12);
140 }
141}
142
143void testIndexCurve(QuantLib::ext::shared_ptr<ore::data::Market>& initMarket,
144 QuantLib::ext::shared_ptr<ore::analytics::ScenarioSimMarket>& simMarket,
145 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters>& parameters) {
146
147 for (const auto& ind : parameters->indices()) {
148 Handle<YieldTermStructure> simCurve = simMarket->iborIndex(ind)->forwardingTermStructure();
149 Handle<YieldTermStructure> initCurve = initMarket->iborIndex(ind)->forwardingTermStructure();
150
151 BOOST_CHECK_CLOSE(simCurve->discount(1), initCurve->discount(1), 1e-4);
152 }
153}
154
155void testSwaptionVolCurve(QuantLib::ext::shared_ptr<ore::data::Market>& initMarket,
156 QuantLib::ext::shared_ptr<ore::analytics::ScenarioSimMarket>& simMarket,
157 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters>& parameters) {
158 for (const auto& ccy : parameters->ccys()) {
159 Handle<QuantLib::SwaptionVolatilityStructure> simCurve = simMarket->swaptionVol(ccy);
160 Handle<QuantLib::SwaptionVolatilityStructure> initCurve = initMarket->swaptionVol(ccy);
161 for (const auto& maturity : parameters->swapVolExpiries("")) {
162 for (const auto& tenor : parameters->swapVolTerms("")) {
163 BOOST_CHECK_CLOSE(simCurve->volatility(maturity, tenor, 0.0, true),
164 initCurve->volatility(maturity, tenor, 0.0, true), 1e-12);
165 }
166 }
167 }
168}
169
170void testFxVolCurve(QuantLib::ext::shared_ptr<data::Market>& initMarket,
171 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarket>& simMarket,
172 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters>& parameters) {
173 for (const auto& ccyPair : parameters->fxVolCcyPairs()) {
174 Handle<BlackVolTermStructure> simCurve = simMarket->fxVol(ccyPair);
175 Handle<BlackVolTermStructure> initCurve = initMarket->fxVol(ccyPair);
176 vector<Date> dates;
177 Date asof = initMarket->asofDate();
178 for (Size i = 0; i < parameters->fxVolExpiries(ccyPair).size(); i++) {
179 dates.push_back(asof + parameters->fxVolExpiries(ccyPair)[i]);
180 }
181
182 for (const auto& date : dates) {
183 BOOST_CHECK_CLOSE(simCurve->blackVol(date, 0.0, true), initCurve->blackVol(date, 0.0, true), 1e-12);
184 }
185 }
186}
187
188void testDefaultCurve(QuantLib::ext::shared_ptr<ore::data::Market>& initMarket,
189 QuantLib::ext::shared_ptr<ore::analytics::ScenarioSimMarket>& simMarket,
190 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters>& parameters) {
191 for (const auto& spec : parameters->defaultNames()) {
192
193 Handle<DefaultProbabilityTermStructure> simCurve = simMarket->defaultCurve(spec)->curve();
194 Handle<DefaultProbabilityTermStructure> initCurve = initMarket->defaultCurve(spec)->curve();
195 BOOST_CHECK_EQUAL(initCurve->referenceDate(), simCurve->referenceDate());
196 vector<Date> dates;
197 Date asof = initMarket->asofDate();
198 for (Size i = 0; i < parameters->defaultTenors("").size(); i++) {
199 dates.push_back(asof + parameters->defaultTenors("")[i]);
200 }
201
202 for (const auto& date : dates) {
203 BOOST_CHECK_CLOSE(simCurve->survivalProbability(date, true), initCurve->survivalProbability(date, true),
204 1e-12);
205 }
206 }
207}
208
209void testZeroInflationCurve(QuantLib::ext::shared_ptr<ore::data::Market>& initMarket,
210 QuantLib::ext::shared_ptr<ore::analytics::ScenarioSimMarket>& simMarket,
211 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters>& parameters) {
212 for (const auto& spec : parameters->zeroInflationIndices()) {
213
214 Handle<ZeroInflationTermStructure> simCurve = simMarket->zeroInflationIndex(spec)->zeroInflationTermStructure();
215 Handle<ZeroInflationTermStructure> initCurve =
216 initMarket->zeroInflationIndex(spec)->zeroInflationTermStructure();
217 BOOST_CHECK_EQUAL(initCurve->referenceDate(), simCurve->referenceDate());
218 vector<Date> dates;
219 Date asof = initMarket->asofDate();
220 for (Size i = 0; i < parameters->zeroInflationTenors("").size(); i++) {
221 dates.push_back(asof + parameters->zeroInflationTenors("")[i]);
222 }
223
224 for (const auto& date : dates) {
225 BOOST_CHECK_CLOSE(simCurve->zeroRate(date), initCurve->zeroRate(date), 1e-12);
226 }
227 }
228}
229
230void testCorrelationCurve(QuantLib::ext::shared_ptr<ore::data::Market>& initMarket,
231 QuantLib::ext::shared_ptr<ore::analytics::ScenarioSimMarket>& simMarket,
232 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters>& parameters) {
233 for (const auto& spec : parameters->correlationPairs()) {
234 vector<string> tokens;
235 boost::split(tokens, spec, boost::is_any_of(":&"));
236 QL_REQUIRE(tokens.size() == 2, "not a valid correlation pair: " << spec);
237 pair<string, string> pair = std::make_pair(tokens[0], tokens[1]);
238 Handle<QuantExt::CorrelationTermStructure> simCurve = simMarket->correlationCurve(pair.first, pair.second);
239 Handle<QuantExt::CorrelationTermStructure> initCurve = initMarket->correlationCurve(pair.first, pair.second);
240 BOOST_CHECK_EQUAL(initCurve->referenceDate(), simCurve->referenceDate());
241 vector<Date> dates;
242 Date asof = initMarket->asofDate();
243 for (Size i = 0; i < parameters->correlationExpiries().size(); i++) {
244 dates.push_back(asof + parameters->correlationExpiries()[i]);
245 }
246
247 for (const auto& date : dates) {
248 BOOST_CHECK_CLOSE(simCurve->correlation(date), initCurve->correlation(date), 1e-12);
249 }
250 }
251}
252
253void testToXML(QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> params) {
254
255 BOOST_TEST_MESSAGE("Testing to XML...");
256 XMLDocument outDoc;
257 string testFile = "simtest.xml";
258 XMLNode* simulationNode = params->toXML(outDoc);
259
260 outDoc.appendNode(simulationNode);
261 outDoc.toFile(testFile);
262
263 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> newParams(new analytics::ScenarioSimMarketParameters());
264 newParams->fromFile(testFile);
265 BOOST_CHECK(*params == *newParams);
266
267 newParams->baseCcy() = "JPY";
268 BOOST_CHECK(*params != *newParams);
269
270 remove("simtest.xml");
271}
272
273BOOST_FIXTURE_TEST_SUITE(OREAnalyticsTestSuite, ore::test::OreaTopLevelFixture)
274
275BOOST_AUTO_TEST_SUITE(ScenarioSimMarketTest)
276
277BOOST_AUTO_TEST_CASE(testScenarioSimMarket) {
278 BOOST_TEST_MESSAGE("Testing OREAnalytics ScenarioSimMarket...");
279
280 SavedSettings backup;
281
282 Date today(20, Jan, 2015);
283 Settings::instance().evaluationDate() = today;
284 QuantLib::ext::shared_ptr<ore::data::Market> initMarket = QuantLib::ext::make_shared<TestMarket>(today);
285
286 // Empty scenario generator
287 QuantLib::ext::shared_ptr<ore::analytics::ScenarioGenerator> scenarioGenerator;
288
289 // build scenario
290 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> parameters = scenarioParameters();
291 convs();
292 // build scenario sim market
293 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarket> simMarket(
294 new analytics::ScenarioSimMarket(initMarket, parameters));
295 simMarket->scenarioGenerator() = scenarioGenerator;
296
297 // test
298 testFxSpot(initMarket, simMarket, parameters);
299 testDiscountCurve(initMarket, simMarket, parameters);
300 testIndexCurve(initMarket, simMarket, parameters);
301 testSwaptionVolCurve(initMarket, simMarket, parameters);
302 testFxVolCurve(initMarket, simMarket, parameters);
303 testDefaultCurve(initMarket, simMarket, parameters);
304 testZeroInflationCurve(initMarket, simMarket, parameters);
305 testCorrelationCurve(initMarket, simMarket, parameters);
306 testToXML(parameters);
307}
308
309BOOST_AUTO_TEST_SUITE_END()
310
311BOOST_AUTO_TEST_SUITE_END()
Simulation Market updated with discrete scenarios.
void appendNode(XMLNode *)
void toFile(const string &filename) const
OREAnalytics Top level fixture.
Simple flat market setup to be used in the test suite.
Definition: testmarket.hpp:64
Time maturity
Size size(const ValueType &v)
QuantLib::ext::shared_ptr< data::Conventions > convs()
Fixture that can be used at top level of OREAnalytics test suites.
A Market class that can be updated by Scenarios.
A class to hold Scenario parameters for scenarioSimMarket.
Date asof(14, Jun, 2018)
void testZeroInflationCurve(QuantLib::ext::shared_ptr< ore::data::Market > &initMarket, QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarket > &simMarket, QuantLib::ext::shared_ptr< analytics::ScenarioSimMarketParameters > &parameters)
void testDefaultCurve(QuantLib::ext::shared_ptr< ore::data::Market > &initMarket, QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarket > &simMarket, QuantLib::ext::shared_ptr< analytics::ScenarioSimMarketParameters > &parameters)
BOOST_AUTO_TEST_CASE(testScenarioSimMarket)
void testCorrelationCurve(QuantLib::ext::shared_ptr< ore::data::Market > &initMarket, QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarket > &simMarket, QuantLib::ext::shared_ptr< analytics::ScenarioSimMarketParameters > &parameters)
void testDiscountCurve(QuantLib::ext::shared_ptr< ore::data::Market > &initMarket, QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarket > &simMarket, QuantLib::ext::shared_ptr< analytics::ScenarioSimMarketParameters > &parameters)
void testIndexCurve(QuantLib::ext::shared_ptr< ore::data::Market > &initMarket, QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarket > &simMarket, QuantLib::ext::shared_ptr< analytics::ScenarioSimMarketParameters > &parameters)
void testSwaptionVolCurve(QuantLib::ext::shared_ptr< ore::data::Market > &initMarket, QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarket > &simMarket, QuantLib::ext::shared_ptr< analytics::ScenarioSimMarketParameters > &parameters)
void testToXML(QuantLib::ext::shared_ptr< analytics::ScenarioSimMarketParameters > params)
void testFxSpot(QuantLib::ext::shared_ptr< ore::data::Market > &initMarket, QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarket > &simMarket, QuantLib::ext::shared_ptr< analytics::ScenarioSimMarketParameters > &parameters)
void testFxVolCurve(QuantLib::ext::shared_ptr< data::Market > &initMarket, QuantLib::ext::shared_ptr< analytics::ScenarioSimMarket > &simMarket, QuantLib::ext::shared_ptr< analytics::ScenarioSimMarketParameters > &parameters)