Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
basistwoswaphelper.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2016 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
19#include <ql/cashflows/floatingratecoupon.hpp>
20#include <ql/cashflows/iborcoupon.hpp>
21#include <ql/instruments/makevanillaswap.hpp>
22#include <ql/utilities/null_deleter.hpp>
24
25namespace QuantExt {
26
27BasisTwoSwapHelper::BasisTwoSwapHelper(const Handle<Quote>& spread, const Period& swapTenor, const Calendar& calendar,
28 // Long tenor swap
29 Frequency longFixedFrequency, BusinessDayConvention longFixedConvention,
30 const DayCounter& longFixedDayCount,
31 const QuantLib::ext::shared_ptr<IborIndex>& longIndex,
32 // Short tenor swap
33 Frequency shortFixedFrequency, BusinessDayConvention shortFixedConvention,
34 const DayCounter& shortFixedDayCount,
35 const QuantLib::ext::shared_ptr<IborIndex>& shortIndex, bool longMinusShort,
36 // Discount curve
37 const Handle<YieldTermStructure>& discountingCurve)
38 : RelativeDateRateHelper(spread), swapTenor_(swapTenor), calendar_(calendar),
39 longFixedFrequency_(longFixedFrequency), longFixedConvention_(longFixedConvention),
40 longFixedDayCount_(longFixedDayCount), longIndex_(longIndex), shortFixedFrequency_(shortFixedFrequency),
41 shortFixedConvention_(shortFixedConvention), shortFixedDayCount_(shortFixedDayCount), shortIndex_(shortIndex),
42 longMinusShort_(longMinusShort), discountHandle_(discountingCurve) {
43
44 QL_REQUIRE(longIndex_->tenor() >= shortIndex_->tenor(),
45 "Tenor of longIndex should be at least tenor of shortIndex.");
46
47 bool longIndexHasCurve = !longIndex_->forwardingTermStructure().empty();
48 bool shortIndexHasCurve = !shortIndex_->forwardingTermStructure().empty();
49 bool haveDiscountCurve = !discountHandle_.empty();
50 QL_REQUIRE(!(longIndexHasCurve && shortIndexHasCurve && haveDiscountCurve),
51 "Have all curves nothing to solve for.");
52
53 if (longIndexHasCurve && !shortIndexHasCurve) {
55 shortIndex_->unregisterWith(termStructureHandle_);
56 } else if (!longIndexHasCurve && shortIndexHasCurve) {
58 longIndex_->unregisterWith(termStructureHandle_);
59 } else if (!longIndexHasCurve && !shortIndexHasCurve) {
60 QL_FAIL("Need at least one of the indices to have a valid curve.");
61 }
62
63 registerWith(longIndex_);
64 registerWith(shortIndex_);
65 registerWith(discountHandle_);
67}
68
70
71 /* Important to use a fixed rate of 0.0 here to avoid the calculation
72 of the atm swap rate in MakeVanillaSwap operator ...(). If it is
73 Null, you get an exception because the discountRelinkableHandle_
74 is initially empty. */
75 longSwap_ = MakeVanillaSwap(swapTenor_, longIndex_, 0.0)
76 .withDiscountingTermStructure(discountRelinkableHandle_)
77 .withFixedLegDayCount(longFixedDayCount_)
78 .withFixedLegTenor(Period(longFixedFrequency_))
79 .withFixedLegConvention(longFixedConvention_)
80 .withFixedLegTerminationDateConvention(longFixedConvention_)
81 .withFixedLegCalendar(calendar_)
82 .withFloatingLegCalendar(calendar_);
83
84 shortSwap_ = MakeVanillaSwap(swapTenor_, shortIndex_, 0.0)
85 .withDiscountingTermStructure(discountRelinkableHandle_)
86 .withFixedLegDayCount(shortFixedDayCount_)
87 .withFixedLegTenor(Period(shortFixedFrequency_))
88 .withFixedLegConvention(shortFixedConvention_)
89 .withFixedLegTerminationDateConvention(shortFixedConvention_)
90 .withFixedLegCalendar(calendar_)
91 .withFloatingLegCalendar(calendar_);
92
93 earliestDate_ = std::min(longSwap_->startDate(), shortSwap_->startDate());
94 latestDate_ = std::max(longSwap_->maturityDate(), shortSwap_->maturityDate());
95
96/* May need to adjust latestDate_ if you are projecting libor based
97 on tenor length rather than from accrual date to accrual date. */
98 if (!IborCoupon::Settings::instance().usingAtParCoupons()) {
99 if (termStructureHandle_ == shortIndex_->forwardingTermStructure()) {
100 QuantLib::ext::shared_ptr<FloatingRateCoupon> lastFloating =
101 QuantLib::ext::dynamic_pointer_cast<FloatingRateCoupon>(shortSwap_->floatingLeg().back());
102 Date fixingValueDate = shortIndex_->valueDate(lastFloating->fixingDate());
103 Date endValueDate = shortIndex_->maturityDate(fixingValueDate);
104 latestDate_ = std::max(latestDate_, endValueDate);
105 }
106 if (termStructureHandle_ == longIndex_->forwardingTermStructure()) {
107 QuantLib::ext::shared_ptr<FloatingRateCoupon> lastFloating =
108 QuantLib::ext::dynamic_pointer_cast<FloatingRateCoupon>(longSwap_->floatingLeg().back());
109 Date fixingValueDate = longIndex_->valueDate(lastFloating->fixingDate());
110 Date endValueDate = longIndex_->maturityDate(fixingValueDate);
111 latestDate_ = std::max(latestDate_, endValueDate);
112 }
113 }
114}
115
116void BasisTwoSwapHelper::setTermStructure(YieldTermStructure* t) {
117
118 bool observer = false;
119
120 QuantLib::ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
121 termStructureHandle_.linkTo(temp, observer);
122
123 if (discountHandle_.empty())
124 discountRelinkableHandle_.linkTo(temp, observer);
125 else
127
128 RelativeDateRateHelper::setTermStructure(t);
129}
130
132 QL_REQUIRE(termStructure_ != 0, "Termstructure not set");
133 longSwap_->deepUpdate();
134 shortSwap_->deepUpdate();
135 if (longMinusShort_)
136 return longSwap_->fairRate() - shortSwap_->fairRate();
137 else
138 return shortSwap_->fairRate() - longSwap_->fairRate();
139}
140
141void BasisTwoSwapHelper::accept(AcyclicVisitor& v) {
142 Visitor<BasisTwoSwapHelper>* v1 = dynamic_cast<Visitor<BasisTwoSwapHelper>*>(&v);
143 if (v1 != 0)
144 v1->visit(*this);
145 else
146 RateHelper::accept(v);
147}
148} // namespace QuantExt
Libor basis swap helper as two swaps.
RelinkableHandle< YieldTermStructure > discountRelinkableHandle_
void setTermStructure(YieldTermStructure *) override
BasisTwoSwapHelper(const Handle< Quote > &spread, const Period &swapTenor, const Calendar &calendar, Frequency longFixedFrequency, BusinessDayConvention longFixedConvention, const DayCounter &longFixedDayCount, const QuantLib::ext::shared_ptr< IborIndex > &longIndex, Frequency shortFixedFrequency, BusinessDayConvention shortFixedConvention, const DayCounter &shortFixedDayCount, const QuantLib::ext::shared_ptr< IborIndex > &shortIndex, bool longMinusShort=true, const Handle< YieldTermStructure > &discountingCurve=Handle< YieldTermStructure >())
RelinkableHandle< YieldTermStructure > termStructureHandle_
BusinessDayConvention longFixedConvention_
QuantLib::ext::shared_ptr< VanillaSwap > longSwap_
Handle< YieldTermStructure > discountHandle_
void accept(AcyclicVisitor &) override
QuantLib::ext::shared_ptr< VanillaSwap > shortSwap_
BusinessDayConvention shortFixedConvention_
Real impliedQuote() const override
QuantLib::ext::shared_ptr< IborIndex > shortIndex_
QuantLib::ext::shared_ptr< IborIndex > longIndex_