/src/quantlib/ql/models/marketmodels/evolutiondescription.cpp
Line | Count | Source |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | Copyright (C) 2006, 2007 Ferdinando Ametrano |
5 | | Copyright (C) 2006 Marco Bianchetti |
6 | | Copyright (C) 2006 Cristina Duminuco |
7 | | Copyright (C) 2006 Giorgio Facchinetti |
8 | | Copyright (C) 2006, 2007 Mark Joshi |
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 | | <https://www.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 | | |
24 | | #include <ql/models/marketmodels/evolutiondescription.hpp> |
25 | | #include <ql/models/marketmodels/utilities.hpp> |
26 | | #include <ql/math/matrix.hpp> |
27 | | #include <ql/utilities/dataformatters.hpp> |
28 | | |
29 | | namespace QuantLib { |
30 | | |
31 | | EvolutionDescription::EvolutionDescription( |
32 | | const std::vector<Time>& rateTimes, |
33 | | const std::vector<Time>& evolutionTimes, |
34 | | const std::vector<std::pair<Size,Size> >& relevanceRates) |
35 | 0 | : numberOfRates_(rateTimes.empty() ? 0 : rateTimes.size()-1), |
36 | 0 | rateTimes_(rateTimes), |
37 | 0 | evolutionTimes_(evolutionTimes.empty() && !rateTimes.empty() ? |
38 | 0 | std::vector<Time>(rateTimes.begin(), rateTimes.end()-1) : |
39 | 0 | evolutionTimes), |
40 | 0 | relevanceRates_(relevanceRates), |
41 | 0 | rateTaus_(numberOfRates_), |
42 | | //effStopTime_(evolutionTimes_.size(), rateTimes_.size()-1), |
43 | 0 | firstAliveRate_(evolutionTimes_.size()) |
44 | 0 | { |
45 | |
|
46 | 0 | checkIncreasingTimesAndCalculateTaus(rateTimes_, rateTaus_); |
47 | |
|
48 | 0 | checkIncreasingTimes(evolutionTimes_); |
49 | 0 | Size numberOfSteps = evolutionTimes_.size(); |
50 | |
|
51 | 0 | QL_REQUIRE(evolutionTimes_.back()<=rateTimes[rateTimes.size()-2], |
52 | 0 | "The last evolution time (" << evolutionTimes_.back() << |
53 | 0 | ") is past the last fixing time (" << |
54 | 0 | rateTimes[numberOfRates_-2] << ")"); |
55 | | |
56 | 0 | if (relevanceRates.empty()) |
57 | 0 | relevanceRates_ = std::vector<std::pair<Size,Size> >( |
58 | 0 | numberOfSteps, std::make_pair(0,numberOfRates_)); |
59 | 0 | else |
60 | 0 | QL_REQUIRE(relevanceRates.size() == numberOfSteps, |
61 | 0 | "relevanceRates / evolutionTimes mismatch"); |
62 | | |
63 | | //for (Size j=0; j<numberOfSteps; ++j) { |
64 | | // for (Size i=0; i<numberOfRates_; ++i) |
65 | | // effStopTime_[j][i] = |
66 | | // std::min(evolutionTimes_[j], rateTimes_[i]); |
67 | | //} |
68 | | |
69 | 0 | Time currentEvolutionTime = 0.0; |
70 | 0 | Size firstAliveRate = 0; |
71 | 0 | for (Size j=0; j<numberOfSteps; ++j) { |
72 | 0 | while (rateTimes_[firstAliveRate] <= currentEvolutionTime) |
73 | 0 | ++firstAliveRate; |
74 | 0 | firstAliveRate_[j] = firstAliveRate; |
75 | 0 | currentEvolutionTime = evolutionTimes_[j]; |
76 | 0 | } |
77 | 0 | } |
78 | | |
79 | 0 | const std::vector<Time>& EvolutionDescription::rateTimes() const { |
80 | 0 | return rateTimes_; |
81 | 0 | } |
82 | | |
83 | 0 | const std::vector<Time>& EvolutionDescription::rateTaus() const { |
84 | 0 | return rateTaus_; |
85 | 0 | } |
86 | | |
87 | 0 | const std::vector<Time>& EvolutionDescription::evolutionTimes() const { |
88 | 0 | return evolutionTimes_; |
89 | 0 | } |
90 | | |
91 | | //const Matrix& EvolutionDescription::effectiveStopTimes() const { |
92 | | // return effStopTime_; |
93 | | //} |
94 | | |
95 | 0 | const std::vector<Size>& EvolutionDescription::firstAliveRate() const { |
96 | 0 | return firstAliveRate_; |
97 | 0 | } |
98 | | |
99 | 0 | const std::vector<std::pair<Size,Size> >& EvolutionDescription::relevanceRates() const { |
100 | 0 | return relevanceRates_; |
101 | 0 | } |
102 | | |
103 | 0 | Size EvolutionDescription::numberOfRates() const { |
104 | 0 | return numberOfRates_; |
105 | 0 | } |
106 | | |
107 | 0 | Size EvolutionDescription::numberOfSteps() const { |
108 | 0 | return evolutionTimes_.size(); |
109 | 0 | } |
110 | | |
111 | | void checkCompatibility(const EvolutionDescription& evolution, |
112 | | const std::vector<Size>& numeraires) |
113 | 0 | { |
114 | 0 | const std::vector<Time>& evolutionTimes = evolution.evolutionTimes(); |
115 | 0 | Size n = evolutionTimes.size(); |
116 | 0 | QL_REQUIRE(numeraires.size() == n, |
117 | 0 | "Size mismatch between numeraires (" << numeraires.size() |
118 | 0 | << ") and evolution times (" << n << ")"); |
119 | | |
120 | 0 | const std::vector<Time>& rateTimes = evolution.rateTimes(); |
121 | 0 | for (Size i=0; i<n-1; i++) |
122 | 0 | QL_REQUIRE(rateTimes[numeraires[i]] >= evolutionTimes[i], |
123 | 0 | io::ordinal(i+1) << " step, evolution time " << |
124 | 0 | evolutionTimes[i] << ": the numeraire (" << numeraires[i] << |
125 | 0 | "), corresponding to rate time " << |
126 | 0 | rateTimes[numeraires[i]] << ", is expired"); |
127 | 0 | } |
128 | | |
129 | | bool isInTerminalMeasure(const EvolutionDescription& evolution, |
130 | 0 | const std::vector<Size>& numeraires) { |
131 | 0 | const std::vector<Time>& rateTimes = evolution.rateTimes(); |
132 | 0 | return *std::min_element(numeraires.begin(), numeraires.end()) == |
133 | 0 | rateTimes.size()-1; |
134 | 0 | } |
135 | | |
136 | | bool isInMoneyMarketPlusMeasure(const EvolutionDescription& evolution, |
137 | | const std::vector<Size>& numeraires, |
138 | 0 | Size offset) { |
139 | 0 | bool res = true; |
140 | 0 | const std::vector<Time>& rateTimes = evolution.rateTimes(); |
141 | 0 | Size maxNumeraire=rateTimes.size()-1; |
142 | 0 | QL_REQUIRE(offset<=maxNumeraire, |
143 | 0 | "offset (" << offset << |
144 | 0 | ") is greater than the max allowed value for numeraire (" |
145 | 0 | << maxNumeraire << ")"); |
146 | 0 | const std::vector<Time>& evolutionTimes = evolution.evolutionTimes(); |
147 | 0 | for (Size i=0, j=0; i<evolutionTimes.size(); ++i) { |
148 | 0 | while (rateTimes[j] < evolutionTimes[i]) |
149 | 0 | j++; |
150 | 0 | res = (numeraires[i] == std::min(j+offset, maxNumeraire)) && res; |
151 | 0 | } |
152 | 0 | return res; |
153 | 0 | } |
154 | | |
155 | | bool isInMoneyMarketMeasure(const EvolutionDescription& evolution, |
156 | 0 | const std::vector<Size>& numeraires) { |
157 | 0 | return isInMoneyMarketPlusMeasure(evolution, numeraires, 0); |
158 | 0 | } |
159 | | |
160 | | std::vector<Size> terminalMeasure(const EvolutionDescription& evolution) |
161 | 0 | { |
162 | 0 | return std::vector<Size>(evolution.evolutionTimes().size(), |
163 | 0 | evolution.rateTimes().size()-1); |
164 | 0 | } |
165 | | |
166 | | std::vector<Size> moneyMarketPlusMeasure(const EvolutionDescription& ev, |
167 | 0 | Size offset) { |
168 | 0 | const std::vector<Time>& rateTimes = ev.rateTimes(); |
169 | 0 | Size maxNumeraire = rateTimes.size()-1; |
170 | 0 | QL_REQUIRE(offset<=maxNumeraire, |
171 | 0 | "offset (" << offset << |
172 | 0 | ") is greater than the max allowed value for numeraire (" |
173 | 0 | << maxNumeraire << ")"); |
174 | | |
175 | 0 | const std::vector<Time>& evolutionTimes = ev.evolutionTimes(); |
176 | 0 | Size n = evolutionTimes.size(); |
177 | 0 | std::vector<Size> numeraires(n); |
178 | 0 | for (Size i=0, j=0; i<n; ++i) { |
179 | 0 | while (rateTimes[j] < evolutionTimes[i]) |
180 | 0 | j++; |
181 | 0 | numeraires[i] = std::min(j+offset, maxNumeraire); |
182 | 0 | } |
183 | 0 | return numeraires; |
184 | 0 | } |
185 | | |
186 | 0 | std::vector<Size> moneyMarketMeasure(const EvolutionDescription& evol) { |
187 | 0 | return moneyMarketPlusMeasure(evol, 0); |
188 | 0 | } |
189 | | |
190 | | } |