[go: up one dir, main page]

1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2013 Peter Caspers
5
6 This file is part of QuantLib, a free-software/open-source library
7 for financial quantitative analysts and developers - http://quantlib.org/
8
9 QuantLib is free software: you can redistribute it and/or modify it
10 under the terms of the QuantLib license. You should have received a
11 copy of the license along with this program; if not, please email
12 <quantlib-dev@lists.sf.net>. The license is also available online at
13 <http://quantlib.org/license.shtml>.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
20#include "creditriskplus.hpp"
21#include "utilities.hpp"
22#include <ql/experimental/risk/creditriskplus.hpp>
23#include <ql/math/comparison.hpp>
24
25using namespace QuantLib;
26using namespace boost::unit_test_framework;
27
28void CreditRiskPlusTest::testReferenceValues() {
29
30 BOOST_TEST_MESSAGE(
31 "Testing extended credit risk plus model against reference values...");
32
33 static const Real tol = 1E-8;
34
35 /* Reference Values are taken from [1] Integrating Correlations, Risk,
36 July 1999, table A, table B and figure 1 */
37
38 std::vector<Real> sector1Exposure(1000, 1.0);
39 std::vector<Real> sector1Pd(1000, 0.04);
40 std::vector<Size> sector1Sector(1000, 0);
41
42 std::vector<Real> sector2Exposure(1000, 2.0);
43 std::vector<Real> sector2Pd(1000, 0.02);
44 std::vector<Size> sector2Sector(1000, 1);
45
46 std::vector<Real> exposure;
47 exposure.insert(position: exposure.end(), first: sector1Exposure.begin(),
48 last: sector1Exposure.end());
49 exposure.insert(position: exposure.end(), first: sector2Exposure.begin(),
50 last: sector2Exposure.end());
51
52 std::vector<Real> pd;
53 pd.insert(position: pd.end(), first: sector1Pd.begin(), last: sector1Pd.end());
54 pd.insert(position: pd.end(), first: sector2Pd.begin(), last: sector2Pd.end());
55
56 std::vector<Size> sector;
57 sector.insert(position: sector.end(), first: sector1Sector.begin(), last: sector1Sector.end());
58 sector.insert(position: sector.end(), first: sector2Sector.begin(), last: sector2Sector.end());
59
60 std::vector<Real> relativeDefaultVariance;
61 relativeDefaultVariance.push_back(x: 0.75 * 0.75);
62 relativeDefaultVariance.push_back(x: 0.75 * 0.75);
63
64 Matrix rho(2, 2);
65 rho[0][0] = rho[1][1] = 1.0;
66 rho[0][1] = rho[1][0] = 0.50;
67
68 Real unit = 0.1;
69
70 CreditRiskPlus cr(exposure, pd, sector, relativeDefaultVariance, rho, unit);
71
72 if ( std::fabs(x: cr.sectorExposures()[0] - 1000.0) > tol )
73 BOOST_FAIL("failed to reproduce sector 1 exposure ("
74 << cr.sectorExposures()[0] << ", should be 1000)");
75
76 if ( std::fabs(x: cr.sectorExposures()[1] - 2000.0) > tol )
77 BOOST_FAIL("failed to reproduce sector 2 exposure ("
78 << cr.sectorExposures()[1] << ", should be 2000)");
79
80 if ( std::fabs(x: cr.sectorExpectedLoss()[0] - 40.0) > tol )
81 BOOST_FAIL("failed to reproduce sector 1 expected loss ("
82 << cr.sectorExpectedLoss()[0] << ", should be 40)");
83
84 if ( std::fabs(x: cr.sectorExpectedLoss()[1] - 40.0) > tol )
85 BOOST_FAIL("failed to reproduce sector 2 expected loss ("
86 << cr.sectorExpectedLoss()[1] << ", should be 40)");
87
88 if ( std::fabs(x: cr.sectorUnexpectedLoss()[0] - 30.7) > 0.05 )
89 BOOST_FAIL("failed to reproduce sector 1 unexpected loss ("
90 << cr.sectorUnexpectedLoss()[0] << ", should be 30.7)");
91
92 if ( std::fabs(x: cr.sectorUnexpectedLoss()[1] - 31.3) > 0.05 )
93 BOOST_FAIL("failed to reproduce sector 2 unexpected loss ("
94 << cr.sectorUnexpectedLoss()[1] << ", should be 31.3)");
95
96 if ( std::fabs(x: cr.exposure() - 3000.0) > tol )
97 BOOST_FAIL("failed to reproduce overall exposure ("
98 << cr.exposure() << ", should be 3000)");
99
100 if ( std::fabs(x: cr.expectedLoss() - 80.0) > tol )
101 BOOST_FAIL("failed to reproduce overall expected loss ("
102 << cr.expectedLoss() << ", should be 80)");
103
104 if ( std::fabs(x: cr.unexpectedLoss() - 53.1) > 0.01 )
105 BOOST_FAIL("failed to reproduce overall unexpected loss ("
106 << cr.unexpectedLoss() << ", should be 53.1)");
107
108 // the overall relative default variance in the paper seems generously rounded,
109 // but since EL and UL is matching closely and the former is retrieved
110 // as a simple expression in the latter, we do not suspect a problem in our
111 // calculation
112
113 if ( std::fabs(x: cr.relativeDefaultVariance() - 0.65 * 0.65) > 0.001 )
114 BOOST_FAIL("failed to reproduce overall relative default variance ("
115 << cr.relativeDefaultVariance() << ", should be 0.4225)");
116
117 if ( std::fabs(x: cr.lossQuantile(p: 0.99) - 250) > 0.5 )
118 BOOST_FAIL("failed to reproduce overall 99 percentile ("
119 << cr.lossQuantile(0.99) << ", should be 250)");
120}
121
122test_suite *CreditRiskPlusTest::suite() {
123 auto* suite = BOOST_TEST_SUITE("Credit risk plus tests");
124 suite->add(QUANTLIB_TEST_CASE(&CreditRiskPlusTest::testReferenceValues));
125 return suite;
126}
127

source code of quantlib/test-suite/creditriskplus.cpp