Coverage Report

Created: 2025-09-04 07:11

/src/quantlib/ql/indexes/swapindex.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 Copyright (C) 2006, 2009 Ferdinando Ametrano
3
 Copyright (C) 2006, 2007, 2009 StatPro Italia srl
4
5
 This file is part of QuantLib, a free-software/open-source library
6
 for financial quantitative analysts and developers - http://quantlib.org/
7
8
 QuantLib is free software: you can redistribute it and/or modify it
9
 under the terms of the QuantLib license.  You should have received a
10
 copy of the license along with this program; if not, please email
11
 <quantlib-dev@lists.sf.net>. The license is also available online at
12
 <https://www.quantlib.org/license.shtml>.
13
14
15
 This program is distributed in the hope that it will be useful, but
16
 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17
 or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */
18
19
#include <ql/indexes/iborindex.hpp>
20
#include <ql/indexes/swapindex.hpp>
21
#include <ql/instruments/makeois.hpp>
22
#include <ql/instruments/makevanillaswap.hpp>
23
#include <ql/time/schedule.hpp>
24
#include <sstream>
25
#include <utility>
26
27
namespace QuantLib {
28
29
    SwapIndex::SwapIndex(const std::string& familyName,
30
                         const Period& tenor,
31
                         Natural settlementDays,
32
                         const Currency& currency,
33
                         const Calendar& fixingCalendar,
34
                         const Period& fixedLegTenor,
35
                         BusinessDayConvention fixedLegConvention,
36
                         const DayCounter& fixedLegDayCounter,
37
                         ext::shared_ptr<IborIndex> iborIndex)
38
0
    : InterestRateIndex(
39
0
          familyName, tenor, settlementDays, currency, fixingCalendar, fixedLegDayCounter),
40
0
      tenor_(tenor), iborIndex_(std::move(iborIndex)), fixedLegTenor_(fixedLegTenor),
41
0
      fixedLegConvention_(fixedLegConvention), exogenousDiscount_(false) {
42
0
        registerWith(iborIndex_);
43
0
    }
44
45
    SwapIndex::SwapIndex(const std::string& familyName,
46
                         const Period& tenor,
47
                         Natural settlementDays,
48
                         const Currency& currency,
49
                         const Calendar& fixingCalendar,
50
                         const Period& fixedLegTenor,
51
                         BusinessDayConvention fixedLegConvention,
52
                         const DayCounter& fixedLegDayCounter,
53
                         ext::shared_ptr<IborIndex> iborIndex,
54
                         Handle<YieldTermStructure> discount)
55
0
    : InterestRateIndex(
56
0
          familyName, tenor, settlementDays, currency, fixingCalendar, fixedLegDayCounter),
57
0
      tenor_(tenor), iborIndex_(std::move(iborIndex)), fixedLegTenor_(fixedLegTenor),
58
0
      fixedLegConvention_(fixedLegConvention), exogenousDiscount_(true),
59
0
      discount_(std::move(discount)) {
60
0
        registerWith(iborIndex_);
61
0
        registerWith(discount_);
62
0
    }
63
64
0
    Handle<YieldTermStructure> SwapIndex::forwardingTermStructure() const {
65
0
        return iborIndex_->forwardingTermStructure();
66
0
    }
67
68
0
    Handle<YieldTermStructure> SwapIndex::discountingTermStructure() const {
69
0
        return discount_;  // empty if not exogenous
70
0
    }
71
72
0
    Rate SwapIndex::forecastFixing(const Date& fixingDate) const {
73
0
        return underlyingSwap(fixingDate)->fairRate();
74
0
    }
75
76
    ext::shared_ptr<VanillaSwap>
77
0
    SwapIndex::underlyingSwap(const Date& fixingDate) const {
78
79
0
        QL_REQUIRE(fixingDate!=Date(), "null fixing date");
80
81
        // caching mechanism
82
0
        if (lastFixingDate_!=fixingDate) {
83
0
            Rate fixedRate = 0.0;
84
0
            if (exogenousDiscount_)
85
0
                lastSwap_ = MakeVanillaSwap(tenor_, iborIndex_, fixedRate)
86
0
                    .withEffectiveDate(valueDate(fixingDate))
87
0
                    .withFixedLegCalendar(fixingCalendar())
88
0
                    .withFixedLegDayCount(dayCounter_)
89
0
                    .withFixedLegTenor(fixedLegTenor_)
90
0
                    .withFixedLegConvention(fixedLegConvention_)
91
0
                    .withFixedLegTerminationDateConvention(fixedLegConvention_)
92
0
                    .withDiscountingTermStructure(discount_);
93
0
            else
94
0
                lastSwap_ = MakeVanillaSwap(tenor_, iborIndex_, fixedRate)
95
0
                    .withEffectiveDate(valueDate(fixingDate))
96
0
                    .withFixedLegCalendar(fixingCalendar())
97
0
                    .withFixedLegDayCount(dayCounter_)
98
0
                    .withFixedLegTenor(fixedLegTenor_)
99
0
                    .withFixedLegConvention(fixedLegConvention_)
100
0
                    .withFixedLegTerminationDateConvention(fixedLegConvention_);
101
0
            lastFixingDate_ = fixingDate;
102
0
        }
103
0
        return lastSwap_;
104
0
    }
105
106
0
    Date SwapIndex::maturityDate(const Date& valueDate) const {
107
0
        Date fixDate = fixingDate(valueDate);
108
0
        return underlyingSwap(fixDate)->maturityDate();
109
0
    }
110
111
    ext::shared_ptr<SwapIndex>
112
0
    SwapIndex::clone(const Handle<YieldTermStructure>& forwarding) const {
113
114
0
        if (exogenousDiscount_)
115
0
            return ext::make_shared<SwapIndex>(familyName(),
116
0
                          tenor(),
117
0
                          fixingDays(),
118
0
                          currency(),
119
0
                          fixingCalendar(),
120
0
                          fixedLegTenor(),
121
0
                          fixedLegConvention(),
122
0
                          dayCounter(),
123
0
                          iborIndex_->clone(forwarding),
124
0
                          discount_);
125
0
        else
126
0
            return ext::make_shared<SwapIndex>(familyName(),
127
0
                          tenor(),
128
0
                          fixingDays(),
129
0
                          currency(),
130
0
                          fixingCalendar(),
131
0
                          fixedLegTenor(),
132
0
                          fixedLegConvention(),
133
0
                          dayCounter(),
134
0
                          iborIndex_->clone(forwarding));
135
0
    }
136
137
    ext::shared_ptr<SwapIndex>
138
    SwapIndex::clone(const Handle<YieldTermStructure>& forwarding,
139
0
                     const Handle<YieldTermStructure>& discounting) const {
140
0
        return ext::make_shared<SwapIndex>(familyName(),
141
0
                       tenor(),
142
0
                       fixingDays(),
143
0
                       currency(),
144
0
                       fixingCalendar(),
145
0
                       fixedLegTenor(),
146
0
                       fixedLegConvention(),
147
0
                       dayCounter(),
148
0
                       iborIndex_->clone(forwarding),
149
0
                       discounting);
150
0
    }
151
152
    ext::shared_ptr<SwapIndex>
153
0
    SwapIndex::clone(const Period& tenor) const {
154
155
0
        if (exogenousDiscount_)
156
0
            return ext::make_shared<SwapIndex>(familyName(),
157
0
                          tenor,
158
0
                          fixingDays(),
159
0
                          currency(),
160
0
                          fixingCalendar(),
161
0
                          fixedLegTenor(),
162
0
                          fixedLegConvention(),
163
0
                          dayCounter(),
164
0
                          iborIndex(),
165
0
                          discountingTermStructure());
166
0
        else
167
0
            return ext::make_shared<SwapIndex>(familyName(),
168
0
                          tenor,
169
0
                          fixingDays(),
170
0
                          currency(),
171
0
                          fixingCalendar(),
172
0
                          fixedLegTenor(),
173
0
                          fixedLegConvention(),
174
0
                          dayCounter(),
175
0
                          iborIndex());
176
177
0
    }
178
179
    OvernightIndexedSwapIndex::OvernightIndexedSwapIndex(
180
        const std::string& familyName,
181
        const Period& tenor,
182
        Natural settlementDays,
183
        const Currency& currency,
184
        const ext::shared_ptr<OvernightIndex>& overnightIndex,
185
        bool telescopicValueDates,
186
        RateAveraging::Type averagingMethod)
187
0
    : SwapIndex(familyName,
188
0
                tenor,
189
0
                settlementDays,
190
0
                currency,
191
0
                overnightIndex->fixingCalendar(),
192
0
                1 * Years,
193
0
                ModifiedFollowing,
194
0
                overnightIndex->dayCounter(),
195
0
                overnightIndex),
196
0
      overnightIndex_(overnightIndex), 
197
0
      telescopicValueDates_(telescopicValueDates), 
198
0
      averagingMethod_(averagingMethod) {}
199
200
201
    ext::shared_ptr<OvernightIndexedSwap>
202
0
    OvernightIndexedSwapIndex::underlyingSwap(const Date& fixingDate) const {
203
204
0
        QL_REQUIRE(fixingDate!=Date(), "null fixing date");
205
206
        // caching mechanism
207
0
        if (lastFixingDate_!=fixingDate) {
208
0
            Rate fixedRate = 0.0;
209
0
            lastSwap_ = MakeOIS(tenor_, overnightIndex_, fixedRate)
210
0
                .withEffectiveDate(valueDate(fixingDate))
211
0
                .withFixedLegDayCount(dayCounter_)
212
0
                .withTelescopicValueDates(telescopicValueDates_)
213
0
                .withAveragingMethod(averagingMethod_);
214
0
            lastFixingDate_ = fixingDate;
215
0
        }
216
0
        return lastSwap_;
217
0
    }
218
219
}