QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
ratehelpers.cpp
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#include <ql/cashflows/iborcoupon.hpp>
27#include <ql/currency.hpp>
28#include <ql/indexes/swapindex.hpp>
29#include <ql/instruments/makevanillaswap.hpp>
30#include <ql/instruments/simplifynotificationgraph.hpp>
31#include <ql/pricingengines/swap/discountingswapengine.hpp>
32#include <ql/quote.hpp>
33#include <ql/termstructures/yield/ratehelpers.hpp>
34#include <ql/time/asx.hpp>
35#include <ql/time/calendars/jointcalendar.hpp>
36#include <ql/time/calendars/unitedstates.hpp>
37#include <ql/time/imm.hpp>
38#include <ql/utilities/null_deleter.hpp>
39#include <ql/optional.hpp>
40#include <utility>
41
42namespace QuantLib {
43
45 const Date& iborStartDate,
46 Natural lengthInMonths,
47 const Calendar& calendar,
48 BusinessDayConvention convention,
49 bool endOfMonth,
50 const DayCounter& dayCounter,
51 Handle<Quote> convAdj,
52 Futures::Type type)
53 : RateHelper(price), convAdj_(std::move(convAdj)) {
54 switch (type) {
55 case Futures::IMM:
56 QL_REQUIRE(IMM::isIMMdate(iborStartDate, false),
57 iborStartDate << " is not a valid IMM date");
58 break;
59 case Futures::ASX:
60 QL_REQUIRE(ASX::isASXdate(iborStartDate, false),
61 iborStartDate << " is not a valid ASX date");
62 break;
63 default:
64 QL_FAIL("unknown futures type (" << Integer(type) << ")");
65 }
66 earliestDate_ = iborStartDate;
67 maturityDate_ = calendar.advance(iborStartDate, lengthInMonths*Months,
68 convention, endOfMonth);
71
73 }
74
76 const Date& iborStartDate,
77 Natural lengthInMonths,
78 const Calendar& calendar,
79 BusinessDayConvention convention,
80 bool endOfMonth,
81 const DayCounter& dayCounter,
82 Rate convAdj,
83 Futures::Type type)
84 : RateHelper(price),
85 convAdj_(Handle<Quote>(ext::shared_ptr<Quote>(new SimpleQuote(convAdj))))
86 {
87 switch (type) {
88 case Futures::IMM:
89 QL_REQUIRE(IMM::isIMMdate(iborStartDate, false),
90 iborStartDate << " is not a valid IMM date");
91 break;
92 case Futures::ASX:
93 QL_REQUIRE(ASX::isASXdate(iborStartDate, false),
94 iborStartDate << " is not a valid ASX date");
95 break;
96 default:
97 QL_FAIL("unknown futures type (" << Integer(type) << ")");
98 }
99 earliestDate_ = iborStartDate;
100 maturityDate_ = calendar.advance(iborStartDate, lengthInMonths*Months,
101 convention, endOfMonth);
104 }
105
107 const Date& iborStartDate,
108 const Date& iborEndDate,
109 const DayCounter& dayCounter,
110 Handle<Quote> convAdj,
111 Futures::Type type)
112 : RateHelper(price), convAdj_(std::move(convAdj)) {
113 switch (type) {
114 case Futures::IMM:
115 QL_REQUIRE(IMM::isIMMdate(iborStartDate, false),
116 iborStartDate << " is not a valid IMM date");
117 if (iborEndDate == Date()) {
118 // advance 3 months
119 maturityDate_ = IMM::nextDate(iborStartDate, false);
122 }
123 else {
124 QL_REQUIRE(iborEndDate>iborStartDate,
125 "end date (" << iborEndDate <<
126 ") must be greater than start date (" <<
127 iborStartDate << ")");
128 maturityDate_ = iborEndDate;
129 }
130 break;
131 case Futures::ASX:
132 QL_REQUIRE(ASX::isASXdate(iborStartDate, false),
133 iborStartDate << " is not a valid ASX date");
134 if (iborEndDate == Date()) {
135 // advance 3 months
136 maturityDate_ = ASX::nextDate(iborStartDate, false);
139 }
140 else {
141 QL_REQUIRE(iborEndDate>iborStartDate,
142 "end date (" << iborEndDate <<
143 ") must be greater than start date (" <<
144 iborStartDate << ")");
145 maturityDate_ = iborEndDate;
146 }
147 break;
148 default:
149 QL_FAIL("unknown futures type (" << Integer(type) << ")");
150 }
151 earliestDate_ = iborStartDate;
154
156 }
157
159 const Date& iborStartDate,
160 const Date& iborEndDate,
161 const DayCounter& dayCounter,
162 Rate convAdj,
163 Futures::Type type)
164 : RateHelper(price),
165 convAdj_(Handle<Quote>(ext::shared_ptr<Quote>(new SimpleQuote(convAdj))))
166 {
167 switch (type) {
168 case Futures::IMM:
169 QL_REQUIRE(IMM::isIMMdate(iborStartDate, false),
170 iborStartDate << " is not a valid IMM date");
171 if (iborEndDate == Date()) {
172 // advance 3 months
173 maturityDate_ = IMM::nextDate(iborStartDate, false);
176 }
177 else {
178 QL_REQUIRE(iborEndDate>iborStartDate,
179 "end date (" << iborEndDate <<
180 ") must be greater than start date (" <<
181 iborStartDate << ")");
182 maturityDate_ = iborEndDate;
183 }
184 break;
185 case Futures::ASX:
186 QL_REQUIRE(ASX::isASXdate(iborStartDate, false),
187 iborStartDate << " is not a valid ASX date");
188 if (iborEndDate == Date()) {
189 // advance 3 months
190 maturityDate_ = ASX::nextDate(iborStartDate, false);
193 }
194 else {
195 QL_REQUIRE(iborEndDate>iborStartDate,
196 "end date (" << iborEndDate <<
197 ") must be greater than start date (" <<
198 iborStartDate << ")");
199 maturityDate_ = iborEndDate;
200 }
201 break;
202 default:
203 QL_FAIL("unknown futures type (" << Integer(type) << ")");
204 }
205 earliestDate_ = iborStartDate;
208 }
209
211 const Date& iborStartDate,
212 const ext::shared_ptr<IborIndex>& i,
213 const Handle<Quote>& convAdj,
214 Futures::Type type)
215 : RateHelper(price), convAdj_(convAdj) {
216 switch (type) {
217 case Futures::IMM:
218 QL_REQUIRE(IMM::isIMMdate(iborStartDate, false),
219 iborStartDate << " is not a valid IMM date");
220 break;
221 case Futures::ASX:
222 QL_REQUIRE(ASX::isASXdate(iborStartDate, false),
223 iborStartDate << " is not a valid ASX date");
224 break;
225 default:
226 QL_FAIL("unknown futures type (" << Integer(type) << ")");
227 }
228 earliestDate_ = iborStartDate;
229 const Calendar& cal = i->fixingCalendar();
230 maturityDate_ = cal.advance(iborStartDate, i->tenor(),
231 i->businessDayConvention());
232 yearFraction_ = i->dayCounter().yearFraction(earliestDate_,
235
236 registerWith(convAdj);
237 }
238
240 const Date& iborStartDate,
241 const ext::shared_ptr<IborIndex>& i,
242 Rate convAdj,
243 Futures::Type type)
244 : RateHelper(price),
245 convAdj_(Handle<Quote>(ext::shared_ptr<Quote>(new SimpleQuote(convAdj))))
246 {
247 switch (type) {
248 case Futures::IMM:
249 QL_REQUIRE(IMM::isIMMdate(iborStartDate, false),
250 iborStartDate << " is not a valid IMM date");
251 break;
252 case Futures::ASX:
253 QL_REQUIRE(ASX::isASXdate(iborStartDate, false),
254 iborStartDate << " is not a valid ASX date");
255 break;
256 default:
257 QL_FAIL("unknown futures type (" << Integer(type) << ")");
258 }
259 earliestDate_ = iborStartDate;
260 const Calendar& cal = i->fixingCalendar();
261 maturityDate_ = cal.advance(iborStartDate, i->tenor(),
262 i->businessDayConvention());
263 yearFraction_ = i->dayCounter().yearFraction(earliestDate_,
266 }
267
269 QL_REQUIRE(termStructure_ != nullptr, "term structure not set");
270 Rate forwardRate = (termStructure_->discount(earliestDate_) /
271 termStructure_->discount(maturityDate_) - 1.0) / yearFraction_;
272 Rate convAdj = convAdj_.empty() ? 0.0 : convAdj_->value();
273 // Convexity, as FRA/futures adjustment, has been used in the
274 // past to take into account futures margining vs FRA.
275 // Therefore, there's no requirement for it to be non-negative.
276 Rate futureRate = forwardRate + convAdj;
277 return 100.0 * (1.0 - futureRate);
278 }
279
281 return convAdj_.empty() ? 0.0 : convAdj_->value();
282 }
283
285 auto* v1 = dynamic_cast<Visitor<FuturesRateHelper>*>(&v);
286 if (v1 != nullptr)
287 v1->visit(*this);
288 else
290 }
291
293 const Period& tenor,
294 Natural fixingDays,
295 const Calendar& calendar,
296 BusinessDayConvention convention,
297 bool endOfMonth,
298 const DayCounter& dayCounter)
299 : RelativeDateRateHelper(rate) {
300 iborIndex_ = ext::make_shared<IborIndex>("no-fix", // never take fixing into account
301 tenor, fixingDays,
302 Currency(), calendar, convention,
303 endOfMonth, dayCounter, termStructureHandle_);
305 }
306
308 const Period& tenor,
309 Natural fixingDays,
310 const Calendar& calendar,
311 BusinessDayConvention convention,
312 bool endOfMonth,
313 const DayCounter& dayCounter)
314 : RelativeDateRateHelper(rate) {
315 iborIndex_ = ext::make_shared<IborIndex>("no-fix", // never take fixing into account
316 tenor, fixingDays,
317 Currency(), calendar, convention,
318 endOfMonth, dayCounter, termStructureHandle_);
320 }
321
323 const ext::shared_ptr<IborIndex>& i)
324 : RelativeDateRateHelper(rate) {
327 }
328
330 const ext::shared_ptr<IborIndex>& i)
331 : RelativeDateRateHelper(rate) {
334 }
335
337 QL_REQUIRE(termStructure_ != nullptr, "term structure not set");
338 // the forecast fixing flag is set to true because
339 // we do not want to take fixing into account
340 return iborIndex_->fixing(fixingDate_, true);
341 }
342
344 // do not set the relinkable handle as an observer -
345 // force recalculation when needed---the index is not lazy
346 bool observer = false;
347
348 ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
349 termStructureHandle_.linkTo(temp, observer);
350
352 }
353
355 // if the evaluation date is not a business day
356 // then move to the next business day
357 Date referenceDate =
358 iborIndex_->fixingCalendar().adjust(evaluationDate_);
359 earliestDate_ = iborIndex_->valueDate(referenceDate);
360 fixingDate_ = iborIndex_->fixingDate(earliestDate_);
361 maturityDate_ = iborIndex_->maturityDate(earliestDate_);
363 }
364
366 auto* v1 = dynamic_cast<Visitor<DepositRateHelper>*>(&v);
367 if (v1 != nullptr)
368 v1->visit(*this);
369 else
371 }
372
373
375 Natural monthsToStart,
376 Natural monthsToEnd,
377 Natural fixingDays,
378 const Calendar& calendar,
379 BusinessDayConvention convention,
380 bool endOfMonth,
381 const DayCounter& dayCounter,
382 Pillar::Choice pillarChoice,
383 Date customPillarDate,
384 bool useIndexedCoupon)
385 : RelativeDateRateHelper(rate), periodToStart_(monthsToStart*Months),
386 pillarChoice_(pillarChoice), useIndexedCoupon_(useIndexedCoupon) {
387 QL_REQUIRE(monthsToEnd>monthsToStart,
388 "monthsToEnd (" << monthsToEnd <<
389 ") must be grater than monthsToStart (" << monthsToStart <<
390 ")");
391 // no way to take fixing into account,
392 // even if we would like to for FRA over today
393 iborIndex_ = ext::make_shared<IborIndex>("no-fix", // correct family name would be needed
394 (monthsToEnd-monthsToStart)*Months,
395 fixingDays,
396 Currency(), calendar, convention,
397 endOfMonth, dayCounter, termStructureHandle_);
398 pillarDate_ = customPillarDate;
400 }
401
403 Natural monthsToStart,
404 Natural monthsToEnd,
405 Natural fixingDays,
406 const Calendar& calendar,
407 BusinessDayConvention convention,
408 bool endOfMonth,
409 const DayCounter& dayCounter,
410 Pillar::Choice pillarChoice,
411 Date customPillarDate,
412 bool useIndexedCoupon)
413 : RelativeDateRateHelper(rate), periodToStart_(monthsToStart*Months),
414 pillarChoice_(pillarChoice), useIndexedCoupon_(useIndexedCoupon) {
415 QL_REQUIRE(monthsToEnd>monthsToStart,
416 "monthsToEnd (" << monthsToEnd <<
417 ") must be grater than monthsToStart (" << monthsToStart <<
418 ")");
419 // no way to take fixing into account,
420 // even if we would like to for FRA over today
421 iborIndex_ = ext::make_shared<IborIndex>("no-fix", // correct family name would be needed
422 (monthsToEnd-monthsToStart)*Months,
423 fixingDays,
424 Currency(), calendar, convention,
425 endOfMonth, dayCounter, termStructureHandle_);
426 pillarDate_ = customPillarDate;
428 }
429
431 Natural monthsToStart,
432 const ext::shared_ptr<IborIndex>& i,
433 Pillar::Choice pillarChoice,
434 Date customPillarDate,
435 bool useIndexedCoupon)
436 : RelativeDateRateHelper(rate), periodToStart_(monthsToStart*Months),
437 pillarChoice_(pillarChoice), useIndexedCoupon_(useIndexedCoupon) {
438 // take fixing into account
440 // We want to be notified of changes of fixings, but we don't
441 // want notifications from termStructureHandle_ (they would
442 // interfere with bootstrapping.)
443 iborIndex_->unregisterWith(termStructureHandle_);
445 pillarDate_ = customPillarDate;
447 }
448
450 Natural monthsToStart,
451 const ext::shared_ptr<IborIndex>& i,
452 Pillar::Choice pillarChoice,
453 Date customPillarDate,
454 bool useIndexedCoupon)
455 : RelativeDateRateHelper(rate), periodToStart_(monthsToStart*Months),
456 pillarChoice_(pillarChoice), useIndexedCoupon_(useIndexedCoupon) {
457 // take fixing into account
459 // see above
460 iborIndex_->unregisterWith(termStructureHandle_);
462 pillarDate_ = customPillarDate;
464 }
465
467 Period periodToStart,
468 Natural lengthInMonths,
469 Natural fixingDays,
470 const Calendar& calendar,
471 BusinessDayConvention convention,
472 bool endOfMonth,
473 const DayCounter& dayCounter,
474 Pillar::Choice pillarChoice,
475 Date customPillarDate,
476 bool useIndexedCoupon)
477 : RelativeDateRateHelper(rate), periodToStart_(periodToStart),
478 pillarChoice_(pillarChoice), useIndexedCoupon_(useIndexedCoupon) {
479 // no way to take fixing into account,
480 // even if we would like to for FRA over today
481 iborIndex_ = ext::make_shared<IborIndex>("no-fix", // correct family name would be needed
482 lengthInMonths*Months,
483 fixingDays,
484 Currency(), calendar, convention,
485 endOfMonth, dayCounter, termStructureHandle_);
486 pillarDate_ = customPillarDate;
488 }
489
491 Period periodToStart,
492 Natural lengthInMonths,
493 Natural fixingDays,
494 const Calendar& calendar,
495 BusinessDayConvention convention,
496 bool endOfMonth,
497 const DayCounter& dayCounter,
498 Pillar::Choice pillarChoice,
499 Date customPillarDate,
500 bool useIndexedCoupon)
501 : RelativeDateRateHelper(rate), periodToStart_(periodToStart),
502 pillarChoice_(pillarChoice), useIndexedCoupon_(useIndexedCoupon) {
503 // no way to take fixing into account,
504 // even if we would like to for FRA over today
505 iborIndex_ = ext::make_shared<IborIndex>("no-fix", // correct family name would be needed
506 lengthInMonths*Months,
507 fixingDays,
508 Currency(), calendar, convention,
509 endOfMonth, dayCounter, termStructureHandle_);
510 pillarDate_ = customPillarDate;
512 }
513
515 Period periodToStart,
516 const ext::shared_ptr<IborIndex>& i,
517 Pillar::Choice pillarChoice,
518 Date customPillarDate,
519 bool useIndexedCoupon)
520 : RelativeDateRateHelper(rate), periodToStart_(periodToStart),
521 pillarChoice_(pillarChoice), useIndexedCoupon_(useIndexedCoupon) {
522 // take fixing into account
524 // see above
525 iborIndex_->unregisterWith(termStructureHandle_);
527 pillarDate_ = customPillarDate;
529 }
530
532 Period periodToStart,
533 const ext::shared_ptr<IborIndex>& i,
534 Pillar::Choice pillarChoice,
535 Date customPillarDate,
536 bool useIndexedCoupon)
537 : RelativeDateRateHelper(rate), periodToStart_(periodToStart),
538 pillarChoice_(pillarChoice), useIndexedCoupon_(useIndexedCoupon) {
539 // take fixing into account
541 // see above
542 iborIndex_->unregisterWith(termStructureHandle_);
544 pillarDate_ = customPillarDate;
546 }
547
549 Natural immOffsetStart,
550 Natural immOffsetEnd,
551 const ext::shared_ptr<IborIndex>& i,
552 Pillar::Choice pillarChoice,
553 Date customPillarDate,
554 bool useIndexedCoupon)
555 : RelativeDateRateHelper(rate), immOffsetStart_(immOffsetStart), immOffsetEnd_(immOffsetEnd),
556 pillarChoice_(pillarChoice), useIndexedCoupon_(useIndexedCoupon) {
557 // take fixing into account
559 // see above
560 iborIndex_->unregisterWith(termStructureHandle_);
562 pillarDate_ = customPillarDate;
564 }
565
567 Natural immOffsetStart,
568 Natural immOffsetEnd,
569 const ext::shared_ptr<IborIndex>& i,
570 Pillar::Choice pillarChoice,
571 Date customPillarDate,
572 bool useIndexedCoupon)
573 : RelativeDateRateHelper(rate), immOffsetStart_(immOffsetStart), immOffsetEnd_(immOffsetEnd),
574 pillarChoice_(pillarChoice), useIndexedCoupon_(useIndexedCoupon) {
575 // take fixing into account
577 // see above
578 iborIndex_->unregisterWith(termStructureHandle_);
580 pillarDate_ = customPillarDate;
582 }
583
585 QL_REQUIRE(termStructure_ != nullptr, "term structure not set");
587 return iborIndex_->fixing(fixingDate_, true);
588 else
589 return (termStructure_->discount(earliestDate_) /
590 termStructure_->discount(maturityDate_) -
591 1.0) /
593 }
594
596 // do not set the relinkable handle as an observer -
597 // force recalculation when needed---the index is not lazy
598 bool observer = false;
599
600 ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
601 termStructureHandle_.linkTo(temp, observer);
602
604 }
605
606 namespace {
607 Date nthImmDate(const Date& asof, const Size n) {
608 Date imm = asof;
609 for (Size i = 0; i < n; ++i) {
610 imm = IMM::nextDate(imm, true);
611 }
612 return imm;
613 }
614 }
615
617 // if the evaluation date is not a business day
618 // then move to the next business day
619 Date referenceDate =
620 iborIndex_->fixingCalendar().adjust(evaluationDate_);
621 Date spotDate = iborIndex_->fixingCalendar().advance(
622 referenceDate, iborIndex_->fixingDays()*Days);
623 if (periodToStart_) { // NOLINT(readability-implicit-bool-conversion)
624 earliestDate_ = iborIndex_->fixingCalendar().advance(
625 spotDate, *periodToStart_, iborIndex_->businessDayConvention(),
626 iborIndex_->endOfMonth());
627 // maturity date is calculated from spot date
628 maturityDate_ = iborIndex_->fixingCalendar().advance(
629 spotDate, *periodToStart_ + iborIndex_->tenor(), iborIndex_->businessDayConvention(),
630 iborIndex_->endOfMonth());
631
632 } else if ((immOffsetStart_) && (immOffsetEnd_)) { // NOLINT(readability-implicit-bool-conversion)
633 earliestDate_ = iborIndex_->fixingCalendar().adjust(nthImmDate(spotDate, *immOffsetStart_));
634 maturityDate_ = iborIndex_->fixingCalendar().adjust(nthImmDate(spotDate, *immOffsetEnd_));
635 } else {
636 QL_FAIL("neither periodToStart nor immOffsetStart/End given");
637 }
638
640 // latest relevant date is calculated from earliestDate_
642 else {
644 spanningTime_ = iborIndex_->dayCounter().yearFraction(earliestDate_, maturityDate_);
645 }
646
647 switch (pillarChoice_) {
650 break;
653 break;
655 // pillarDate_ already assigned at construction time
656 QL_REQUIRE(pillarDate_ >= earliestDate_,
657 "pillar date (" << pillarDate_ << ") must be later "
658 "than or equal to the instrument's earliest date (" <<
659 earliestDate_ << ")");
660 QL_REQUIRE(pillarDate_ <= latestRelevantDate_,
661 "pillar date (" << pillarDate_ << ") must be before "
662 "or equal to the instrument's latest relevant date (" <<
663 latestRelevantDate_ << ")");
664 break;
665 default:
666 QL_FAIL("unknown Pillar::Choice(" << Integer(pillarChoice_) << ")");
667 }
668
669 latestDate_ = pillarDate_; // backward compatibility
670
671 fixingDate_ = iborIndex_->fixingDate(earliestDate_);
672 }
673
675 auto* v1 = dynamic_cast<Visitor<FraRateHelper>*>(&v);
676 if (v1 != nullptr)
677 v1->visit(*this);
678 else
680 }
681
682
684 const ext::shared_ptr<SwapIndex>& swapIndex,
685 Handle<Quote> spread,
686 const Period& fwdStart,
688 Pillar::Choice pillarChoice,
689 Date customPillarDate,
690 bool endOfMonth,
691 const ext::optional<bool>& useIndexedCoupons)
692 : RelativeDateRateHelper(rate), settlementDays_(Null<Natural>()), tenor_(swapIndex->tenor()),
693 pillarChoice_(pillarChoice), calendar_(swapIndex->fixingCalendar()),
694 fixedConvention_(swapIndex->fixedLegConvention()),
695 fixedFrequency_(swapIndex->fixedLegTenor().frequency()),
696 fixedDayCount_(swapIndex->dayCounter()), spread_(std::move(spread)), endOfMonth_(endOfMonth),
697 fwdStart_(fwdStart), discountHandle_(std::move(discount)), useIndexedCoupons_(useIndexedCoupons) {
698 // take fixing into account
699 iborIndex_ = swapIndex->iborIndex()->clone(termStructureHandle_);
700 // We want to be notified of changes of fixings, but we don't
701 // want notifications from termStructureHandle_ (they would
702 // interfere with bootstrapping.)
703 iborIndex_->unregisterWith(termStructureHandle_);
704
708
709 pillarDate_ = customPillarDate;
711 }
712
714 const Period& tenor,
715 Calendar calendar,
716 Frequency fixedFrequency,
717 BusinessDayConvention fixedConvention,
718 DayCounter fixedDayCount,
719 const ext::shared_ptr<IborIndex>& iborIndex,
720 Handle<Quote> spread,
721 const Period& fwdStart,
723 Natural settlementDays,
724 Pillar::Choice pillarChoice,
725 Date customPillarDate,
726 bool endOfMonth,
727 const ext::optional<bool>& useIndexedCoupons)
728 : RelativeDateRateHelper(rate), settlementDays_(settlementDays), tenor_(tenor),
729 pillarChoice_(pillarChoice), calendar_(std::move(calendar)),
730 fixedConvention_(fixedConvention), fixedFrequency_(fixedFrequency),
731 fixedDayCount_(std::move(fixedDayCount)), spread_(std::move(spread)), endOfMonth_(endOfMonth),
732 fwdStart_(fwdStart), discountHandle_(std::move(discount)),
733 useIndexedCoupons_(useIndexedCoupons) {
734
735 // take fixing into account
736 iborIndex_ = iborIndex->clone(termStructureHandle_);
737 // We want to be notified of changes of fixings, but we don't
738 // want notifications from termStructureHandle_ (they would
739 // interfere with bootstrapping.)
740 iborIndex_->unregisterWith(termStructureHandle_);
741
745
746 pillarDate_ = customPillarDate;
748 }
749
751 const ext::shared_ptr<SwapIndex>& swapIndex,
752 Handle<Quote> spread,
753 const Period& fwdStart,
755 Pillar::Choice pillarChoice,
756 Date customPillarDate,
757 bool endOfMonth,
758 const ext::optional<bool>& useIndexedCoupons)
759 : RelativeDateRateHelper(rate), settlementDays_(Null<Natural>()), tenor_(swapIndex->tenor()),
760 pillarChoice_(pillarChoice), calendar_(swapIndex->fixingCalendar()),
761 fixedConvention_(swapIndex->fixedLegConvention()),
762 fixedFrequency_(swapIndex->fixedLegTenor().frequency()),
763 fixedDayCount_(swapIndex->dayCounter()), spread_(std::move(spread)), endOfMonth_(endOfMonth),
764 fwdStart_(fwdStart), discountHandle_(std::move(discount)),
765 useIndexedCoupons_(useIndexedCoupons) {
766 // take fixing into account
767 iborIndex_ = swapIndex->iborIndex()->clone(termStructureHandle_);
768 // We want to be notified of changes of fixings, but we don't
769 // want notifications from termStructureHandle_ (they would
770 // interfere with bootstrapping.)
771 iborIndex_->unregisterWith(termStructureHandle_);
772
776
777 pillarDate_ = customPillarDate;
779 }
780
782 const Period& tenor,
783 Calendar calendar,
784 Frequency fixedFrequency,
785 BusinessDayConvention fixedConvention,
786 DayCounter fixedDayCount,
787 const ext::shared_ptr<IborIndex>& iborIndex,
788 Handle<Quote> spread,
789 const Period& fwdStart,
791 Natural settlementDays,
792 Pillar::Choice pillarChoice,
793 Date customPillarDate,
794 bool endOfMonth,
795 const ext::optional<bool>& useIndexedCoupons)
796 : RelativeDateRateHelper(rate), settlementDays_(settlementDays), tenor_(tenor),
797 pillarChoice_(pillarChoice), calendar_(std::move(calendar)),
798 fixedConvention_(fixedConvention), fixedFrequency_(fixedFrequency),
799 fixedDayCount_(std::move(fixedDayCount)), spread_(std::move(spread)), endOfMonth_(endOfMonth),
800 fwdStart_(fwdStart), discountHandle_(std::move(discount)),
801 useIndexedCoupons_(useIndexedCoupons) {
802
803 // take fixing into account
804 iborIndex_ = iborIndex->clone(termStructureHandle_);
805 // We want to be notified of changes of fixings, but we don't
806 // want notifications from termStructureHandle_ (they would
807 // interfere with bootstrapping.)
808 iborIndex_->unregisterWith(termStructureHandle_);
809
813
814 pillarDate_ = customPillarDate;
816 }
817
819
820 // 1. do not pass the spread here, as it might be a Quote
821 // i.e. it can dinamically change
822 // 2. input discount curve Handle might be empty now but it could
823 // be assigned a curve later; use a RelinkableHandle here
836
838
839 earliestDate_ = swap_->startDate();
840 maturityDate_ = swap_->maturityDate();
841
842 ext::shared_ptr<IborCoupon> lastCoupon =
843 ext::dynamic_pointer_cast<IborCoupon>(swap_->floatingLeg().back());
844 latestRelevantDate_ = std::max(maturityDate_, lastCoupon->fixingEndDate());
845
846 switch (pillarChoice_) {
849 break;
852 break;
854 // pillarDate_ already assigned at construction time
855 QL_REQUIRE(pillarDate_ >= earliestDate_,
856 "pillar date (" << pillarDate_ << ") must be later "
857 "than or equal to the instrument's earliest date (" <<
858 earliestDate_ << ")");
859 QL_REQUIRE(pillarDate_ <= latestRelevantDate_,
860 "pillar date (" << pillarDate_ << ") must be before "
861 "or equal to the instrument's latest relevant date (" <<
862 latestRelevantDate_ << ")");
863 break;
864 default:
865 QL_FAIL("unknown Pillar::Choice(" << Integer(pillarChoice_) << ")");
866 }
867
868 latestDate_ = pillarDate_; // backward compatibility
869
870 }
871
873 // do not set the relinkable handle as an observer -
874 // force recalculation when needed
875 bool observer = false;
876
877 ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
878 termStructureHandle_.linkTo(temp, observer);
879
880 if (discountHandle_.empty())
881 discountRelinkableHandle_.linkTo(temp, observer);
882 else
884
886 }
887
889 QL_REQUIRE(termStructure_ != nullptr, "term structure not set");
890 // we didn't register as observers - force calculation
891 swap_->deepUpdate();
892 // weak implementation... to be improved
893 static const Spread basisPoint = 1.0e-4;
894 Real floatingLegNPV = swap_->floatingLegNPV();
895 Spread spread = spread_.empty() ? 0.0 : spread_->value();
896 Real spreadNPV = swap_->floatingLegBPS()/basisPoint*spread;
897 Real totNPV = - (floatingLegNPV+spreadNPV);
898 Real result = totNPV/(swap_->fixedLegBPS()/basisPoint);
899 return result;
900 }
901
903 auto* v1 = dynamic_cast<Visitor<SwapRateHelper>*>(&v);
904 if (v1 != nullptr)
905 v1->visit(*this);
906 else
908 }
909
911 const Period& tenor,
912 Natural settlementDays,
913 Calendar calendar,
914 // bma leg
915 const Period& bmaPeriod,
916 BusinessDayConvention bmaConvention,
917 DayCounter bmaDayCount,
918 ext::shared_ptr<BMAIndex> bmaIndex,
919 // libor leg
920 ext::shared_ptr<IborIndex> iborIndex)
921 : RelativeDateRateHelper(liborFraction), tenor_(tenor), settlementDays_(settlementDays),
922 calendar_(std::move(calendar)), bmaPeriod_(bmaPeriod), bmaConvention_(bmaConvention),
923 bmaDayCount_(std::move(bmaDayCount)), bmaIndex_(std::move(bmaIndex)),
924 iborIndex_(std::move(iborIndex)) {
928 }
929
931 // if the evaluation date is not a business day
932 // then move to the next business day
934 iborIndex_->fixingCalendar());
935 Date referenceDate = jc.adjust(evaluationDate_);
938
939 Date maturity = earliestDate_ + tenor_;
940
941 // dummy BMA index with curve/swap arguments
942 ext::shared_ptr<BMAIndex> clonedIndex(new BMAIndex(termStructureHandle_));
943
944 Schedule bmaSchedule =
945 MakeSchedule().from(earliestDate_).to(maturity)
947 .withCalendar(bmaIndex_->fixingCalendar())
949 .backwards();
950
951 Schedule liborSchedule =
952 MakeSchedule().from(earliestDate_).to(maturity)
953 .withTenor(iborIndex_->tenor())
954 .withCalendar(iborIndex_->fixingCalendar())
955 .withConvention(iborIndex_->businessDayConvention())
956 .endOfMonth(iborIndex_->endOfMonth())
957 .backwards();
958
959 swap_ = ext::make_shared<BMASwap>(Swap::Payer, 100.0,
960 liborSchedule,
961 0.75, // arbitrary
962 0.0,
964 iborIndex_->dayCounter(),
965 bmaSchedule,
966 clonedIndex,
968 swap_->setPricingEngine(ext::shared_ptr<PricingEngine>(new
969 DiscountingSwapEngine(iborIndex_->forwardingTermStructure())));
970
971 Date d = calendar_.adjust(swap_->maturityDate(), Following);
972 Weekday w = d.weekday();
973 Date nextWednesday = (w >= 4) ?
974 d + (11 - w) * Days :
975 d + (4 - w) * Days;
976 latestDate_ = clonedIndex->valueDate(
977 clonedIndex->fixingCalendar().adjust(nextWednesday));
978 }
979
981 // do not set the relinkable handle as an observer -
982 // force recalculation when needed
983 bool observer = false;
984
985 ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
986 termStructureHandle_.linkTo(temp, observer);
987
989 }
990
992 QL_REQUIRE(termStructure_ != nullptr, "term structure not set");
993 // we didn't register as observers - force calculation
994 swap_->deepUpdate();
995 return swap_->fairLiborFraction();
996 }
997
999 auto* v1 = dynamic_cast<Visitor<BMASwapRateHelper>*>(&v);
1000 if (v1 != nullptr)
1001 v1->visit(*this);
1002 else
1004 }
1005
1007 Handle<Quote> spotFx,
1008 const Period& tenor,
1009 Natural fixingDays,
1010 Calendar calendar,
1011 BusinessDayConvention convention,
1012 bool endOfMonth,
1013 bool isFxBaseCurrencyCollateralCurrency,
1015 Calendar tradingCalendar)
1016 : RelativeDateRateHelper(fwdPoint), spot_(std::move(spotFx)), tenor_(tenor),
1017 fixingDays_(fixingDays), cal_(std::move(calendar)), conv_(convention), eom_(endOfMonth),
1018 isFxBaseCurrencyCollateralCurrency_(isFxBaseCurrencyCollateralCurrency),
1019 collHandle_(std::move(coll)), tradingCalendar_(std::move(tradingCalendar)) {
1022
1023 if (tradingCalendar_.empty())
1025 else
1027 JoinHolidays);
1029 }
1030
1032 // if the evaluation date is not a business day
1033 // then move to the next business day
1034 Date refDate = cal_.adjust(evaluationDate_);
1036
1037 if (!tradingCalendar_.empty()) {
1038 // check if fx trade can be settled in US, if not, adjust it
1041 conv_, eom_);
1042 } else {
1044 }
1045 }
1046
1048 QL_REQUIRE(termStructure_ != nullptr, "term structure not set");
1049
1050 QL_REQUIRE(!collHandle_.empty(), "collateral term structure not set");
1051
1053 DiscountFactor d2 = collHandle_->discount(latestDate_);
1054 Real collRatio = d1 / d2;
1055 d1 = termStructureHandle_->discount(earliestDate_);
1056 d2 = termStructureHandle_->discount(latestDate_);
1057 Real ratio = d1 / d2;
1058 Real spot = spot_->value();
1060 return (ratio/collRatio-1)*spot;
1061 } else {
1062 return (collRatio/ratio-1)*spot;
1063 }
1064 }
1065
1067 // do not set the relinkable handle as an observer -
1068 // force recalculation when needed
1069 bool observer = false;
1070
1071 ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
1072 termStructureHandle_.linkTo(temp, observer);
1073
1074 collRelinkableHandle_.linkTo(*collHandle_, observer);
1075
1077 }
1078
1080 auto* v1 = dynamic_cast<Visitor<FxSwapRateHelper>*>(&v);
1081 if (v1 != nullptr)
1082 v1->visit(*this);
1083 else
1085 }
1086
1087}
degenerate base class for the Acyclic Visitor pattern
Definition: visitor.hpp:33
Bond Market Association index.
Definition: bmaindex.hpp:40
void setTermStructure(YieldTermStructure *) override
RelinkableHandle< YieldTermStructure > termStructureHandle_
ext::shared_ptr< IborIndex > iborIndex_
void accept(AcyclicVisitor &) override
void initializeDates() override
ext::shared_ptr< BMAIndex > bmaIndex_
Real impliedQuote() const override
BusinessDayConvention bmaConvention_
BMASwapRateHelper(const Handle< Quote > &liborFraction, const Period &tenor, Natural settlementDays, Calendar calendar, const Period &bmaPeriod, BusinessDayConvention bmaConvention, DayCounter bmaDayCount, ext::shared_ptr< BMAIndex > bmaIndex, ext::shared_ptr< IborIndex > index)
ext::shared_ptr< BMASwap > swap_
Base helper class for bootstrapping.
virtual void accept(AcyclicVisitor &)
virtual void setTermStructure(TS *)
sets the term structure to be used for pricing
calendar class
Definition: calendar.hpp:61
bool empty() const
Returns whether or not the calendar is initialized.
Definition: calendar.hpp:202
Date adjust(const Date &, BusinessDayConvention convention=Following) const
Definition: calendar.cpp:84
Date advance(const Date &, Integer n, TimeUnit unit, BusinessDayConvention convention=Following, bool endOfMonth=false) const
Definition: calendar.cpp:130
Currency specification
Definition: currency.hpp:36
Concrete date class.
Definition: date.hpp:125
day counter class
Definition: daycounter.hpp:44
Time yearFraction(const Date &, const Date &, const Date &refPeriodStart=Date(), const Date &refPeriodEnd=Date()) const
Returns the period between two dates as a fraction of year.
Definition: daycounter.hpp:128
void setTermStructure(YieldTermStructure *) override
RelinkableHandle< YieldTermStructure > termStructureHandle_
ext::shared_ptr< IborIndex > iborIndex_
void accept(AcyclicVisitor &) override
void initializeDates() override
Real impliedQuote() const override
DepositRateHelper(const Handle< Quote > &rate, const Period &tenor, Natural fixingDays, const Calendar &calendar, BusinessDayConvention convention, bool endOfMonth, const DayCounter &dayCounter)
ext::optional< Natural > immOffsetEnd_
void setTermStructure(YieldTermStructure *) override
ext::optional< Natural > immOffsetStart_
RelinkableHandle< YieldTermStructure > termStructureHandle_
Pillar::Choice pillarChoice_
ext::shared_ptr< IborIndex > iborIndex_
ext::optional< Period > periodToStart_
void accept(AcyclicVisitor &) override
FraRateHelper(const Handle< Quote > &rate, Natural monthsToStart, Natural monthsToEnd, Natural fixingDays, const Calendar &calendar, BusinessDayConvention convention, bool endOfMonth, const DayCounter &dayCounter, Pillar::Choice pillar=Pillar::LastRelevantDate, Date customPillarDate=Date(), bool useIndexedCoupon=true)
void initializeDates() override
Real impliedQuote() const override
void accept(AcyclicVisitor &) override
Real impliedQuote() const override
FuturesRateHelper(const Handle< Quote > &price, const Date &iborStartDate, Natural lengthInMonths, const Calendar &calendar, BusinessDayConvention convention, bool endOfMonth, const DayCounter &dayCounter, Handle< Quote > convexityAdjustment={}, Futures::Type type=Futures::IMM)
Definition: ratehelpers.cpp:44
void setTermStructure(YieldTermStructure *) override
RelinkableHandle< YieldTermStructure > termStructureHandle_
void accept(AcyclicVisitor &) override
RelinkableHandle< YieldTermStructure > collRelinkableHandle_
Handle< YieldTermStructure > collHandle_
void initializeDates() override
BusinessDayConvention conv_
Real impliedQuote() const override
FxSwapRateHelper(const Handle< Quote > &fwdPoint, Handle< Quote > spotFx, const Period &tenor, Natural fixingDays, Calendar calendar, BusinessDayConvention convention, bool endOfMonth, bool isFxBaseCurrencyCollateralCurrency, Handle< YieldTermStructure > collateralCurve, Calendar tradingCalendar=Calendar())
Shared handle to an observable.
Definition: handle.hpp:41
MakeSchedule & withConvention(BusinessDayConvention)
Definition: schedule.cpp:557
MakeSchedule & backwards()
Definition: schedule.cpp:578
MakeSchedule & to(const Date &terminationDate)
Definition: schedule.cpp:537
MakeSchedule & withTenor(const Period &)
Definition: schedule.cpp:542
MakeSchedule & from(const Date &effectiveDate)
Definition: schedule.cpp:532
MakeSchedule & endOfMonth(bool flag=true)
Definition: schedule.cpp:583
MakeSchedule & withCalendar(const Calendar &)
Definition: schedule.cpp:552
MakeVanillaSwap & withFixedLegConvention(BusinessDayConvention bdc)
MakeVanillaSwap & withFixedLegTerminationDateConvention(BusinessDayConvention bdc)
MakeVanillaSwap & withFixedLegCalendar(const Calendar &cal)
MakeVanillaSwap & withDiscountingTermStructure(const Handle< YieldTermStructure > &discountCurve)
MakeVanillaSwap & withIndexedCoupons(const ext::optional< bool > &b=true)
MakeVanillaSwap & withSettlementDays(Natural settlementDays)
MakeVanillaSwap & withFixedLegDayCount(const DayCounter &dc)
MakeVanillaSwap & withFixedLegEndOfMonth(bool flag=true)
MakeVanillaSwap & withFloatingLegCalendar(const Calendar &cal)
MakeVanillaSwap & withFloatingLegEndOfMonth(bool flag=true)
MakeVanillaSwap & withFixedLegTenor(const Period &t)
template class providing a null value for a given type.
Definition: null.hpp:76
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
Definition: observable.hpp:228
purely virtual base class for market observables
Definition: quote.hpp:37
Bootstrap helper with date schedule relative to global evaluation date.
Payment schedule.
Definition: schedule.hpp:40
market element returning a stored value
Definition: simplequote.hpp:33
RelinkableHandle< YieldTermStructure > discountRelinkableHandle_
void setTermStructure(YieldTermStructure *) override
BusinessDayConvention fixedConvention_
RelinkableHandle< YieldTermStructure > termStructureHandle_
ext::shared_ptr< VanillaSwap > swap_
Pillar::Choice pillarChoice_
Handle< YieldTermStructure > discountHandle_
Handle< Quote > spread_
ext::shared_ptr< IborIndex > iborIndex_
ext::optional< bool > useIndexedCoupons_
void accept(AcyclicVisitor &) override
SwapRateHelper(const Handle< Quote > &rate, const ext::shared_ptr< SwapIndex > &swapIndex, Handle< Quote > spread={}, const Period &fwdStart=0 *Days, Handle< YieldTermStructure > discountingCurve={}, Pillar::Choice pillar=Pillar::LastRelevantDate, Date customPillarDate=Date(), bool endOfMonth=false, const ext::optional< bool > &useIndexedCoupons=ext::nullopt)
void initializeDates() override
Real impliedQuote() const override
Visitor for a specific class
Definition: visitor.hpp:40
virtual void visit(T &)=0
Interest-rate term structure.
Frequency
Frequency of events.
Definition: frequency.hpp:37
BusinessDayConvention
Business Day conventions.
QL_REAL Real
real number
Definition: types.hpp:50
Real DiscountFactor
discount factor between dates
Definition: types.hpp:66
unsigned QL_INTEGER Natural
positive integer
Definition: types.hpp:43
QL_INTEGER Integer
integer number
Definition: types.hpp:35
Real Spread
spreads on interest rates
Definition: types.hpp:74
Real Rate
interest rates
Definition: types.hpp:70
std::size_t Size
size of a container
Definition: types.hpp:58
Definition: any.hpp:35
void simplifyNotificationGraph(Instrument &instrument, const Leg &leg, bool unregisterCoupons)
Utility function to optimize the observability graph of an instrument.
STL namespace.
static Date nextDate(const Date &d=Date(), bool mainCycle=true)
next ASX date following the given date
Definition: asx.cpp:165
static bool isASXdate(const Date &d, bool mainCycle=true)
returns whether or not the given date is an ASX date
Definition: asx.cpp:35
Type
Futures type enumeration.
Definition: futures.hpp:36
static bool isIMMdate(const Date &d, bool mainCycle=true)
returns whether or not the given date is an IMM date
Definition: imm.cpp:34
static Date nextDate(const Date &d=Date(), bool mainCycle=true)
next IMM date following the given date
Definition: imm.cpp:164
Choice
Enumeration for pillar determination alternatives.
@ CustomDate
last date relevant for instrument pricing
@ LastRelevantDate
instruments maturity date