• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lballabio / QuantLib / 22527252709

28 Feb 2026 07:16PM UTC coverage: 74.244% (-0.009%) from 74.253%
22527252709

Pull #2459

github

web-flow
Merge ef761a963 into 266039865
Pull Request #2459: MakeOIS and MakeVanilla end-of-month handling

5 of 18 new or added lines in 2 files covered. (27.78%)

48 existing lines in 2 files now uncovered.

57639 of 77635 relevant lines covered (74.24%)

8735529.53 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.06
/ql/instruments/makeois.cpp
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2

3
/*
4
 Copyright (C) 2009, 2014, 2015 Ferdinando Ametrano
5
 Copyright (C) 2015 Paolo Mazzocchi
6
 Copyright (C) 2017 Joseph Jeisman
7
 Copyright (C) 2017 Fabrice Lecuyer
8

9
 This file is part of QuantLib, a free-software/open-source library
10
 for financial quantitative analysts and developers - http://quantlib.org/
11

12
 QuantLib is free software: you can redistribute it and/or modify it
13
 under the terms of the QuantLib license.  You should have received a
14
 copy of the license along with this program; if not, please email
15
 <quantlib-dev@lists.sf.net>. The license is also available online at
16
 <https://www.quantlib.org/license.shtml>.
17

18
 This program is distributed in the hope that it will be useful, but WITHOUT
19
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20
 FOR A PARTICULAR PURPOSE.  See the license for more details.
21
*/
22

23
#include <ql/instruments/makeois.hpp>
24
#include <ql/pricingengines/swap/discountingswapengine.hpp>
25
#include <ql/indexes/iborindex.hpp>
26
#include <ql/time/schedule.hpp>
27
#include <ql/indexes/ibor/sonia.hpp>
28
#include <ql/indexes/ibor/corra.hpp>
29

