1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 3 /* 4 Copyright (C) 2008 Toyin Akin 5 6 This file is part of QuantLib, a free-software/open-source library 7 for financial quantitative analysts and developers - http://quantlib.org/ 8 9 QuantLib is free software: you can redistribute it and/or modify it 10 under the terms of the QuantLib license. You should have received a 11 copy of the license along with this program; if not, please email 12 <quantlib-dev@lists.sf.net>. The license is also available online at 13 <http://quantlib.org/license.shtml>. 14 15 This program is distributed in the hope that it will be useful, but WITHOUT 16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 17 FOR A PARTICULAR PURPOSE. See the license for more details. 18 */ 19 20 #include <ql/experimental/coupons/subperiodcoupons.hpp> 21 #include <ql/cashflows/cashflowvectors.hpp> 22 #include <ql/time/schedule.hpp> 23 #include <ql/indexes/iborindex.hpp> 24 #include <ql/termstructures/yieldtermstructure.hpp> 25 #include <cmath> 26 27 namespace QuantLib { 28 SubPeriodsCoupon(const Date & paymentDate,Real nominal,const ext::shared_ptr<IborIndex> & index,const Date & startDate,const Date & endDate,Natural fixingDays,const DayCounter & dayCounter,Real gearing,Rate couponSpread,Rate rateSpread,const Date & refPeriodStart,const Date & refPeriodEnd)29 SubPeriodsCoupon::SubPeriodsCoupon( 30 const Date& paymentDate, 31 Real nominal, 32 const ext::shared_ptr<IborIndex>& index, 33 const Date& startDate, 34 const Date& endDate, 35 Natural fixingDays, 36 const DayCounter& dayCounter, 37 Real gearing, 38 Rate couponSpread, 39 Rate rateSpread, 40 const Date& refPeriodStart, 41 const Date& refPeriodEnd) 42 : FloatingRateCoupon(paymentDate, nominal, startDate, endDate, 43 fixingDays, index, gearing, couponSpread, 44 refPeriodStart, refPeriodEnd, dayCounter), 45 rateSpread_(rateSpread) { 46 const Handle<YieldTermStructure>& rateCurve = 47 index->forwardingTermStructure(); 48 const Date& referenceDate = rateCurve->referenceDate(); 49 50 observationsSchedule_ = ext::make_shared<Schedule>(startDate, endDate, 51 index->tenor(), 52 NullCalendar(), 53 Unadjusted, 54 Unadjusted, 55 DateGeneration::Forward, 56 false); 57 58 observationDates_ = observationsSchedule_->dates(); 59 observationDates_.pop_back(); //remove end date 60 observations_ = observationDates_.size(); 61 62 startTime_ = dayCounter.yearFraction(referenceDate, startDate); 63 endTime_ = dayCounter.yearFraction(referenceDate, endDate); 64 65 for (Size i=0; i<observations_; ++i) { 66 observationTimes_.push_back( 67 dayCounter.yearFraction(referenceDate, observationDates_[i])); 68 } 69 } 70 accept(AcyclicVisitor & v)71 void SubPeriodsCoupon::accept(AcyclicVisitor& v) { 72 Visitor<SubPeriodsCoupon>* v1 = 73 dynamic_cast<Visitor<SubPeriodsCoupon>*>(&v); 74 if (v1 != 0) 75 v1->visit(*this); 76 else 77 FloatingRateCoupon::accept(v); 78 } 79 80 initialize(const FloatingRateCoupon & coupon)81 void SubPeriodsPricer::initialize(const FloatingRateCoupon& coupon) { 82 coupon_ = dynamic_cast<const SubPeriodsCoupon*>(&coupon); 83 QL_REQUIRE(coupon_, "sub-periods coupon required"); 84 gearing_ = coupon_->gearing(); 85 spread_ = coupon_->spread(); 86 87 Date paymentDate = coupon_->date(); 88 89 ext::shared_ptr<IborIndex> index = 90 ext::dynamic_pointer_cast<IborIndex>(coupon_->index()); 91 const Handle<YieldTermStructure>& rateCurve = 92 index->forwardingTermStructure(); 93 discount_ = rateCurve->discount(paymentDate); 94 accrualFactor_ = coupon_->accrualPeriod(); 95 spreadLegValue_ = spread_ * accrualFactor_* discount_; 96 97 startTime_ = coupon_->startTime(); 98 endTime_ = coupon_->endTime(); 99 observationTimes_ = coupon_->observationTimes(); 100 observations_ = coupon_->observations(); 101 102 const std::vector<Date>& observationDates = 103 coupon_->observationsSchedule()->dates(); 104 105 QL_REQUIRE(observationDates.size()==observations_+2, 106 "incompatible size of initialValues vector"); 107 108 initialValues_ = std::vector<Real>(observationDates.size(),0.); 109 110 observationCvg_ = std::vector<Real>(observationDates.size(),0.); 111 112 observationIndexStartDates_ = 113 std::vector<Date>(observationDates.size()); 114 observationIndexEndDates_ = 115 std::vector<Date>(observationDates.size()); 116 117 Calendar calendar = index->fixingCalendar(); 118 119 for(Size i=0; i<observationDates.size(); i++) { 120 Date fixingDate = calendar.advance( 121 observationDates[i], 122 -static_cast<Integer>(coupon_->fixingDays()), 123 Days); 124 125 initialValues_[i] = 126 index->fixing(fixingDate) + coupon_->rateSpread(); 127 128 Date fixingValueDate = index->valueDate(fixingDate); 129 Date endValueDate = index->maturityDate(fixingValueDate); 130 131 observationIndexStartDates_[i] = fixingValueDate; 132 observationIndexEndDates_[i] = endValueDate; 133 134 observationCvg_[i] = 135 index->dayCounter().yearFraction(fixingValueDate, endValueDate); 136 } 137 } 138 swapletRate() const139 Real SubPeriodsPricer::swapletRate() const { 140 return swapletPrice()/(accrualFactor_*discount_); 141 } 142 capletPrice(Rate) const143 Real SubPeriodsPricer::capletPrice(Rate) const { 144 QL_FAIL("SubPeriodsPricer::capletPrice not implemented"); 145 } 146 capletRate(Rate) const147 Rate SubPeriodsPricer::capletRate(Rate) const { 148 QL_FAIL("SubPeriodsPricer::capletRate not implemented"); 149 } 150 floorletPrice(Rate) const151 Real SubPeriodsPricer::floorletPrice(Rate) const { 152 QL_FAIL("SubPeriodsPricer::floorletPrice not implemented"); 153 } 154 floorletRate(Rate) const155 Rate SubPeriodsPricer::floorletRate(Rate) const { 156 QL_FAIL("SubPeriodsPricer::floorletRate not implemented"); 157 } 158 swapletPrice() const159 Real AveragingRatePricer::swapletPrice() const { 160 // past or future fixing is managed in InterestRateIndex::fixing() 161 162 Size nCount = initialValues_.size(); 163 Real dAvgRate = 0.0, dTotalCvg = 0.0, dTotalPayment = 0.0; 164 for (Size i=0; i<nCount; i++) { 165 dTotalPayment += initialValues_[i] * observationCvg_[i]; 166 dTotalCvg += observationCvg_[i]; 167 } 168 169 dAvgRate = dTotalPayment/dTotalCvg; 170 171 Real swapletPrice = dAvgRate*coupon_->accrualPeriod()*discount_; 172 return gearing_ * swapletPrice + spreadLegValue_; 173 } 174 swapletPrice() const175 Real CompoundingRatePricer::swapletPrice() const { 176 // past or future fixing is managed in InterestRateIndex::fixing() 177 178 Real dNotional = 1.0; 179 180 Size nCount = initialValues_.size(); 181 Real dCompRate = 0.0, dTotalCvg = 0.0, dTotalPayment = 0.0; 182 for (Size i=0; i<nCount; i++) { 183 dTotalPayment = initialValues_[i] * observationCvg_[i]*dNotional; 184 dNotional += dTotalPayment; 185 dTotalCvg += observationCvg_[i]; 186 } 187 188 dCompRate = (dNotional - 1.0)/dTotalCvg; 189 190 Real swapletPrice = dCompRate*coupon_->accrualPeriod()*discount_; 191 return gearing_ * swapletPrice + spreadLegValue_; 192 } 193 194 } 195 196