QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.38
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 const std::variant<Real, Handle<Quote>>& convAdj,
77 Futures::Type type)
78 : RateHelper(price), convAdj_(handleFromVariant(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 const Date& iborEndDate,
93 const DayCounter& dayCounter,
94 const std::variant<Real, Handle<Quote>>& convAdj,
95 Futures::Type type)
96 : RateHelper(price), convAdj_(handleFromVariant(convAdj)) {
97 CheckDate(iborStartDate, type);
98
99 const auto determineMaturityDate =
100 [&iborStartDate, &iborEndDate](const auto nextDateCalculator) -> Date {
102 if (iborEndDate == Date()) {
103 // advance 3 months
104 maturityDate = nextDateCalculator(iborStartDate);
105 maturityDate = nextDateCalculator(maturityDate);
106 maturityDate = nextDateCalculator(maturityDate);
107 } else {
108 QL_REQUIRE(iborEndDate > iborStartDate,
109 "end date (" << iborEndDate << ") must be greater than start date ("
110 << iborStartDate << ')');
111 maturityDate = iborEndDate;
112 }
113 return maturityDate;
114 };
115
116 switch (type) {
117 case Futures::IMM:
118 maturityDate_ = determineMaturityDate(
119 [](const Date date) -> Date { return IMM::nextDate(date, false); });
120 break;
121 case Futures::ASX:
122 maturityDate_ = determineMaturityDate(
123 [](const Date date) -> Date { return ASX::nextDate(date, false); });
124 break;
125 case Futures::Custom:
126 maturityDate_ = iborEndDate;
127 break;
128 default:
129 QL_FAIL("unsupported futures type (" << type << ')');
130 }
131 earliestDate_ = iborStartDate;
132 yearFraction_ = DetermineYearFraction(earliestDate_, maturityDate_, dayCounter);
134
136 }
137
139 const Date& iborStartDate,
140 const ext::shared_ptr<IborIndex>& index,
141 const std::variant<Real, Handle<Quote>>& convAdj,
142 Futures::Type type)
143 : RateHelper(price), convAdj_(handleFromVariant(convAdj)) {
144 CheckDate(iborStartDate, type);
145
146 earliestDate_ = iborStartDate;
147 const Calendar& cal = index->fixingCalendar();
149 cal.advance(iborStartDate, index->tenor(), index->businessDayConvention());
150 yearFraction_ = DetermineYearFraction(earliestDate_, maturityDate_, index->dayCounter());
152
154 }
155
157 QL_REQUIRE(termStructure_ != nullptr, "term structure not set");
158 Rate forwardRate = (termStructure_->discount(earliestDate_) /
159 termStructure_->discount(maturityDate_) - 1.0) / yearFraction_;
160 // Convexity, as FRA/futures adjustment, has been used in the
161 // past to take into account futures margining vs FRA.
162 // Therefore, there's no requirement for it to be non-negative.
163 Rate futureRate = forwardRate + convexityAdjustment();
164 return 100.0 * (1.0 - futureRate);
165 }
166
168 return convAdj_.empty() ? 0.0 : convAdj_->value();
169 }
170
172 auto* v1 = dynamic_cast<Visitor<FuturesRateHelper>*>(&v);
173 if (v1 != nullptr)
174 v1->visit(*this);
175 else
177 }
178
180 const Period& tenor,
181 Natural fixingDays,
182 const Calendar& calendar,
183 BusinessDayConvention convention,
184 bool endOfMonth,
185 const DayCounter& dayCounter)
186 : RelativeDateRateHelper(rate) {
187 iborIndex_ = ext::make_shared<IborIndex>("no-fix", // never take fixing into account
188 tenor, fixingDays,
189 Currency(), calendar, convention,
190 endOfMonth, dayCounter, termStructureHandle_);
192 }
193
195 const ext::shared_ptr<IborIndex>& i)
196 : RelativeDateRateHelper(rate) {
199 }
200
202 Date fixingDate,
203 const ext::shared_ptr<IborIndex>& i)
204 : RelativeDateRateHelper(rate, false), fixingDate_(fixingDate) {
207 }
208
210 QL_REQUIRE(termStructure_ != nullptr, "term structure not set");
211 // the forecast fixing flag is set to true because
212 // we do not want to take fixing into account
213 return iborIndex_->fixing(fixingDate_, true);
214 }
215
217 // do not set the relinkable handle as an observer -
218 // force recalculation when needed---the index is not lazy
219 bool observer = false;
220
221 ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
222 termStructureHandle_.linkTo(temp, observer);
223
225 }
226
228 if (updateDates_) {
229 // if the evaluation date is not a business day
230 // then move to the next business day
231 Date referenceDate =
232 iborIndex_->fixingCalendar().adjust(evaluationDate_);
233 earliestDate_ = iborIndex_->valueDate(referenceDate);
234 fixingDate_ = iborIndex_->fixingDate(earliestDate_);
235 } else {
237 }
238 maturityDate_ = iborIndex_->maturityDate(earliestDate_);
240 }
241
243 auto* v1 = dynamic_cast<Visitor<DepositRateHelper>*>(&v);
244 if (v1 != nullptr)
245 v1->visit(*this);
246 else
248 }
249
250
252 Natural monthsToStart,
253 Natural monthsToEnd,
254 Natural fixingDays,
255 const Calendar& calendar,
256 BusinessDayConvention convention,
257 bool endOfMonth,
258 const DayCounter& dayCounter,
259 Pillar::Choice pillarChoice,
260 Date customPillarDate,
261 bool useIndexedCoupon)
262 : FraRateHelper(rate, monthsToStart*Months, monthsToEnd-monthsToStart, fixingDays, calendar,
263 convention, endOfMonth, dayCounter, pillarChoice, customPillarDate, useIndexedCoupon) {
264 QL_REQUIRE(monthsToEnd>monthsToStart,
265 "monthsToEnd (" << monthsToEnd <<
266 ") must be grater than monthsToStart (" << monthsToStart <<
267 ")");
268 }
269
271 Natural monthsToStart,
272 const ext::shared_ptr<IborIndex>& i,
273 Pillar::Choice pillarChoice,
274 Date customPillarDate,
275 bool useIndexedCoupon)
276 : FraRateHelper(rate, monthsToStart*Months, i, pillarChoice, customPillarDate, useIndexedCoupon)
277 {}
278
280 Period periodToStart,
281 Natural lengthInMonths,
282 Natural fixingDays,
283 const Calendar& calendar,
284 BusinessDayConvention convention,
285 bool endOfMonth,
286 const DayCounter& dayCounter,
287 Pillar::Choice pillarChoice,
288 Date customPillarDate,
289 bool useIndexedCoupon)
290 : RelativeDateRateHelper(rate), periodToStart_(periodToStart),
291 pillarChoice_(pillarChoice), useIndexedCoupon_(useIndexedCoupon) {
292 // no way to take fixing into account,
293 // even if we would like to for FRA over today
294 iborIndex_ = ext::make_shared<IborIndex>("no-fix", // correct family name would be needed
295 lengthInMonths*Months,
296 fixingDays,
297 Currency(), calendar, convention,
298 endOfMonth, dayCounter, termStructureHandle_);
299 pillarDate_ = customPillarDate;
301 }
302
304 Period periodToStart,
305 const ext::shared_ptr<IborIndex>& i,
306 Pillar::Choice pillarChoice,
307 Date customPillarDate,
308 bool useIndexedCoupon)
309 : RelativeDateRateHelper(rate), periodToStart_(periodToStart),
310 pillarChoice_(pillarChoice), useIndexedCoupon_(useIndexedCoupon) {
311 // take fixing into account
313 // We want to be notified of changes of fixings, but we don't
314 // want notifications from termStructureHandle_ (they would
315 // interfere with bootstrapping.)
316 iborIndex_->unregisterWith(termStructureHandle_);
318 pillarDate_ = customPillarDate;
320 }
321
323 Natural immOffsetStart,
324 Natural immOffsetEnd,
325 const ext::shared_ptr<IborIndex>& i,
326 Pillar::Choice pillarChoice,
327 Date customPillarDate,
328 bool useIndexedCoupon)
329 : RelativeDateRateHelper(rate), immOffsetStart_(immOffsetStart), immOffsetEnd_(immOffsetEnd),
330 pillarChoice_(pillarChoice), useIndexedCoupon_(useIndexedCoupon) {
331 // take fixing into account
333 // see above
334 iborIndex_->unregisterWith(termStructureHandle_);
336 pillarDate_ = customPillarDate;
338 }
339
341 Date startDate,
342 Date endDate,
343 const ext::shared_ptr<IborIndex>& i,
344 Pillar::Choice pillarChoice,
345 Date customPillarDate,
346 bool useIndexedCoupon)
347 : RelativeDateRateHelper(rate, false), pillarChoice_(pillarChoice),
348 useIndexedCoupon_(useIndexedCoupon) {
349 // take fixing into account
351 // see above
352 iborIndex_->unregisterWith(termStructureHandle_);
354 earliestDate_ = startDate;
355 maturityDate_ = endDate;
356 pillarDate_ = customPillarDate;
358 }
359
361 QL_REQUIRE(termStructure_ != nullptr, "term structure not set");
363 return iborIndex_->fixing(fixingDate_, true);
364 else
365 return (termStructure_->discount(earliestDate_) /
366 termStructure_->discount(maturityDate_) -
367 1.0) /
369 }
370
372 // do not set the relinkable handle as an observer -
373 // force recalculation when needed---the index is not lazy
374 bool observer = false;
375
376 ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
377 termStructureHandle_.linkTo(temp, observer);
378
380 }
381
382 namespace {
383 Date nthImmDate(const Date& asof, const Size n) {
384 Date imm = asof;
385 for (Size i = 0; i < n; ++i) {
386 imm = IMM::nextDate(imm, true);
387 }
388 return imm;
389 }
390 }
391
393 if (updateDates_) {
394 // if the evaluation date is not a business day
395 // then move to the next business day
396 Date referenceDate =
397 iborIndex_->fixingCalendar().adjust(evaluationDate_);
398 Date spotDate = iborIndex_->fixingCalendar().advance(
399 referenceDate, iborIndex_->fixingDays()*Days);
400 if (periodToStart_) { // NOLINT(readability-implicit-bool-conversion)
401 earliestDate_ = iborIndex_->fixingCalendar().advance(
402 spotDate, *periodToStart_, iborIndex_->businessDayConvention(),
403 iborIndex_->endOfMonth());
404 // maturity date is calculated from spot date
405 maturityDate_ = iborIndex_->fixingCalendar().advance(
406 spotDate, *periodToStart_ + iborIndex_->tenor(), iborIndex_->businessDayConvention(),
407 iborIndex_->endOfMonth());
408
409 } else if ((immOffsetStart_) && (immOffsetEnd_)) { // NOLINT(readability-implicit-bool-conversion)
410 earliestDate_ = iborIndex_->fixingCalendar().adjust(nthImmDate(spotDate, *immOffsetStart_));
411 maturityDate_ = iborIndex_->fixingCalendar().adjust(nthImmDate(spotDate, *immOffsetEnd_));
412 } else {
413 QL_FAIL("neither periodToStart nor immOffsetStart/End given");
414 }
415 }
416
418 // latest relevant date is calculated from earliestDate_
420 else {
422 spanningTime_ = iborIndex_->dayCounter().yearFraction(earliestDate_, maturityDate_);
423 }
424
425 switch (pillarChoice_) {
428 break;
431 break;
433 // pillarDate_ already assigned at construction time
435 "pillar date (" << pillarDate_ << ") must be later "
436 "than or equal to the instrument's earliest date (" <<
437 earliestDate_ << ")");
439 "pillar date (" << pillarDate_ << ") must be before "
440 "or equal to the instrument's latest relevant date (" <<
441 latestRelevantDate_ << ")");
442 break;
443 default:
444 QL_FAIL("unknown Pillar::Choice(" << Integer(pillarChoice_) << ")");
445 }
446
447 latestDate_ = pillarDate_; // backward compatibility
448
449 fixingDate_ = iborIndex_->fixingDate(earliestDate_);
450 }
451
453 auto* v1 = dynamic_cast<Visitor<FraRateHelper>*>(&v);
454 if (v1 != nullptr)
455 v1->visit(*this);
456 else
458 }
459
460
462 const ext::shared_ptr<SwapIndex>& swapIndex,
463 Handle<Quote> spread,
464 const Period& fwdStart,
466 Pillar::Choice pillarChoice,
467 Date customPillarDate,
468 bool endOfMonth,
469 const ext::optional<bool>& useIndexedCoupons)
470 : SwapRateHelper(rate, swapIndex->tenor(), swapIndex->fixingCalendar(),
471 swapIndex->fixedLegTenor().frequency(), swapIndex->fixedLegConvention(),
472 swapIndex->dayCounter(), swapIndex->iborIndex(), std::move(spread), fwdStart,
473 std::move(discount), Null<Natural>(), pillarChoice, customPillarDate, endOfMonth,
474 useIndexedCoupons) {}
475
477 const Period& tenor,
478 Calendar calendar,
479 Frequency fixedFrequency,
480 BusinessDayConvention fixedConvention,
481 DayCounter fixedDayCount,
482 const ext::shared_ptr<IborIndex>& iborIndex,
483 Handle<Quote> spread,
484 const Period& fwdStart,
486 Natural settlementDays,
487 Pillar::Choice pillarChoice,
488 Date customPillarDate,
489 bool endOfMonth,
490 const ext::optional<bool>& useIndexedCoupons)
491 : RelativeDateRateHelper(rate), settlementDays_(settlementDays), tenor_(tenor),
492 pillarChoice_(pillarChoice), calendar_(std::move(calendar)),
493 fixedConvention_(fixedConvention), fixedFrequency_(fixedFrequency),
494 fixedDayCount_(std::move(fixedDayCount)), spread_(std::move(spread)), endOfMonth_(endOfMonth),
495 fwdStart_(fwdStart), discountHandle_(std::move(discount)),
496 useIndexedCoupons_(useIndexedCoupons) {
497 initialize(iborIndex, customPillarDate);
498 }
499
501 const Date& startDate,
502 const Date& endDate,
503 Calendar calendar,
504 Frequency fixedFrequency,
505 BusinessDayConvention fixedConvention,
506 DayCounter fixedDayCount,
507 const ext::shared_ptr<IborIndex>& iborIndex,
508 Handle<Quote> spread,
510 Pillar::Choice pillarChoice,
511 Date customPillarDate,
512 bool endOfMonth,
513 const ext::optional<bool>& useIndexedCoupons)
514 : RelativeDateRateHelper(rate, false), startDate_(startDate), endDate_(endDate),
515 pillarChoice_(pillarChoice), calendar_(std::move(calendar)),
516 fixedConvention_(fixedConvention), fixedFrequency_(fixedFrequency),
517 fixedDayCount_(std::move(fixedDayCount)), spread_(std::move(spread)), endOfMonth_(endOfMonth),
518 discountHandle_(std::move(discount)), useIndexedCoupons_(useIndexedCoupons) {
519 QL_REQUIRE(fixedFrequency != Once,
520 "fixedFrequency == Once is not supported when passing explicit "
521 "startDate and endDate");
522 initialize(iborIndex, customPillarDate);
523 }
524
525 void SwapRateHelper::initialize(const ext::shared_ptr<IborIndex>& iborIndex,
526 Date customPillarDate) {
527 // take fixing into account
528 iborIndex_ = iborIndex->clone(termStructureHandle_);
529 // We want to be notified of changes of fixings, but we don't
530 // want notifications from termStructureHandle_ (they would
531 // interfere with bootstrapping.)
532 iborIndex_->unregisterWith(termStructureHandle_);
533
537
538 pillarDate_ = customPillarDate;
540 }
541
543
544 // 1. do not pass the spread here, as it might be a Quote
545 // i.e. it can dynamically change
546 // 2. input discount curve Handle might be empty now but it could
547 // be assigned a curve later; use a RelinkableHandle here
549 .withSettlementDays(settlementDays_) // resets effectiveDate
562
564
565 earliestDate_ = swap_->startDate();
566 maturityDate_ = swap_->maturityDate();
567
568 ext::shared_ptr<IborCoupon> lastCoupon =
569 ext::dynamic_pointer_cast<IborCoupon>(swap_->floatingLeg().back());
570 latestRelevantDate_ = std::max(maturityDate_, lastCoupon->fixingEndDate());
571
572 switch (pillarChoice_) {
575 break;
578 break;
580 // pillarDate_ already assigned at construction time
582 "pillar date (" << pillarDate_ << ") must be later "
583 "than or equal to the instrument's earliest date (" <<
584 earliestDate_ << ")");
586 "pillar date (" << pillarDate_ << ") must be before "
587 "or equal to the instrument's latest relevant date (" <<
588 latestRelevantDate_ << ")");
589 break;
590 default:
591 QL_FAIL("unknown Pillar::Choice(" << Integer(pillarChoice_) << ")");
592 }
593
594 latestDate_ = pillarDate_; // backward compatibility
595
596 }
597
599 // do not set the relinkable handle as an observer -
600 // force recalculation when needed
601 bool observer = false;
602
603 ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
604 termStructureHandle_.linkTo(temp, observer);
605
606 if (discountHandle_.empty())
607 discountRelinkableHandle_.linkTo(temp, observer);
608 else
610
612 }
613
615 QL_REQUIRE(termStructure_ != nullptr, "term structure not set");
616 // we didn't register as observers - force calculation
617 swap_->deepUpdate();
618 // weak implementation... to be improved
619 static const Spread basisPoint = 1.0e-4;
620 Real floatingLegNPV = swap_->floatingLegNPV();
621 Spread spread = spread_.empty() ? 0.0 : spread_->value();
622 Real spreadNPV = swap_->floatingLegBPS()/basisPoint*spread;
623 Real totNPV = - (floatingLegNPV+spreadNPV);
624 Real result = totNPV/(swap_->fixedLegBPS()/basisPoint);
625 return result;
626 }
627
629 auto* v1 = dynamic_cast<Visitor<SwapRateHelper>*>(&v);
630 if (v1 != nullptr)
631 v1->visit(*this);
632 else
634 }
635
637 const Period& tenor,
638 Natural settlementDays,
639 Calendar calendar,
640 // bma leg
641 const Period& bmaPeriod,
642 BusinessDayConvention bmaConvention,
643 DayCounter bmaDayCount,
644 ext::shared_ptr<BMAIndex> bmaIndex,
645 // libor leg
646 ext::shared_ptr<IborIndex> iborIndex)
647 : RelativeDateRateHelper(liborFraction), tenor_(tenor), settlementDays_(settlementDays),
648 calendar_(std::move(calendar)), bmaPeriod_(bmaPeriod), bmaConvention_(bmaConvention),
649 bmaDayCount_(std::move(bmaDayCount)), bmaIndex_(std::move(bmaIndex)),
650 iborIndex_(std::move(iborIndex)) {
654 }
655
657 // if the evaluation date is not a business day
658 // then move to the next business day
660 iborIndex_->fixingCalendar());
661 Date referenceDate = jc.adjust(evaluationDate_);
664
665 Date maturity = earliestDate_ + tenor_;
666
667 // dummy BMA index with curve/swap arguments
668 ext::shared_ptr<BMAIndex> clonedIndex(new BMAIndex(termStructureHandle_));
669
670 Schedule bmaSchedule =
671 MakeSchedule().from(earliestDate_).to(maturity)
673 .withCalendar(bmaIndex_->fixingCalendar())
675 .backwards();
676
677 Schedule liborSchedule =
678 MakeSchedule().from(earliestDate_).to(maturity)
679 .withTenor(iborIndex_->tenor())
680 .withCalendar(iborIndex_->fixingCalendar())
681 .withConvention(iborIndex_->businessDayConvention())
682 .endOfMonth(iborIndex_->endOfMonth())
683 .backwards();
684
685 swap_ = ext::make_shared<BMASwap>(Swap::Payer, 100.0,
686 liborSchedule,
687 0.75, // arbitrary
688 0.0,
690 iborIndex_->dayCounter(),
691 bmaSchedule,
692 clonedIndex,
694 swap_->setPricingEngine(ext::shared_ptr<PricingEngine>(new
695 DiscountingSwapEngine(iborIndex_->forwardingTermStructure())));
696
697 Date d = calendar_.adjust(swap_->maturityDate(), Following);
698 Weekday w = d.weekday();
699 Date nextWednesday = (w >= 4) ?
700 d + (11 - w) * Days :
701 d + (4 - w) * Days;
702 latestDate_ = clonedIndex->valueDate(
703 clonedIndex->fixingCalendar().adjust(nextWednesday));
704 }
705
707 // do not set the relinkable handle as an observer -
708 // force recalculation when needed
709 bool observer = false;
710
711 ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
712 termStructureHandle_.linkTo(temp, observer);
713
715 }
716
718 QL_REQUIRE(termStructure_ != nullptr, "term structure not set");
719 // we didn't register as observers - force calculation
720 swap_->deepUpdate();
721 return swap_->fairLiborFraction();
722 }
723
725 auto* v1 = dynamic_cast<Visitor<BMASwapRateHelper>*>(&v);
726 if (v1 != nullptr)
727 v1->visit(*this);
728 else
730 }
731
733 Handle<Quote> spotFx,
734 const Period& tenor,
735 Natural fixingDays,
736 Calendar calendar,
737 BusinessDayConvention convention,
738 bool endOfMonth,
739 bool isFxBaseCurrencyCollateralCurrency,
741 Calendar tradingCalendar)
742 : RelativeDateRateHelper(fwdPoint), spot_(std::move(spotFx)), tenor_(tenor),
743 fixingDays_(fixingDays), cal_(std::move(calendar)), conv_(convention), eom_(endOfMonth),
744 isFxBaseCurrencyCollateralCurrency_(isFxBaseCurrencyCollateralCurrency),
745 collHandle_(std::move(coll)), tradingCalendar_(std::move(tradingCalendar)) {
748
751 else
755 }
756
758 // if the evaluation date is not a business day
759 // then move to the next business day
760 Date refDate = cal_.adjust(evaluationDate_);
762
763 if (!tradingCalendar_.empty()) {
764 // check if fx trade can be settled in US, if not, adjust it
767 conv_, eom_);
768 } else {
770 }
771 }
772
774 QL_REQUIRE(termStructure_ != nullptr, "term structure not set");
775
776 QL_REQUIRE(!collHandle_.empty(), "collateral term structure not set");
777
779 DiscountFactor d2 = collHandle_->discount(latestDate_);
780 Real collRatio = d1 / d2;
781 d1 = termStructureHandle_->discount(earliestDate_);
782 d2 = termStructureHandle_->discount(latestDate_);
783 Real ratio = d1 / d2;
784 Real spot = spot_->value();
786 return (ratio/collRatio-1)*spot;
787 } else {
788 return (collRatio/ratio-1)*spot;
789 }
790 }
791
793 // do not set the relinkable handle as an observer -
794 // force recalculation when needed
795 bool observer = false;
796
797 ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
798 termStructureHandle_.linkTo(temp, observer);
799
800 collRelinkableHandle_.linkTo(*collHandle_, observer);
801
803 }
804
806 auto* v1 = dynamic_cast<Visitor<FxSwapRateHelper>*>(&v);
807 if (v1 != nullptr)
808 v1->visit(*this);
809 else
811 }
812
813}
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:208
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
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 std::variant< Rate, 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_
FraRateHelper(const std::variant< Rate, 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)
ext::shared_ptr< IborIndex > iborIndex_
ext::optional< Period > periodToStart_
void accept(AcyclicVisitor &) override
void initializeDates() override
Real impliedQuote() const override
void accept(AcyclicVisitor &) override
FuturesRateHelper(const std::variant< Real, Handle< Quote > > &price, const Date &iborStartDate, Natural lengthInMonths, const Calendar &calendar, BusinessDayConvention convention, bool endOfMonth, const DayCounter &dayCounter, const std::variant< Real, Handle< Quote > > &convexityAdjustment=0.0, Futures::Type type=Futures::IMM)
Definition: ratehelpers.cpp:69
Real impliedQuote() const override
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:552
MakeSchedule & backwards()
Definition: schedule.cpp:573
MakeSchedule & to(const Date &terminationDate)
Definition: schedule.cpp:532
MakeSchedule & withTenor(const Period &)
Definition: schedule.cpp:537
MakeSchedule & from(const Date &effectiveDate)
Definition: schedule.cpp:527
MakeSchedule & endOfMonth(bool flag=true)
Definition: schedule.cpp:578
MakeSchedule & withCalendar(const Calendar &)
Definition: schedule.cpp:547
MakeVanillaSwap & withEffectiveDate(const Date &)
MakeVanillaSwap & withFixedLegConvention(BusinessDayConvention bdc)
MakeVanillaSwap & withFixedLegTerminationDateConvention(BusinessDayConvention bdc)
MakeVanillaSwap & withFixedLegCalendar(const Calendar &cal)
MakeVanillaSwap & withTerminationDate(const Date &)
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:59
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
Definition: observable.hpp:226
Bootstrap helper with date schedule relative to global evaluation date.
Payment schedule.
Definition: schedule.hpp:40
Rate helper for bootstrapping over swap rates.
SwapRateHelper(const std::variant< Rate, 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)
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
void initializeDates() override
Real impliedQuote() const override
void initialize(const ext::shared_ptr< IborIndex > &iborIndex, Date customPillarDate)
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.
@ Once
only once, e.g., a zero-coupon
Definition: frequency.hpp:38
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:37
Handle< Quote > handleFromVariant(const std::variant< Real, Handle< Quote > > &value)
Definition: quote.cpp:27
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
Alternatives ways of determining the pillar date.
@ CustomDate
last date relevant for instrument pricing
@ LastRelevantDate
instruments maturity date
swap-rate indexes