File: basecorrelationlossmodel.hpp

package info (click to toggle)
quantlib 1.41-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 41,480 kB
  • sloc: cpp: 400,885; makefile: 6,547; python: 214; sh: 150; lisp: 86
file content (294 lines) | stat: -rw-r--r-- 13,001 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/*
 Copyright (C) 2014 Jose Aparicio

 This file is part of QuantLib, a free-software/open-source library
 for financial quantitative analysts and developers - http://quantlib.org/

 QuantLib is free software: you can redistribute it and/or modify it
 under the terms of the QuantLib license.  You should have received a
 copy of the license along with this program; if not, please email
 <quantlib-dev@lists.sf.net>. The license is also available online at
 <https://www.quantlib.org/license.shtml>.

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the license for more details.
*/

#ifndef quantlib_base_correl_lossmodel_hpp
#define quantlib_base_correl_lossmodel_hpp


#include <ql/quote.hpp>
#include <ql/quotes/simplequote.hpp>

#include <ql/experimental/credit/basket.hpp>
#include <ql/experimental/credit/defaultlossmodel.hpp>
#include <ql/experimental/credit/basecorrelationstructure.hpp>

// move these to the CPP (and the template spezs)
#include <ql/experimental/credit/binomiallossmodel.hpp>
#include <ql/experimental/credit/gaussianlhplossmodel.hpp>
#include <ql/experimental/credit/inhomogeneouspooldef.hpp>
#include <utility>

namespace QuantLib {

