/src/quantlib/ql/cashflows/inflationcouponpricer.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | #include <ql/cashflows/inflationcouponpricer.hpp> |
21 | | #include <ql/pricingengines/blackformula.hpp> |
22 | | #include <ql/termstructures/volatility/inflation/yoyinflationoptionletvolatilitystructure.hpp> |
23 | | #include <utility> |
24 | | |
25 | | namespace QuantLib { |
26 | | |
27 | | void setCouponPricer(const Leg& leg, |
28 | 0 | const ext::shared_ptr<InflationCouponPricer>& p) { |
29 | 0 | for (const auto& i : leg) { |
30 | 0 | ext::shared_ptr<InflationCoupon> c = ext::dynamic_pointer_cast<InflationCoupon>(i); |
31 | 0 | if (c != nullptr) |
32 | 0 | c->setPricer(p); |
33 | 0 | } |
34 | 0 | } |
35 | | |
36 | | |
37 | | YoYInflationCouponPricer::YoYInflationCouponPricer( |
38 | | Handle<YieldTermStructure> nominalTermStructure) |
39 | 0 | : nominalTermStructure_(std::move(nominalTermStructure)) { |
40 | 0 | registerWith(nominalTermStructure_); |
41 | 0 | } Unexecuted instantiation: QuantLib::YoYInflationCouponPricer::YoYInflationCouponPricer(QuantLib::Handle<QuantLib::YieldTermStructure>) Unexecuted instantiation: QuantLib::YoYInflationCouponPricer::YoYInflationCouponPricer(QuantLib::Handle<QuantLib::YieldTermStructure>) |
42 | | |
43 | | YoYInflationCouponPricer::YoYInflationCouponPricer( |
44 | | Handle<YoYOptionletVolatilitySurface> capletVol, |
45 | | Handle<YieldTermStructure> nominalTermStructure) |
46 | 0 | : capletVol_(std::move(capletVol)), nominalTermStructure_(std::move(nominalTermStructure)) { |
47 | 0 | registerWith(capletVol_); |
48 | 0 | registerWith(nominalTermStructure_); |
49 | 0 | } Unexecuted instantiation: QuantLib::YoYInflationCouponPricer::YoYInflationCouponPricer(QuantLib::Handle<QuantLib::YoYOptionletVolatilitySurface>, QuantLib::Handle<QuantLib::YieldTermStructure>) Unexecuted instantiation: QuantLib::YoYInflationCouponPricer::YoYInflationCouponPricer(QuantLib::Handle<QuantLib::YoYOptionletVolatilitySurface>, QuantLib::Handle<QuantLib::YieldTermStructure>) |
50 | | |
51 | | |
52 | | void YoYInflationCouponPricer::setCapletVolatility( |
53 | 0 | const Handle<YoYOptionletVolatilitySurface>& capletVol) { |
54 | 0 | QL_REQUIRE(!capletVol.empty(),"empty capletVol handle"); |
55 | 0 | capletVol_ = capletVol; |
56 | 0 | registerWith(capletVol_); |
57 | 0 | } |
58 | | |
59 | | |
60 | 0 | Real YoYInflationCouponPricer::floorletPrice(Rate effectiveFloor) const{ |
61 | 0 | Real floorletPrice = optionletPrice(Option::Put, effectiveFloor); |
62 | 0 | return gearing_ * floorletPrice; |
63 | 0 | } |
64 | | |
65 | 0 | Real YoYInflationCouponPricer::capletPrice(Rate effectiveCap) const{ |
66 | 0 | Real capletPrice = optionletPrice(Option::Call, effectiveCap); |
67 | 0 | return gearing_ * capletPrice; |
68 | 0 | } |
69 | | |
70 | | |
71 | 0 | Rate YoYInflationCouponPricer::floorletRate(Rate effectiveFloor) const{ |
72 | 0 | return gearing_ * optionletRate(Option::Put, effectiveFloor); |
73 | 0 | } |
74 | | |
75 | 0 | Rate YoYInflationCouponPricer::capletRate(Rate effectiveCap) const{ |
76 | 0 | return gearing_ * optionletRate(Option::Call, effectiveCap); |
77 | 0 | } |
78 | | |
79 | | |
80 | | Real YoYInflationCouponPricer::optionletPriceImp( |
81 | | Option::Type, |
82 | | Real, |
83 | | Real, |
84 | 0 | Real) const { |
85 | 0 | QL_FAIL("you must implement this to get a vol-dependent price"); |
86 | 0 | } |
87 | | |
88 | | |
89 | | Real YoYInflationCouponPricer::optionletPrice(Option::Type optionType, |
90 | 0 | Real effStrike) const { |
91 | 0 | QL_REQUIRE(discount_ != Null<Real>(), "no nominal term structure provided"); |
92 | 0 | return optionletRate(optionType, effStrike) * coupon_->accrualPeriod() * discount_; |
93 | 0 | } |
94 | | |
95 | | |
96 | | Real YoYInflationCouponPricer::optionletRate(Option::Type optionType, |
97 | 0 | Real effStrike) const { |
98 | 0 | Date fixingDate = coupon_->fixingDate(); |
99 | 0 | if (fixingDate <= capletVolatility()->baseDate()) { |
100 | | // the amount is determined |
101 | 0 | Real a, b; |
102 | 0 | if (optionType==Option::Call) { |
103 | 0 | a = coupon_->indexFixing(); |
104 | 0 | b = effStrike; |
105 | 0 | } else { |
106 | 0 | a = effStrike; |
107 | 0 | b = coupon_->indexFixing(); |
108 | 0 | } |
109 | 0 | return std::max(a - b, 0.0); |
110 | 0 | } else { |
111 | | // not yet determined, use Black/DD1/Bachelier/whatever from Impl |
112 | 0 | QL_REQUIRE(!capletVolatility().empty(), "missing optionlet volatility"); |
113 | | |
114 | 0 | Real stdDev = |
115 | 0 | std::sqrt(capletVolatility()->totalVariance(fixingDate, |
116 | 0 | effStrike, |
117 | 0 | Period(0, Days))); |
118 | 0 | return optionletPriceImp(optionType, |
119 | 0 | effStrike, |
120 | 0 | adjustedFixing(), |
121 | 0 | stdDev); |
122 | 0 | } |
123 | 0 | } |
124 | | |
125 | | |
126 | 0 | Rate YoYInflationCouponPricer::adjustedFixing(Rate fixing) const { |
127 | |
|
128 | 0 | if (fixing == Null<Rate>()) |
129 | 0 | fixing = coupon_->indexFixing(); |
130 | | |
131 | | // no adjustment |
132 | 0 | return fixing; |
133 | 0 | } |
134 | | |
135 | | |
136 | 0 | void YoYInflationCouponPricer::initialize(const InflationCoupon& coupon) { |
137 | 0 | coupon_ = dynamic_cast<const YoYInflationCoupon*>(&coupon); |
138 | 0 | QL_REQUIRE(coupon_, "year-on-year inflation coupon needed"); |
139 | 0 | gearing_ = coupon_->gearing(); |
140 | 0 | spread_ = coupon_->spread(); |
141 | 0 | paymentDate_ = coupon_->date(); |
142 | | |
143 | | // past or future fixing is managed in YoYInflationIndex::fixing() |
144 | | // use yield curve from index (which sets discount) |
145 | |
|
146 | 0 | discount_ = 1.0; |
147 | 0 | if (nominalTermStructure_.empty()) { |
148 | | // allow to extract rates, but mark the discount as invalid for prices |
149 | 0 | discount_ = Null<Real>(); |
150 | 0 | } else { |
151 | 0 | if (paymentDate_ > nominalTermStructure_->referenceDate()) |
152 | 0 | discount_ = nominalTermStructure_->discount(paymentDate_); |
153 | 0 | } |
154 | 0 | } |
155 | | |
156 | | |
157 | 0 | Real YoYInflationCouponPricer::swapletPrice() const { |
158 | 0 | QL_REQUIRE(discount_ != Null<Real>(), "no nominal term structure provided"); |
159 | 0 | return swapletRate() * coupon_->accrualPeriod() * discount_; |
160 | 0 | } |
161 | | |
162 | | |
163 | 0 | Rate YoYInflationCouponPricer::swapletRate() const { |
164 | | // This way we do not require the index to have |
165 | | // a yield curve, i.e. we do not get the problem |
166 | | // that a discounting-instrument-pricer is used |
167 | | // with a different yield curve |
168 | 0 | return gearing_ * adjustedFixing() + spread_; |
169 | 0 | } |
170 | | |
171 | | |
172 | | //========================================================================= |
173 | | // vol-dependent pricers, note that these do not discount |
174 | | //========================================================================= |
175 | | |
176 | | |
177 | | |
178 | | Real BlackYoYInflationCouponPricer::optionletPriceImp(Option::Type optionType, |
179 | | Real effStrike, |
180 | | Real forward, |
181 | | Real stdDev |
182 | 0 | ) const { |
183 | |
|
184 | 0 | return blackFormula(optionType, |
185 | 0 | effStrike, |
186 | 0 | forward, |
187 | 0 | stdDev); |
188 | 0 | } |
189 | | |
190 | | Real UnitDisplacedBlackYoYInflationCouponPricer::optionletPriceImp(Option::Type optionType, |
191 | | Real effStrike, |
192 | | Real forward, |
193 | | Real stdDev |
194 | 0 | ) const { |
195 | |
|
196 | 0 | return blackFormula(optionType, |
197 | 0 | effStrike + 1.0, |
198 | 0 | forward + 1.0, |
199 | 0 | stdDev); |
200 | 0 | } |
201 | | |
202 | | Real BachelierYoYInflationCouponPricer::optionletPriceImp(Option::Type optionType, |
203 | | Real effStrike, |
204 | | Real forward, |
205 | | Real stdDev |
206 | 0 | ) const { |
207 | 0 | return bachelierBlackFormula(optionType, |
208 | 0 | effStrike, |
209 | 0 | forward, |
210 | 0 | stdDev); |
211 | 0 | } |
212 | | |
213 | | } |