Coverage Report

Created: 2026-06-08 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/experimental/credit/onefactorcopula.cpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2008 Roland Lichters
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
 <https://www.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 <ql/experimental/credit/onefactorcopula.hpp>
21
22
using namespace std;
23
24
namespace QuantLib {
25
26
    //-------------------------------------------------------------------------
27
0
    Real OneFactorCopula::conditionalProbability(Real p, Real m) const {
28
    //-------------------------------------------------------------------------
29
0
        calculate ();
30
        // FIXME
31
0
        if (p < 1e-10) return 0;
32
33
0
        Real c = correlation_->value();
34
35
0
        Real res = cumulativeZ ((inverseCumulativeY (p) - sqrt(c) * m)
36
0
                                / sqrt (1. - c));
37
38
0
        QL_REQUIRE (res >= 0 && res <= 1,
39
0
                    "conditional probability " << res << "out of range");
40
41
0
        return res;
42
0
    }
43
44
    //-------------------------------------------------------------------------
45
    vector<Real> OneFactorCopula::conditionalProbability(
46
                                                     const vector<Real>& prob,
47
0
                                                     Real m) const {
48
    //-------------------------------------------------------------------------
49
0
        calculate ();
50
0
        vector<Real> p (prob.size(), 0);
51
0
        for (Size i = 0; i < p.size(); i++)
52
0
            p[i] = conditionalProbability (prob[i], m);
53
0
        return p;
54
0
    }
55
56
    //-------------------------------------------------------------------------
57
0
    Real OneFactorCopula::cumulativeY (Real y) const {
58
    //-------------------------------------------------------------------------
59
0
        calculate ();
60
61
0
        QL_REQUIRE(!y_.empty(), "cumulative Y not tabulated yet");
62
63
        // linear interpolation on the tabulated cumulative distribution of Y
64
0
        if (y < y_.front())
65
0
            return cumulativeY_.front();
66
67
0
        for (Size i = 0; i < y_.size(); i++) {
68
0
            if (y_[i] > y)
69
0
                return (   (y_[i] - y)   * cumulativeY_[i-1]
70
0
                           + (y - y_[i-1]) * cumulativeY_[i]   )
71
0
                    / (y_[i] - y_[i-1]);
72
0
        }
73
74
0
        return cumulativeY_.back();
75
0
    }
76
77
    //-------------------------------------------------------------------------
78
0
    Real OneFactorCopula::inverseCumulativeY (Real x) const {
79
    //-------------------------------------------------------------------------
80
0
        calculate ();
81
82
0
        QL_REQUIRE(!y_.empty(), "cumulative Y not tabulated yet");
83
84
        // linear interpolation on the tabulated cumulative distribution of Y
85
0
        if (x < cumulativeY_.front())
86
0
            return y_.front();
87
88
0
        for (Size i = 0; i < cumulativeY_.size(); i++) {
89
0
            if (cumulativeY_[i] > x)
90
0
                return (   (cumulativeY_[i] - x)   * y_[i-1]
91
0
                           + (x - cumulativeY_[i-1]) * y_[i]   )
92
0
                    / (cumulativeY_[i] - cumulativeY_[i-1]);
93
0
        }
94
95
0
        return y_.back();
96
0
    }
97
98
    //-------------------------------------------------------------------------
99
0
    int OneFactorCopula::checkMoments (Real tolerance) const {
100
    //-------------------------------------------------------------------------
101
0
        calculate ();
102
103
0
        Real norm = 0, mean = 0, var = 0;
104
0
        for (Size i = 0; i < steps(); i++) {
105
0
            norm += densitydm (i);
106
0
            mean += m(i) * densitydm (i);
107
0
            var += pow (m(i), 2) * densitydm (i);
108
0
        }
109
110
0
        QL_REQUIRE (fabs (norm - 1.0) < tolerance, "norm out of tolerance range");
111
0
        QL_REQUIRE (fabs (mean) < tolerance, "mean out of tolerance range");
112
0
        QL_REQUIRE (fabs (var - 1.0) < tolerance, "variance out of tolerance range");
113
114
        // FIXME: define range for Y via cutoff quantil?
115
0
        Real zMin = -10;
116
0
        Real zMax = +10;
117
0
        Size zSteps = 200;
118
0
        norm = 0;
119
0
        mean = 0;
120
0
        var = 0;
121
0
        for (Size i = 1; i < zSteps; i++) {
122
0
            Real z1 = zMin + (zMax - zMin) / zSteps * (i - 1);
123
0
            Real z2 = zMin + (zMax - zMin) / zSteps * i;
124
0
            Real z  = (z1 + z2) / 2;
125
0
            Real densitydz = cumulativeZ (z2) - cumulativeZ (z1);
126
0
            norm += densitydz;
127
0
            mean += z * densitydz;
128
0
            var += pow (z, 2) * densitydz;
129
0
        }
130
131
0
        QL_REQUIRE (fabs (norm - 1.0) < tolerance, "norm out of tolerance range");
132
0
        QL_REQUIRE (fabs (mean) < tolerance, "mean out of tolerance range");
133
0
        QL_REQUIRE (fabs (var - 1.0) < tolerance, "variance out of tolerance range");
134
135
        // FIXME: define range for Y via cutoff quantil?
136
0
        Real yMin = -10;
137
0
        Real yMax = +10;
138
0
        Size ySteps = 200;
139
0
        norm = 0;
140
0
        mean = 0;
141
0
        var = 0;
142
0
        for (Size i = 1; i < ySteps; i++) {
143
0
            Real y1 = yMin + (yMax - yMin) / ySteps * (i - 1);
144
0
            Real y2 = yMin + (yMax - yMin) / ySteps * i;
145
0
            Real y  = (y1 + y2) / 2;
146
0
            Real densitydy = cumulativeY (y2) - cumulativeY (y1);
147
0
            norm += densitydy;
148
0
            mean += y * densitydy;
149
0
            var += y * y * densitydy;
150
0
        }
151
152
0
        QL_REQUIRE (fabs (norm - 1.0) < tolerance, "norm out of tolerance range");
153
0
        QL_REQUIRE (fabs (mean) < tolerance, "mean out of tolerance range");
154
0
        QL_REQUIRE (fabs (var - 1.0) < tolerance, "variance out of tolerance range");
155
156
0
        return 0;
157
0
    }
158
159
}
160