Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
hullwhitebucketing.hpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2017 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
19/*! \file qle/models/hullwhitebucketing.hpp
20 \brief probability bucketing as in Valuation of a CDO and an nth to Default CDS
21 without Monte Carlo Simulation, Appdx. B
22 \ingroup models
23*/
24
25#pragma once
26
27#include <ql/math/array.hpp>
28#include <ql/math/comparison.hpp>
29
30namespace QuantExt {
31using namespace QuantLib;
32
33class Bucketing {
34public:
35 /*! buckets are (-QL_MAX_REAL, b1), [b1, b2), [b2,b3), ... , [b_{n-1}, b_n), [b_n, +QL_MAX_REAL) */
36 template <class I> Bucketing(I bucketsBegin, I bucketsEnd);
37 /*! there are n+2 buckets constructed, lb = lower bound, ub = upper bound, h = (ub - lb) / n
38 buckets are (-QL_MAX_REAL, lb), [lb, lb+h), [lb+h, lb+2h), ... , [lb+(n-1)h, ub), [ub,+QL_MAX_REAL) */
39 Bucketing(const Real lowerBound, const Real upperBound, const Size n);
40 const std::vector<Real>& upperBucketBound() const { return buckets_; }
41 Size index(const Real x) const;
42 Size buckets() const { return buckets_.size(); }
43
44protected:
45 void initBuckets();
46 std::vector<Real> buckets_;
47 bool uniformBuckets_ = false;
49}; // Bucketing
50
52public:
53 template <class I> HullWhiteBucketing(I bucketsBegin, I bucketsEnd) : Bucketing(bucketsBegin, bucketsEnd) {}
54 HullWhiteBucketing(const Real lowerBound, const Real upperBound, const Size n)
55 : Bucketing(lowerBound, upperBound, n) {}
56
57 /* losses might be negative, warning: pd and losses container sizes must match, this is not checked */
58 template <class I1, class I2> void compute(I1 pdBegin, I1 pdEnd, I2 lossesBegin);
59 /* Each p is itself a vector p[0], p[1], ... , p[n], with a corresponding
60 vector of losses l[0], l[1], ... , l[n]; now a loss is realised
61 with probability P = p[0] + ... + p[n] and conditional on this, l[0] is realised
62 with probability p[0] / P, l[1] with probability p[1] / P, ..., l[n] with probability p[n] / P,
63 Warning: container sizes and p, l vector sizes must match, this is not checked */
64 template <class I1, class I2> void computeMultiState(I1 pBegin, I1 pEnd, I2 lossesBegin);
65
66 const Array& probability() const { return p_; }
67 const Array& averageLoss() const { return A_; }
68
69private:
70 void init_p_A();
71 void finalize_p_A();
72 Array p_, A_;
73}; // HullWhiteBucketing
74
75// definitions
76
77template <class I> Bucketing::Bucketing(I bucketsBegin, I bucketsEnd) : buckets_(bucketsBegin, bucketsEnd) {
79}
80
81template <class I1, class I2> void HullWhiteBucketing::compute(I1 pdBegin, I1 pdEnd, I2 lossesBegin) {
82 init_p_A();
83 Array A2(A_.size()), p2(p_.size());
84
85 auto it2 = lossesBegin;
86 for (auto it = pdBegin; it != pdEnd; ++it, ++it2) {
87 if (QuantLib::close_enough(*it, 0.0) || QuantLib::close_enough(*it2, 0.0))
88 continue;
89 std::fill(A2.begin(), A2.end(), 0.0);
90 std::fill(p2.begin(), p2.end(), 0.0);
91 for (Size k = 0; k < buckets_.size(); ++k) {
92 if (QuantLib::close_enough(p_[k], 0.0))
93 continue;
94 Size t = index(A_[k] / p_[k] + *it2);
95 p2[k] += p_[k] * (1.0 - (*it));
96 A2[k] += A_[k] * (1.0 - (*it));
97 p2[t] += p_[k] * (*it);
98 A2[t] += (*it) * (A_[k] + p_[k] * (*it2));
99 }
100 std::copy(A2.begin(), A2.end(), A_.begin());
101 std::copy(p2.begin(), p2.end(), p_.begin());
102 }
103
104 finalize_p_A();
105
106} // compute
107
108template <class I1, class I2> void HullWhiteBucketing::computeMultiState(I1 pBegin, I1 pEnd, I2 lossesBegin) {
109 init_p_A();
110 Array A2(A_.size()), p2(p_.size());
111
112 auto it2 = lossesBegin;
113 for (auto it = pBegin; it != pEnd; ++it, ++it2) {
114 std::fill(A2.begin(), A2.end(), 0.0);
115 std::fill(p2.begin(), p2.end(), 0.0);
116 for (Size k = 0; k < buckets_.size(); ++k) {
117 if (QuantLib::close_enough(p_[k], 0.0))
118 continue;
119 Real q = 0.0;
120 auto it2_i = (*it2).begin();
121 for (auto it_i = (*it).begin(), itend = (*it).end(); it_i != itend; ++it_i, ++it2_i) {
122 if (QuantLib::close_enough(*it_i, 0.0) || QuantLib::close_enough(*it2_i, 0.0))
123 continue;
124 Size t = index(A_[k] / p_[k] + *it2_i);
125 p2[t] += p_[k] * (*it_i);
126 A2[t] += (*it_i) * (A_[k] + p_[k] * (*it2_i));
127 q += *it_i;
128 }
129 p2[k] += p_[k] * (1.0 - q);
130 A2[k] += A_[k] * (1.0 - q);
131 }
132 std::copy(A2.begin(), A2.end(), A_.begin());
133 std::copy(p2.begin(), p2.end(), p_.begin());
134 } // for it
135
136 finalize_p_A();
137
138} // computeMultiState
139
140} // namespace QuantExt
Bucketing(I bucketsBegin, I bucketsEnd)
std::vector< Real > buckets_
Size index(const Real x) const
const std::vector< Real > & upperBucketBound() const
HullWhiteBucketing(I bucketsBegin, I bucketsEnd)
void computeMultiState(I1 pBegin, I1 pEnd, I2 lossesBegin)
const Array & probability() const
void compute(I1 pdBegin, I1 pdEnd, I2 lossesBegin)
const Array & averageLoss() const
HullWhiteBucketing(const Real lowerBound, const Real upperBound, const Size n)