1 | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
---|---|
2 | |
3 | /* |
4 | Copyright (C) 2007 Giorgio Facchinetti |
5 | Copyright (C) 2007 Cristina Duminuco |
6 | Copyright (C) 2011 Ferdinando Ametrano |
7 | Copyright (C) 2015 Peter Caspers |
8 | |
9 | This file is part of QuantLib, a free-software/open-source library |
10 | for financial quantitative analysts and developers - http://quantlib.org/ |
11 | |
12 | QuantLib is free software: you can redistribute it and/or modify it |
13 | under the terms of the QuantLib license. You should have received a |
14 | copy of the license along with this program; if not, please email |
15 | <quantlib-dev@lists.sf.net>. The license is also available online at |
16 | <http://quantlib.org/license.shtml>. |
17 | |
18 | This program is distributed in the hope that it will be useful, but WITHOUT |
19 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
20 | FOR A PARTICULAR PURPOSE. See the license for more details. |
21 | */ |
22 | |
23 | /*! \file couponpricer.hpp |
24 | \brief Coupon pricers |
25 | */ |
26 | |
27 | #ifndef quantlib_coupon_pricer_hpp |
28 | #define quantlib_coupon_pricer_hpp |
29 | |
30 | #include <ql/cashflow.hpp> |
31 | #include <ql/indexes/iborindex.hpp> |
32 | #include <ql/option.hpp> |
33 | #include <ql/optional.hpp> |
34 | #include <ql/quotes/simplequote.hpp> |
35 | #include <ql/termstructures/volatility/optionlet/optionletvolatilitystructure.hpp> |
36 | #include <ql/termstructures/volatility/swaption/swaptionvolstructure.hpp> |
37 | #include <utility> |
38 | |
39 | namespace QuantLib { |
40 | |
41 | class FloatingRateCoupon; |
42 | class IborCoupon; |
43 | |
44 | //! generic pricer for floating-rate coupons |
45 | class FloatingRateCouponPricer: public virtual Observer, |
46 | public virtual Observable { |
47 | public: |
48 | ~FloatingRateCouponPricer() override = default; |
49 | //! \name required interface |
50 | //@{ |
51 | virtual Real swapletPrice() const = 0; |
52 | virtual Rate swapletRate() const = 0; |
53 | virtual Real capletPrice(Rate effectiveCap) const = 0; |
54 | virtual Rate capletRate(Rate effectiveCap) const = 0; |
55 | virtual Real floorletPrice(Rate effectiveFloor) const = 0; |
56 | virtual Rate floorletRate(Rate effectiveFloor) const = 0; |
57 | virtual void initialize(const FloatingRateCoupon& coupon) = 0; |
58 | //@} |
59 | //! \name Observer interface |
60 | //@{ |
61 | void update() override { notifyObservers(); } |
62 | //@} |
63 | }; |
64 | |
65 | //! base pricer for capped/floored Ibor coupons |
66 | class IborCouponPricer : public FloatingRateCouponPricer { |
67 | public: |
68 | explicit IborCouponPricer( |
69 | Handle<OptionletVolatilityStructure> v = Handle<OptionletVolatilityStructure>(), |
70 | ext::optional<bool> useIndexedCoupon = ext::nullopt); |
71 | |
72 | bool useIndexedCoupon() const { return useIndexedCoupon_; } |
73 | |
74 | Handle<OptionletVolatilityStructure> capletVolatility() const { |
75 | return capletVol_; |
76 | } |
77 | void setCapletVolatility( |
78 | const Handle<OptionletVolatilityStructure>& v = |
79 | Handle<OptionletVolatilityStructure>()) { |
80 | unregisterWith(h: capletVol_); |
81 | capletVol_ = v; |
82 | registerWith(h: capletVol_); |
83 | update(); |
84 | } |
85 | void initialize(const FloatingRateCoupon& coupon) override; |
86 | |
87 | void initializeCachedData(const IborCoupon& coupon) const; |
88 | |
89 | protected: |
90 | |
91 | const IborCoupon* coupon_; |
92 | |
93 | ext::shared_ptr<IborIndex> index_; |
94 | Date fixingDate_; |
95 | Real gearing_; |
96 | Spread spread_; |
97 | Time accrualPeriod_; |
98 | |
99 | Date fixingValueDate_, fixingEndDate_, fixingMaturityDate_; |
100 | Time spanningTime_, spanningTimeIndexMaturity_; |
101 | |
102 | Handle<OptionletVolatilityStructure> capletVol_; |
103 | bool useIndexedCoupon_; |
104 | }; |
105 | |
106 | /*! Black-formula pricer for capped/floored Ibor coupons |
107 | References for timing adjustments |
108 | Black76 Hull, Options, Futures and other |
109 | derivatives, 4th ed., page 550 |
110 | BivariateLognormal http://ssrn.com/abstract=2170721 */ |
111 | class BlackIborCouponPricer : public IborCouponPricer { |
112 | public: |
113 | enum TimingAdjustment { Black76, BivariateLognormal }; |
114 | BlackIborCouponPricer( |
115 | const Handle<OptionletVolatilityStructure>& v = Handle<OptionletVolatilityStructure>(), |
116 | const TimingAdjustment timingAdjustment = Black76, |
117 | Handle<Quote> correlation = Handle<Quote>(ext::shared_ptr<Quote>(new SimpleQuote(1.0))), |
118 | const ext::optional<bool> useIndexedCoupon = ext::nullopt) |
119 | : IborCouponPricer(v, useIndexedCoupon), timingAdjustment_(timingAdjustment), |
120 | correlation_(std::move(correlation)) { |
121 | { // this additional scope seems required to avoid a misleading-indentation warning |
122 | QL_REQUIRE(timingAdjustment_ == Black76 || timingAdjustment_ == BivariateLognormal, |
123 | "unknown timing adjustment (code "<< timingAdjustment_ << ")"); |
124 | } |
125 | registerWith(h: correlation_); |
126 | }; |
127 | void initialize(const FloatingRateCoupon& coupon) override; |
128 | Real swapletPrice() const override; |
129 | Rate swapletRate() const override; |
130 | Real capletPrice(Rate effectiveCap) const override; |
131 | Rate capletRate(Rate effectiveCap) const override; |
132 | Real floorletPrice(Rate effectiveFloor) const override; |
133 | Rate floorletRate(Rate effectiveFloor) const override; |
134 | |
135 | protected: |
136 | Real optionletPrice(Option::Type optionType, Real effStrike) const; |
137 | Real optionletRate(Option::Type optionType, Real effStrike) const; |
138 | |
139 | virtual Rate adjustedFixing(Rate fixing = Null<Rate>()) const; |
140 | |
141 | Real discount_; |
142 | |
143 | private: |
144 | const TimingAdjustment timingAdjustment_; |
145 | const Handle<Quote> correlation_; |
146 | }; |
147 | |
148 | //! base pricer for vanilla CMS coupons |
149 | class CmsCouponPricer : public FloatingRateCouponPricer { |
150 | public: |
151 | explicit CmsCouponPricer( |
152 | Handle<SwaptionVolatilityStructure> v = Handle<SwaptionVolatilityStructure>()) |
153 | : swaptionVol_(std::move(v)) { |
154 | registerWith(h: swaptionVol_); |
155 | } |
156 | |
157 | Handle<SwaptionVolatilityStructure> swaptionVolatility() const{ |
158 | return swaptionVol_; |
159 | } |
160 | void setSwaptionVolatility( |
161 | const Handle<SwaptionVolatilityStructure>& v= |
162 | Handle<SwaptionVolatilityStructure>()) { |
163 | unregisterWith(h: swaptionVol_); |
164 | swaptionVol_ = v; |
165 | registerWith(h: swaptionVol_); |
166 | update(); |
167 | } |
168 | private: |
169 | Handle<SwaptionVolatilityStructure> swaptionVol_; |
170 | }; |
171 | |
172 | /*! (CMS) coupon pricer that has a mean reversion parameter which can be |
173 | used to calibrate to cms market quotes */ |
174 | class MeanRevertingPricer { |
175 | public: |
176 | virtual Real meanReversion() const = 0; |
177 | virtual void setMeanReversion(const Handle<Quote>&) = 0; |
178 | virtual ~MeanRevertingPricer() = default; |
179 | }; |
180 | |
181 | void setCouponPricer(const Leg& leg, |
182 | const ext::shared_ptr<FloatingRateCouponPricer>&); |
183 | |
184 | void setCouponPricers( |
185 | const Leg& leg, |
186 | const std::vector<ext::shared_ptr<FloatingRateCouponPricer> >&); |
187 | |
188 | /*! set the first matching pricer (if any) to each coupon of the leg */ |
189 | void setCouponPricers( |
190 | const Leg& leg, |
191 | const ext::shared_ptr<FloatingRateCouponPricer>&, |
192 | const ext::shared_ptr<FloatingRateCouponPricer>&); |
193 | |
194 | void setCouponPricers( |
195 | const Leg& leg, |
196 | const ext::shared_ptr<FloatingRateCouponPricer>&, |
197 | const ext::shared_ptr<FloatingRateCouponPricer>&, |
198 | const ext::shared_ptr<FloatingRateCouponPricer>&); |
199 | |
200 | void setCouponPricers( |
201 | const Leg& leg, |
202 | const ext::shared_ptr<FloatingRateCouponPricer>&, |
203 | const ext::shared_ptr<FloatingRateCouponPricer>&, |
204 | const ext::shared_ptr<FloatingRateCouponPricer>&, |
205 | const ext::shared_ptr<FloatingRateCouponPricer>&); |
206 | |
207 | // inline |
208 | |
209 | inline Real BlackIborCouponPricer::swapletPrice() const { |
210 | // past or future fixing is managed in InterestRateIndex::fixing() |
211 | QL_REQUIRE(discount_ != Null<Rate>(), "no forecast curve provided"); |
212 | return swapletRate() * accrualPeriod_ * discount_; |
213 | } |
214 | |
215 | inline Rate BlackIborCouponPricer::swapletRate() const { |
216 | return gearing_ * adjustedFixing() + spread_; |
217 | } |
218 | |
219 | inline Real BlackIborCouponPricer::capletPrice(Rate effectiveCap) const { |
220 | QL_REQUIRE(discount_ != Null<Rate>(), "no forecast curve provided"); |
221 | return capletRate(effectiveCap) * accrualPeriod_ * discount_; |
222 | } |
223 | |
224 | inline Rate BlackIborCouponPricer::capletRate(Rate effectiveCap) const { |
225 | return gearing_ * optionletRate(optionType: Option::Call, effStrike: effectiveCap); |
226 | } |
227 | |
228 | inline |
229 | Real BlackIborCouponPricer::floorletPrice(Rate effectiveFloor) const { |
230 | QL_REQUIRE(discount_ != Null<Rate>(), "no forecast curve provided"); |
231 | return floorletRate(effectiveFloor) * accrualPeriod_ * discount_; |
232 | } |
233 | |
234 | inline |
235 | Rate BlackIborCouponPricer::floorletRate(Rate effectiveFloor) const { |
236 | return gearing_ * optionletRate(optionType: Option::Put, effStrike: effectiveFloor); |
237 | } |
238 | |
239 | } |
240 | |
241 | #endif |
242 |
Definitions
- FloatingRateCouponPricer
- ~FloatingRateCouponPricer
- update
- IborCouponPricer
- useIndexedCoupon
- capletVolatility
- setCapletVolatility
- BlackIborCouponPricer
- TimingAdjustment
- BlackIborCouponPricer
- CmsCouponPricer
- CmsCouponPricer
- swaptionVolatility
- setSwaptionVolatility
- MeanRevertingPricer
- ~MeanRevertingPricer
- swapletPrice
- swapletRate
- capletPrice
- capletRate
- floorletPrice
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more