QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
ratehelpers.cpp
Go to the documentation of this file.
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
27#include <ql/currency.hpp>
31#include <ql/optional.hpp>
33#include <ql/quote.hpp>
35#include <ql/time/asx.hpp>
37#include <ql/time/imm.hpp>
39#include <utility>
40
41namespace QuantLib {
42
43 namespace {
44
45 void CheckDate(const Date& date, const Futures::Type type) {
46 switch (type) {
47 case Futures::IMM:
48 QL_REQUIRE(IMM::isIMMdate(date, false), date << " is not a valid IMM date");
49 break;
50 case Futures::ASX:
51 QL_REQUIRE(ASX::isASXdate(date, false), date << " is not a valid ASX date");
52 break;
53 case Futures::Custom:
54 break;
55 default:
56 QL_FAIL("unknown futures type (" << type << ')');
57 }
58 }
59
60 Time DetermineYearFraction(const Date& earliestDate,
61 const Date& maturityDate,
62 const DayCounter& dayCounter) {
63 return dayCounter.yearFraction(earliestDate, maturityDate,
64 earliestDate, maturityDate);
65 }
66
67 } // namespace
68
70 const Date& iborStartDate,
71 Natural lengthInMonths,
72 const Calendar& calendar,
73 BusinessDayConvention convention,
74 bool endOfMonth,
75 const DayCounter& dayCounter,
76 Handle<Quote> convAdj,
77 Futures::Type type)
78 : RateHelper(price), convAdj_(std::move(convAdj)) {
79 CheckDate(iborStartDate, type);
80
81 earliestDate_ = iborStartDate;
83 calendar.advance(iborStartDate, lengthInMonths * Months, convention, endOfMonth);
84 yearFraction_ = DetermineYearFraction(earliestDate_, maturityDate_, dayCounter);
86
88 }
89
91 const Date& iborStartDate,
92 Natural lengthInMonths,
93 const Calendar& calendar,
94 BusinessDayConvention convention,
95 bool endOfMonth,
96 const DayCounter& dayCounter,
97 Rate convAdj,
98 Futures::Type type)
99 : FuturesRateHelper(makeQuoteHandle(price), iborStartDate, lengthInMonths, calendar,
100 convention, endOfMonth, dayCounter, makeQuoteHandle(convAdj), type) {}
101
103 const Date& iborStartDate,
104 const Date& iborEndDate,
105 const DayCounter& dayCounter,
106 Handle<Quote> convAdj,
107 Futures::Type type)
108 : RateHelper(price), convAdj_(std::move(convAdj)) {
109 CheckDate(iborStartDate, type);
110
111 const auto determineMaturityDate =
112 [&iborStartDate, &iborEndDate](const auto nextDateCalculator) -> Date {
114 if (iborEndDate == Date()) {
115 // advance 3 months
116 maturityDate = nextDateCalculator(iborStartDate);
117 maturityDate = nextDateCalculator(maturityDate);
118 maturityDate = nextDateCalculator(maturityDate);
119 } else {
120 QL_REQUIRE(iborEndDate > iborStartDate,
121 "end date (" << iborEndDate << ") must be greater than start date ("
122 << iborStartDate << ')');
123 maturityDate = iborEndDate;
124 }
125 return maturityDate;
126 };
127
128 switch (type) {
129 case Futures::IMM:
130 maturityDate_ = determineMaturityDate(
131 [](const Date date) -> Date { return IMM::nextDate(date, false); });
132 break;
133 case Futures::ASX:
134 maturityDate_ = determineMaturityDate(
135 [](const Date date) -> Date { return ASX::nextDate(date, false); });
136 break;
137 case Futures::Custom:
138 maturityDate_ = iborEndDate;
139 break;
140 default:
141 QL_FAIL("unsupported futures type (" << type << ')');
142 }
143 earliestDate_ = iborStartDate;
144 yearFraction_ = DetermineYearFraction(earliestDate_, maturityDate_, dayCounter);
146
148 }
149
151 const Date& iborStartDate,
152 const Date& iborEndDate,
153 const DayCounter& dayCounter,
154 Rate convAdj,
155 Futures::Type type)
156 : FuturesRateHelper(makeQuoteHandle(price), iborStartDate, iborEndDate, dayCounter,
157 makeQuoteHandle(convAdj), type) {}
158
160 const Date& iborStartDate,
161 const ext::shared_ptr<IborIndex>& index,
162 const Handle<Quote>& convAdj,
163 Futures::Type type)
164 : RateHelper(price), convAdj_(convAdj) {
165 CheckDate(iborStartDate, type);
166
167 earliestDate_ = iborStartDate;
168 const Calendar& cal = index->fixingCalendar();
170 cal.advance(iborStartDate, index->tenor(), index->businessDayConvention());
171 yearFraction_ = DetermineYearFraction(earliestDate_, maturityDate_, index->dayCounter());
173
174 registerWith(convAdj);
175 }
176
178 const Date& iborStartDate,
179 const ext::shared_ptr<IborIndex>& index,
180 Rate convAdj,
181 Futures::Type type)
182 : FuturesRateHelper(makeQuoteHandle(price), iborStartDate, index, makeQuoteHandle(convAdj), type) {}
183
185 QL_REQUIRE(termStructure_ != nullptr, "term structure not set");
186 Rate forwardRate = (termStructure_->discount(earliestDate_) /
187 termStructure_->discount(maturityDate_) - 1.0) / yearFraction_;
188 // Convexity, as FRA/futures adjustment, has been used in the
189 // past to take into account futures margining vs FRA.
190 // Therefore, there's no requirement for it to be non-negative.
191 Rate futureRate = forwardRate + convexityAdjustment();
192 return 100.0 * (1.0 - futureRate);
193 }
194
196 return convAdj_.empty() ? 0.0 : convAdj_->value();
197 }
198
200 auto* v1 = dynamic_cast<Visitor<FuturesRateHelper>*>(&v);
201 if (v1 != nullptr)
202 v1->visit(*this);
203 else
205 }
206
208 const Period& tenor,
209 Natural fixingDays,
210 const Calendar& calendar,
211 BusinessDayConvention convention,
212 bool endOfMonth,
213 const DayCounter& dayCounter)
214 : RelativeDateRateHelper(rate) {
215 iborIndex_ = ext::make_shared<IborIndex>("no-fix", // never take fixing into account
216 tenor, fixingDays,
217 Currency(), calendar, convention,
218 endOfMonth, dayCounter, termStructureHandle_);
220 }
221
223 const Period& tenor,
224 Natural fixingDays,
225 const Calendar& calendar,
226 BusinessDayConvention convention,
227 bool endOfMonth,
228 const DayCounter& dayCounter)
229 : DepositRateHelper(makeQuoteHandle(rate), tenor, fixingDays, calendar, convention,
230 endOfMonth, dayCounter) {}
231
233 const ext::shared_ptr<IborIndex>& i)
234 : RelativeDateRateHelper(rate) {
237 }
238
240 const ext::shared_ptr<IborIndex>& i)
242
244 QL_REQUIRE(termStructure_ != nullptr, "term structure not set");
245 // the forecast fixing flag is set to true because
246 // we do not want to take fixing into account
247 return iborIndex_->fixing(fixingDate_, true);
248 }
249
251 // do not set the relinkable handle as an observer -
252 // force recalculation when needed---the index is not lazy
253 bool observer = false;
254
255 ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
256 termStructureHandle_.linkTo(temp, observer);
257
259 }
260
262 // if the evaluation date is not a business day
263 // then move to the next business day
264 Date referenceDate =
265 iborIndex_->fixingCalendar().adjust(evaluationDate_);
266 earliestDate_ = iborIndex_->valueDate(referenceDate);
267 fixingDate_ = iborIndex_->fixingDate(earliestDate_);
268 maturityDate_ = iborIndex_->maturityDate(earliestDate_);
270 }
271
273 auto* v1 = dynamic_cast<Visitor<DepositRateHelper>*>(&v);
274 if (v1 != nullptr)
275 v1->visit(*this);
276 else
278 }
279
280
282 Natural monthsToStart,
283 Natural monthsToEnd,
284 Natural fixingDays,
285 const Calendar& calendar,
286 BusinessDayConvention convention,
287 bool endOfMonth,
288 const DayCounter& dayCounter,
289 Pillar::Choice pillarChoice,
290 Date customPillarDate,
291 bool useIndexedCoupon)
292 : FraRateHelper(rate, monthsToStart*Months, monthsToEnd-monthsToStart, fixingDays, calendar,
293 convention, endOfMonth, dayCounter, pillarChoice, customPillarDate, useIndexedCoupon) {
294 QL_REQUIRE(monthsToEnd>monthsToStart,
295 "monthsToEnd (" << monthsToEnd <<
296 ") must be grater than monthsToStart (" << monthsToStart <<
297 ")");
298 }
299
301 Natural monthsToStart,
302 Natural monthsToEnd,
303 Natural fixingDays,
304 const Calendar& calendar,
305 BusinessDayConvention convention,
306 bool endOfMonth,
307 const DayCounter& dayCounter,
308 Pillar::Choice pillarChoice,
309 Date customPillarDate,
310 bool useIndexedCoupon)
311 : FraRateHelper(makeQuoteHandle(rate), monthsToStart, monthsToEnd, fixingDays, calendar,
312 convention, endOfMonth, dayCounter, pillarChoice, customPillarDate, useIndexedCoupon) {}
313
315 Natural monthsToStart,
316 const ext::shared_ptr<IborIndex>& i,
317 Pillar::Choice pillarChoice,
318 Date customPillarDate,
319 bool useIndexedCoupon)
320 : FraRateHelper(rate, monthsToStart*Months, i, pillarChoice, customPillarDate, useIndexedCoupon)
321 {}
322
324 Natural monthsToStart,
325 const ext::shared_ptr<IborIndex>& i,
326 Pillar::Choice pillarChoice,
327 Date customPillarDate,
328 bool useIndexedCoupon)
329 : FraRateHelper(makeQuoteHandle(rate), monthsToStart, i, pillarChoice, customPillarDate, useIndexedCoupon) {}
330
332 Period periodToStart,
333 Natural lengthInMonths,
334 Natural fixingDays,
335 const Calendar& calendar,
336 BusinessDayConvention convention,
337 bool endOfMonth,
338 const DayCounter& dayCounter,
339 Pillar::Choice pillarChoice,
340 Date customPillarDate,
341 bool useIndexedCoupon)
342 : RelativeDateRateHelper(rate), periodToStart_(periodToStart),
343 pillarChoice_(pillarChoice), useIndexedCoupon_(useIndexedCoupon) {
344 // no way to take fixing into account,
345 // even if we would like to for FRA over today
346 iborIndex_ = ext::make_shared<IborIndex>("no-fix", // correct family name would be needed
347 lengthInMonths*Months,
348 fixingDays,
349 Currency(), calendar, convention,
350 endOfMonth, dayCounter, termStructureHandle_);
351 pillarDate_ = customPillarDate;
353 }
354
356 Period periodToStart,
357 Natural lengthInMonths,
358 Natural fixingDays,
359 const Calendar& calendar,
360 BusinessDayConvention convention,
361 bool endOfMonth,
362 const DayCounter& dayCounter,
363 Pillar::Choice pillarChoice,
364 Date customPillarDate,
365 bool useIndexedCoupon)
366 : FraRateHelper(makeQuoteHandle(rate), periodToStart, lengthInMonths, fixingDays, calendar,
367 convention, endOfMonth, dayCounter, pillarChoice, customPillarDate, useIndexedCoupon) {}
368
370 Period periodToStart,
371 const ext::shared_ptr<IborIndex>& i,
372 Pillar::Choice pillarChoice,
373 Date customPillarDate,
374 bool useIndexedCoupon)
375 : RelativeDateRateHelper(rate), periodToStart_(periodToStart),
376 pillarChoice_(pillarChoice), useIndexedCoupon_(useIndexedCoupon) {
377 // take fixing into account
379 // We want to be notified of changes of fixings, but we don't
380 // want notifications from termStructureHandle_ (they would
381 // interfere with bootstrapping.)
382 iborIndex_->unregisterWith(termStructureHandle_);
384 pillarDate_ = customPillarDate;
386 }
387
389 Period periodToStart,
390 const ext::shared_ptr<IborIndex>& i,
391 Pillar::Choice pillarChoice,
392 Date customPillarDate,
393 bool useIndexedCoupon)
394 : FraRateHelper(makeQuoteHandle(rate), periodToStart, i, pillarChoice, customPillarDate, useIndexedCoupon) {}
395
397 Natural immOffsetStart,
398 Natural immOffsetEnd,
399 const ext::shared_ptr<IborIndex>& i,
400 Pillar::Choice pillarChoice,
401 Date customPillarDate,
402 bool useIndexedCoupon)
403 : RelativeDateRateHelper(rate), immOffsetStart_(immOffsetStart), immOffsetEnd_(immOffsetEnd),
404 pillarChoice_(pillarChoice), useIndexedCoupon_(useIndexedCoupon) {
405 // take fixing into account
407 // see above
408 iborIndex_->unregisterWith(termStructureHandle_);
410 pillarDate_ = customPillarDate;
412 }
413
415 Natural immOffsetStart,
416 Natural immOffsetEnd,
417 const ext::shared_ptr<IborIndex>& i,
418 Pillar::Choice pillarChoice,
419 Date customPillarDate,
420 bool useIndexedCoupon)
421 : FraRateHelper(makeQuoteHandle(rate), immOffsetStart, immOffsetEnd, i, pillarChoice,
422 customPillarDate, useIndexedCoupon) {}
423
425 QL_REQUIRE(termStructure_ != nullptr, "term structure not set");
427 return iborIndex_->fixing(fixingDate_, true);
428 else
429 return (termStructure_->discount(earliestDate_) /
430 termStructure_->discount(maturityDate_) -
431 1.0) /
433 }
434
436 // do not set the relinkable handle as an observer -
437 // force recalculation when needed---the index is not lazy
438 bool observer = false;
439
440 ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
441 termStructureHandle_.linkTo(temp, observer);
442
444 }
445
446 namespace {
447 Date nthImmDate(const Date& asof, const Size n) {
448 Date imm = asof;
449 for (Size i = 0; i < n; ++i) {
450 imm = IMM::nextDate(imm, true);
451 }
452 return imm;
453 }
454 }
455
457 // if the evaluation date is not a business day
458 // then move to the next business day
459 Date referenceDate =
460 iborIndex_->fixingCalendar().adjust(evaluationDate_);
461 Date spotDate = iborIndex_->fixingCalendar().advance(
462 referenceDate, iborIndex_->fixingDays()*Days);
463 if (periodToStart_) { // NOLINT(readability-implicit-bool-conversion)
464 earliestDate_ = iborIndex_->fixingCalendar().advance(
465 spotDate, *periodToStart_, iborIndex_->businessDayConvention(),
466 iborIndex_->endOfMonth());
467 // maturity date is calculated from spot date
468 maturityDate_ = iborIndex_->fixingCalendar().advance(
469 spotDate, *periodToStart_ + iborIndex_->tenor(), iborIndex_->businessDayConvention(),
470 iborIndex_->endOfMonth());
471
472 } else if ((immOffsetStart_) && (immOffsetEnd_)) { // NOLINT(readability-implicit-bool-conversion)
473 earliestDate_ = iborIndex_->fixingCalendar().adjust(nthImmDate(spotDate, *immOffsetStart_));
474 maturityDate_ = iborIndex_->fixingCalendar().adjust(nthImmDate(spotDate, *immOffsetEnd_));
475 } else {
476 QL_FAIL("neither periodToStart nor immOffsetStart/End given");
477 }
478
480 // latest relevant date is calculated from earliestDate_
482 else {
484 spanningTime_ = iborIndex_->dayCounter().yearFraction(earliestDate_, maturityDate_);
485 }
486
487 switch (pillarChoice_) {
490 break;
493 break;
495 // pillarDate_ already assigned at construction time
497 "pillar date (" << pillarDate_ << ") must be later "
498 "than or equal to the instrument's earliest date (" <<
499 earliestDate_ << ")");
501 "pillar date (" << pillarDate_ << ") must be before "
502 "or equal to the instrument's latest relevant date (" <<
503 latestRelevantDate_ << ")");
504 break;
505 default:
506 QL_FAIL("unknown Pillar::Choice(" << Integer(pillarChoice_) << ")");
507 }
508
509 latestDate_ = pillarDate_; // backward compatibility
510
511 fixingDate_ = iborIndex_->fixingDate(earliestDate_);
512 }
513
515 auto* v1 = dynamic_cast<Visitor<FraRateHelper>*>(&v);
516 if (v1 != nullptr)
517 v1->visit(*this);
518 else
520 }
521
522
524 const ext::shared_ptr<SwapIndex>& swapIndex,
525 Handle<Quote> spread,
526 const Period& fwdStart,
528 Pillar::Choice pillarChoice,
529 Date customPillarDate,
530 bool endOfMonth,
531 const ext::optional<bool>& useIndexedCoupons)
532 : SwapRateHelper(rate, swapIndex->tenor(), swapIndex->fixingCalendar(),
533 swapIndex->fixedLegTenor().frequency(), swapIndex->fixedLegConvention(),
534 swapIndex->dayCounter(), swapIndex->iborIndex(), std::move(spread), fwdStart,
535 std::move(discount), Null<Natural>(), pillarChoice, customPillarDate, endOfMonth,
536 useIndexedCoupons) {}
537
539 const Period& tenor,
540 Calendar calendar,
541 Frequency fixedFrequency,
542 BusinessDayConvention fixedConvention,
543 DayCounter fixedDayCount,
544 const ext::shared_ptr<IborIndex>& iborIndex,
545 Handle<Quote> spread,
546 const Period& fwdStart,
548 Natural settlementDays,
549 Pillar::Choice pillarChoice,
550 Date customPillarDate,
551 bool endOfMonth,
552 const ext::optional<bool>& useIndexedCoupons)
553 : RelativeDateRateHelper(rate), settlementDays_(settlementDays), tenor_(tenor),
554 pillarChoice_(pillarChoice), calendar_(std::move(calendar)),
555 fixedConvention_(fixedConvention), fixedFrequency_(fixedFrequency),
556 fixedDayCount_(std::move(fixedDayCount)), spread_(std::move(spread)), endOfMonth_(endOfMonth),
557 fwdStart_(fwdStart), discountHandle_(std::move(discount)),
558 useIndexedCoupons_(useIndexedCoupons) {
559
560 // take fixing into account
561 iborIndex_ = iborIndex->clone(termStructureHandle_);
562 // We want to be notified of changes of fixings, but we don't
563 // want notifications from termStructureHandle_ (they would
564 // interfere with bootstrapping.)
565 iborIndex_->unregisterWith(termStructureHandle_);
566
570
571 pillarDate_ = customPillarDate;
573 }
574
576 const ext::shared_ptr<SwapIndex>& swapIndex,
577 Handle<Quote> spread,
578 const Period& fwdStart,
580 Pillar::Choice pillarChoice,
581 Date customPillarDate,
582 bool endOfMonth,
583 const ext::optional<bool>& useIndexedCoupons)
584 : SwapRateHelper(makeQuoteHandle(rate), swapIndex, std::move(spread), fwdStart,
585 std::move(discount), pillarChoice, customPillarDate, endOfMonth, useIndexedCoupons) {}
586
588 const Period& tenor,
589 Calendar calendar,
590 Frequency fixedFrequency,
591 BusinessDayConvention fixedConvention,
592 DayCounter fixedDayCount,
593 const ext::shared_ptr<IborIndex>& iborIndex,
594 Handle<Quote> spread,
595 const Period& fwdStart,
597 Natural settlementDays,
598 Pillar::Choice pillarChoice,
599 Date customPillarDate,
600 bool endOfMonth,
601 const ext::optional<bool>& useIndexedCoupons)
602 : SwapRateHelper(makeQuoteHandle(rate), tenor, std::move(calendar), fixedFrequency, fixedConvention,
603 std::move(fixedDayCount), iborIndex, std::move(spread), fwdStart, std::move(discount), settlementDays,
604 pillarChoice, customPillarDate, endOfMonth, useIndexedCoupons) {}
605
607
608 // 1. do not pass the spread here, as it might be a Quote
609 // i.e. it can dynamically change
610 // 2. input discount curve Handle might be empty now but it could
611 // be assigned a curve later; use a RelinkableHandle here
624
626
627 earliestDate_ = swap_->startDate();
628 maturityDate_ = swap_->maturityDate();
629
630 ext::shared_ptr<IborCoupon> lastCoupon =
631 ext::dynamic_pointer_cast<IborCoupon>(swap_->floatingLeg().back());
632 latestRelevantDate_ = std::max(maturityDate_, lastCoupon->fixingEndDate());
633
634 switch (pillarChoice_) {
637 break;
640 break;
642 // pillarDate_ already assigned at construction time
644 "pillar date (" << pillarDate_ << ") must be later "
645 "than or equal to the instrument's earliest date (" <<
646 earliestDate_ << ")");
648 "pillar date (" << pillarDate_ << ") must be before "
649 "or equal to the instrument's latest relevant date (" <<
650 latestRelevantDate_ << ")");
651 break;
652 default:
653 QL_FAIL("unknown Pillar::Choice(" << Integer(pillarChoice_) << ")");
654 }
655
656 latestDate_ = pillarDate_; // backward compatibility
657
658 }
659
661 // do not set the relinkable handle as an observer -
662 // force recalculation when needed
663 bool observer = false;
664
665 ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
666 termStructureHandle_.linkTo(temp, observer);
667
668 if (discountHandle_.empty())
669 discountRelinkableHandle_.linkTo(temp, observer);
670 else
672
674 }
675
677 QL_REQUIRE(termStructure_ != nullptr, "term structure not set");
678 // we didn't register as observers - force calculation
679 swap_->deepUpdate();
680 // weak implementation... to be improved
681 static const Spread basisPoint = 1.0e-4;
682 Real floatingLegNPV = swap_->floatingLegNPV();
683 Spread spread = spread_.empty() ? 0.0 : spread_->value();
684 Real spreadNPV = swap_->floatingLegBPS()/basisPoint*spread;
685 Real totNPV = - (floatingLegNPV+spreadNPV);
686 Real result = totNPV/(swap_->fixedLegBPS()/basisPoint);
687 return result;
688 }
689
691 auto* v1 = dynamic_cast<Visitor<SwapRateHelper>*>(&v);
692 if (v1 != nullptr)
693 v1->visit(*this);
694 else
696 }
697
699 const Period& tenor,
700 Natural settlementDays,
701 Calendar calendar,
702 // bma leg
703 const Period& bmaPeriod,
704 BusinessDayConvention bmaConvention,
705 DayCounter bmaDayCount,
706 ext::shared_ptr<BMAIndex> bmaIndex,
707 // libor leg
708 ext::shared_ptr<IborIndex> iborIndex)
709 : RelativeDateRateHelper(liborFraction), tenor_(tenor), settlementDays_(settlementDays),
710 calendar_(std::move(calendar)), bmaPeriod_(bmaPeriod), bmaConvention_(bmaConvention),
711 bmaDayCount_(std::move(bmaDayCount)), bmaIndex_(std::move(bmaIndex)),
712 iborIndex_(std::move(iborIndex)) {
716 }
717
719 // if the evaluation date is not a business day
720 // then move to the next business day
722 iborIndex_->fixingCalendar());
723 Date referenceDate = jc.adjust(evaluationDate_);
726
727 Date maturity = earliestDate_ + tenor_;
728
729 // dummy BMA index with curve/swap arguments
730 ext::shared_ptr<BMAIndex> clonedIndex(new BMAIndex(termStructureHandle_));
731
732 Schedule bmaSchedule =
733 MakeSchedule().from(earliestDate_).to(maturity)
735 .withCalendar(bmaIndex_->fixingCalendar())
737 .backwards();
738
739 Schedule liborSchedule =
740 MakeSchedule().from(earliestDate_).to(maturity)
741 .withTenor(iborIndex_->tenor())
742 .withCalendar(iborIndex_->fixingCalendar())
743 .withConvention(iborIndex_->businessDayConvention())
744 .endOfMonth(iborIndex_->endOfMonth())
745 .backwards();
746
747 swap_ = ext::make_shared<BMASwap>(Swap::Payer, 100.0,
748 liborSchedule,
749 0.75, // arbitrary
750 0.0,
752 iborIndex_->dayCounter(),
753 bmaSchedule,
754 clonedIndex,
756 swap_->setPricingEngine(ext::shared_ptr<PricingEngine>(new
757 DiscountingSwapEngine(iborIndex_->forwardingTermStructure())));
758
759 Date d = calendar_.adjust(swap_->maturityDate(), Following);
760 Weekday w = d.weekday();
761 Date nextWednesday = (w >= 4) ?
762 d + (11 - w) * Days :
763 d + (4 - w) * Days;
764 latestDate_ = clonedIndex->valueDate(
765 clonedIndex->fixingCalendar().adjust(nextWednesday));
766 }
767
769 // do not set the relinkable handle as an observer -
770 // force recalculation when needed
771 bool observer = false;
772
773 ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
774 termStructureHandle_.linkTo(temp, observer);
775
777 }
778
780 QL_REQUIRE(termStructure_ != nullptr, "term structure not set");
781 // we didn't register as observers - force calculation
782 swap_->deepUpdate();
783 return swap_->fairLiborFraction();
784 }
785
787 auto* v1 = dynamic_cast<Visitor<BMASwapRateHelper>*>(&v);
788 if (v1 != nullptr)
789 v1->visit(*this);
790 else
792 }
793
795 Handle<Quote> spotFx,
796 const Period& tenor,
797 Natural fixingDays,
798 Calendar calendar,
799 BusinessDayConvention convention,
800 bool endOfMonth,
801 bool isFxBaseCurrencyCollateralCurrency,
803 Calendar tradingCalendar)
804 : RelativeDateRateHelper(fwdPoint), spot_(std::move(spotFx)), tenor_(tenor),
805 fixingDays_(fixingDays), cal_(std::move(calendar)), conv_(convention), eom_(endOfMonth),
806 isFxBaseCurrencyCollateralCurrency_(isFxBaseCurrencyCollateralCurrency),
807 collHandle_(std::move(coll)), tradingCalendar_(std::move(tradingCalendar)) {
810
813 else
817 }
818
820 // if the evaluation date is not a business day
821 // then move to the next business day
822 Date refDate = cal_.adjust(evaluationDate_);
824
825 if (!tradingCalendar_.empty()) {
826 // check if fx trade can be settled in US, if not, adjust it
829 conv_, eom_);
830 } else {
832 }
833 }
834
836 QL_REQUIRE(termStructure_ != nullptr, "term structure not set");
837
838 QL_REQUIRE(!collHandle_.empty(), "collateral term structure not set");
839
841 DiscountFactor d2 = collHandle_->discount(latestDate_);
842 Real collRatio = d1 / d2;
843 d1 = termStructureHandle_->discount(earliestDate_);
844 d2 = termStructureHandle_->discount(latestDate_);
845 Real ratio = d1 / d2;
846 Real spot = spot_->value();
848 return (ratio/collRatio-1)*spot;
849 } else {
850 return (collRatio/ratio-1)*spot;
851 }
852 }
853
855 // do not set the relinkable handle as an observer -
856 // force recalculation when needed
857 bool observer = false;
858
859 ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
860 termStructureHandle_.linkTo(temp, observer);
861
862 collRelinkableHandle_.linkTo(*collHandle_, observer);
863
865 }
866
868 auto* v1 = dynamic_cast<Visitor<FxSwapRateHelper>*>(&v);
869 if (v1 != nullptr)
870 v1->visit(*this);
871 else
873 }
874
875}
ASX-related date functions.
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 Date maturityDate() const
instrument's maturity date
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
Rate helper for bootstrapping over deposit rates.
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)
Discounting engine for swaps.
Rate helper for bootstrapping over FRA rates.
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
Rate helper for bootstrapping over IborIndex futures prices.
Definition: ratehelpers.hpp:51
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:69
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
Bootstrap helper with date schedule relative to global evaluation date.
Payment schedule.
Definition: schedule.hpp:40
Rate helper for bootstrapping over swap rates.
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.
Currency specification.
const DefaultType & t
discounting swap engine
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
#define QL_FAIL(message)
throw an error (possibly with file and line information)
Definition: errors.hpp:92
Date d
Frequency
Frequency of events.
Definition: frequency.hpp:37
BusinessDayConvention
Business Day conventions.
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
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
Coupon paying a Libor-type index.
IMM-related date functions.
Joint calendar.
Helper class to instantiate standard market swaps.
Definition: any.hpp:35
RelinkableHandle< Quote > makeQuoteHandle(Real value)
Definition: simplequote.hpp:56
void simplifyNotificationGraph(Instrument &instrument, const Leg &leg, bool unregisterCoupons)
Utility function to optimize the observability graph of an instrument.
STL namespace.
empty deleter for shared_ptr
Maps optional to either the boost or std implementation.
ext::shared_ptr< BlackVolTermStructure > v
purely virtual base class for market observables
deposit, FRA, futures, and various swap rate helpers
utility functions to reduce number of notifications sent by observables
static Date nextDate(const Date &d=Date(), bool mainCycle=true)
next ASX date following the given date
Definition: asx.cpp:119
static bool isASXdate(const Date &d, bool mainCycle=true)
returns whether or not the given date is an ASX date
Definition: asx.cpp:38
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
swap-rate indexes