Coverage Report

Created: 2025-08-11 06:28

/src/quantlib/ql/experimental/credit/defaultlossmodel.hpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2008 Roland Lichters
5
 Copyright (C) 2014 Jose Aparicio
6
7
 This file is part of QuantLib, a free-software/open-source library
8
 for financial quantitative analysts and developers - http://quantlib.org/
9
10
 QuantLib is free software: you can redistribute it and/or modify it
11
 under the terms of the QuantLib license.  You should have received a
12
 copy of the license along with this program; if not, please email
13
 <quantlib-dev@lists.sf.net>. The license is also available online at
14
 <http://quantlib.org/license.shtml>.
15
16
 This program is distributed in the hope that it will be useful, but WITHOUT
17
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
 FOR A PARTICULAR PURPOSE.  See the license for more details.
19
*/
20
21
#ifndef quantlib_defaultlossmodel_hpp
22
#define quantlib_defaultlossmodel_hpp
23
24
#include <ql/instruments/claim.hpp>
25
#include <ql/experimental/credit/defaultprobabilitykey.hpp>
26
#include <ql/experimental/credit/basket.hpp>
27
28
#include <ql/utilities/null_deleter.hpp>
29
30
/* Intended to replace LossDistribution in 
31
    ql/experimental/credit/lossdistribution, not sure its covering all the 
32
    functionality (see mthod below)
33
*/
34
35
namespace QuantLib {
36
37
    /*! Default loss model interface definition.
38
    Allows communication between the basket and specific algorithms. Intended to
39
    hold any kind of portfolio joint loss, latent models, top-down,....
40
41
    An inconvenience of this design as opposed to the full arguments/results
42
    is that when pricing several derivatives instruments on the same basket
43
    not all the pricing engines would point to the same loss model; thus when
44
    pricing a set of such instruments there might be some switching on the 
45
    basket loss models, which might require recalculations (of the basket) or 
46
    not depending on the pricing order.
47
    */
48
    class DefaultLossModel : public Observable {// joint-? basket?-defaultLoss
49
     /* Protection together with frienship to avoid the need of checking the 
50
     basket-argument pointer integrity. It is the responsibility of the basket 
51
     now; our only caller.
52
     */
53
        friend class Basket;
54
    protected:
55
        // argument basket:
56
        mutable RelinkableHandle<Basket> basket_;
57
58
0
        DefaultLossModel() = default;
59
        //! \name Statistics
60
        //@{
61
        /* Non mandatory implementations, fails if client is not providing what 
62
        requested. */
63
64
        /* Default implementation using the expectedLoss(Date) method. 
65
          Typically this method is called repeatedly with the same 
66
          date parameter which makes it innefficient. */
67
0
        virtual Real expectedTrancheLoss(const Date& d) const {
68
0
            QL_FAIL("expectedTrancheLoss Not implemented for this model.");
69
0
        }
70
        /*! Probability of the tranche losing the same or more than the 
71
            fractional amount given.
72
73
            The passed lossFraction is a fraction of losses over the
74
            tranche notional (not the portfolio).
75
        */
76
        virtual Probability probOverLoss(
77
0
            const Date& d, Real lossFraction) const {
78
0
            QL_FAIL("probOverLoss Not implemented for this model.");   
79
0
        }
80
        //! Value at Risk given a default loss percentile.
81
0
        virtual Real percentile(const Date& d, Real percentile) const {
82
0
            QL_FAIL("percentile Not implemented for this model.");   
83
0
        }
84
        //! Expected shortfall given a default loss percentile.
85
0
        virtual Real expectedShortfall(const Date& d, Real percentile) const {
86
0
            QL_FAIL("eSF Not implemented for this model.");   
87
0
        }
88
        //! Associated VaR fraction to each counterparty.
89
0
        virtual std::vector<Real> splitVaRLevel(const Date& d, Real loss) const {
90
0
            QL_FAIL("splitVaRLevel Not implemented for this model.");   
91
0
        }
92
        //! Associated ESF fraction to each counterparty.
93
0
        virtual std::vector<Real> splitESFLevel(const Date& d, Real loss) const {
94
0
            QL_FAIL("splitESFLevel Not implemented for this model.");   
95
0
        }
96
97
        // \todo Add splits by instrument position.
98
99
        //! Full loss distribution.
100
0
        virtual std::map<Real, Probability> lossDistribution(const Date&) const {
101
0
            QL_FAIL("lossDistribution Not implemented for this model.");   
102
0
        }
103
        //! Probability density of a given loss fraction of the basket notional.
104
        virtual Real densityTrancheLoss(
105
0
            const Date& d, Real lossFraction) const {
106
0
            QL_FAIL("densityTrancheLoss Not implemented for this model.");
107
0
        }
108
        /*! Probabilities for each of the (remaining) basket elements in the 
109
        pool to have defaulted by time d and at the same time be the Nth 
110
        defaulting name to default in the basket. This method is oriented to 
111
        default order dependent portfolio pricing (e.g. NTDs)
112
            The the probabilities ordering in the vector coincides with the 
113
            pool order.
114
        */
115
0
        virtual std::vector<Probability> probsBeingNthEvent(Size n, const Date& d) const {
116
0
            QL_FAIL("probsBeingNthEvent Not implemented for this model.");
117
0
        }
118
        //! Pearsons' default probability correlation. 
119
        virtual Real defaultCorrelation(const Date& d, Size iName, 
120
0
            Size jName) const {
121
0
            QL_FAIL("defaultCorrelation Not implemented for this model.");
122
0
        }
123
        /*! Returns the probaility of having a given or larger number of 
124
        defaults in the basket portfolio at a given time.
125
        */
126
0
        virtual Probability probAtLeastNEvents(Size n, const Date& d) const {
127
0
            QL_FAIL("probAtLeastNEvents Not implemented for this model.");
128
0
        }
129
        /*! Expected RR for name conditinal to default by that date.
130
        */
131
        virtual Real expectedRecovery(const Date&, Size iName, 
132
0
            const DefaultProbKey&) const {
133
0
            QL_FAIL("expected recovery Not implemented for this model.");
134
0
        }
135
        //@}
136
137
        /*! Send a reference to the basket to allow the model to read the 
138
        problem arguments (contained in the basket)
139
        */
140
    private: //can only be called from Basket
141
0
        void setBasket(Basket* bskt) {
142
            /* After this; if the model modifies its internal status/caches (if 
143
            any) it should notify the  prior basket to recognise that basket is 
144
            not in a calculated=true state. Since we dont know at this level if 
145
            the model keeps caches it is the children responsibility. Typically 
146
            this is done at the first call to calculate to the loss model, there
147
            it notifies the basket. The old basket is still registered with us 
148
            until the basket takes in a new model....
149
            ..alternatively both old basket and model could be forced reset here
150
            */
151
0
            basket_.linkTo(ext::shared_ptr<Basket>(bskt, null_deleter()),
152
0
                           false);
153
0
            resetModel();// or rename to setBasketImpl(...)
154
0
        }
155
        // the call order matters, which is the reason for the parent to be the 
156
        //   sole caller.
157
        //! Concrete models do now any updates/inits they need on basket reset
158
        virtual void resetModel() = 0;
159
    };
160
161
}
162
163
#endif