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