1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 3 /* 4 Copyright (C) 2011 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 /*! \file cpicoupon.hpp 21 \brief Coupon paying a zero-inflation index 22 */ 23 24 #ifndef quantlib_cpicoupon_hpp 25 #define quantlib_cpicoupon_hpp 26 27 #include <ql/cashflows/inflationcoupon.hpp> 28 #include <ql/cashflows/indexedcashflow.hpp> 29 #include <ql/indexes/inflationindex.hpp> 30 #include <ql/time/schedule.hpp> 31 32 namespace QuantLib { 33 34 struct CPI { 35 //! when you observe an index, how do you interpolate between fixings? 36 enum InterpolationType { 37 AsIndex, //!< same interpolation as index 38 Flat, //!< flat from previous fixing 39 Linear //!< linearly between bracketing fixings 40 }; 41 }; 42 43 44 class CPICouponPricer; 45 46 //! %Coupon paying the performance of a CPI (zero inflation) index 47 /*! The performance is relative to the index value on the base date. 48 49 The other inflation value is taken from the refPeriodEnd date 50 with observation lag, so any roll/calendar etc. will be built 51 in by the caller. By default this is done in the 52 InflationCoupon which uses ModifiedPreceding with fixing days 53 assumed positive meaning earlier, i.e. always stay in same 54 month (relative to referencePeriodEnd). 55 56 This is more sophisticated than an %IndexedCashFlow because it 57 does date calculations itself. 58 59 \todo we do not do any convexity adjustment for lags different 60 to the natural ZCIIS lag that was used to create the 61 forward inflation curve. 62 */ 63 class CPICoupon : public InflationCoupon { 64 public: 65 CPICoupon(Real baseCPI, // user provided, could be arbitrary 66 const Date& paymentDate, 67 Real nominal, 68 const Date& startDate, 69 const Date& endDate, 70 Natural fixingDays, 71 const ext::shared_ptr<ZeroInflationIndex>& index, 72 const Period& observationLag, 73 CPI::InterpolationType observationInterpolation, 74 const DayCounter& dayCounter, 75 Real fixedRate, // aka gearing 76 Spread spread = 0.0, 77 const Date& refPeriodStart = Date(), 78 const Date& refPeriodEnd = Date(), 79 const Date& exCouponDate = Date()); 80 81 //! \name Inspectors 82 //@{ 83 //! fixed rate that will be inflated by the index ratio 84 Real fixedRate() const; 85 //! spread paid over the fixing of the underlying index 86 Spread spread() const; 87 88 //! adjusted fixing (already divided by the base fixing) 89 Rate adjustedFixing() const; 90 //! allows for a different interpolation from the index 91 Rate indexFixing() const; 92 //! base value for the CPI index 93 /*! \warning make sure that the interpolation used to create 94 this is what you are using for the fixing, 95 i.e. the observationInterpolation. 96 */ 97 Rate baseCPI() const; 98 //! how do you observe the index? as-is, flat, linear? 99 CPI::InterpolationType observationInterpolation() const; 100 //! utility method, calls indexFixing 101 Rate indexObservation(const Date& onDate) const; 102 //! index used 103 ext::shared_ptr<ZeroInflationIndex> cpiIndex() const; 104 //@} 105 106 //! \name Visitability 107 //@{ 108 virtual void accept(AcyclicVisitor&); 109 //@} 110 protected: 111 Real baseCPI_; 112 Real fixedRate_; 113 Spread spread_; 114 CPI::InterpolationType observationInterpolation_; 115 116 bool checkPricerImpl( 117 const ext::shared_ptr<InflationCouponPricer>&) const; 118 // use to calculate for fixing date, allows change of 119 // interpolation w.r.t. index. Can also be used ahead of time 120 Rate indexFixing(const Date &) const; 121 }; 122 123 124 //! Cash flow paying the performance of a CPI (zero inflation) index 125 /*! It is NOT a coupon, i.e. no accruals. */ 126 class CPICashFlow : public IndexedCashFlow { 127 public: CPICashFlow(Real notional,const ext::shared_ptr<ZeroInflationIndex> & index,const Date & baseDate,Real baseFixing,const Date & fixingDate,const Date & paymentDate,bool growthOnly=false,CPI::InterpolationType interpolation=CPI::AsIndex,const Frequency & frequency=QuantLib::NoFrequency)128 CPICashFlow(Real notional, 129 const ext::shared_ptr<ZeroInflationIndex>& index, 130 const Date& baseDate, 131 Real baseFixing, 132 const Date& fixingDate, 133 const Date& paymentDate, 134 bool growthOnly = false, 135 CPI::InterpolationType interpolation = CPI::AsIndex, 136 const Frequency& frequency = QuantLib::NoFrequency) 137 : IndexedCashFlow(notional, index, baseDate, fixingDate, 138 paymentDate, growthOnly), 139 baseFixing_(baseFixing), interpolation_(interpolation), 140 frequency_(frequency) { 141 QL_REQUIRE(std::fabs(baseFixing_)>1e-16, 142 "|baseFixing|<1e-16, future divide-by-zero error"); 143 if (interpolation_ != CPI::AsIndex) { 144 QL_REQUIRE(frequency_ != QuantLib::NoFrequency, 145 "non-index interpolation w/o frequency"); 146 } 147 } 148 149 //! value used on base date 150 /*! This does not have to agree with index on that date. */ 151 virtual Real baseFixing() const; 152 //! you may not have a valid date 153 virtual Date baseDate() const; 154 155 //! do you want linear/constant/as-index interpolation of future data? interpolation() const156 virtual CPI::InterpolationType interpolation() const { 157 return interpolation_; 158 } frequency() const159 virtual Frequency frequency() const { return frequency_; } 160 161 //! redefined to use baseFixing() and interpolation 162 virtual Real amount() const; 163 protected: 164 Real baseFixing_; 165 CPI::InterpolationType interpolation_; 166 Frequency frequency_; 167 }; 168 169 170 //! Helper class building a sequence of capped/floored CPI coupons. 171 /*! Also allowing for the inflated notional at the end... 172 especially if there is only one date in the schedule. 173 If a fixedRate is zero you get a FixedRateCoupon, otherwise 174 you get a ZeroInflationCoupon. 175 176 payoff is: spread + fixedRate x index 177 */ 178 class CPILeg { 179 public: 180 CPILeg(const Schedule& schedule, 181 const ext::shared_ptr<ZeroInflationIndex>& index, 182 Real baseCPI, 183 const Period& observationLag); 184 CPILeg& withNotionals(Real notional); 185 CPILeg& withNotionals(const std::vector<Real>& notionals); 186 CPILeg& withFixedRates(Real fixedRate); 187 CPILeg& withFixedRates(const std::vector<Real>& fixedRates); 188 CPILeg& withPaymentDayCounter(const DayCounter&); 189 CPILeg& withPaymentAdjustment(BusinessDayConvention); 190 CPILeg& withPaymentCalendar(const Calendar&); 191 CPILeg& withFixingDays(Natural fixingDays); 192 CPILeg& withFixingDays(const std::vector<Natural>& fixingDays); 193 CPILeg& withObservationInterpolation(CPI::InterpolationType); 194 CPILeg& withSubtractInflationNominal(bool); 195 CPILeg& withSpreads(Spread spread); 196 CPILeg& withSpreads(const std::vector<Spread>& spreads); 197 CPILeg& withCaps(Rate cap); 198 CPILeg& withCaps(const std::vector<Rate>& caps); 199 CPILeg& withFloors(Rate floor); 200 CPILeg& withFloors(const std::vector<Rate>& floors); 201 CPILeg& withExCouponPeriod(const Period&, 202 const Calendar&, 203 BusinessDayConvention, 204 bool endOfMonth = false); 205 operator Leg() const; 206 207 private: 208 Schedule schedule_; 209 ext::shared_ptr<ZeroInflationIndex> index_; 210 Real baseCPI_; 211 Period observationLag_; 212 std::vector<Real> notionals_; 213 std::vector<Real> fixedRates_; // aka gearing 214 DayCounter paymentDayCounter_; 215 BusinessDayConvention paymentAdjustment_; 216 Calendar paymentCalendar_; 217 std::vector<Natural> fixingDays_; 218 CPI::InterpolationType observationInterpolation_; 219 bool subtractInflationNominal_; 220 std::vector<Spread> spreads_; 221 std::vector<Rate> caps_, floors_; 222 Period exCouponPeriod_; 223 Calendar exCouponCalendar_; 224 BusinessDayConvention exCouponAdjustment_; 225 bool exCouponEndOfMonth_; 226 }; 227 228 229 // inline definitions 230 fixedRate() const231 inline Real CPICoupon::fixedRate() const { 232 return fixedRate_; 233 } 234 spread() const235 inline Real CPICoupon::spread() const { 236 return spread_; 237 } 238 adjustedFixing() const239 inline Rate CPICoupon::adjustedFixing() const { 240 return (rate()-spread())/fixedRate(); 241 } 242 indexFixing() const243 inline Rate CPICoupon::indexFixing() const { 244 return indexFixing(fixingDate()); 245 } 246 baseCPI() const247 inline Rate CPICoupon::baseCPI() const { 248 return baseCPI_; 249 } 250 observationInterpolation() const251 inline CPI::InterpolationType CPICoupon::observationInterpolation() const { 252 return observationInterpolation_; 253 } 254 indexObservation(const Date & onDate) const255 inline Rate CPICoupon::indexObservation(const Date& onDate) const { 256 return indexFixing(onDate); 257 } 258 cpiIndex() const259 inline ext::shared_ptr<ZeroInflationIndex> CPICoupon::cpiIndex() const { 260 return ext::dynamic_pointer_cast<ZeroInflationIndex>(index()); 261 } 262 263 } 264 265 #endif 266