| 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 | <http://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 | 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 | 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 | bool includeSettlementDateFlows, |
| 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 | bool includeSettlementDateFlows, |
| 90 | Date settlementDate = Date()); |
| 91 | //! the first cashflow paying after the given date |
| 92 | static Leg::const_iterator |
| 93 | nextCashFlow(const Leg& leg, |
| 94 | bool includeSettlementDateFlows, |
| 95 | Date settlementDate = Date()); |
| 96 | static Date |
| 97 | previousCashFlowDate(const Leg& leg, |
| 98 | bool includeSettlementDateFlows, |
| 99 | Date settlementDate = Date()); |
| 100 | static Date |
| 101 | nextCashFlowDate(const Leg& leg, |
| 102 | bool includeSettlementDateFlows, |
| 103 | Date settlementDate = Date()); |
| 104 | static Real |
| 105 | previousCashFlowAmount(const Leg& leg, |
| 106 | bool includeSettlementDateFlows, |
| 107 | Date settlementDate = Date()); |
| 108 | static Real |
| 109 | nextCashFlowAmount(const Leg& leg, |
| 110 | bool includeSettlementDateFlows, |
| 111 | Date settlementDate = Date()); |
| 112 | //@} |
| 113 | |
| 114 | //! \name Coupon inspectors |
| 115 | //@{ |
| 116 | static Rate |
| 117 | previousCouponRate(const Leg& leg, |
| 118 | bool includeSettlementDateFlows, |
| 119 | Date settlementDate = Date()); |
| 120 | static Rate |
| 121 | nextCouponRate(const Leg& leg, |
| 122 | bool includeSettlementDateFlows, |
| 123 | Date settlementDate = Date()); |
| 124 | |
| 125 | static Real |
| 126 | nominal(const Leg& leg, |
| 127 | bool includeSettlementDateFlows, |
| 128 | Date settlDate = Date()); |
| 129 | static Date |
| 130 | accrualStartDate(const Leg& leg, |
| 131 | bool includeSettlementDateFlows, |
| 132 | Date settlDate = Date()); |
| 133 | static Date |
| 134 | accrualEndDate(const Leg& leg, |
| 135 | bool includeSettlementDateFlows, |
| 136 | Date settlementDate = Date()); |
| 137 | static Date |
| 138 | referencePeriodStart(const Leg& leg, |
| 139 | bool includeSettlementDateFlows, |
| 140 | Date settlDate = Date()); |
| 141 | static Date |
| 142 | referencePeriodEnd(const Leg& leg, |
| 143 | bool includeSettlementDateFlows, |
| 144 | Date settlDate = Date()); |
| 145 | static Time |
| 146 | accrualPeriod(const Leg& leg, |
| 147 | bool includeSettlementDateFlows, |
| 148 | Date settlementDate = Date()); |
| 149 | static Date::serial_type |
| 150 | accrualDays(const Leg& leg, |
| 151 | bool includeSettlementDateFlows, |
| 152 | Date settlementDate = Date()); |
| 153 | static Time |
| 154 | accruedPeriod(const Leg& leg, |
| 155 | bool includeSettlementDateFlows, |
| 156 | Date settlementDate = Date()); |
| 157 | static Date::serial_type |
| 158 | accruedDays(const Leg& leg, |
| 159 | bool includeSettlementDateFlows, |
| 160 | Date settlementDate = Date()); |
| 161 | static Real |
| 162 | accruedAmount(const Leg& leg, |
| 163 | bool includeSettlementDateFlows, |
| 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 | bool includeSettlementDateFlows, |
| 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 | bool includeSettlementDateFlows, |
| 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 | bool includeSettlementDateFlows, |
| 197 | Date settlementDate = Date(), |
| 198 | Date npvDate = Date()); |
| 199 | |
| 200 | //! NPV and BPS of the cash flows. |
| 201 | /*! \deprecated Use the overload returning a pair of Reals. |
| 202 | Deprecated in version 1.29. |
| 203 | */ |
| 204 | QL_DEPRECATED |
| 205 | static void npvbps(const Leg& leg, |
| 206 | const YieldTermStructure& discountCurve, |
| 207 | bool includeSettlementDateFlows, |
| 208 | Date settlementDate, |
| 209 | Date npvDate, |
| 210 | Real& npv, |
| 211 | Real& bps); |
| 212 | |
| 213 | //! At-the-money rate of the cash flows. |
| 214 | /*! The result is the fixed rate for which a fixed rate cash flow |
| 215 | vector, equivalent to the input vector, has the required NPV |
| 216 | according to the given term structure. If the required NPV is |
| 217 | not given, the input cash flow vector's NPV is used instead. |
| 218 | */ |
| 219 | static Rate atmRate(const Leg& leg, |
| 220 | const YieldTermStructure& discountCurve, |
| 221 | bool includeSettlementDateFlows, |
| 222 | Date settlementDate = Date(), |
| 223 | Date npvDate = Date(), |
| 224 | Real npv = Null<Real>()); |
| 225 | //@} |
| 226 | |
| 227 | //! \name Yield (a.k.a. Internal Rate of Return, i.e. IRR) functions |
| 228 | /*! The IRR is the interest rate at which the NPV of the cash |
| 229 | flows equals the dirty price. |
| 230 | */ |
| 231 | //@{ |
| 232 | //! NPV of the cash flows. |
| 233 | /*! The NPV is the sum of the cash flows, each discounted |
| 234 | according to the given constant interest rate. The result |
| 235 | is affected by the choice of the interest-rate compounding |
| 236 | and the relative frequency and day counter. |
| 237 | */ |
| 238 | static Real npv(const Leg& leg, |
| 239 | const InterestRate& yield, |
| 240 | bool includeSettlementDateFlows, |
| 241 | Date settlementDate = Date(), |
| 242 | Date npvDate = Date()); |
| 243 | static Real npv(const Leg& leg, |
| 244 | Rate yield, |
| 245 | const DayCounter& dayCounter, |
| 246 | Compounding compounding, |
| 247 | Frequency frequency, |
| 248 | bool includeSettlementDateFlows, |
| 249 | Date settlementDate = Date(), |
| 250 | Date npvDate = Date()); |
| 251 | //! Basis-point sensitivity of the cash flows. |
| 252 | /*! The result is the change in NPV due to a uniform |
| 253 | 1-basis-point change in the rate paid by the cash |
| 254 | flows. The change for each coupon is discounted according |
| 255 | to the given constant interest rate. The result is |
| 256 | affected by the choice of the interest-rate compounding |
| 257 | and the relative frequency and day counter. |
| 258 | */ |
| 259 | static Real bps(const Leg& leg, |
| 260 | const InterestRate& yield, |
| 261 | bool includeSettlementDateFlows, |
| 262 | Date settlementDate = Date(), |
| 263 | Date npvDate = Date()); |
| 264 | static Real bps(const Leg& leg, |
| 265 | Rate yield, |
| 266 | const DayCounter& dayCounter, |
| 267 | Compounding compounding, |
| 268 | Frequency frequency, |
| 269 | bool includeSettlementDateFlows, |
| 270 | Date settlementDate = Date(), |
| 271 | Date npvDate = Date()); |
| 272 | //! Implied internal rate of return. |
| 273 | /*! The function verifies |
| 274 | the theoretical existence of an IRR and numerically |
| 275 | establishes the IRR to the desired precision. |
| 276 | */ |
| 277 | static Rate yield(const Leg& leg, |
| 278 | Real npv, |
| 279 | const DayCounter& dayCounter, |
| 280 | Compounding compounding, |
| 281 | Frequency frequency, |
| 282 | bool includeSettlementDateFlows, |
| 283 | Date settlementDate = Date(), |
| 284 | Date npvDate = Date(), |
| 285 | Real accuracy = 1.0e-10, |
| 286 | Size maxIterations = 100, |
| 287 | Rate guess = 0.05); |
| 288 | |
| 289 | template <typename Solver> |
| 290 | static Rate yield(const Solver& solver, |
| 291 | const Leg& leg, |
| 292 | Real npv, |
| 293 | const DayCounter& dayCounter, |
| 294 | Compounding compounding, |
| 295 | Frequency frequency, |
| 296 | bool includeSettlementDateFlows, |
| 297 | Date settlementDate = Date(), |
| 298 | Date npvDate = Date(), |
| 299 | Real accuracy = 1.0e-10, |
| 300 | Rate guess = 0.05) { |
| 301 | IrrFinder objFunction(leg, npv, dayCounter, compounding, |
| 302 | frequency, includeSettlementDateFlows, |
| 303 | settlementDate, npvDate); |
| 304 | return solver.solve(objFunction, accuracy, guess, guess/10.0); |
| 305 | } |
| 306 | |
| 307 | //! Cash-flow duration. |
| 308 | /*! The simple duration of a string of cash flows is defined as |
| 309 | \f[ |
| 310 | D_{\mathrm{simple}} = \frac{\sum t_i c_i B(t_i)}{\sum c_i B(t_i)} |
| 311 | \f] |
| 312 | where \f$ c_i \f$ is the amount of the \f$ i \f$-th cash |
| 313 | flow, \f$ t_i \f$ is its payment time, and \f$ B(t_i) \f$ |
| 314 | is the corresponding discount according to the passed yield. |
| 315 | |
| 316 | The modified duration is defined as |
| 317 | \f[ |
| 318 | D_{\mathrm{modified}} = -\frac{1}{P} \frac{\partial P}{\partial y} |
| 319 | \f] |
| 320 | where \f$ P \f$ is the present value of the cash flows |
| 321 | according to the given IRR \f$ y \f$. |
| 322 | |
| 323 | The Macaulay duration is defined for a compounded IRR as |
| 324 | \f[ |
| 325 | D_{\mathrm{Macaulay}} = \left( 1 + \frac{y}{N} \right) |
| 326 | D_{\mathrm{modified}} |
| 327 | \f] |
| 328 | where \f$ y \f$ is the IRR and \f$ N \f$ is the number of |
| 329 | cash flows per year. |
| 330 | */ |
| 331 | static Time duration(const Leg& leg, |
| 332 | const InterestRate& yield, |
| 333 | Duration::Type type, |
| 334 | bool includeSettlementDateFlows, |
| 335 | Date settlementDate = Date(), |
| 336 | Date npvDate = Date()); |
| 337 | static Time duration(const Leg& leg, |
| 338 | Rate yield, |
| 339 | const DayCounter& dayCounter, |
| 340 | Compounding compounding, |
| 341 | Frequency frequency, |
| 342 | Duration::Type type, |
| 343 | bool includeSettlementDateFlows, |
| 344 | Date settlementDate = Date(), |
| 345 | Date npvDate = Date()); |
| 346 | |
| 347 | //! Cash-flow convexity |
| 348 | /*! The convexity of a string of cash flows is defined as |
| 349 | \f[ |
| 350 | C = \frac{1}{P} \frac{\partial^2 P}{\partial y^2} |
| 351 | \f] |
| 352 | where \f$ P \f$ is the present value of the cash flows |
| 353 | according to the given IRR \f$ y \f$. |
| 354 | */ |
| 355 | static Real convexity(const Leg& leg, |
| 356 | const InterestRate& yield, |
| 357 | bool includeSettlementDateFlows, |
| 358 | Date settlementDate = Date(), |
| 359 | Date npvDate = Date()); |
| 360 | static Real convexity(const Leg& leg, |
| 361 | Rate yield, |
| 362 | const DayCounter& dayCounter, |
| 363 | Compounding compounding, |
| 364 | Frequency frequency, |
| 365 | bool includeSettlementDateFlows, |
| 366 | Date settlementDate = Date(), |
| 367 | Date npvDate = Date()); |
| 368 | |
| 369 | //! Basis-point value |
| 370 | /*! Obtained by setting dy = 0.0001 in the 2nd-order Taylor |
| 371 | series expansion. |
| 372 | */ |
| 373 | static Real basisPointValue(const Leg& leg, |
| 374 | const InterestRate& yield, |
| 375 | bool includeSettlementDateFlows, |
| 376 | Date settlementDate = Date(), |
| 377 | Date npvDate = Date()); |
| 378 | static Real basisPointValue(const Leg& leg, |
| 379 | Rate yield, |
| 380 | const DayCounter& dayCounter, |
| 381 | Compounding compounding, |
| 382 | Frequency frequency, |
| 383 | bool includeSettlementDateFlows, |
| 384 | Date settlementDate = Date(), |
| 385 | Date npvDate = Date()); |
| 386 | |
| 387 | //! Yield value of a basis point |
| 388 | /*! The yield value of a one basis point change in price is |
| 389 | the derivative of the yield with respect to the price |
| 390 | multiplied by 0.01 |
| 391 | */ |
| 392 | static Real yieldValueBasisPoint(const Leg& leg, |
| 393 | const InterestRate& yield, |
| 394 | bool includeSettlementDateFlows, |
| 395 | Date settlementDate = Date(), |
| 396 | Date npvDate = Date()); |
| 397 | static Real yieldValueBasisPoint(const Leg& leg, |
| 398 | Rate yield, |
| 399 | const DayCounter& dayCounter, |
| 400 | Compounding compounding, |
| 401 | Frequency frequency, |
| 402 | bool includeSettlementDateFlows, |
| 403 | Date settlementDate = Date(), |
| 404 | Date npvDate = Date()); |
| 405 | //@} |
| 406 | |
| 407 | //! \name Z-spread functions |
| 408 | /*! For details on z-spread refer to: |
| 409 | "Credit Spreads Explained", Lehman Brothers European Fixed |
| 410 | Income Research - March 2004, D. O'Kane |
| 411 | */ |
| 412 | //@{ |
| 413 | //! NPV of the cash flows. |
| 414 | /*! The NPV is the sum of the cash flows, each discounted |
| 415 | according to the z-spreaded term structure. The result |
| 416 | is affected by the choice of the z-spread compounding |
| 417 | and the relative frequency and day counter. |
| 418 | */ |
| 419 | static Real npv(const Leg& leg, |
| 420 | const ext::shared_ptr<YieldTermStructure>& discount, |
| 421 | Spread zSpread, |
| 422 | const DayCounter& dayCounter, |
| 423 | Compounding compounding, |
| 424 | Frequency frequency, |
| 425 | bool includeSettlementDateFlows, |
| 426 | Date settlementDate = Date(), |
| 427 | Date npvDate = Date()); |
| 428 | //! implied Z-spread. |
| 429 | static Spread zSpread(const Leg& leg, |
| 430 | Real npv, |
| 431 | const ext::shared_ptr<YieldTermStructure>&, |
| 432 | const DayCounter& dayCounter, |
| 433 | Compounding compounding, |
| 434 | Frequency frequency, |
| 435 | bool includeSettlementDateFlows, |
| 436 | Date settlementDate = Date(), |
| 437 | Date npvDate = Date(), |
| 438 | Real accuracy = 1.0e-10, |
| 439 | Size maxIterations = 100, |
| 440 | Rate guess = 0.0); |
| 441 | //! deprecated implied Z-spread. |
| 442 | static Spread zSpread(const Leg& leg, |
| 443 | const ext::shared_ptr<YieldTermStructure>& d, |
| 444 | Real npv, |
| 445 | const DayCounter& dayCounter, |
| 446 | Compounding compounding, |
| 447 | Frequency frequency, |
| 448 | bool includeSettlementDateFlows, |
| 449 | Date settlementDate = Date(), |
| 450 | Date npvDate = Date(), |
| 451 | Real accuracy = 1.0e-10, |
| 452 | Size maxIterations = 100, |
| 453 | Rate guess = 0.0) { |
| 454 | return zSpread(leg, npv, d, dayCounter, compounding, frequency, |
| 455 | includeSettlementDateFlows, settlementDate, npvDate, |
| 456 | accuracy, maxIterations, guess); |
| 457 | } |
| 458 | //@} |
| 459 | |
| 460 | }; |
| 461 | |
| 462 | } |
| 463 | |
| 464 | #endif |
| 465 | |