1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 3 /* 4 Copyright (C) 2009 Chris Kenyon 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 21 #include <ql/cashflows/inflationcouponpricer.hpp> 22 #include <ql/cashflows/inflationcoupon.hpp> 23 #include <ql/cashflows/capflooredinflationcoupon.hpp> 24 #include <ql/cashflows/cashflowvectors.hpp> 25 26 namespace QuantLib { 27 28 YoYInflationCoupon:: YoYInflationCoupon(const Date & paymentDate,Real nominal,const Date & startDate,const Date & endDate,Natural fixingDays,const ext::shared_ptr<YoYInflationIndex> & yoyIndex,const Period & observationLag,const DayCounter & dayCounter,Real gearing,Spread spread,const Date & refPeriodStart,const Date & refPeriodEnd)29 YoYInflationCoupon(const Date& paymentDate, 30 Real nominal, 31 const Date& startDate, 32 const Date& endDate, 33 Natural fixingDays, 34 const ext::shared_ptr<YoYInflationIndex>& yoyIndex, 35 const Period& observationLag, 36 const DayCounter& dayCounter, 37 Real gearing, 38 Spread spread, 39 const Date& refPeriodStart, 40 const Date& refPeriodEnd) 41 : InflationCoupon(paymentDate, nominal, startDate, endDate, 42 fixingDays, yoyIndex, observationLag, 43 dayCounter, refPeriodStart, refPeriodEnd), 44 yoyIndex_(yoyIndex), gearing_(gearing), spread_(spread) {} 45 46 accept(AcyclicVisitor & v)47 void YoYInflationCoupon::accept(AcyclicVisitor& v) { 48 Visitor<YoYInflationCoupon>* v1 = 49 dynamic_cast<Visitor<YoYInflationCoupon>*>(&v); 50 if (v1 != 0) 51 v1->visit(*this); 52 else 53 InflationCoupon::accept(v); 54 } 55 56 checkPricerImpl(const ext::shared_ptr<InflationCouponPricer> & pricer) const57 bool YoYInflationCoupon::checkPricerImpl( 58 const ext::shared_ptr<InflationCouponPricer>&pricer) const { 59 return static_cast<bool>( 60 ext::dynamic_pointer_cast<YoYInflationCouponPricer>(pricer)); 61 } 62 63 64 65 yoyInflationLeg:: yoyInflationLeg(const Schedule & schedule,const Calendar & paymentCalendar,const ext::shared_ptr<YoYInflationIndex> & index,const Period & observationLag)66 yoyInflationLeg(const Schedule& schedule, const Calendar& paymentCalendar, 67 const ext::shared_ptr<YoYInflationIndex>& index, 68 const Period& observationLag) 69 : schedule_(schedule), index_(index), 70 observationLag_(observationLag), 71 paymentAdjustment_(ModifiedFollowing), 72 paymentCalendar_(paymentCalendar) {} 73 74 withNotionals(Real notional)75 yoyInflationLeg& yoyInflationLeg::withNotionals(Real notional) { 76 notionals_ = std::vector<Real>(1,notional); 77 return *this; 78 } 79 withNotionals(const std::vector<Real> & notionals)80 yoyInflationLeg& yoyInflationLeg::withNotionals(const std::vector<Real>& notionals) { 81 notionals_ = notionals; 82 return *this; 83 } 84 withPaymentDayCounter(const DayCounter & dayCounter)85 yoyInflationLeg& yoyInflationLeg::withPaymentDayCounter(const DayCounter& dayCounter) { 86 paymentDayCounter_ = dayCounter; 87 return *this; 88 } 89 withPaymentAdjustment(BusinessDayConvention convention)90 yoyInflationLeg& yoyInflationLeg::withPaymentAdjustment(BusinessDayConvention convention) { 91 paymentAdjustment_ = convention; 92 return *this; 93 } 94 withFixingDays(Natural fixingDays)95 yoyInflationLeg& yoyInflationLeg::withFixingDays(Natural fixingDays) { 96 fixingDays_ = std::vector<Natural>(1,fixingDays); 97 return *this; 98 } 99 withFixingDays(const std::vector<Natural> & fixingDays)100 yoyInflationLeg& yoyInflationLeg::withFixingDays(const std::vector<Natural>& fixingDays) { 101 fixingDays_ = fixingDays; 102 return *this; 103 } 104 withGearings(Real gearing)105 yoyInflationLeg& yoyInflationLeg::withGearings(Real gearing) { 106 gearings_ = std::vector<Real>(1,gearing); 107 return *this; 108 } 109 withGearings(const std::vector<Real> & gearings)110 yoyInflationLeg& yoyInflationLeg::withGearings(const std::vector<Real>& gearings) { 111 gearings_ = gearings; 112 return *this; 113 } 114 withSpreads(Spread spread)115 yoyInflationLeg& yoyInflationLeg::withSpreads(Spread spread) { 116 spreads_ = std::vector<Spread>(1,spread); 117 return *this; 118 } 119 withSpreads(const std::vector<Spread> & spreads)120 yoyInflationLeg& yoyInflationLeg::withSpreads(const std::vector<Spread>& spreads) { 121 spreads_ = spreads; 122 return *this; 123 } 124 withCaps(Rate cap)125 yoyInflationLeg& yoyInflationLeg::withCaps(Rate cap) { 126 caps_ = std::vector<Rate>(1,cap); 127 return *this; 128 } 129 withCaps(const std::vector<Rate> & caps)130 yoyInflationLeg& yoyInflationLeg::withCaps(const std::vector<Rate>& caps) { 131 caps_ = caps; 132 return *this; 133 } 134 withFloors(Rate floor)135 yoyInflationLeg& yoyInflationLeg::withFloors(Rate floor) { 136 floors_ = std::vector<Rate>(1,floor); 137 return *this; 138 } 139 withFloors(const std::vector<Rate> & floors)140 yoyInflationLeg& yoyInflationLeg::withFloors(const std::vector<Rate>& floors) { 141 floors_ = floors; 142 return *this; 143 } 144 145 operator Leg() const146 yoyInflationLeg::operator Leg() const { 147 148 Size n = schedule_.size()-1; 149 QL_REQUIRE(!paymentDayCounter_.empty(), "no payment daycounter given"); 150 QL_REQUIRE(!notionals_.empty(), "no notional given"); 151 QL_REQUIRE(notionals_.size() <= n, 152 "too many nominals (" << notionals_.size() << 153 "), only " << n << " required"); 154 QL_REQUIRE(gearings_.size()<=n, 155 "too many gearings (" << gearings_.size() << 156 "), only " << n << " required"); 157 QL_REQUIRE(spreads_.size()<=n, 158 "too many spreads (" << spreads_.size() << 159 "), only " << n << " required"); 160 QL_REQUIRE(caps_.size()<=n, 161 "too many caps (" << caps_.size() << 162 "), only " << n << " required"); 163 QL_REQUIRE(floors_.size()<=n, 164 "too many floors (" << floors_.size() << 165 "), only " << n << " required"); 166 167 Leg leg; leg.reserve(n); 168 169 Calendar calendar = paymentCalendar_; 170 171 Date refStart, start, refEnd, end; 172 173 for (Size i=0; i<n; ++i) { 174 refStart = start = schedule_.date(i); 175 refEnd = end = schedule_.date(i+1); 176 Date paymentDate = calendar.adjust(end, paymentAdjustment_); 177 if (i==0 && schedule_.hasIsRegular() && !schedule_.isRegular(i+1)) { 178 BusinessDayConvention bdc = schedule_.businessDayConvention(); 179 refStart = schedule_.calendar().adjust(end - schedule_.tenor(), bdc); 180 } 181 if (i==n-1 && schedule_.hasIsRegular() && !schedule_.isRegular(i+1)) { 182 BusinessDayConvention bdc = schedule_.businessDayConvention(); 183 refEnd = schedule_.calendar().adjust(start + schedule_.tenor(), bdc); 184 } 185 if (detail::get(gearings_, i, 1.0) == 0.0) { // fixed coupon 186 leg.push_back(ext::shared_ptr<CashFlow>(new 187 FixedRateCoupon(paymentDate, 188 detail::get(notionals_, i, 1.0), 189 detail::effectiveFixedRate(spreads_,caps_, 190 floors_,i), 191 paymentDayCounter_, 192 start, end, refStart, refEnd))); 193 } else { // yoy inflation coupon 194 if (detail::noOption(caps_, floors_, i)) { // just swaplet 195 ext::shared_ptr<YoYInflationCoupon> coup(new 196 YoYInflationCoupon( 197 paymentDate, 198 detail::get(notionals_, i, 1.0), 199 start, end, 200 detail::get(fixingDays_, i, 0), 201 index_, 202 observationLag_, 203 paymentDayCounter_, 204 detail::get(gearings_, i, 1.0), 205 detail::get(spreads_, i, 0.0), 206 refStart, refEnd)); 207 208 // in this case you can set a pricer 209 // straight away because it only provides computation - not data 210 ext::shared_ptr<YoYInflationCouponPricer> pricer = 211 ext::make_shared<YoYInflationCouponPricer>(Handle<YoYOptionletVolatilitySurface>(), 212 Handle<YieldTermStructure>()); 213 coup->setPricer(pricer); 214 leg.push_back(ext::dynamic_pointer_cast<CashFlow>(coup)); 215 216 217 218 } else { // cap/floorlet 219 leg.push_back(ext::shared_ptr<CashFlow>(new 220 CappedFlooredYoYInflationCoupon( 221 paymentDate, 222 detail::get(notionals_, i, 1.0), 223 start, end, 224 detail::get(fixingDays_, i, 0), 225 index_, 226 observationLag_, 227 paymentDayCounter_, 228 detail::get(gearings_, i, 1.0), 229 detail::get(spreads_, i, 0.0), 230 detail::get(caps_, i, Null<Rate>()), 231 detail::get(floors_, i, Null<Rate>()), 232 refStart, refEnd))); 233 } 234 } 235 } 236 237 return leg; 238 } 239 240 241 242 243 244 245 } 246 247