QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
lmmdriftcalculator.cpp
Go to the documentation of this file.
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2007 Ferdinando Ametrano
5 Copyright (C) 2006 Marco Bianchetti
6 Copyright (C) 2006 Silvia Frasson
7 Copyright (C) 2006 Mario Pucci
8 Copyright (C) 2006 StatPro Italia srl
9
10 This file is part of QuantLib, a free-software/open-source library
11 for financial quantitative analysts and developers - http://quantlib.org/
12
13 QuantLib is free software: you can redistribute it and/or modify it
14 under the terms of the QuantLib license. You should have received a
15 copy of the license along with this program; if not, please email
16 <quantlib-dev@lists.sf.net>. The license is also available online at
17 <http://quantlib.org/license.shtml>.
18
19 This program is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21 FOR A PARTICULAR PURPOSE. See the license for more details.
22*/
23
26
27namespace QuantLib {
28
30 const std::vector<Spread>& displacements,
31 const std::vector<Time>& taus,
32 Size numeraire,
33 Size alive)
34 : numberOfRates_(taus.size()), numberOfFactors_(pseudo.columns()),
35 isFullFactor_(numberOfFactors_ == numberOfRates_), numeraire_(numeraire), alive_(alive),
36 displacements_(displacements), oneOverTaus_(taus.size()), pseudo_(pseudo),
37 tmp_(taus.size(), 0.0), e_(pseudo_.columns(), pseudo_.rows(), 0.0), downs_(taus.size()),
38 ups_(taus.size()) {
39
40 // Check requirements
41 QL_REQUIRE(numberOfRates_>0, "Dim out of range");
42 QL_REQUIRE(displacements.size() == numberOfRates_,
43 "Displacements out of range");
45 "pseudo.rows() not consistent with dim");
46 QL_REQUIRE(pseudo.columns()>0 && pseudo.columns()<=numberOfRates_,
47 "pseudo.rows() not consistent with pseudo.columns()");
48 QL_REQUIRE(alive<numberOfRates_, "Alive out of bounds");
49 QL_REQUIRE(numeraire_<=numberOfRates_, "Numeraire larger than dim");
50 QL_REQUIRE(numeraire_>=alive, "Numeraire smaller than alive");
51
52 // Precompute 1/taus
53 for (Size i=0; i<taus.size(); ++i)
54 oneOverTaus_[i] = 1.0/taus[i];
55
56 // Compute covariance matrix from pseudoroot
58 C_ = pseudo_*pT;
59
60 // Compute lower and upper extrema for (non reduced) drift calculation
61 for (Size i=alive_; i<numberOfRates_; ++i) {
62 downs_[i] = std::min(i+1, numeraire_);
63 ups_[i] = std::max(i+1, numeraire_);
64 }
65 }
66
68 std::vector<Real>& drifts) const {
69 compute(cs.forwardRates(), drifts);
70 }
71
72 void LMMDriftCalculator::compute(const std::vector<Rate>& fwds,
73 std::vector<Real>& drifts) const {
74 #if defined(QL_EXTRA_SAFETY_CHECKS)
75 QL_REQUIRE(fwds.size()==numberOfRates_, "numberOfRates <> dim");
76 QL_REQUIRE(drifts.size()==numberOfRates_, "drifts.size() <> dim");
77 #endif
78
79 if (isFullFactor_)
80 computePlain(fwds, drifts);
81 else
82 computeReduced(fwds, drifts);
83 }
84
86 std::vector<Real>& drifts) const {
87 computePlain(cs.forwardRates(), drifts);
88 }
89
90 void LMMDriftCalculator::computePlain(const std::vector<Rate>& forwards,
91 std::vector<Real>& drifts) const {
92
93 // Compute drifts without factor reduction,
94 // using directly the covariance matrix.
95
96 // Precompute forwards factor
97 Size i;
98 for(i=alive_; i<numberOfRates_; ++i)
99 tmp_[i] = (forwards[i]+displacements_[i]) /
100 (oneOverTaus_[i]+forwards[i]);
101
102 // Compute drifts
103 for (i=alive_; i<numberOfRates_; ++i) {
104 drifts[i] = std::inner_product(tmp_.begin()+downs_[i],
105 tmp_.begin()+ups_[i],
106 C_.row_begin(i)+downs_[i], Real(0.0));
107 if (numeraire_>i+1)
108 drifts[i] = -drifts[i];
109 }
110 }
111
113 std::vector<Real>& drifts) const {
114 computeReduced(cs.forwardRates(), drifts);
115 }
116
117 void LMMDriftCalculator::computeReduced(const std::vector<Rate>& forwards,
118 std::vector<Real>& drifts) const {
119
120 // Compute drifts with factor reduction,
121 // using the pseudo square root of the covariance matrix.
122
123 // Precompute forwards factor
124 for (Size i=alive_; i<numberOfRates_; ++i)
125 tmp_[i] = (forwards[i]+displacements_[i]) /
126 (oneOverTaus_[i]+forwards[i]);
127
128 // Enforce initialization
129 for (Size r=0; r<numberOfFactors_; ++r)
130 e_[r][std::max(0,static_cast<Integer>(numeraire_)-1)] = 0.0;
131
132 // Now compute drifts: take the numeraire P_N (numeraire_=N)
133 // as the reference point, divide the summation into 3 steps,
134 // et impera:
135
136 // 1st step: the drift corresponding to the numeraire P_N is zero.
137 // (if N=0 no drift is null, if N=numberOfRates_ the last drift is null).
138 if (numeraire_>0) drifts[numeraire_-1] = 0.0;
139
140 // 2nd step: then, move backward from N-2 (included) back to
141 // alive (included) (if N=0 jumps to 3rd step, if N=numberOfRates_ the
142 // e_[r][N-1] are correctly initialized):
143
144 for (Integer i=static_cast<Integer>(numeraire_)-2;
145 i>=static_cast<Integer>(alive_); --i) {
146 drifts[i] = 0.0;
147 for (Size r=0; r<numberOfFactors_; ++r) {
148 e_[r][i] = e_[r][i+1] + tmp_[i+1] * pseudo_[i+1][r];
149 drifts[i] -= e_[r][i]*pseudo_[i][r];
150 }
151
152 /*
153 Matrix::column_iterator p1 = e_.column_begin(i);
154 Matrix::column_iterator end = e_.column_end(i);
155 Matrix::const_column_iterator p2 = e_.column_begin(i+1);
156 Matrix::const_row_iterator q1 = pseudo_.row_begin(i);
157 Matrix::const_row_iterator q2 = pseudo_.row_begin(i+1);
158 Real x = tmp_[i+1];
159 while (p1 != end) {
160 *p1 = *p2 + x*(*q2);
161 drifts[i] -= *p1*(*q1);
162 ++p1; ++p2; ++q1; ++q2;
163 }
164 */
165 }
166
167 // 3rd step: now, move forward from N (included) up to n (excluded)
168 // (if N=0 this is the only relevant computation):
169 for (Size i=numeraire_; i<numberOfRates_; ++i) {
170 drifts[i] = 0.0;
171 for (Size r=0; r<numberOfFactors_; ++r) {
172 if (i==0)
173 e_[r][i] = tmp_[i] * pseudo_[i][r];
174 else
175 e_[r][i] = e_[r][i-1] + tmp_[i] * pseudo_[i][r];
176 drifts[i] += e_[r][i]*pseudo_[i][r];
177 }
178 }
179 }
180
181}
Curve state for Libor market models
const std::vector< Rate > & forwardRates() const override
std::vector< Spread > displacements_
LMMDriftCalculator(const Matrix &pseudo, const std::vector< Spread > &displacements, const std::vector< Time > &taus, Size numeraire, Size alive)
void computePlain(const LMMCurveState &cs, std::vector< Real > &drifts) const
void compute(const LMMCurveState &cs, std::vector< Real > &drifts) const
Computes the drifts.
void computeReduced(const LMMCurveState &cs, std::vector< Real > &drifts) const
Matrix used in linear algebra.
Definition: matrix.hpp:41
const_row_iterator row_begin(Size i) const
Definition: matrix.hpp:360
Size rows() const
Definition: matrix.hpp:504
Size columns() const
Definition: matrix.hpp:508
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
QL_REAL Real
real number
Definition: types.hpp:50
QL_INTEGER Integer
integer number
Definition: types.hpp:35
std::size_t Size
size of a container
Definition: types.hpp:58
Drift computation for Libor market model.
Definition: any.hpp:35
Matrix transpose(const Matrix &m)
Definition: matrix.hpp:700
ext::shared_ptr< YieldTermStructure > r