1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 3 /* 4 Copyright (C) 2009, 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 #include <ql/cashflows/cpicouponpricer.hpp> 21 22 namespace QuantLib { 23 CPICouponPricer()24 CPICouponPricer::CPICouponPricer() {} 25 CPICouponPricer(const Handle<YieldTermStructure> & nominalTermStructure)26 CPICouponPricer::CPICouponPricer( 27 const Handle<YieldTermStructure>& nominalTermStructure) 28 : nominalTermStructure_(nominalTermStructure) { 29 registerWith(nominalTermStructure_); 30 } 31 CPICouponPricer(const Handle<CPIVolatilitySurface> & capletVol,const Handle<YieldTermStructure> & nominalTermStructure)32 CPICouponPricer::CPICouponPricer( 33 const Handle<CPIVolatilitySurface>& capletVol, 34 const Handle<YieldTermStructure>& nominalTermStructure) 35 : capletVol_(capletVol), nominalTermStructure_(nominalTermStructure) { 36 registerWith(capletVol_); 37 registerWith(nominalTermStructure_); 38 } 39 40 setCapletVolatility(const Handle<CPIVolatilitySurface> & capletVol)41 void CPICouponPricer::setCapletVolatility( 42 const Handle<CPIVolatilitySurface>& capletVol) { 43 QL_REQUIRE(!capletVol.empty(),"empty capletVol handle") 44 capletVol_ = capletVol; 45 registerWith(capletVol_); 46 } 47 48 floorletPrice(Rate effectiveFloor) const49 Real CPICouponPricer::floorletPrice(Rate effectiveFloor) const{ 50 Real floorletPrice = optionletPrice(Option::Put, effectiveFloor); 51 return gearing_ * floorletPrice; 52 } 53 capletPrice(Rate effectiveCap) const54 Real CPICouponPricer::capletPrice(Rate effectiveCap) const{ 55 Real capletPrice = optionletPrice(Option::Call, effectiveCap); 56 return gearing_ * capletPrice; 57 } 58 59 floorletRate(Rate effectiveFloor) const60 Rate CPICouponPricer::floorletRate(Rate effectiveFloor) const { 61 return gearing_ * optionletRate(Option::Put, effectiveFloor); 62 } 63 capletRate(Rate effectiveCap) const64 Rate CPICouponPricer::capletRate(Rate effectiveCap) const{ 65 return gearing_ * optionletRate(Option::Call, effectiveCap); 66 } 67 68 optionletPriceImp(Option::Type,Real,Real,Real) const69 Real CPICouponPricer::optionletPriceImp(Option::Type, 70 Real, 71 Real, 72 Real) const { 73 QL_FAIL("you must implement this to get a vol-dependent price"); 74 } 75 76 optionletPrice(Option::Type optionType,Real effStrike) const77 Real CPICouponPricer::optionletPrice(Option::Type optionType, 78 Real effStrike) const { 79 QL_REQUIRE(discount_ != Null<Real>(), "no nominal term structure provided"); 80 return optionletRate(optionType, effStrike) * coupon_->accrualPeriod() * discount_; 81 } 82 83 optionletRate(Option::Type optionType,Real effStrike) const84 Real CPICouponPricer::optionletRate(Option::Type optionType, 85 Real effStrike) const { 86 Date fixingDate = coupon_->fixingDate(); 87 if (fixingDate <= Settings::instance().evaluationDate()) { 88 // the amount is determined 89 Real a, b; 90 if (optionType==Option::Call) { 91 a = coupon_->indexFixing(); 92 b = effStrike; 93 } else { 94 a = effStrike; 95 b = coupon_->indexFixing(); 96 } 97 return std::max(a - b, 0.0); 98 } else { 99 // not yet determined, use Black/DD1/Bachelier/whatever from Impl 100 QL_REQUIRE(!capletVolatility().empty(), 101 "missing optionlet volatility"); 102 Real stdDev = 103 std::sqrt(capletVolatility()->totalVariance(fixingDate, 104 effStrike)); 105 return optionletPriceImp(optionType, 106 effStrike, 107 adjustedFixing(), 108 stdDev); 109 } 110 } 111 112 adjustedFixing(Rate fixing) const113 Rate CPICouponPricer::adjustedFixing(Rate fixing) const { 114 115 if (fixing == Null<Rate>()) 116 fixing = coupon_->indexFixing() / coupon_->baseCPI(); 117 //std::cout << " adjustedFixing " << fixing << std::endl; 118 // no adjustment 119 return fixing; 120 } 121 122 initialize(const InflationCoupon & coupon)123 void CPICouponPricer::initialize(const InflationCoupon& coupon) { 124 coupon_ = dynamic_cast<const CPICoupon*>(&coupon); 125 gearing_ = coupon_->fixedRate(); 126 spread_ = coupon_->spread(); 127 paymentDate_ = coupon_->date(); 128 rateCurve_ = 129 !nominalTermStructure_.empty() ? 130 nominalTermStructure_ : 131 ext::dynamic_pointer_cast<ZeroInflationIndex>(coupon.index()) 132 ->zeroInflationTermStructure() 133 ->nominalTermStructure(); 134 135 // past or future fixing is managed in YoYInflationIndex::fixing() 136 // use yield curve from index (which sets discount) 137 138 discount_ = 1.0; 139 if (paymentDate_ > rateCurve_->referenceDate()) { 140 if (rateCurve_.empty()) { 141 // allow to extract rates, but mark the discount as invalid for prices 142 discount_ = Null<Real>(); 143 } else { 144 discount_ = rateCurve_->discount(paymentDate_); 145 } 146 } 147 } 148 149 swapletPrice() const150 Real CPICouponPricer::swapletPrice() const { 151 QL_REQUIRE(discount_ != Null<Real>(), "no nominal term structure provided"); 152 return swapletRate() * coupon_->accrualPeriod() * discount_; 153 } 154 155 swapletRate() const156 Rate CPICouponPricer::swapletRate() const { 157 // This way we do not require the index to have 158 // a yield curve, i.e. we do not get the problem 159 // that a discounting-instrument-pricer is used 160 // with a different yield curve 161 return gearing_ * adjustedFixing() + spread_; 162 } 163 164 } 165