    /*! Base Correlation loss model; interpolation is performed by portfolio 
    (live) amount percentage.\par
    Though the literature on this model is inmense, see for a more than 
    introductory level (precrisis) chapters 19, 20 and 21 of <b>Modelling single
    name and multi-name credit derivatives.</b> Dominic O'Kane, Wiley Finance, 
    2008\par
    For freely available documentation see:\par
    Credit Correlation: A Guide; JP Morgan Credit Derivatives Strategy; 
        12 March 2004 \par
    Introducing Base Correlations; JP Morgan Credit Derivatives Strategy; 
        22 March 2004 \par
    A Relative Value Framework for Credit Correlation; JP Morgan Credit 
        Derivatives Strategy; 27 April 2004 \par
    Valuing and Hedging Synthetic CDO Tranches Using Base Correlations; Bear 
        Stearns; May 17, 2004 \par
    Correlation Primer; Nomura Fixed Income Research, August 6, 2004 \par
    Base Correlation Explained; Lehman Brothers Fixed Income Quantitative 
        Credit Research; 15 November 2004 \par
    'Pricing CDOs with a smile' in Societe Generale Credit Research; 
        February 2005 \par
    For bespoke base correlation see: \par
    Base Correlation Mapping in Lehman Brothers' Quantitative Credit Research 
        Quarterly; Volume 2007-Q1 \par
    You can explore typical postcrisis data by perusing some of the JPMorgan 
    Global Correlation Daily Analytics \par
    Here the crisis model problems of ability to price stressed portfolios 
    or tranches over the maximum loss are the responsibility of the base models.
    Users should select their models according to this; choosing the copula or
    a random loss given default base model (or more exotic ones). \par
    Notice this is different to a bespoke base correlation loss (bespoke here 
    referring to basket composition, not just attachment levels) ; where 
    loss interpolation is on the expected loss value to match the two baskets. 
    Therefore the correlation surface should refer to the same basket intended
    to be priced. But this is left to the user and is not implemented in the 
    correlation surface (yet...)

    \todo Bespoke portfolios BC models are yet to be implemented.

    BaseModel_T must have a constructor with a single quote value
    */
    /* Criticism:
    This model is not as generic as it could be. In principle a default loss 
    model dependent on a single factor correlation parameter is the only 
    restriction on the base loss model(s) type. This class however is tied to a 
    LatentModel single factor. But there is no need for the 
    underlying model to be of a latent type. This link is due to the copula 
    initialization traits which have to be present for non trivial copula 
    policies initialization (e.g. Student-T base correl models)

    Maybe a possibility is to pass copiable instances of the model and relinking
    to the correlation in two internal copies.
    */
    template <class BaseModel_T, class Corr2DInt_T>
    class BaseCorrelationLossModel : public DefaultLossModel, 
        public virtual Observer {
    private:
        typedef typename BaseModel_T::copulaType::initTraits initTraits;
    public:
      BaseCorrelationLossModel(const Handle<BaseCorrelationTermStructure<Corr2DInt_T> >& correlTS,
                               std::vector<Real> recoveries,
                               const initTraits& traits = initTraits())
      : localCorrelationAttach_(ext::make_shared<SimpleQuote>(0.)),
        localCorrelationDetach_(ext::make_shared<SimpleQuote>(0.)),
        recoveries_(std::move(recoveries)), correlTS_(correlTS), copulaTraits_(traits) {
          registerWith(correlTS);
          registerWith(Settings::instance().evaluationDate());
      }

    private:
        // react to base correl surface notifications (quotes or reference date)
      void update() override {
          setupModels();
          // tell basket to notify instruments, etc, we are invalid
          if (!basket_.empty())
              basket_->notifyObservers();
      }

        /* Update model caches after basket assignement. */
      void resetModel() override {
          remainingNotional_ = basket_->remainingNotional();
          attachRatio_ = basket_->remainingAttachmentAmount() / remainingNotional_;
          detachRatio_ = basket_->remainingDetachmentAmount() / remainingNotional_;

          basketAttach_ = ext::make_shared<Basket>(basket_->refDate(), basket_->remainingNames(),
                                                   basket_->remainingNotionals(), basket_->pool(),
                                                   0.0, attachRatio_, basket_->claim());
          basketDetach_ = ext::make_shared<Basket>(basket_->refDate(), basket_->remainingNames(),
                                                   basket_->remainingNotionals(), basket_->pool(),
                                                   0.0, detachRatio_, basket_->claim());
          setupModels();
      }
        /* Most of the statistics are not implemented, not impossible but
        the model is intended for pricing rather than ptfolio risk management.
        */
      Real expectedTrancheLoss(const Date& d) const override;

    protected:
        /*! Sets up attach/detach models. Gets called on basket update. 
        To be specialized on the spacific model type.
        */
        void setupModels() const;
    private:
        mutable Real attachRatio_, detachRatio_;
        mutable Real remainingNotional_;

        //! Correlation buffer to pick up values from the surface and 
        //  trigger calculation.
        ext::shared_ptr<SimpleQuote> localCorrelationAttach_, 
            localCorrelationDetach_;
        mutable ext::shared_ptr<Basket> basketAttach_,
            basketDetach_;
        // just cached for the update method
        mutable std::vector<Real> recoveries_;
        Handle<BaseCorrelationTermStructure<Corr2DInt_T> > correlTS_;
        // Initialization parameters for models copula
        mutable typename BaseModel_T::copulaType::initTraits copulaTraits_;
        // Models of equity baskets.
        mutable ext::shared_ptr<BaseModel_T> scalarCorrelModelAttach_;
        mutable ext::shared_ptr<BaseModel_T> scalarCorrelModelDetach_;
    };


    // Remember ETL returns the EL on the live part of the basket. 
    template<class LM, class I>
    Real BaseCorrelationLossModel<LM, I>::expectedTrancheLoss(
        const Date& d) const 
    {
        Real correlK1 = correlTS_->correlation(d, attachRatio_);
        Real correlK2 = correlTS_->correlation(d, detachRatio_);

        /* reset correl and call base models which have the different baskets 
        associated.*/
        localCorrelationAttach_->setValue(correlK1);
        Real expLossK1 = 
            basketAttach_->expectedTrancheLoss(d);
        localCorrelationDetach_->setValue(correlK2);
        Real expLossK2 = 
            basketDetach_->expectedTrancheLoss(d);
        return expLossK2 - expLossK1;
    }


    // ----------------------------------------------------------------------


    /* Concrete specializations submodels construction. With the dummy template 
    parameter trick partial specializations leaving the interpolation open 
    would be possible.
    */

    #ifndef QL_PATCH_SOLARIS

    template<>
    inline void BaseCorrelationLossModel<GaussianLHPLossModel, 
        BilinearInterpolation>::setupModels() const 
    {
        // on this assignment any previous registration with the attach and 
        //   detach baskets should be removed
        scalarCorrelModelAttach_ = ext::make_shared<GaussianLHPLossModel>(
            Handle<Quote>(localCorrelationAttach_), recoveries_);
        scalarCorrelModelDetach_ = ext::make_shared<GaussianLHPLossModel>(
            Handle<Quote>(localCorrelationDetach_), recoveries_);

        basketAttach_->setLossModel(scalarCorrelModelAttach_);
        basketDetach_->setLossModel(scalarCorrelModelDetach_);
    }