30
namespace QuantLib {
31

32
    MakeOIS::MakeOIS(const Period& swapTenor,
1,621✔
33
                     const ext::shared_ptr<OvernightIndex>& overnightIndex,
34
                     Rate fixedRate,
35
                     const Period& forwardStart)
1,621✔
36
    : swapTenor_(swapTenor), overnightIndex_(overnightIndex), fixedRate_(fixedRate),
1,621✔
37
      forwardStart_(forwardStart),
1,621✔
38
      fixedCalendar_(overnightIndex->fixingCalendar()),
1,621✔
39
      overnightCalendar_(overnightIndex->fixingCalendar()),
1,621✔
40
      fixedDayCount_(overnightIndex->dayCounter()) {}
4,863✔
41

42
    MakeOIS::operator OvernightIndexedSwap() const {
29✔
43
        ext::shared_ptr<OvernightIndexedSwap> ois = *this;
29✔
44
        return *ois;
58✔
45
    }
46

47
    MakeOIS::operator ext::shared_ptr<OvernightIndexedSwap>() const {
1,621✔
48

49
        Date startDate;
1,621✔
50
        if (effectiveDate_ != Date())
1,621✔
51
            startDate = effectiveDate_;
1,178✔
52
        else {
53
            // settlement days: override if set, else fallback to default by index name
54
            Natural settlementDays = settlementDays_;
443✔
55
            if (settlementDays == Null<Natural>()) {
443✔
56
                if (ext::dynamic_pointer_cast<Sonia>(overnightIndex_)) {
32✔
57
                    settlementDays = 0; 
58
                }
59
                else if (ext::dynamic_pointer_cast<Corra>(overnightIndex_)) {
28✔
60
                    settlementDays = 1;
61
                }
62
                else {
63
                    settlementDays = 2;
64
                }
65
            }            
66

67
            Date refDate = Settings::instance().evaluationDate();
443✔
68
            // if the evaluation date is not a business day
69
            // then move to the next business day
70
            refDate = overnightCalendar_.adjust(refDate);
443✔
71
            Date spotDate = overnightCalendar_.advance(refDate,
443✔
72
                                                       settlementDays*Days);
443✔
73
            startDate = spotDate+forwardStart_;
443✔
74
            if (forwardStart_.length()<0)
443✔
75
                startDate = overnightCalendar_.adjust(startDate, Preceding);
×
76
            else
77
                startDate = overnightCalendar_.adjust(startDate, Following);
443✔
78
        }
79

80
        bool fixedEndOfMonth, overnightEndOfMonth, maturityEndOfMonth;
81
        if (isDefaultEOM_)
1,621✔
82
            fixedEndOfMonth = overnightEndOfMonth = maturityEndOfMonth =
83
                overnightCalendar_.isEndOfMonth(startDate);
1,621✔
84
        else {
85
            fixedEndOfMonth = fixedEndOfMonth_;
×
86
            overnightEndOfMonth = overnightEndOfMonth_;
×
NEW
87
            maturityEndOfMonth = maturityEndOfMonth_;
×
88
        }
89

90
        Date endDate = terminationDate_;
1,621✔
91
        if (endDate == Date()) {
1,621✔
92
            endDate = startDate + swapTenor_;
1,615✔
93
            if (maturityEndOfMonth && allowsEndOfMonth(swapTenor_) &&
1,615✔
NEW
94
                overnightCalendar_.isEndOfMonth(startDate))
×
NEW
95
                endDate = maturityEndOfMonthCalendarDate_ ? Date::endOfMonth(endDate) :
×
NEW
UNCOV
96
                                                            overnightCalendar_.endOfMonth(endDate);
×
97
        }
98

99
        Frequency fixedPaymentFrequency, overnightPaymentFrequency;
100
        DateGeneration::Rule fixedRule, overnightRule;
101
        if (fixedPaymentFrequency_ == Once || fixedRule_ == DateGeneration::Zero) {
1,621✔
102
            fixedPaymentFrequency = Once;
103
            fixedRule = DateGeneration::Zero;
104
        } else {
105
            fixedPaymentFrequency = fixedPaymentFrequency_;
106
            fixedRule = fixedRule_;
107
        }
108
        if (overnightPaymentFrequency_ == Once || overnightRule_ == DateGeneration::Zero) {
1,621✔
109
            overnightPaymentFrequency = Once;
110
            overnightRule = DateGeneration::Zero;
111
        } else {
112
            overnightPaymentFrequency = overnightPaymentFrequency_;
113
            overnightRule = overnightRule_;
114
        }
115

116
        Schedule fixedSchedule(startDate, endDate,
117
                               Period(fixedPaymentFrequency),
3,242✔
118
                               fixedCalendar_,
119
                               fixedConvention_,
1,621✔
120
                               fixedTerminationDateConvention_,
1,621✔
121
                               fixedRule,
122
                               fixedEndOfMonth);
3,242✔
123

124
        Schedule overnightSchedule(startDate, endDate,
125
                                   Period(overnightPaymentFrequency),
3,242✔
126
                                   overnightCalendar_,
127
                                   overnightConvention_,
1,621✔
128
                                   overnightTerminationDateConvention_,
1,621✔
129
                                   overnightRule,
130
                                   overnightEndOfMonth);
3,242✔
131

132
        Rate usedFixedRate = fixedRate_;
1,621✔
133
        if (fixedRate_ == Null<Rate>()) {
1,621✔
UNCOV
134
            OvernightIndexedSwap temp(type_, nominal_,
×
135
                                      fixedSchedule,
136
                                      0.0, // fixed rate
137
                                      fixedDayCount_,
138
                                      overnightSchedule,
139
                                      overnightIndex_, overnightSpread_,
×
140
                                      paymentLag_, paymentAdjustment_,
×
141
                                      paymentCalendar_, telescopicValueDates_);
×
UNCOV
142
            if (engine_ == nullptr) {
×
143
                Handle<YieldTermStructure> disc =
144
                                    overnightIndex_->forwardingTermStructure();
×
UNCOV
145
                QL_REQUIRE(!disc.empty(),
×
146
                           "null term structure set to this instance of " <<
147
                           overnightIndex_->name());
148
                bool includeSettlementDateFlows = false;
149
                ext::shared_ptr<PricingEngine> engine(new
150
                    DiscountingSwapEngine(disc, includeSettlementDateFlows));
×
UNCOV
151
                temp.setPricingEngine(engine);
×
152
            } else
UNCOV
153
                temp.setPricingEngine(engine_);
×
154

155
            usedFixedRate = temp.fairRate();
×
UNCOV
156
        }
×
157

158
        ext::shared_ptr<OvernightIndexedSwap> ois(new
159
            OvernightIndexedSwap(type_, nominal_,
1,621✔
160
                                 fixedSchedule,
161
                                 usedFixedRate, fixedDayCount_,
162
                                 overnightSchedule,
163
                                 overnightIndex_, overnightSpread_,
1,621✔
164
                                 paymentLag_, paymentAdjustment_,
1,621✔
165
                                 paymentCalendar_, telescopicValueDates_, 
1,621✔
166
                                 averagingMethod_, lookbackDays_,
1,621✔
167
                                 lockoutDays_, applyObservationShift_));
4,865✔
168

169
        if (engine_ == nullptr) {
1,619✔
170
            Handle<YieldTermStructure> disc =
171
                                overnightIndex_->forwardingTermStructure();
606✔
172
            bool includeSettlementDateFlows = false;
173
            ext::shared_ptr<PricingEngine> engine(new
174
                DiscountingSwapEngine(disc, includeSettlementDateFlows));
606✔
175
            ois->setPricingEngine(engine);
606✔
176
        } else
177
            ois->setPricingEngine(engine_);
1,013✔
178

179
        return ois;
1,619✔
180
    }
1,623✔
181

182
    MakeOIS& MakeOIS::receiveFixed(bool flag) {
×
183
        type_ = flag ? Swap::Receiver : Swap::Payer ;
×
UNCOV
184
        return *this;
×
185
    }
186

187
    MakeOIS& MakeOIS::withType(Swap::Type type) {
576✔
188
        type_ = type;
576✔
189
        return *this;
576✔
190
    }
191

192
    MakeOIS& MakeOIS::withNominal(Real n) {
595✔
193
        nominal_ = n;
595✔
194
        return *this;
595✔
195
    }
196

197
    MakeOIS& MakeOIS::withSettlementDays(Natural settlementDays) {
433✔
198
        settlementDays_ = settlementDays;
433✔
199
        effectiveDate_ = Date();
433✔
200
        return *this;
433✔
201
    }
202

203
    MakeOIS& MakeOIS::withEffectiveDate(const Date& effectiveDate) {
1,592✔
204
        effectiveDate_ = effectiveDate;
1,592✔
205
        return *this;
1,592✔
206
    }
207

208
    MakeOIS& MakeOIS::withTerminationDate(const Date& terminationDate) {
420✔
209
        terminationDate_ = terminationDate;
420✔
210
        if (terminationDate != Date())
420✔
211
            swapTenor_ = Period();
6✔
212
        return *this;
420✔
213
    }
214

215
    MakeOIS& MakeOIS::withPaymentFrequency(Frequency f) {
997✔
216
        return withFixedLegPaymentFrequency(f).withOvernightLegPaymentFrequency(f);
997✔
217
    }
218

219
    MakeOIS& MakeOIS::withFixedLegPaymentFrequency(Frequency f) {
997✔
220
        fixedPaymentFrequency_ = f;
997✔
221
        return *this;
997✔
222
    }
223

224
    MakeOIS& MakeOIS::withOvernightLegPaymentFrequency(Frequency f) {
997✔
225
        overnightPaymentFrequency_ = f;
997✔
226
        return *this;
997✔
227
    }
228

229
    MakeOIS& MakeOIS::withPaymentAdjustment(BusinessDayConvention convention) {
420✔
230
        paymentAdjustment_ = convention;
420✔
231
        return *this;
420✔
232
    }
233

234
    MakeOIS& MakeOIS::withPaymentLag(Integer lag) {
1,015✔
235
        paymentLag_ = lag;
1,015✔
236
        return *this;
1,015✔
237
    }
238

239
    MakeOIS& MakeOIS::withPaymentCalendar(const Calendar& cal) {
420✔
240
        paymentCalendar_ = cal;
241
        return *this;
420✔
242
    }
243

244
    MakeOIS& MakeOIS::withCalendar(const Calendar& cal) {
×
UNCOV
245
        return withFixedLegCalendar(cal).withOvernightLegCalendar(cal);
×
246
    }
247

248
    MakeOIS& MakeOIS::withFixedLegCalendar(const Calendar& cal) {
3✔
249
        fixedCalendar_ = cal;
250
        return *this;
3✔
251
    }
252

253
    MakeOIS& MakeOIS::withOvernightLegCalendar(const Calendar& cal) {
3✔
254
        overnightCalendar_ = cal;
255
        return *this;
3✔
256
    }
257

258
    MakeOIS& MakeOIS::withRule(DateGeneration::Rule r) {
420✔
259
        return withFixedLegRule(r).withOvernightLegRule(r);
420✔
260
    }
261

262
    MakeOIS& MakeOIS::withFixedLegRule(DateGeneration::Rule r) {
420✔
263
        fixedRule_ = r;
420✔
264
        return *this;
420✔
265
    }
266

267
    MakeOIS& MakeOIS::withOvernightLegRule(DateGeneration::Rule r) {
420✔
268
        overnightRule_ = r;
420✔
269
        return *this;
420✔
270
    }
271

272
    MakeOIS& MakeOIS::withDiscountingTermStructure(
1,015✔
273
                                        const Handle<YieldTermStructure>& d) {
274
        bool includeSettlementDateFlows = false;
275
        engine_ = ext::shared_ptr<PricingEngine>(new
3,045✔
276
            DiscountingSwapEngine(d, includeSettlementDateFlows));
2,030✔
277
        return *this;
1,015✔
278
    }
279

UNCOV
280
    MakeOIS& MakeOIS::withPricingEngine(
×
281
                             const ext::shared_ptr<PricingEngine>& engine) {
282
        engine_ = engine;
×
UNCOV
283
        return *this;
×
284
    }
285

286
    MakeOIS& MakeOIS::withFixedLegDayCount(const DayCounter& dc) {
577✔
287
        fixedDayCount_ = dc;
288
        return *this;
577✔
289
    }
290

291
    MakeOIS& MakeOIS::withConvention(BusinessDayConvention bdc) {
420✔
292
        return withFixedLegConvention(bdc).withOvernightLegConvention(bdc);
420✔
293
    }
294

295
    MakeOIS& MakeOIS::withFixedLegConvention(BusinessDayConvention bdc) {
420✔
296
        fixedConvention_ = bdc;
420✔
297
        return *this;
420✔
298
    }
299

300
    MakeOIS& MakeOIS::withOvernightLegConvention(BusinessDayConvention bdc) {
420✔
301
        overnightConvention_ = bdc;
420✔
302
        return *this;
420✔
303
    }
304

305
    MakeOIS& MakeOIS::withTerminationDateConvention(BusinessDayConvention bdc) {
420✔
306
        withFixedLegTerminationDateConvention(bdc);
420✔
307
        return withOvernightLegTerminationDateConvention(bdc);
420✔
308
    }
309

310
    MakeOIS& MakeOIS::withFixedLegTerminationDateConvention(BusinessDayConvention bdc) {
420✔
311
        fixedTerminationDateConvention_ = bdc;
420✔
312
        return *this;
420✔
313
    }
314

315
    MakeOIS& MakeOIS::withOvernightLegTerminationDateConvention(BusinessDayConvention bdc) {
420✔
316
        overnightTerminationDateConvention_ = bdc;
420✔
317
        return *this;
420✔
318
    }
319

320
    MakeOIS& MakeOIS::withEndOfMonth(bool flag) {
×
NEW
UNCOV
321
        return withFixedLegEndOfMonth(flag).withOvernightLegEndOfMonth(flag).withMaturityEndOfMonth(
×
NEW
UNCOV
322
            flag);
×
323
    }
324

325
    MakeOIS& MakeOIS::withFixedLegEndOfMonth(bool flag) {
×
326
        fixedEndOfMonth_ = flag;
×
UNCOV
327
        isDefaultEOM_ = false;
×
UNCOV
328
        return *this;
×
329
    }
330

331
    MakeOIS& MakeOIS::withOvernightLegEndOfMonth(bool flag) {
×
332
        overnightEndOfMonth_ = flag;
×
UNCOV
333
        isDefaultEOM_ = false;
×
UNCOV
334
        return *this;
×
335
    }
336

NEW
337
    MakeOIS& MakeOIS::withMaturityEndOfMonth(bool flag) {
×
NEW
338
        maturityEndOfMonth_ = flag;
×
NEW
339
        isDefaultEOM_ = false;
×
NEW
340
        return *this;
×
341
    }
342

NEW
UNCOV
343
    MakeOIS& MakeOIS::withMaturityEndOfMonthCalendarDate(bool flag) {
×
NEW
UNCOV
344
        maturityEndOfMonthCalendarDate_ = flag;
×
NEW
UNCOV
345
        return *this;
×
346
    }
347

348
    MakeOIS& MakeOIS::withOvernightLegSpread(Spread sp) {
397✔
349
        overnightSpread_ = sp;
397✔
350
        return *this;
397✔
351
    }
352

353
    MakeOIS& MakeOIS::withTelescopicValueDates(bool telescopicValueDates) {
1,015✔
354
        telescopicValueDates_ = telescopicValueDates;
1,015✔
355
        return *this;
1,015✔
356
    }
357

358
    MakeOIS& MakeOIS::withAveragingMethod(RateAveraging::Type averagingMethod) {
817✔
359
        averagingMethod_ = averagingMethod;
817✔
360
        return *this;
817✔
361
    }
362

363
    MakeOIS& MakeOIS::withLookbackDays(Natural lookbackDays) {
618✔
364
        lookbackDays_ = lookbackDays;
618✔
365
        return *this;
618✔
366
    }
367

368
    MakeOIS& MakeOIS::withLockoutDays(Natural lockoutDays) {
618✔
369
        lockoutDays_ = lockoutDays;
618✔
370
        return *this;
618✔
371
    }
372

373
    MakeOIS& MakeOIS::withObservationShift(bool applyObservationShift) {
618✔
374
        applyObservationShift_ = applyObservationShift;
618✔
375
        return *this;
618✔
376
    }
377

378
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc