Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
curveconfig.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/algorithm/string.hpp>
20#include <boost/make_shared.hpp>
21// clang-format off
22#include <boost/test/unit_test.hpp>
23#include <boost/test/data/test_case.hpp>
24// clang-format on
40#include <oret/datapaths.hpp>
41#include <oret/fileutilities.hpp>
42#include <oret/toplevelfixture.hpp>
43
44#include <ql/time/calendar.hpp>
45#include <ql/time/daycounter.hpp>
46
47using namespace QuantLib;
48using namespace QuantExt;
49using namespace boost::unit_test_framework;
50using namespace std;
51using namespace ore;
52using namespace ore::data;
53
54using ore::test::TopLevelFixture;
55using std::ostream;
56
58
59namespace {
60
61// Suite level fixture that:
62// - loads curve configurations
63// - cleans up output files
64class F : public TopLevelFixture {
65public:
67
68 F() {
69
70 // Clear previous output if any.
71 clearOutput(TEST_OUTPUT_PATH);
72
73 // Read curve configurations from file
74 curveConfigs.fromFile(TEST_INPUT_FILE("curve_config.xml"));
75 curveConfigs.parseAll();
76 }
77
78 ~F() {}
79};
80
81set<string> readQuotes(const string& filename) {
82 // Read the quotes from the file
83 CSVFileReader reader(filename, false, ",");
84
85 // Insert the quotes in a set
86 set<string> quotes;
87 while (reader.next()) {
88 quotes.insert(reader.get(0));
89 }
90
91 return quotes;
92}
93
94// Todays market input and expected quotes output file
95vector<pair<string, string>> files = {
96 make_pair("todays_market_only_ir.xml", "expected_quotes_only_ir.csv"),
97 make_pair("todays_market_with_fx_vol_smile.xml", "expected_quotes_with_fx_vol_smile.csv"),
98 make_pair("todays_market_with_fx_vol_smile_delta.xml", "expected_quotes_with_fx_vol_smile_delta.csv"),
99 make_pair("todays_market_with_fx_vol_atm.xml", "expected_quotes_with_fx_vol_atm.csv"),
100 make_pair("todays_market_single_config_gbp.xml", "expected_quotes_tmp_single_gbp.csv")};
101
102} // namespace
103
104// Needed for BOOST_DATA_TEST_CASE below as it writes out the string pair
105// https://stackoverflow.com/a/33965517/1771882
106namespace boost {
107namespace test_tools {
108namespace tt_detail {
109template <> struct print_log_value<pair<string, string>> {
110 void operator()(std::ostream& os, const pair<string, string>& p) { os << "[" << p.first << "," << p.second << "]"; }
111};
112} // namespace tt_detail
113} // namespace test_tools
114} // namespace boost
115
116BOOST_FIXTURE_TEST_SUITE(OREDataTestSuite, TopLevelFixture)
117
118BOOST_FIXTURE_TEST_SUITE(CurveConfigTest, F)
119
120BOOST_AUTO_TEST_CASE(testFromToXml) {
121
122 // Write the curve configurations to file
123 string outputFile_1 = TEST_OUTPUT_FILE("curve_config_out_1.xml");
124 curveConfigs.toFile(outputFile_1);
125
126 // Read curve configurations from output file
127 CurveConfigurations curveConfigsNew;
128 curveConfigsNew.fromFile(outputFile_1);
129 curveConfigsNew.parseAll();
130
131 // Write curve configurations to file again
132 string outputFile_2 = TEST_OUTPUT_FILE("curve_config_out_2.xml");
133 curveConfigsNew.toFile(outputFile_2);
134
135 // Compare contents of the output files
136 BOOST_CHECK(compareFiles(outputFile_1, outputFile_2));
137}
138
139// Testing curve config quotes method with no restrictions
140BOOST_AUTO_TEST_CASE(testCurveConfigQuotesAll) {
141
142 // Ask the curve configurations object for all of its quotes
143 set<string> quotes = curveConfigs.quotes();
144
145 // Read the expected set of quotes from the file
146 set<string> expectedQuotes = readQuotes(TEST_INPUT_FILE("expected_quotes_all.csv"));
147
148 // Check that the quotes match the expected quotes
149 BOOST_REQUIRE_EQUAL(quotes.size(), expectedQuotes.size());
150 BOOST_CHECK_EQUAL_COLLECTIONS(quotes.begin(), quotes.end(), expectedQuotes.begin(), expectedQuotes.end());
151}
152
153// Testing curve config quotes method for various TodaysMarketParameters
154BOOST_DATA_TEST_CASE(testCurveConfigQuotesSimpleTodaysMarket, bdata::make(files), filePair) {
155
156 BOOST_TEST_MESSAGE("Testing with todaysmarket file: " << filePair.first);
157
158 // Read the simple, single default configuration, TodaysMarketParameters instance from file
159 QuantLib::ext::shared_ptr<TodaysMarketParameters> tmp = QuantLib::ext::make_shared<TodaysMarketParameters>();
160 tmp->fromFile(TEST_INPUT_FILE(filePair.first));
161
162 // Ask the curve configurations object for its quotes, restricted by the TodaysMarketParameters instance
163 set<string> quotes = curveConfigs.quotes(tmp, {Market::defaultConfiguration});
164
165 // Read the expected set of quotes from the file
166 set<string> expectedQuotes = readQuotes(TEST_INPUT_FILE(filePair.second));
167
168 // Check that the quotes match the expected quotes
169 BOOST_REQUIRE_EQUAL(quotes.size(), expectedQuotes.size());
170 BOOST_CHECK_EQUAL_COLLECTIONS(quotes.begin(), quotes.end(), expectedQuotes.begin(), expectedQuotes.end());
171}
172
173// Testing curve config quotes method for a TodaysMarketParameters with multiple configurations
174BOOST_AUTO_TEST_CASE(testCurveConfigQuotesTodaysMarketMultipleConfigs) {
175
176 // Read the TodaysMarketParameters instance, containing multiple configurations, from file
177 QuantLib::ext::shared_ptr<TodaysMarketParameters> tmp = QuantLib::ext::make_shared<TodaysMarketParameters>();
178 tmp->fromFile(TEST_INPUT_FILE("todays_market_multiple_configs.xml"));
179
180 BOOST_REQUIRE_EQUAL(tmp->configurations().size(), 4);
181
182 // Check the quotes for each configuration in turn
183 for (const auto& kv : tmp->configurations()) {
184
185 BOOST_TEST_MESSAGE("Checking quotes for configuration: " << kv.first);
186
187 // Ask the curve configurations object for its quotes, restricted by the TodaysMarketParameters
188 // instance and the configuration
189 set<string> quotes = curveConfigs.quotes(tmp, {kv.first});
190
191 // Read the expected set of quotes from the file
192 set<string> expectedQuotes;
193 if (kv.first == "collateral_inccy") {
194 expectedQuotes = readQuotes(TEST_INPUT_FILE("expected_quotes_tmp_multiple_collateral_inccy.csv"));
195 } else {
196 expectedQuotes = readQuotes(TEST_INPUT_FILE("expected_quotes_tmp_multiple.csv"));
197 }
198
199 // Check that the quotes match the expected quotes
200 BOOST_REQUIRE_EQUAL(quotes.size(), expectedQuotes.size());
201 BOOST_CHECK_EQUAL_COLLECTIONS(quotes.begin(), quotes.end(), expectedQuotes.begin(), expectedQuotes.end());
202 }
203}
204
205// Test fromXML for DiscountRatioYieldCurveSegment
206BOOST_AUTO_TEST_CASE(testDiscountRatioSegmentFromXml) {
207
208 // XML string
209 string xml;
210 xml.append("<DiscountRatio>");
211 xml.append(" <Type>Discount Ratio</Type>");
212 xml.append(" <BaseCurve currency=\"EUR\">EUR1D</BaseCurve>");
213 xml.append(" <NumeratorCurve currency=\"BRL\">BRL-IN-USD</NumeratorCurve>");
214 xml.append(" <DenominatorCurve currency=\"EUR\">EUR-IN-USD</DenominatorCurve>");
215 xml.append("</DiscountRatio>");
216
217 // XMLDocument from string
218 XMLDocument doc;
219 doc.fromXMLString(xml);
220
221 // Populate empty segment from XML node
223 seg.fromXML(doc.getFirstNode(""));
224
225 // Perform the checks
226 BOOST_CHECK(seg.type() == YieldCurveSegment::Type::DiscountRatio);
227 BOOST_CHECK_EQUAL(seg.typeID(), "Discount Ratio");
228 BOOST_CHECK_EQUAL(seg.conventionsID(), "");
229 BOOST_CHECK(seg.quotes().empty());
230
231 BOOST_CHECK_EQUAL(seg.baseCurveId(), "EUR1D");
232 BOOST_CHECK_EQUAL(seg.baseCurveCurrency(), "EUR");
233 BOOST_CHECK_EQUAL(seg.numeratorCurveId(), "BRL-IN-USD");
234 BOOST_CHECK_EQUAL(seg.numeratorCurveCurrency(), "BRL");
235 BOOST_CHECK_EQUAL(seg.denominatorCurveId(), "EUR-IN-USD");
236 BOOST_CHECK_EQUAL(seg.denominatorCurveCurrency(), "EUR");
237}
238
239// Test toXML for DiscountRatioYieldCurveSegment
240BOOST_AUTO_TEST_CASE(testDiscountRatioSegmentToXml) {
241 // Create a discount ratio segment
242 DiscountRatioYieldCurveSegment seg("Discount Ratio", "EUR1D", "EUR", "BRL-IN-USD", "BRL", "EUR-IN-USD", "EUR");
243
244 // Create an XML document from the segment using toXML
245 XMLDocument doc;
246 doc.appendNode(seg.toXML(doc));
247
248 // Create new segment using fromXML and check entries
250 BOOST_CHECK_NO_THROW(newSeg.fromXML(doc.getFirstNode("")));
251 BOOST_CHECK(newSeg.type() == YieldCurveSegment::Type::DiscountRatio);
252 BOOST_CHECK_EQUAL(newSeg.typeID(), "Discount Ratio");
253 BOOST_CHECK_EQUAL(newSeg.conventionsID(), "");
254 BOOST_CHECK(newSeg.quotes().empty());
255
256 BOOST_CHECK_EQUAL(newSeg.baseCurveId(), "EUR1D");
257 BOOST_CHECK_EQUAL(newSeg.baseCurveCurrency(), "EUR");
258 BOOST_CHECK_EQUAL(newSeg.numeratorCurveId(), "BRL-IN-USD");
259 BOOST_CHECK_EQUAL(newSeg.numeratorCurveCurrency(), "BRL");
260 BOOST_CHECK_EQUAL(newSeg.denominatorCurveId(), "EUR-IN-USD");
261 BOOST_CHECK_EQUAL(newSeg.denominatorCurveCurrency(), "EUR");
262}
263
264BOOST_AUTO_TEST_SUITE_END()
265
266BOOST_AUTO_TEST_SUITE_END()
Base Correlation curve configuration classes.
Cap floor volatility curve configuration class.
CDS and index CDS volatility configuration.
Container class for all Curve Configurations.
Discount ratio yield curve segment.
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
static const string defaultConfiguration
Default configuration label.
Definition: market.hpp:296
Small XML Document wrapper class.
Definition: xmlutils.hpp:65
void appendNode(XMLNode *)
Definition: xmlutils.cpp:118
void fromXMLString(const string &xmlString)
load a document from a hard-coded string
Definition: xmlutils.cpp:103
XMLNode * getFirstNode(const string &name) const
Definition: xmlutils.cpp:116
void fromFile(const std::string &filename)
Definition: xmlutils.cpp:150
void toFile(const std::string &filename) const
Definition: xmlutils.cpp:155
const vector< pair< string, bool > > & quotes() const
const string & conventionsID() const
const string & typeID() const
utility class to access CSV files
Curve configuration repository.
Default curve configuration classes.
Equity curve configuration classes.
Equity volatility curve configuration classes.
security spread configuration classes
FX volatility curve configuration classes.
Inflation curve config.
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Map text representations to QuantLib/QuantExt types.
security spread configuration classes
Swaption volatility curve configuration classes.
vector< string > curveConfigs
BOOST_DATA_TEST_CASE(testCurveConfigQuotesSimpleTodaysMarket, bdata::make(files), filePair)
BOOST_AUTO_TEST_CASE(testFromToXml)
Yield curve configuration classes.