/src/quantlib/ql/cashflows/cashflows.hpp
Line | Count | Source |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | Copyright (C) 2005, 2006 StatPro Italia srl |
5 | | Copyright (C) 2005 Charles Whitmore |
6 | | Copyright (C) 2007, 2008, 2009, 2010, 2011 Ferdinando Ametrano |
7 | | Copyright (C) 2008 Toyin Akin |
8 | | |
9 | | This file is part of QuantLib, a free-software/open-source library |
10 | | for financial quantitative analysts and developers - http://quantlib.org/ |
11 | | |
12 | | QuantLib is free software: you can redistribute it and/or modify it |
13 | | under the terms of the QuantLib license. You should have received a |
14 | | copy of the license along with this program; if not, please email |
15 | | <quantlib-dev@lists.sf.net>. The license is also available online at |
16 | | <https://www.quantlib.org/license.shtml>. |
17 | | |
18 | | This program is distributed in the hope that it will be useful, but WITHOUT |
19 | | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
20 | | FOR A PARTICULAR PURPOSE. See the license for more details. |
21 | | */ |
22 | | |
23 | | /*! \file cashflows.hpp |
24 | | \brief Cash-flow analysis functions |
25 | | */ |
26 | | |
27 | | #ifndef quantlib_cashflows_hpp |
28 | | #define quantlib_cashflows_hpp |
29 | | |
30 | | #include <ql/cashflows/duration.hpp> |
31 | | #include <ql/cashflow.hpp> |
32 | | #include <ql/interestrate.hpp> |
33 | | #include <ql/shared_ptr.hpp> |
34 | | |
35 | | namespace QuantLib { |
36 | | |
37 | | class YieldTermStructure; |
38 | | |
39 | | //! %cashflow-analysis functions |
40 | | /*! \todo add tests */ |
41 | | class CashFlows { |
42 | | private: |
43 | | class IrrFinder { |
44 | | public: |
45 | | IrrFinder(const Leg& leg, |
46 | | Real npv, |
47 | | DayCounter dayCounter, |
48 | | Compounding comp, |
49 | | Frequency freq, |
50 | | const ext::optional<bool>& includeSettlementDateFlows, |
51 | | Date settlementDate, |
52 | | Date npvDate); |
53 | | |
54 | | Real operator()(Rate y) const; |
55 | | Real derivative(Rate y) const; |
56 | | private: |
57 | | void checkSign() const; |
58 | | |
59 | | const Leg& leg_; |
60 | | Real npv_; |
61 | | DayCounter dayCounter_; |
62 | | Compounding compounding_; |
63 | | Frequency frequency_; |
64 | | ext::optional<bool> includeSettlementDateFlows_; |
65 | | Date settlementDate_, npvDate_; |
66 | | }; |
67 | | public: |
68 | | CashFlows() = delete; |
69 | | CashFlows(CashFlows&&) = delete; |
70 | | CashFlows(const CashFlows&) = delete; |
71 | | CashFlows& operator=(CashFlows&&) = delete; |
72 | | CashFlows& operator=(const CashFlows&) = delete; |
73 | | ~CashFlows() = default; |
74 | | |
75 | | //! \name Date functions |
76 | | //@{ |
77 | | static Date startDate(const Leg& leg); |
78 | | static Date maturityDate(const Leg& leg); |
79 | | static bool isExpired(const Leg& leg, |
80 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
81 | | Date settlementDate = Date()); |
82 | | //@} |
83 | | |
84 | | //! \name CashFlow functions |
85 | | //@{ |
86 | | //! the last cashflow paying before or at the given date |
87 | | static Leg::const_reverse_iterator |
88 | | previousCashFlow(const Leg& leg, |
89 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
90 | | Date settlementDate = Date()); |
91 | | //! the first cashflow paying after the given date |
92 | | static Leg::const_iterator |
93 | | nextCashFlow(const Leg& leg, |
94 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
95 | | Date settlementDate = Date()); |
96 | | static Date |
97 | | previousCashFlowDate(const Leg& leg, |
98 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
99 | | Date settlementDate = Date()); |
100 | | static Date |
101 | | nextCashFlowDate(const Leg& leg, |
102 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
103 | | Date settlementDate = Date()); |
104 | | static Real |
105 | | previousCashFlowAmount(const Leg& leg, |
106 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
107 | | Date settlementDate = Date()); |
108 | | static Real |
109 | | nextCashFlowAmount(const Leg& leg, |
110 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
111 | | Date settlementDate = Date()); |
112 | | //@} |
113 | | |
114 | | //! \name Coupon inspectors |
115 | | //@{ |
116 | | static Rate |
117 | | previousCouponRate(const Leg& leg, |
118 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
119 | | Date settlementDate = Date()); |
120 | | static Rate |
121 | | nextCouponRate(const Leg& leg, |
122 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
123 | | Date settlementDate = Date()); |
124 | | |
125 | | static Real |
126 | | nominal(const Leg& leg, |
127 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
128 | | Date settlementDate = Date()); |
129 | | static Date |
130 | | accrualStartDate(const Leg& leg, |
131 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
132 | | Date settlementDate = Date()); |
133 | | static Date |
134 | | accrualEndDate(const Leg& leg, |
135 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
136 | | Date settlementDate = Date()); |
137 | | static Date |
138 | | referencePeriodStart(const Leg& leg, |
139 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
140 | | Date settlementDate = Date()); |
141 | | static Date |
142 | | referencePeriodEnd(const Leg& leg, |
143 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
144 | | Date settlementDate = Date()); |
145 | | static Time |
146 | | accrualPeriod(const Leg& leg, |
147 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
148 | | Date settlementDate = Date()); |
149 | | static Date::serial_type |
150 | | accrualDays(const Leg& leg, |
151 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
152 | | Date settlementDate = Date()); |
153 | | static Time |
154 | | accruedPeriod(const Leg& leg, |
155 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
156 | | Date settlementDate = Date()); |
157 | | static Date::serial_type |
158 | | accruedDays(const Leg& leg, |
159 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
160 | | Date settlementDate = Date()); |
161 | | static Real |
162 | | accruedAmount(const Leg& leg, |
163 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
164 | | Date settlementDate = Date()); |
165 | | //@} |
166 | | |
167 | | //! \name YieldTermStructure functions |
168 | | //@{ |
169 | | //! NPV of the cash flows. |
170 | | /*! The NPV is the sum of the cash flows, each discounted |
171 | | according to the given term structure. |
172 | | */ |
173 | | static Real npv(const Leg& leg, |
174 | | const YieldTermStructure& discountCurve, |
175 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
176 | | Date settlementDate = Date(), |
177 | | Date npvDate = Date()); |
178 | | //! Basis-point sensitivity of the cash flows. |
179 | | /*! The result is the change in NPV due to a uniform |
180 | | 1-basis-point change in the rate paid by the cash |
181 | | flows. The change for each coupon is discounted according |
182 | | to the given term structure. |
183 | | */ |
184 | | static Real bps(const Leg& leg, |
185 | | const YieldTermStructure& discountCurve, |
186 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
187 | | Date settlementDate = Date(), |
188 | | Date npvDate = Date()); |
189 | | |
190 | | //! NPV and BPS of the cash flows. |
191 | | /*! The NPV and BPS of the cash flows calculated |
192 | | together for performance reason |
193 | | */ |
194 | | static std::pair<Real, Real> npvbps(const Leg& leg, |
195 | | const YieldTermStructure& discountCurve, |
196 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
197 | | Date settlementDate = Date(), |
198 | | Date npvDate = Date()); |
199 | | |
200 | | //! At-the-money rate of the cash flows. |
201 | | /*! The result is the fixed rate for which a fixed rate cash flow |
202 | | vector, equivalent to the input vector, has the required NPV |
203 | | according to the given term structure. If the required NPV is |
204 | | not given, the input cash flow vector's NPV is used instead. |
205 | | */ |
206 | | static Rate atmRate(const Leg& leg, |
207 | | const YieldTermStructure& discountCurve, |
208 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
209 | | Date settlementDate = Date(), |
210 | | Date npvDate = Date(), |
211 | | Real npv = Null<Real>()); |
212 | | //@} |
213 | | |
214 | | //! \name Yield (a.k.a. Internal Rate of Return, i.e. IRR) functions |
215 | | /*! The IRR is the interest rate at which the NPV of the cash |
216 | | flows equals the dirty price. |
217 | | */ |
218 | | //@{ |
219 | | //! NPV of the cash flows. |
220 | | /*! The NPV is the sum of the cash flows, each discounted |
221 | | according to the given constant interest rate. The result |
222 | | is affected by the choice of the interest-rate compounding |
223 | | and the relative frequency and day counter. |
224 | | */ |
225 | | static Real npv(const Leg& leg, |
226 | | const InterestRate& yield, |
227 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
228 | | Date settlementDate = Date(), |
229 | | Date npvDate = Date()); |
230 | | static Real npv(const Leg& leg, |
231 | | Rate yield, |
232 | | const DayCounter& dayCounter, |
233 | | Compounding compounding, |
234 | | Frequency frequency, |
235 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
236 | | Date settlementDate = Date(), |
237 | | Date npvDate = Date()); |
238 | | //! Basis-point sensitivity of the cash flows. |
239 | | /*! The result is the change in NPV due to a uniform |
240 | | 1-basis-point change in the rate paid by the cash |
241 | | flows. The change for each coupon is discounted according |
242 | | to the given constant interest rate. The result is |
243 | | affected by the choice of the interest-rate compounding |
244 | | and the relative frequency and day counter. |
245 | | */ |
246 | | static Real bps(const Leg& leg, |
247 | | const InterestRate& yield, |
248 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
249 | | Date settlementDate = Date(), |
250 | | Date npvDate = Date()); |
251 | | static Real bps(const Leg& leg, |
252 | | Rate yield, |
253 | | const DayCounter& dayCounter, |
254 | | Compounding compounding, |
255 | | Frequency frequency, |
256 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
257 | | Date settlementDate = Date(), |
258 | | Date npvDate = Date()); |
259 | | //! Implied internal rate of return. |
260 | | /*! The function verifies |
261 | | the theoretical existence of an IRR and numerically |
262 | | establishes the IRR to the desired precision. |
263 | | */ |
264 | | static Rate yield(const Leg& leg, |
265 | | Real npv, |
266 | | const DayCounter& dayCounter, |
267 | | Compounding compounding, |
268 | | Frequency frequency, |
269 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
270 | | Date settlementDate = Date(), |
271 | | Date npvDate = Date(), |
272 | | Real accuracy = 1.0e-10, |
273 | | Size maxIterations = 100, |
274 | | Rate guess = 0.05); |
275 | | |
276 | | template <typename Solver> |
277 | | static Rate yield(const Solver& solver, |
278 | | const Leg& leg, |
279 | | Real npv, |
280 | | const DayCounter& dayCounter, |
281 | | Compounding compounding, |
282 | | Frequency frequency, |
283 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
284 | | Date settlementDate = Date(), |
285 | | Date npvDate = Date(), |
286 | | Real accuracy = 1.0e-10, |
287 | 0 | Rate guess = 0.05) { |
288 | 0 | IrrFinder objFunction(leg, npv, dayCounter, compounding, |
289 | 0 | frequency, includeSettlementDateFlows, |
290 | 0 | settlementDate, npvDate); |
291 | 0 | return solver.solve(objFunction, accuracy, guess, guess/10.0); |
292 | 0 | } |
293 | | |
294 | | //! Cash-flow duration. |
295 | | /*! The simple duration of a string of cash flows is defined as |
296 | | \f[ |
297 | | D_{\mathrm{simple}} = \frac{\sum t_i c_i B(t_i)}{\sum c_i B(t_i)} |
298 | | \f] |
299 | | where \f$ c_i \f$ is the amount of the \f$ i \f$-th cash |
300 | | flow, \f$ t_i \f$ is its payment time, and \f$ B(t_i) \f$ |
301 | | is the corresponding discount according to the passed yield. |
302 | | |
303 | | The modified duration is defined as |
304 | | \f[ |
305 | | D_{\mathrm{modified}} = -\frac{1}{P} \frac{\partial P}{\partial y} |
306 | | \f] |
307 | | where \f$ P \f$ is the present value of the cash flows |
308 | | according to the given IRR \f$ y \f$. |
309 | | |
310 | | The Macaulay duration is defined for a compounded IRR as |
311 | | \f[ |
312 | | D_{\mathrm{Macaulay}} = \left( 1 + \frac{y}{N} \right) |
313 | | D_{\mathrm{modified}} |
314 | | \f] |
315 | | where \f$ y \f$ is the IRR and \f$ N \f$ is the number of |
316 | | cash flows per year. |
317 | | */ |
318 | | static Time duration(const Leg& leg, |
319 | | const InterestRate& yield, |
320 | | Duration::Type type, |
321 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
322 | | Date settlementDate = Date(), |
323 | | Date npvDate = Date()); |
324 | | static Time duration(const Leg& leg, |
325 | | Rate yield, |
326 | | const DayCounter& dayCounter, |
327 | | Compounding compounding, |
328 | | Frequency frequency, |
329 | | Duration::Type type, |
330 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
331 | | Date settlementDate = Date(), |
332 | | Date npvDate = Date()); |
333 | | |
334 | | //! Cash-flow convexity |
335 | | /*! The convexity of a string of cash flows is defined as |
336 | | \f[ |
337 | | C = \frac{1}{P} \frac{\partial^2 P}{\partial y^2} |
338 | | \f] |
339 | | where \f$ P \f$ is the present value of the cash flows |
340 | | according to the given IRR \f$ y \f$. |
341 | | */ |
342 | | static Real convexity(const Leg& leg, |
343 | | const InterestRate& yield, |
344 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
345 | | Date settlementDate = Date(), |
346 | | Date npvDate = Date()); |
347 | | static Real convexity(const Leg& leg, |
348 | | Rate yield, |
349 | | const DayCounter& dayCounter, |
350 | | Compounding compounding, |
351 | | Frequency frequency, |
352 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
353 | | Date settlementDate = Date(), |
354 | | Date npvDate = Date()); |
355 | | |
356 | | //! Basis-point value |
357 | | /*! Obtained by setting dy = 0.0001 in the 2nd-order Taylor |
358 | | series expansion. |
359 | | */ |
360 | | static Real basisPointValue(const Leg& leg, |
361 | | const InterestRate& yield, |
362 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
363 | | Date settlementDate = Date(), |
364 | | Date npvDate = Date()); |
365 | | static Real basisPointValue(const Leg& leg, |
366 | | Rate yield, |
367 | | const DayCounter& dayCounter, |
368 | | Compounding compounding, |
369 | | Frequency frequency, |
370 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
371 | | Date settlementDate = Date(), |
372 | | Date npvDate = Date()); |
373 | | |
374 | | //! Yield value of a basis point |
375 | | /*! The yield value of a one basis point change in price is |
376 | | the derivative of the yield with respect to the price |
377 | | multiplied by 0.01 |
378 | | */ |
379 | | static Real yieldValueBasisPoint(const Leg& leg, |
380 | | const InterestRate& yield, |
381 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
382 | | Date settlementDate = Date(), |
383 | | Date npvDate = Date()); |
384 | | static Real yieldValueBasisPoint(const Leg& leg, |
385 | | Rate yield, |
386 | | const DayCounter& dayCounter, |
387 | | Compounding compounding, |
388 | | Frequency frequency, |
389 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
390 | | Date settlementDate = Date(), |
391 | | Date npvDate = Date()); |
392 | | //@} |
393 | | |
394 | | //! \name Z-spread functions |
395 | | /*! For details on z-spread refer to: |
396 | | "Credit Spreads Explained", Lehman Brothers European Fixed |
397 | | Income Research - March 2004, D. O'Kane |
398 | | */ |
399 | | //@{ |
400 | | //! NPV of the cash flows. |
401 | | /*! The NPV is the sum of the cash flows, each discounted |
402 | | according to the z-spreaded term structure. The spread |
403 | | is expressed in terms of the underlying curve's day counter. |
404 | | */ |
405 | | static Real npv(const Leg& leg, |
406 | | const ext::shared_ptr<YieldTermStructure>& discount, |
407 | | Spread zSpread, |
408 | | Compounding compounding, |
409 | | Frequency frequency, |
410 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
411 | | Date settlementDate = Date(), |
412 | | Date npvDate = Date()); |
413 | | /*! \deprecated Use the overload without a day counter. |
414 | | Deprecated in version 1.42. |
415 | | */ |
416 | | [[deprecated("Use the overload without a day counter")]] |
417 | | static Real npv(const Leg& leg, |
418 | | const ext::shared_ptr<YieldTermStructure>& discount, |
419 | | Spread zSpread, |
420 | | const DayCounter& dayCounter, |
421 | | Compounding compounding, |
422 | | Frequency frequency, |
423 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
424 | | Date settlementDate = Date(), |
425 | | Date npvDate = Date()); |
426 | | //! implied Z-spread. |
427 | | static Spread zSpread(const Leg& leg, |
428 | | Real npv, |
429 | | const ext::shared_ptr<YieldTermStructure>&, |
430 | | Compounding compounding, |
431 | | Frequency frequency, |
432 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
433 | | Date settlementDate = Date(), |
434 | | Date npvDate = Date(), |
435 | | Real accuracy = 1.0e-10, |
436 | | Size maxIterations = 100, |
437 | | Rate guess = 0.0); |
438 | | /*! \deprecated Use the overload without a day counter. |
439 | | Deprecated in version 1.42. |
440 | | */ |
441 | | [[deprecated("Use the overload without a day counter")]] |
442 | | static Spread zSpread(const Leg& leg, |
443 | | Real npv, |
444 | | const ext::shared_ptr<YieldTermStructure>&, |
445 | | const DayCounter& dayCounter, |
446 | | Compounding compounding, |
447 | | Frequency frequency, |
448 | | const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt, |
449 | | Date settlementDate = Date(), |
450 | | Date npvDate = Date(), |
451 | | Real accuracy = 1.0e-10, |
452 | | Size maxIterations = 100, |
453 | | Rate guess = 0.0); |
454 | | //@} |
455 | | |
456 | | }; |
457 | | |
458 | | } |
459 | | |
460 | | #endif |