1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*
4  Copyright (C) 2001, 2002, 2003 Sadruddin Rejeb
5  Copyright (C) 2004, 2007 StatPro Italia srl
6 
7  This file is part of QuantLib, a free-software/open-source library
8  for financial quantitative analysts and developers - http://quantlib.org/
9 
10  QuantLib is free software: you can redistribute it and/or modify it
11  under the terms of the QuantLib license.  You should have received a
12  copy of the license along with this program; if not, please email
13  <quantlib-dev@lists.sf.net>. The license is also available online at
14  <http://quantlib.org/license.shtml>.
15 
16  This program is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18  FOR A PARTICULAR PURPOSE.  See the license for more details.
19 */
20 
21 #include <ql/pricingengines/swap/discretizedswap.hpp>
22 #include <ql/settings.hpp>
23 
24 namespace QuantLib {
25     namespace {
useCouponInPostAdjust(const Time & resetTime,const Time & payTime,const bool & includeTodaysCashFlows)26         inline bool useCouponInPostAdjust(const Time& resetTime,
27                                           const Time& payTime,
28                                           const bool& includeTodaysCashFlows) {
29             return (resetTime < 0.0) &&
30                    ((payTime > 0.0) || (includeTodaysCashFlows && (payTime == 0.0)));
31         }
32     }
33 
DiscretizedSwap(const VanillaSwap::arguments & args,const Date & referenceDate,const DayCounter & dayCounter)34     DiscretizedSwap::DiscretizedSwap(const VanillaSwap::arguments& args,
35                                      const Date& referenceDate,
36                                      const DayCounter& dayCounter)
37     : arguments_(args) {
38         // NOLINTNEXTLINE(readability-implicit-bool-conversion)
39         includeTodaysCashFlows_ = Settings::instance().includeTodaysCashFlows() &&
40                                   *Settings::instance().includeTodaysCashFlows();
41 
42         fixedResetTimes_.resize(args.fixedResetDates.size());
43         for (Size i=0; i<fixedResetTimes_.size(); ++i)
44             fixedResetTimes_[i] =
45                 dayCounter.yearFraction(referenceDate,
46                                         args.fixedResetDates[i]);
47 
48         fixedPayTimes_.resize(args.fixedPayDates.size());
49         for (Size i=0; i<fixedPayTimes_.size(); ++i)
50             fixedPayTimes_[i] =
51                 dayCounter.yearFraction(referenceDate,
52                                         args.fixedPayDates[i]);
53 
54         floatingResetTimes_.resize(args.floatingResetDates.size());
55         for (Size i=0; i<floatingResetTimes_.size(); ++i)
56             floatingResetTimes_[i] =
57                 dayCounter.yearFraction(referenceDate,
58                                         args.floatingResetDates[i]);
59 
60         floatingPayTimes_.resize(args.floatingPayDates.size());
61         for (Size i=0; i<floatingPayTimes_.size(); ++i)
62             floatingPayTimes_[i] =
63                 dayCounter.yearFraction(referenceDate,
64                                         args.floatingPayDates[i]);
65     }
66 
reset(Size size)67     void DiscretizedSwap::reset(Size size) {
68         values_ = Array(size, 0.0);
69         adjustValues();
70     }
71 
mandatoryTimes() const72     std::vector<Time> DiscretizedSwap::mandatoryTimes() const {
73         std::vector<Time> times;
74         for (Size i=0; i<fixedResetTimes_.size(); i++) {
75             Time t = fixedResetTimes_[i];
76             if (t >= 0.0)
77                 times.push_back(t);
78         }
79         for (Size i=0; i<fixedPayTimes_.size(); i++) {
80             Time t = fixedPayTimes_[i];
81             if (t >= 0.0)
82                 times.push_back(t);
83         }
84         for (Size i=0; i<floatingResetTimes_.size(); i++) {
85             Time t = floatingResetTimes_[i];
86             if (t >= 0.0)
87                 times.push_back(t);
88         }
89         for (Size i=0; i<floatingPayTimes_.size(); i++) {
90             Time t = floatingPayTimes_[i];
91             if (t >= 0.0)
92                 times.push_back(t);
93         }
94         return times;
95     }
96 
preAdjustValuesImpl()97     void DiscretizedSwap::preAdjustValuesImpl() {
98         // floating payments
99         for (Size i=0; i<floatingResetTimes_.size(); i++) {
100             Time t = floatingResetTimes_[i];
101             if (t >= 0.0 && isOnTime(t)) {
102                 DiscretizedDiscountBond bond;
103                 bond.initialize(method(), floatingPayTimes_[i]);
104                 bond.rollback(time_);
105 
106                 Real nominal = arguments_.nominal;
107                 Time T = arguments_.floatingAccrualTimes[i];
108                 Spread spread = arguments_.floatingSpreads[i];
109                 Real accruedSpread = nominal*T*spread;
110                 for (Size j=0; j<values_.size(); j++) {
111                     Real coupon = nominal * (1.0 - bond.values()[j])
112                                 + accruedSpread * bond.values()[j];
113                     if (arguments_.type == VanillaSwap::Payer)
114                         values_[j] += coupon;
115                     else
116                         values_[j] -= coupon;
117                 }
118             }
119         }
120         // fixed payments
121         for (Size i=0; i<fixedResetTimes_.size(); i++) {
122             Time t = fixedResetTimes_[i];
123             if (t >= 0.0 && isOnTime(t)) {
124                 DiscretizedDiscountBond bond;
125                 bond.initialize(method(), fixedPayTimes_[i]);
126                 bond.rollback(time_);
127 
128                 Real fixedCoupon = arguments_.fixedCoupons[i];
129                 for (Size j=0; j<values_.size(); j++) {
130                     Real coupon = fixedCoupon*bond.values()[j];
131                     if (arguments_.type == VanillaSwap::Payer)
132                         values_[j] -= coupon;
133                     else
134                         values_[j] += coupon;
135                 }
136             }
137         }
138     }
139 
postAdjustValuesImpl()140     void DiscretizedSwap::postAdjustValuesImpl() {
141         // fixed coupons whose reset time is in the past won't be managed
142         // in preAdjustValues()
143         for (Size i=0; i<fixedPayTimes_.size(); i++) {
144             Time t = fixedPayTimes_[i];
145             Time reset = fixedResetTimes_[i];
146             if (useCouponInPostAdjust(reset, t, includeTodaysCashFlows_) && isOnTime(t)) {
147                 Real fixedCoupon = arguments_.fixedCoupons[i];
148                 if (arguments_.type==VanillaSwap::Payer)
149                     values_ -= fixedCoupon;
150                 else
151                     values_ += fixedCoupon;
152             }
153         }
154 
155         // the same applies to floating payments whose rate is already fixed
156         for (Size i=0; i<floatingPayTimes_.size(); i++) {
157             Time t = floatingPayTimes_[i];
158             Time reset = floatingResetTimes_[i];
159             if (useCouponInPostAdjust(reset, t, includeTodaysCashFlows_) && isOnTime(t)) {
160                 Real currentFloatingCoupon = arguments_.floatingCoupons[i];
161                 QL_REQUIRE(currentFloatingCoupon != Null<Real>(),
162                            "current floating coupon not given");
163                 if (arguments_.type == VanillaSwap::Payer)
164                     values_ += currentFloatingCoupon;
165                 else
166                     values_ -= currentFloatingCoupon;
167             }
168         }
169     }
170 }
171