Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
basecorrelationcurve.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2022 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 "toplevelfixture.hpp"
20#include <boost/make_shared.hpp>
21#include <boost/test/unit_test.hpp>
22
23#include <ql/quotes/simplequote.hpp>
24#include <ql/time/calendars/weekendsonly.hpp>
25#include <ql/time/daycounters/actual365fixed.hpp>
29
30using namespace boost::unit_test_framework;
31using namespace QuantLib;
32
33BOOST_FIXTURE_TEST_SUITE(QuantExtTestSuite, qle::test::TopLevelFixture)
34
35BOOST_AUTO_TEST_SUITE(BaseCorrelationTests)
36
37struct CommonData {
38 Date today;
39 std::vector<double> detachmentPoints;
40 std::vector<Period> tenors;
41 Date startDate;
42
43 CommonData()
44 : today(22, Sep, 2022), detachmentPoints({0.03, 0.07, 0.15, 1.0}), tenors({3 * Years, 5 * Years}),
45 startDate(20, Sep, 2021) {}
46};
47
48void initializeSettings(CommonData& cd) {
49 Settings::instance().evaluationDate() = cd.today;
50}
51
52Handle<QuantExt::BaseCorrelationTermStructure> buildBilinearFlatBaseCorrelationCurve(CommonData& cd) {
53 // Correlation matrix detachmentPoints x tenors
54 std::vector<std::vector<double>> correlations{
55 {0.409223169, 0.405249307}, {0.507498351, 0.486937064}, {0.614741119, 0.623673691}, {1.0, 1.0}};
56
57 std::vector<std::vector<Handle<Quote>>> quotes;
58 for (const auto& row : correlations) {
59 quotes.push_back(std::vector<Handle<Quote>>());
60 for (const auto& correl : row) {
61 quotes.back().push_back(Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(correl)));
62 }
63 }
64
65 return Handle<QuantExt::BaseCorrelationTermStructure>(QuantLib::ext::make_shared<QuantExt::InterpolatedBaseCorrelationTermStructure<QuantExt::BilinearFlat>>(
66 0, WeekendsOnly(), ModifiedFollowing, cd.tenors, cd.detachmentPoints, quotes, Actual365Fixed(), cd.startDate,
67 DateGeneration::CDS2015));
68}
69
70BOOST_AUTO_TEST_CASE(testBaseCorrelationCurve) {
71 CommonData cd;
72
74
76
77
78 BOOST_CHECK_EQUAL(curve->dates()[0], Date(20, Dec, 2024));
79 BOOST_CHECK_EQUAL(curve->dates()[1], Date(20, Dec, 2026));
80
81 // Check quoted points
82 BOOST_CHECK_CLOSE(curve->correlation(Date(20, Dec, 2026), 0.03), 0.405249307, 1e-10);
83 BOOST_CHECK_CLOSE(curve->correlation(Date(20, Dec, 2026), 0.07), 0.486937064, 1e-10);
84 // Check detachment point interpolation
85 BOOST_CHECK_CLOSE(curve->correlation(Date(20, Dec, 2026), 0.05), (0.405249307 + 0.486937064) / 2.0, 1e-10);
86 // Check if exceptions are thrown for extrapolation without enable extrapolation
87 curve->disableExtrapolation();
88 BOOST_CHECK_THROW(curve->correlation(Date(20, Dec, 2026), 0.01), std::exception);
89 BOOST_CHECK_THROW(curve->correlation(Date(20, Dec, 2021), 0.03), std::exception);
90 curve->enableExtrapolation();
91 // Check if extrapolation is flat
92 BOOST_CHECK_CLOSE(curve->correlation(Date(20, Dec, 2026), 0.01), 0.405249307, 1e-10);
93 BOOST_CHECK_CLOSE(curve->correlation(Date(20, Dec, 2028), 0.05), (0.405249307 + 0.486937064) / 2.0, 1e-10);
94 BOOST_CHECK_CLOSE(curve->correlation(Date(20, Dec, 2022), 0.05), (0.409223169 + 0.507498351) / 2.0, 1e-10);
95
96
97}
98
99
100BOOST_AUTO_TEST_CASE(testSpreadedCorrelationCurve) {
101 CommonData cd;
102
104
106
107 std::vector<std::vector<Handle<Quote>>> shifts;
108
109 for (Size i = 0; i < cd.detachmentPoints.size(); ++i) {
110 shifts.push_back(std::vector<Handle<Quote>>());
111 for (Size j = 0; j < cd.tenors.size(); ++j) {
112 shifts[i].push_back(Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(0.0)));
113 }
114 }
115
116 QuantExt::SpreadedBaseCorrelationCurve shiftedCurve(curve, cd.tenors, cd.detachmentPoints, shifts, cd.startDate, DateGeneration::CDS2015);
117
118 BOOST_CHECK_CLOSE(shiftedCurve.correlation(Date(20, Dec, 2026), 0.03), 0.405249307, 1e-10);
119 BOOST_CHECK_CLOSE(shiftedCurve.correlation(Date(20, Dec, 2026), 0.07), 0.486937064, 1e-10);
120
121 QuantLib::ext::dynamic_pointer_cast<SimpleQuote>(*shifts[0][1])->setValue(0.01);
122
123 BOOST_CHECK_CLOSE(shiftedCurve.correlation(Date(20, Dec, 2026), 0.03), 0.415249307, 1e-10);
124 BOOST_CHECK_CLOSE(shiftedCurve.correlation(Date(20, Dec, 2026), 0.07), 0.486937064, 1e-10);
125
126 BOOST_CHECK_CLOSE(shiftedCurve.correlation(Date(20, Dec, 2026), 0.05), (0.415249307 + 0.486937064) / 2.0, 1e-10);
127}
128
129BOOST_AUTO_TEST_CASE(testParallelShift) {
130 CommonData cd;
131
133
135 // Simple parallel shift, we need at least a 2 x 2 matrix for the interpolation
136 // but the actual tenor and detachments points doesn't matter
137 auto parallelShift = QuantLib::ext::make_shared<SimpleQuote>(0.0);
138
139 std::vector<std::vector<Handle<Quote>>> quotes{{Handle<Quote>(parallelShift)}};
140
141 std::vector<Period> terms{1 * Days};
142 std::vector<double> detachmentPoints{1.0};
143
144 Size nt = terms.size();
145 Size nd = detachmentPoints.size();
146
147 if (nt == 1) {
148 terms.push_back(terms[0] + 1 * Days); // arbitrary, but larger than the first term
149 for (Size i = 0; i < nd; ++i)
150 quotes[i].push_back(quotes[i][0]);
151 }
152
153 if (nd == 1) {
154 quotes.push_back(std::vector<Handle<Quote>>(terms.size()));
155 for (Size j = 0; j < terms.size(); ++j)
156 quotes[1][j] = quotes[0][j];
157
158 if (detachmentPoints[0] < 1.0 && !QuantLib::close_enough(detachmentPoints[0], 1.0)) {
159 detachmentPoints.push_back(1.0);
160 } else {
161 detachmentPoints.insert(detachmentPoints.begin(), 0.01);
162 }
163 }
164
165
166 QuantExt::SpreadedBaseCorrelationCurve shiftedCurveParallel(curve, terms, detachmentPoints, quotes);
167 BOOST_CHECK_CLOSE(shiftedCurveParallel.correlation(Date(20, Dec, 2026), 0.03), 0.405249307, 1e-10);
168 BOOST_CHECK_CLOSE(shiftedCurveParallel.correlation(Date(20, Dec, 2026), 0.07), 0.486937064, 1e-10);
169
170 parallelShift->setValue(0.01);
171
172 BOOST_CHECK_CLOSE(shiftedCurveParallel.correlation(Date(20, Dec, 2026), 0.03), 0.415249307, 1e-10);
173 BOOST_CHECK_CLOSE(shiftedCurveParallel.correlation(Date(20, Dec, 2026), 0.07), 0.496937064, 1e-10);
174 BOOST_CHECK_CLOSE(shiftedCurveParallel.correlation(Date(20, Dec, 2026), 1.0), 1.0, 1e-10);
175
176 BOOST_CHECK_CLOSE(shiftedCurveParallel.correlation(Date(20, Dec, 2026), 0.05), (0.415249307 + 0.496937064) / 2.0,
177 1e-10);
178
179 BOOST_CHECK_THROW(shiftedCurveParallel.correlation(Date(20, Dec, 2026), 0.01), std::exception);
180 BOOST_CHECK_THROW(shiftedCurveParallel.correlation(Date(20, Dec, 2028), 0.03), std::exception);
181
182 shiftedCurveParallel.enableExtrapolation();
183 BOOST_CHECK_THROW(shiftedCurveParallel.correlation(Date(20, Dec, 2026), 0.01), std::exception);
184 BOOST_CHECK_THROW(shiftedCurveParallel.correlation(Date(20, Dec, 2028), 0.03), std::exception);
185
186 // No to enable extrapolation on both curves before extrapolate
187 shiftedCurveParallel.enableExtrapolation();
188 curve->enableExtrapolation();
189 BOOST_CHECK_NO_THROW(shiftedCurveParallel.correlation(Date(20, Dec, 2026), 0.01));
190 BOOST_CHECK_NO_THROW(shiftedCurveParallel.correlation(Date(20, Dec, 2028), 0.03));
191}
192
193BOOST_AUTO_TEST_SUITE_END()
194
195BOOST_AUTO_TEST_SUITE_END()
void initializeSettings(CommonData &cd)
BOOST_AUTO_TEST_CASE(testBaseCorrelationCurve)
Handle< QuantExt::BaseCorrelationTermStructure > buildBilinearFlatBaseCorrelationCurve(CommonData &cd)
abstract base correlation structure and an 2d-interpolated base correlation structure
Real correlation(Time t, Real strike=Null< Real >(), bool extrapolate=false) const
Fixture that can be used at top level.