1 | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | |
3 | /* |
4 | Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl |
5 | Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 StatPro Italia srl |
6 | Copyright (C) 2007, 2008, 2009, 2015 Ferdinando Ametrano |
7 | Copyright (C) 2007, 2009 Roland Lichters |
8 | Copyright (C) 2015 Maddalena Zanzi |
9 | Copyright (C) 2015 Paolo Mazzocchi |
10 | Copyright (C) 2018 Matthias Lungwitz |
11 | |
12 | This file is part of QuantLib, a free-software/open-source library |
13 | for financial quantitative analysts and developers - http://quantlib.org/ |
14 | |
15 | QuantLib is free software: you can redistribute it and/or modify it |
16 | under the terms of the QuantLib license. You should have received a |
17 | copy of the license along with this program; if not, please email |
18 | <quantlib-dev@lists.sf.net>. The license is also available online at |
19 | <http://quantlib.org/license.shtml>. |
20 | |
21 | This program is distributed in the hope that it will be useful, but WITHOUT |
22 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
23 | FOR A PARTICULAR PURPOSE. See the license for more details. |
24 | */ |
25 | |
26 | /*! \file ratehelpers.hpp |
27 | \brief deposit, FRA, futures, and various swap rate helpers |
28 | */ |
29 | |
30 | #ifndef quantlib_ratehelpers_hpp |
31 | #define quantlib_ratehelpers_hpp |
32 | |
33 | #include <ql/termstructures/bootstraphelper.hpp> |
34 | #include <ql/instruments/vanillaswap.hpp> |
35 | #include <ql/instruments/bmaswap.hpp> |
36 | #include <ql/instruments/futures.hpp> |
37 | #include <ql/time/calendar.hpp> |
38 | #include <ql/time/daycounter.hpp> |
39 | #include <ql/time/calendars/unitedstates.hpp> |
40 | #include <ql/optional.hpp> |
41 | |
42 | namespace QuantLib { |
43 | |
44 | class SwapIndex; |
45 | class Quote; |
46 | |
47 | typedef BootstrapHelper<YieldTermStructure> RateHelper; |
48 | typedef RelativeDateBootstrapHelper<YieldTermStructure> |
49 | RelativeDateRateHelper; |
50 | |
51 | //! Rate helper for bootstrapping over IborIndex futures prices |
52 | class FuturesRateHelper : public RateHelper { |
53 | public: |
54 | FuturesRateHelper(const Handle<Quote>& price, |
55 | const Date& iborStartDate, |
56 | Natural lengthInMonths, |
57 | const Calendar& calendar, |
58 | BusinessDayConvention convention, |
59 | bool endOfMonth, |
60 | const DayCounter& dayCounter, |
61 | Handle<Quote> convexityAdjustment = {}, |
62 | Futures::Type type = Futures::IMM); |
63 | FuturesRateHelper(Real price, |
64 | const Date& iborStartDate, |
65 | Natural lengthInMonths, |
66 | const Calendar& calendar, |
67 | BusinessDayConvention convention, |
68 | bool endOfMonth, |
69 | const DayCounter& dayCounter, |
70 | Rate convexityAdjustment = 0.0, |
71 | Futures::Type type = Futures::IMM); |
72 | FuturesRateHelper(const Handle<Quote>& price, |
73 | const Date& iborStartDate, |
74 | const Date& iborEndDate, |
75 | const DayCounter& dayCounter, |
76 | Handle<Quote> convexityAdjustment = {}, |
77 | Futures::Type type = Futures::IMM); |
78 | FuturesRateHelper(Real price, |
79 | const Date& iborStartDate, |
80 | const Date& endDate, |
81 | const DayCounter& dayCounter, |
82 | Rate convexityAdjustment = 0.0, |
83 | Futures::Type type = Futures::IMM); |
84 | FuturesRateHelper(const Handle<Quote>& price, |
85 | const Date& iborStartDate, |
86 | const ext::shared_ptr<IborIndex>& iborIndex, |
87 | const Handle<Quote>& convexityAdjustment = {}, |
88 | Futures::Type type = Futures::IMM); |
89 | FuturesRateHelper(Real price, |
90 | const Date& iborStartDate, |
91 | const ext::shared_ptr<IborIndex>& iborIndex, |
92 | Rate convexityAdjustment = 0.0, |
93 | Futures::Type type = Futures::IMM); |
94 | //! \name RateHelper interface |
95 | //@{ |
96 | Real impliedQuote() const override; |
97 | //@} |
98 | //! \name FuturesRateHelper inspectors |
99 | //@{ |
100 | Real convexityAdjustment() const; |
101 | //@} |
102 | //! \name Visitability |
103 | //@{ |
104 | void accept(AcyclicVisitor&) override; |
105 | //@} |
106 | private: |
107 | Time yearFraction_; |
108 | Handle<Quote> convAdj_; |
109 | }; |
110 | |
111 | |
112 | //! Rate helper for bootstrapping over deposit rates |
113 | class DepositRateHelper : public RelativeDateRateHelper { |
114 | public: |
115 | DepositRateHelper(const Handle<Quote>& rate, |
116 | const Period& tenor, |
117 | Natural fixingDays, |
118 | const Calendar& calendar, |
119 | BusinessDayConvention convention, |
120 | bool endOfMonth, |
121 | const DayCounter& dayCounter); |
122 | DepositRateHelper(Rate rate, |
123 | const Period& tenor, |
124 | Natural fixingDays, |
125 | const Calendar& calendar, |
126 | BusinessDayConvention convention, |
127 | bool endOfMonth, |
128 | const DayCounter& dayCounter); |
129 | DepositRateHelper(const Handle<Quote>& rate, |
130 | const ext::shared_ptr<IborIndex>& iborIndex); |
131 | DepositRateHelper(Rate rate, |
132 | const ext::shared_ptr<IborIndex>& iborIndex); |
133 | //! \name RateHelper interface |
134 | //@{ |
135 | Real impliedQuote() const override; |
136 | void setTermStructure(YieldTermStructure*) override; |
137 | //@} |
138 | //! \name Visitability |
139 | //@{ |
140 | void accept(AcyclicVisitor&) override; |
141 | //@} |
142 | private: |
143 | void initializeDates() override; |
144 | Date fixingDate_; |
145 | ext::shared_ptr<IborIndex> iborIndex_; |
146 | RelinkableHandle<YieldTermStructure> termStructureHandle_; |
147 | }; |
148 | |
149 | |
150 | //! Rate helper for bootstrapping over %FRA rates |
151 | class FraRateHelper : public RelativeDateRateHelper { |
152 | public: |
153 | FraRateHelper(const Handle<Quote>& rate, |
154 | Natural monthsToStart, |
155 | Natural monthsToEnd, |
156 | Natural fixingDays, |
157 | const Calendar& calendar, |
158 | BusinessDayConvention convention, |
159 | bool endOfMonth, |
160 | const DayCounter& dayCounter, |
161 | Pillar::Choice pillar = Pillar::LastRelevantDate, |
162 | Date customPillarDate = Date(), |
163 | bool useIndexedCoupon = true); |
164 | FraRateHelper(Rate rate, |
165 | Natural monthsToStart, |
166 | Natural monthsToEnd, |
167 | Natural fixingDays, |
168 | const Calendar& calendar, |
169 | BusinessDayConvention convention, |
170 | bool endOfMonth, |
171 | const DayCounter& dayCounter, |
172 | Pillar::Choice pillar = Pillar::LastRelevantDate, |
173 | Date customPillarDate = Date(), |
174 | bool useIndexedCoupon = true); |
175 | FraRateHelper(const Handle<Quote>& rate, |
176 | Natural monthsToStart, |
177 | const ext::shared_ptr<IborIndex>& iborIndex, |
178 | Pillar::Choice pillar = Pillar::LastRelevantDate, |
179 | Date customPillarDate = Date(), |
180 | bool useIndexedCoupon = true); |
181 | FraRateHelper(Rate rate, |
182 | Natural monthsToStart, |
183 | const ext::shared_ptr<IborIndex>& iborIndex, |
184 | Pillar::Choice pillar = Pillar::LastRelevantDate, |
185 | Date customPillarDate = Date(), |
186 | bool useIndexedCoupon = true); |
187 | FraRateHelper(const Handle<Quote>& rate, |
188 | Period periodToStart, |
189 | Natural lengthInMonths, |
190 | Natural fixingDays, |
191 | const Calendar& calendar, |
192 | BusinessDayConvention convention, |
193 | bool endOfMonth, |
194 | const DayCounter& dayCounter, |
195 | Pillar::Choice pillar = Pillar::LastRelevantDate, |
196 | Date customPillarDate = Date(), |
197 | bool useIndexedCoupon = true); |
198 | FraRateHelper(Rate rate, |
199 | Period periodToStart, |
200 | Natural lengthInMonths, |
201 | Natural fixingDays, |
202 | const Calendar& calendar, |
203 | BusinessDayConvention convention, |
204 | bool endOfMonth, |
205 | const DayCounter& dayCounter, |
206 | Pillar::Choice pillar = Pillar::LastRelevantDate, |
207 | Date customPillarDate = Date(), |
208 | bool useIndexedCoupon = true); |
209 | FraRateHelper(const Handle<Quote>& rate, |
210 | Period periodToStart, |
211 | const ext::shared_ptr<IborIndex>& iborIndex, |
212 | Pillar::Choice pillar = Pillar::LastRelevantDate, |
213 | Date customPillarDate = Date(), |
214 | bool useIndexedCoupon = true); |
215 | FraRateHelper(Rate rate, |
216 | Period periodToStart, |
217 | const ext::shared_ptr<IborIndex>& iborIndex, |
218 | Pillar::Choice pillar = Pillar::LastRelevantDate, |
219 | Date customPillarDate = Date(), |
220 | bool useIndexedCoupon = true); |
221 | FraRateHelper(const Handle<Quote>& rate, |
222 | Natural immOffsetStart, |
223 | Natural immOffsetEnd, |
224 | const ext::shared_ptr<IborIndex>& iborIndex, |
225 | Pillar::Choice pillar = Pillar::LastRelevantDate, |
226 | Date customPillarDate = Date(), |
227 | bool useIndexedCoupon = true); |
228 | FraRateHelper(Rate rate, |
229 | Natural immOffsetStart, |
230 | Natural immOffsetEnd, |
231 | const ext::shared_ptr<IborIndex>& iborIndex, |
232 | Pillar::Choice pillar = Pillar::LastRelevantDate, |
233 | Date customPillarDate = Date(), |
234 | bool useIndexedCoupon = true); |
235 | //! \name RateHelper interface |
236 | //@{ |
237 | Real impliedQuote() const override; |
238 | void setTermStructure(YieldTermStructure*) override; |
239 | //@} |
240 | //! \name Visitability |
241 | //@{ |
242 | void accept(AcyclicVisitor&) override; |
243 | //@} |
244 | private: |
245 | void initializeDates() override; |
246 | Date fixingDate_; |
247 | ext::optional<Period> periodToStart_; |
248 | ext::optional<Natural> immOffsetStart_, immOffsetEnd_; |
249 | Pillar::Choice pillarChoice_; |
250 | ext::shared_ptr<IborIndex> iborIndex_; |
251 | RelinkableHandle<YieldTermStructure> termStructureHandle_; |
252 | bool useIndexedCoupon_; |
253 | Real spanningTime_; |
254 | }; |
255 | |
256 | |
257 | //! Rate helper for bootstrapping over swap rates |
258 | /*! \todo use input SwapIndex to create the swap */ |
259 | class SwapRateHelper : public RelativeDateRateHelper { |
260 | public: |
261 | SwapRateHelper(const Handle<Quote>& rate, |
262 | const ext::shared_ptr<SwapIndex>& swapIndex, |
263 | Handle<Quote> spread = {}, |
264 | const Period& fwdStart = 0 * Days, |
265 | // exogenous discounting curve |
266 | Handle<YieldTermStructure> discountingCurve = {}, |
267 | Pillar::Choice pillar = Pillar::LastRelevantDate, |
268 | Date customPillarDate = Date(), |
269 | bool endOfMonth = false, |
270 | const ext::optional<bool>& useIndexedCoupons = ext::nullopt); |
271 | SwapRateHelper(const Handle<Quote>& rate, |
272 | const Period& tenor, |
273 | Calendar calendar, |
274 | // fixed leg |
275 | Frequency fixedFrequency, |
276 | BusinessDayConvention fixedConvention, |
277 | DayCounter fixedDayCount, |
278 | // floating leg |
279 | const ext::shared_ptr<IborIndex>& iborIndex, |
280 | Handle<Quote> spread = {}, |
281 | const Period& fwdStart = 0 * Days, |
282 | // exogenous discounting curve |
283 | Handle<YieldTermStructure> discountingCurve = {}, |
284 | Natural settlementDays = Null<Natural>(), |
285 | Pillar::Choice pillar = Pillar::LastRelevantDate, |
286 | Date customPillarDate = Date(), |
287 | bool endOfMonth = false, |
288 | const ext::optional<bool>& useIndexedCoupons = ext::nullopt); |
289 | SwapRateHelper(Rate rate, |
290 | const ext::shared_ptr<SwapIndex>& swapIndex, |
291 | Handle<Quote> spread = {}, |
292 | const Period& fwdStart = 0 * Days, |
293 | // exogenous discounting curve |
294 | Handle<YieldTermStructure> discountingCurve = {}, |
295 | Pillar::Choice pillar = Pillar::LastRelevantDate, |
296 | Date customPillarDate = Date(), |
297 | bool endOfMonth = false, |
298 | const ext::optional<bool>& useIndexedCoupons = ext::nullopt); |
299 | SwapRateHelper(Rate rate, |
300 | const Period& tenor, |
301 | Calendar calendar, |
302 | // fixed leg |
303 | Frequency fixedFrequency, |
304 | BusinessDayConvention fixedConvention, |
305 | DayCounter fixedDayCount, |
306 | // floating leg |
307 | const ext::shared_ptr<IborIndex>& iborIndex, |
308 | Handle<Quote> spread = {}, |
309 | const Period& fwdStart = 0 * Days, |
310 | // exogenous discounting curve |
311 | Handle<YieldTermStructure> discountingCurve = {}, |
312 | Natural settlementDays = Null<Natural>(), |
313 | Pillar::Choice pillar = Pillar::LastRelevantDate, |
314 | Date customPillarDate = Date(), |
315 | bool endOfMonth = false, |
316 | const ext::optional<bool>& useIndexedCoupons = ext::nullopt); |
317 | //! \name RateHelper interface |
318 | //@{ |
319 | Real impliedQuote() const override; |
320 | void setTermStructure(YieldTermStructure*) override; |
321 | //@} |
322 | //! \name SwapRateHelper inspectors |
323 | //@{ |
324 | Spread spread() const; |
325 | // NOLINTNEXTLINE(cppcoreguidelines-noexcept-swap,performance-noexcept-swap) |
326 | ext::shared_ptr<VanillaSwap> swap() const; |
327 | const Period& forwardStart() const; |
328 | //@} |
329 | //! \name Visitability |
330 | //@{ |
331 | void accept(AcyclicVisitor&) override; |
332 | //@} |
333 | protected: |
334 | void initializeDates() override; |
335 | Natural settlementDays_; |
336 | Period tenor_; |
337 | Pillar::Choice pillarChoice_; |
338 | Calendar calendar_; |
339 | BusinessDayConvention fixedConvention_; |
340 | Frequency fixedFrequency_; |
341 | DayCounter fixedDayCount_; |
342 | ext::shared_ptr<IborIndex> iborIndex_; |
343 | ext::shared_ptr<VanillaSwap> swap_; |
344 | RelinkableHandle<YieldTermStructure> termStructureHandle_; |
345 | Handle<Quote> spread_; |
346 | bool endOfMonth_; |
347 | Period fwdStart_; |
348 | Handle<YieldTermStructure> discountHandle_; |
349 | RelinkableHandle<YieldTermStructure> discountRelinkableHandle_; |
350 | ext::optional<bool> useIndexedCoupons_; |
351 | }; |
352 | |
353 | |
354 | //! Rate helper for bootstrapping over BMA swap rates |
355 | class BMASwapRateHelper : public RelativeDateRateHelper { |
356 | public: |
357 | BMASwapRateHelper(const Handle<Quote>& liborFraction, |
358 | const Period& tenor, // swap maturity |
359 | Natural settlementDays, |
360 | Calendar calendar, |
361 | // bma leg |
362 | const Period& bmaPeriod, |
363 | BusinessDayConvention bmaConvention, |
364 | DayCounter bmaDayCount, |
365 | ext::shared_ptr<BMAIndex> bmaIndex, |
366 | // ibor leg |
367 | ext::shared_ptr<IborIndex> index); |
368 | //! \name RateHelper interface |
369 | //@{ |
370 | Real impliedQuote() const override; |
371 | void setTermStructure(YieldTermStructure*) override; |
372 | //@} |
373 | //! \name Visitability |
374 | //@{ |
375 | void accept(AcyclicVisitor&) override; |
376 | //@} |
377 | protected: |
378 | void initializeDates() override; |
379 | Period tenor_; |
380 | Natural settlementDays_; |
381 | Calendar calendar_; |
382 | Period bmaPeriod_; |
383 | BusinessDayConvention bmaConvention_; |
384 | DayCounter bmaDayCount_; |
385 | ext::shared_ptr<BMAIndex> bmaIndex_; |
386 | ext::shared_ptr<IborIndex> iborIndex_; |
387 | |
388 | ext::shared_ptr<BMASwap> swap_; |
389 | RelinkableHandle<YieldTermStructure> termStructureHandle_; |
390 | }; |
391 | |
392 | |
393 | //! Rate helper for bootstrapping over Fx Swap rates |
394 | /*! The forward is given by `fwdFx = spotFx + fwdPoint`. |
395 | |
396 | `isFxBaseCurrencyCollateralCurrency` indicates if the base |
397 | currency of the FX currency pair is the one used as collateral. |
398 | |
399 | `calendar` is usually the joint calendar of the two currencies |
400 | in the pair. |
401 | |
402 | `tradingCalendar` can be used when the cross pairs don't |
403 | include the currency of the business center (usually USD; the |
404 | corresponding calendar is `UnitedStates`). If given, it will |
405 | be used for adjusting the earliest settlement date and for |
406 | setting the latest date. Due to FX spot market conventions, it |
407 | is not sufficient to pass a JointCalendar with UnitedStates |
408 | included as `calendar`; with regard the earliest date, this |
409 | calendar is only used in case the spot date of the two |
410 | currencies is not a US business day. |
411 | |
412 | \warning The ON fx swaps can be achieved by setting |
413 | `fixingDays` to 0 and using a tenor of '1d'. The same |
414 | tenor should be used for TN swaps, with `fixingDays` |
415 | set to 1. However, handling ON and TN swaps for |
416 | cross rates without USD is not trivial and should be |
417 | treated with caution. If today is a US holiday, ON |
418 | trade is not possible. If tomorrow is a US Holiday, |
419 | the ON trade will be at least two business days long |
420 | in the other countries and the TN trade will not |
421 | exist. In such cases, if this helper is used for |
422 | curve construction, probably it is safer not to pass |
423 | a trading calendar to the ON and TN helpers and |
424 | provide fwdPoints that will yield proper level of |
425 | discount factors. |
426 | */ |
427 | class FxSwapRateHelper : public RelativeDateRateHelper { |
428 | public: |
429 | FxSwapRateHelper(const Handle<Quote>& fwdPoint, |
430 | Handle<Quote> spotFx, |
431 | const Period& tenor, |
432 | Natural fixingDays, |
433 | Calendar calendar, |
434 | BusinessDayConvention convention, |
435 | bool endOfMonth, |
436 | bool isFxBaseCurrencyCollateralCurrency, |
437 | Handle<YieldTermStructure> collateralCurve, |
438 | Calendar tradingCalendar = Calendar()); |
439 | //! \name RateHelper interface |
440 | //@{ |
441 | Real impliedQuote() const override; |
442 | void setTermStructure(YieldTermStructure*) override; |
443 | //@} |
444 | //! \name FxSwapRateHelper inspectors |
445 | //@{ |
446 | Real spot() const { return spot_->value(); } |
447 | Period tenor() const { return tenor_; } |
448 | Natural fixingDays() const { return fixingDays_; } |
449 | Calendar calendar() const { return cal_; } |
450 | BusinessDayConvention businessDayConvention() const { return conv_; } |
451 | bool endOfMonth() const { return eom_; } |
452 | bool isFxBaseCurrencyCollateralCurrency() const { |
453 | return isFxBaseCurrencyCollateralCurrency_; } |
454 | Calendar tradingCalendar() const { return tradingCalendar_; } |
455 | Calendar adjustmentCalendar() const { return jointCalendar_; } |
456 | //@} |
457 | //! \name Visitability |
458 | //@{ |
459 | void accept(AcyclicVisitor&) override; |
460 | //@} |
461 | private: |
462 | void initializeDates() override; |
463 | Handle<Quote> spot_; |
464 | Period tenor_; |
465 | Natural fixingDays_; |
466 | Calendar cal_; |
467 | BusinessDayConvention conv_; |
468 | bool eom_; |
469 | bool isFxBaseCurrencyCollateralCurrency_; |
470 | |
471 | RelinkableHandle<YieldTermStructure> termStructureHandle_; |
472 | |
473 | Handle<YieldTermStructure> collHandle_; |
474 | RelinkableHandle<YieldTermStructure> collRelinkableHandle_; |
475 | |
476 | Calendar tradingCalendar_; |
477 | Calendar jointCalendar_; |
478 | }; |
479 | |
480 | // inline |
481 | |
482 | inline Spread SwapRateHelper::spread() const { |
483 | return spread_.empty() ? 0.0 : spread_->value(); |
484 | } |
485 | |
486 | // NOLINTNEXTLINE(cppcoreguidelines-noexcept-swap,performance-noexcept-swap) |
487 | inline ext::shared_ptr<VanillaSwap> SwapRateHelper::swap() const { |
488 | return swap_; |
489 | } |
490 | |
491 | inline const Period& SwapRateHelper::forwardStart() const { |
492 | return fwdStart_; |
493 | } |
494 | |
495 | } |
496 | |
497 | #endif |
498 | |