[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) 2014 Jose Aparicio
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 <ql/qldefines.hpp>
21#if !defined(BOOST_ALL_NO_LIB) && defined(BOOST_MSVC)
22# include <ql/auto_link.hpp>
23#endif
24#include <ql/experimental/credit/randomdefaultlatentmodel.hpp>
25#include <ql/termstructures/credit/flathazardrate.hpp>
26#include <ql/currencies/europe.hpp>
27#include <ql/time/calendars/target.hpp>
28#include <ql/time/daycounters/actual365fixed.hpp>
29#include <string>
30#include <iostream>
31#include <iomanip>
32
33using namespace std;
34using namespace QuantLib;
35
36/* This sample code shows basic usage of a Latent variable model.
37 The data and correlation problem presented is the same as in:
38 'Modelling Dependent Defaults: Asset Correlations Are Not Enough!'
39 Frey R., A. J. McNeil and M. A. Nyfeler RiskLab publications March 2001
40*/
41int main(int, char* []) {
42
43 try {
44
45 std::cout << std::endl;
46
47 Calendar calendar = TARGET();
48 Date todaysDate(19, March, 2014);
49 // must be a business day
50 todaysDate = calendar.adjust(todaysDate);
51
52 Settings::instance().evaluationDate() = todaysDate;
53
54
55 /* --------------------------------------------------------------
56 SET UP BASKET PORTFOLIO
57 -------------------------------------------------------------- */
58 // build curves and issuers into a basket of three names
59 std::vector<Real> hazardRates(3, -std::log(x: 1.-0.01));
60 std::vector<std::string> names;
61 for(Size i=0; i<hazardRates.size(); i++)
62 names.push_back(x: std::string("Acme") + std::to_string(val: i));
63 std::vector<Handle<DefaultProbabilityTermStructure>> defTS;
64 defTS.reserve(n: hazardRates.size());
65 for (Real& hazardRate : hazardRates)
66 defTS.emplace_back(
67 args: ext::make_shared<FlatHazardRate>(args: 0, args: TARGET(), args&: hazardRate, args: Actual365Fixed()));
68 std::vector<Issuer> issuers;
69 for(Size i=0; i<hazardRates.size(); i++) {
70 std::vector<QuantLib::Issuer::key_curve_pair> curves(1,
71 std::make_pair(x: NorthAmericaCorpDefaultKey(
72 EURCurrency(), QuantLib::SeniorSec,
73 Period(), 1. // amount threshold
74 ), y&: defTS[i]));
75 issuers.emplace_back(args&: curves);
76 }
77
78 auto thePool = ext::make_shared<Pool>();
79 for(Size i=0; i<hazardRates.size(); i++)
80 thePool->add(name: names[i], issuer: issuers[i], contractTrigger: NorthAmericaCorpDefaultKey(
81 EURCurrency(), QuantLib::SeniorSec, Period(), 1.));
82
83 std::vector<DefaultProbKey> defaultKeys(hazardRates.size(),
84 NorthAmericaCorpDefaultKey(EURCurrency(), SeniorSec, Period(), 1.));
85 // Recoveries are irrelevant in this example but must be given as the
86 // lib stands.
87 std::vector<ext::shared_ptr<RecoveryRateModel>> rrModels(
88 hazardRates.size(), ext::make_shared<ConstantRecoveryModel>(
89 args: ConstantRecoveryModel(0.5, SeniorSec)));
90 auto theBskt = ext::make_shared<Basket>(
91 args&: todaysDate, args&: names, args: std::vector<Real>(hazardRates.size(), 100.),
92 args&: thePool);
93 /* --------------------------------------------------------------
94 SET UP JOINT DEFAULT EVENT LATENT MODELS
95 -------------------------------------------------------------- */
96 // Latent model factors, corresponds to the first entry in Table1 of the
97 // publication mentioned. It is a single factor model
98 std::vector<std::vector<Real>> fctrsWeights(hazardRates.size(),
99 std::vector<Real>(1, std::sqrt(x: 0.1)));
100 // --- Default Latent models -------------------------------------
101 #ifndef QL_PATCH_SOLARIS
102 // Gaussian integrable joint default model:
103 auto lmG = ext::make_shared<GaussianDefProbLM>(args&: fctrsWeights,
104 args: LatentModelIntegrationType::GaussianQuadrature,
105 args: GaussianCopulaPolicy::initTraits() // otherwise gcc screams
106 );
107 #endif
108 // Define StudentT copula
109 // this is as far as we can be from the Gaussian, 2 T_3 factors:
110 std::vector<Integer> ordersT(2, 3);
111 TCopulaPolicy::initTraits iniT;
112 iniT.tOrders = ordersT;
113 // StudentT integrable joint default model:
114 auto lmT = ext::make_shared<TDefProbLM>(args&: fctrsWeights,
115 // LatentModelIntegrationType::GaussianQuadrature,
116 args: LatentModelIntegrationType::Trapezoid, args&: iniT);
117
118 // --- Default Loss models ----------------------------------------
119 // Gaussian random joint default model:
120 Size numSimulations = 100000;
121 // Size numCoresUsed = 4;
122 #ifndef QL_PATCH_SOLARIS
123 // Sobol, many cores
124 auto rdlmG = ext::make_shared<RandomDefaultLM<GaussianCopulaPolicy>>(args&: lmG,
125 args: std::vector<Real>(), args&: numSimulations, args: 1.e-6, args: 2863311530UL);
126 #endif
127 // StudentT random joint default model:
128 auto rdlmT = ext::make_shared<RandomDefaultLM<TCopulaPolicy>>(args&: lmT,
129 args: std::vector<Real>(), args&: numSimulations, args: 1.e-6, args: 2863311530UL);
130
131 /* --------------------------------------------------------------
132 DUMP SOME RESULTS
133 -------------------------------------------------------------- */
134 /* Default correlations in a T copula should be below those of the
135 gaussian for the same factors.
136 The calculations on the MC show dispersion on both copulas (thats
137 ok) and too large values with very large dispersions on the T case.
138 Computations are ok, within the dispersion, for the gaussian; compare
139 with the direct integration in both cases.
140 However the T does converge to the gaussian value for large value of
141 the parameters.
142 */
143 Date calcDate(TARGET().advance(date: Settings::instance().evaluationDate(),
144 period: Period(120, Months)));
145 std::vector<Probability> probEventsTLatent, probEventsTRandLoss;
146 #ifndef QL_PATCH_SOLARIS
147 std::vector<Probability> probEventsGLatent, probEventsGRandLoss;
148 #endif
149 //
150 lmT->resetBasket(basket: theBskt);
151 for(Size numEvts=0; numEvts <=theBskt->size(); numEvts++) {
152 probEventsTLatent.push_back(x: lmT->probAtLeastNEvents(n: numEvts,
153 date: calcDate));
154 }
155 //
156 theBskt->setLossModel(rdlmT);
157 for(Size numEvts=0; numEvts <=theBskt->size(); numEvts++) {
158 probEventsTRandLoss.push_back(x: theBskt->probAtLeastNEvents(n: numEvts,
159 d: calcDate));
160 }
161 //
162 #ifndef QL_PATCH_SOLARIS
163 lmG->resetBasket(basket: theBskt);
164 for(Size numEvts=0; numEvts <=theBskt->size(); numEvts++) {
165 probEventsGLatent.push_back(x: lmG->probAtLeastNEvents(n: numEvts,
166 date: calcDate));
167 }
168 //
169 theBskt->setLossModel(rdlmG);
170 for(Size numEvts=0; numEvts <=theBskt->size(); numEvts++) {
171 probEventsGRandLoss.push_back(x: theBskt->probAtLeastNEvents(n: numEvts,
172 d: calcDate));
173 }
174 #endif
175
176 Date correlDate = TARGET().advance(
177 date: Settings::instance().evaluationDate(), period: Period(12, Months));
178 std::vector<std::vector<Real>> correlsGlm, correlsTlm, correlsGrand,
179 correlsTrand;
180 //
181 lmT->resetBasket(basket: theBskt);
182 for(Size iName1=0; iName1 <theBskt->size(); iName1++) {
183 std::vector<Real> tmp;
184 for(Size iName2=0; iName2 <theBskt->size(); iName2++)
185 tmp.push_back(x: lmT->defaultCorrelation(d: correlDate,
186 iNamei: iName1, iNamej: iName2));
187 correlsTlm.push_back(x: tmp);
188 }
189 //
190 theBskt->setLossModel(rdlmT);
191 for(Size iName1=0; iName1 <theBskt->size(); iName1++) {
192 std::vector<Real> tmp;
193 for(Size iName2=0; iName2 <theBskt->size(); iName2++)
194 tmp.push_back(x: theBskt->defaultCorrelation(d: correlDate,
195 iName: iName1, jName: iName2));
196 correlsTrand.push_back(x: tmp);
197 }
198 #ifndef QL_PATCH_SOLARIS
199 //
200 lmG->resetBasket(basket: theBskt);
201 for(Size iName1=0; iName1 <theBskt->size(); iName1++) {
202 std::vector<Real> tmp;
203 for(Size iName2=0; iName2 <theBskt->size(); iName2++)
204 tmp.push_back(x: lmG->defaultCorrelation(d: correlDate,
205 iNamei: iName1, iNamej: iName2));
206 correlsGlm.push_back(x: tmp);
207 }
208 //
209 theBskt->setLossModel(rdlmG);
210 for(Size iName1=0; iName1 <theBskt->size(); iName1++) {
211 std::vector<Real> tmp;
212 for(Size iName2=0; iName2 <theBskt->size(); iName2++)
213 tmp.push_back(x: theBskt->defaultCorrelation(d: correlDate,
214 iName: iName1, jName: iName2));
215 correlsGrand.push_back(x: tmp);
216 }
217 #endif
218
219
220 std::cout <<
221 " Gaussian versus T prob of extreme event (random and integrable)-"
222 << std::endl;
223 for(Size numEvts=0; numEvts <=theBskt->size(); numEvts++) {
224 std::cout << "-Prob of " << numEvts << " events... " <<
225 #ifndef QL_PATCH_SOLARIS
226 probEventsGLatent[numEvts] << " ** " <<
227 #else
228 "n/a" << " ** " <<
229 #endif
230 probEventsTLatent[numEvts] << " ** " <<
231 #ifndef QL_PATCH_SOLARIS
232 probEventsGRandLoss[numEvts]<< " ** " <<
233 #else
234 "n/a" << " ** " <<
235 #endif
236 probEventsTRandLoss[numEvts]
237 << std::endl;
238 }
239
240 cout << endl;
241 cout << "-- Default correlations G,T,GRand,TRand--" << endl;
242 cout << "-----------------------------------------" << endl;
243 for(Size iName1=0; iName1 <theBskt->size(); iName1++) {
244 for(Size iName2=0; iName2 <theBskt->size(); iName2++)
245 cout <<
246 #ifndef QL_PATCH_SOLARIS
247 correlsGlm[iName1][iName2] << " , ";
248 #else
249 "n/a" << " , ";
250 #endif
251 cout << endl;
252 }
253 cout << endl;
254 for(Size iName1=0; iName1 <theBskt->size(); iName1++) {
255 for(Size iName2=0; iName2 <theBskt->size(); iName2++)
256 cout <<
257 correlsTlm[iName1][iName2] << " , ";
258 ;
259 cout << endl;
260 }
261 cout << endl;
262 for(Size iName1=0; iName1 <theBskt->size(); iName1++) {
263 for(Size iName2=0; iName2 <theBskt->size(); iName2++)
264 cout <<
265 #ifndef QL_PATCH_SOLARIS
266 correlsGrand[iName1][iName2] << " , ";
267 #else
268 "n/a" << " , ";
269 #endif
270 cout << endl;
271 }
272 cout << endl;
273 for(Size iName1=0; iName1 <theBskt->size(); iName1++) {
274 for(Size iName2=0; iName2 <theBskt->size(); iName2++)
275 cout <<
276 correlsTrand[iName1][iName2] << " , ";
277 ;
278 cout << endl;
279 }
280
281 return 0;
282 } catch (exception& e) {
283 cerr << e.what() << endl;
284 return 1;
285 } catch (...) {
286 cerr << "unknown error" << endl;
287 return 1;
288 }
289}
290
291

source code of quantlib/Examples/LatentModel/LatentModel.cpp