    template<>
    inline void BaseCorrelationLossModel<GaussianBinomialLossModel, 
        BilinearInterpolation>::setupModels() const 
    {
        ext::shared_ptr<GaussianConstantLossLM> lmA = 
            ext::make_shared<GaussianConstantLossLM>(
                Handle<Quote>(localCorrelationAttach_), recoveries_, 
                LatentModelIntegrationType::GaussianQuadrature, 
                recoveries_.size(), copulaTraits_);
        ext::shared_ptr<GaussianConstantLossLM> lmD = 
            ext::make_shared<GaussianConstantLossLM>(
                Handle<Quote>(localCorrelationDetach_), recoveries_, 
                LatentModelIntegrationType::GaussianQuadrature, 
                recoveries_.size(), copulaTraits_);
        scalarCorrelModelAttach_ = 
            ext::make_shared<GaussianBinomialLossModel>(lmA);
        scalarCorrelModelDetach_ = 
            ext::make_shared<GaussianBinomialLossModel>(lmD);
            
        basketAttach_->setLossModel(scalarCorrelModelAttach_);
        basketDetach_->setLossModel(scalarCorrelModelDetach_);

    }

    template<>
    inline void BaseCorrelationLossModel<TBinomialLossModel, 
        BilinearInterpolation>::setupModels() const 
    {
        ext::shared_ptr<TConstantLossLM> lmA = 
            ext::make_shared<TConstantLossLM>(
                Handle<Quote>(localCorrelationAttach_), recoveries_, 
                LatentModelIntegrationType::GaussianQuadrature, 
                recoveries_.size(), copulaTraits_);
        ext::shared_ptr<TConstantLossLM> lmD = 
            ext::make_shared<TConstantLossLM>(
                Handle<Quote>(localCorrelationDetach_), recoveries_, 
                LatentModelIntegrationType::GaussianQuadrature, 
                recoveries_.size(), copulaTraits_);

        scalarCorrelModelAttach_ = 
            ext::make_shared<TBinomialLossModel>(lmA);
        scalarCorrelModelDetach_ = 
            ext::make_shared<TBinomialLossModel>(lmD);
            
        basketAttach_->setLossModel(scalarCorrelModelAttach_);
        basketDetach_->setLossModel(scalarCorrelModelDetach_);
    }

    /* \todo Fix this model, is failing for equity tranches at least, the
    base model works all right, its the link here.
    */
    template<>
    inline void BaseCorrelationLossModel<IHGaussPoolLossModel, 
        BilinearInterpolation>::setupModels() const 
    {
        ext::shared_ptr<GaussianConstantLossLM> lmA = 
            ext::make_shared<GaussianConstantLossLM>(
                Handle<Quote>(localCorrelationAttach_), recoveries_, 
                LatentModelIntegrationType::GaussianQuadrature, 
                recoveries_.size(), copulaTraits_);
        ext::shared_ptr<GaussianConstantLossLM> lmD = 
            ext::make_shared<GaussianConstantLossLM>(
                Handle<Quote>(localCorrelationDetach_), recoveries_, 
                LatentModelIntegrationType::GaussianQuadrature, 
                recoveries_.size(), copulaTraits_);

        // \todo Allow the sending specific model params, as the number of 
        //   buckets here.
        scalarCorrelModelAttach_ = 
            ext::make_shared<IHGaussPoolLossModel>(lmA, 500);
        scalarCorrelModelDetach_ = 
            ext::make_shared<IHGaussPoolLossModel>(lmD, 500);
            
        basketAttach_->setLossModel(scalarCorrelModelAttach_);
        basketDetach_->setLossModel(scalarCorrelModelDetach_);
    }

    #endif


    // Vanilla BC model
    #ifndef QL_PATCH_SOLARIS
    typedef BaseCorrelationLossModel<GaussianLHPLossModel, 
                BilinearInterpolation> GaussianLHPFlatBCLM;
    #endif

}

#endif