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

lballabio / QuantLib / 26045849907

18 May 2026 04:18PM UTC coverage: 74.624% (+0.004%) from 74.62%
26045849907

push

github

web-flow
Review default arguments in cross-currency swap constructors (#2588)

21 of 26 new or added lines in 2 files covered. (80.77%)

1 existing line in 1 file now uncovered.

58902 of 78932 relevant lines covered (74.62%)

8599189.12 hits per line

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

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

3
/*
4
 Copyright (C) 2016 Quaternion Risk Management Ltd
5
 Copyright (C) 2025 Paolo D'Elia
6

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

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

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

21
#include <ql/instruments/constnotionalcrosscurrencyfixedvsfloatingswap.hpp>
22
#include <ql/cashflows/cashflows.hpp>
23
#include <ql/cashflows/fixedratecoupon.hpp>
24
#include <ql/cashflows/iborcoupon.hpp>
25
#include <ql/cashflows/simplecashflow.hpp>
26
#include <ql/cashflows/overnightindexedcoupon.hpp>
27

28
namespace QuantLib {
29

30
ConstNotionalCrossCurrencyFixedVsFloatingSwap::ConstNotionalCrossCurrencyFixedVsFloatingSwap(
12✔
31
    Type type, Real fixedNominal, const Currency& fixedCurrency, const Schedule& fixedSchedule, Rate fixedRate,
32
    const DayCounter& fixedDayCount, BusinessDayConvention fixedPaymentBdc, Natural fixedPaymentLag,
33
    const Calendar& fixedPaymentCalendar, Real floatNominal, const Currency& floatCurrency,
34
    const Schedule& floatSchedule, const ext::shared_ptr<IborIndex>& floatIndex, Spread floatSpread,
35
    BusinessDayConvention floatPaymentBdc, Natural floatPaymentLag, const Calendar& floatPaymentCalendar,
36
    const bool telescopicValueDates, bool floatCompoundSpread, Natural floatLookbackDays,
37
    bool floatObservationShift, Natural floatLockoutDays, RateAveraging::Type floatAveragingMethod)
12✔
38
    : ConstNotionalCrossCurrencySwap(2), type_(type), fixedNominal_(fixedNominal), fixedCurrency_(fixedCurrency),
12✔
39
      fixedSchedule_(fixedSchedule), fixedRate_(fixedRate), fixedDayCount_(fixedDayCount),
12✔
40
      fixedPaymentBdc_(fixedPaymentBdc), fixedPaymentLag_(fixedPaymentLag), fixedPaymentCalendar_(fixedPaymentCalendar),
12✔
41
      floatNominal_(floatNominal), floatCurrency_(floatCurrency), floatSchedule_(floatSchedule),
12✔
42
      floatIndex_(floatIndex), floatSpread_(floatSpread), floatPaymentBdc_(floatPaymentBdc),
12✔
43
      floatPaymentLag_(floatPaymentLag), floatPaymentCalendar_(floatPaymentCalendar),
12✔
44
      telescopicValueDates_(telescopicValueDates),
12✔
45
      floatCompoundSpread_(floatCompoundSpread), floatLookbackDays_(floatLookbackDays),
12✔
46
      floatObservationShift_(floatObservationShift),
12✔
47
      floatLockoutDays_(floatLockoutDays), floatAveragingMethod_(floatAveragingMethod) {
24✔
48

49
    // Build the float leg
50
    Leg floatLeg;
51
    if (auto on = ext::dynamic_pointer_cast<OvernightIndex>(floatIndex_)) {
12✔
52
        floatLeg = OvernightLeg(floatSchedule_, on)
×
53
                    .withNotionals(floatNominal_)
×
54
                    .withSpreads(floatSpread_)
×
55
                    .withPaymentAdjustment(floatPaymentBdc_)
×
56
                    .withPaymentLag(floatPaymentLag_)
×
NEW
57
                    .withLookbackDays(floatLookbackDays_)
×
NEW
58
                    .compoundingSpreadDaily(floatCompoundSpread_)
×
NEW
59
                    .withObservationShift(floatObservationShift_)
×
60
                    .withPaymentCalendar(floatPaymentCalendar_)
×
NEW
61
                    .withLockoutDays(floatLockoutDays_)
×
NEW
62
                    .withAveragingMethod(floatAveragingMethod_)
×
UNCOV
63
                    .withTelescopicValueDates(telescopicValueDates_);
×
64
    } else {
65
        floatLeg = IborLeg(floatSchedule_, floatIndex_)
24✔
66
                       .withNotionals(floatNominal_)
12✔
67
                       .withSpreads(floatSpread_)
12✔
68
                       .withPaymentAdjustment(floatPaymentBdc_)
12✔
69
                       .withPaymentLag(floatPaymentLag_)
12✔
70
                       .withPaymentCalendar(floatPaymentCalendar_);
24✔
71
    }
72

73
    // Register with each floating rate coupon
74
    for (Leg::const_iterator it = floatLeg.begin(); it < floatLeg.end(); ++it)
508✔
75
        registerWith(*it);
992✔
76

77
    // Build the fixed rate leg
78
    Leg fixedLeg = FixedRateLeg(fixedSchedule_)
24✔
79
                       .withNotionals(fixedNominal_)
12✔
80
                       .withCouponRates(fixedRate_, fixedDayCount_)
12✔
81
                       .withPaymentAdjustment(fixedPaymentBdc_)
12✔
82
                       .withPaymentLag(fixedPaymentLag)
12✔
83
                       .withPaymentCalendar(fixedPaymentCalendar);
12✔
84

85
    auto earliestDate = std::min(CashFlows::startDate(floatLeg),
12✔
86
                                 CashFlows::startDate(fixedLeg));
12✔
87

88
    auto maturityDate = std::max(CashFlows::maturityDate(floatLeg),
12✔
89
                                 CashFlows::maturityDate(fixedLeg));
12✔
90

91
    // Add notional exchanges on float Leg
92
    ConstNotionalCrossCurrencySwap::addNotionalExchangesToLeg(floatLeg, floatPaymentCalendar_, earliestDate, maturityDate,
12✔
93
                                            floatPaymentLag_, floatPaymentBdc_, floatNominal_);
94
    
95
    // Add notional exchanges on fixed leg
96
    ConstNotionalCrossCurrencySwap::addNotionalExchangesToLeg(fixedLeg, fixedPaymentCalendar_, earliestDate, maturityDate,
12✔
97
                                            fixedPaymentLag_, fixedPaymentBdc_, fixedNominal_);
98

99
    // Deriving from cross currency swap where:
100
    //   First leg should hold the pay flows
101
    //   Second leg should hold the receive flows
102
    payer_[0] = -1.0;
12✔
103
    payer_[1] = 1.0;
12✔
104
    switch (type_) {
12✔
105
    case Payer:
12✔
106
        legs_[0] = fixedLeg;
12✔
107
        currencies_[0] = fixedCurrency_;
108
        legs_[1] = floatLeg;
12✔
109
        currencies_[1] = floatCurrency_;
110
        break;
111
    case Receiver:
×
112
        legs_[1] = fixedLeg;
×
113
        currencies_[1] = fixedCurrency_;
114
        legs_[0] = floatLeg;
×
115
        currencies_[0] = floatCurrency_;
116
        break;
117
    default:
×
118
        QL_FAIL("Unknown cross currency fix float swap type");
×
119
    }
120
}
12✔
121

122
void ConstNotionalCrossCurrencyFixedVsFloatingSwap::setupArguments(PricingEngine::arguments* a) const {
92✔
123
    ConstNotionalCrossCurrencySwap::setupArguments(a);
92✔
124
    if (ConstNotionalCrossCurrencyFixedVsFloatingSwap::arguments* args = dynamic_cast<ConstNotionalCrossCurrencyFixedVsFloatingSwap::arguments*>(a)) {
92✔
125
        args->fixedRate = fixedRate_;
×
126
        args->spread = floatSpread_;
×
127
    }
128
}
92✔
129

130
void ConstNotionalCrossCurrencyFixedVsFloatingSwap::fetchResults(const PricingEngine::results* r) const {
92✔
131

132
    ConstNotionalCrossCurrencySwap::fetchResults(r);
92✔
133

134
    // Depending on the pricing engine used, we may have ConstNotionalCrossCurrencyFixedVsFloatingSwap::results
135
    if (const ConstNotionalCrossCurrencyFixedVsFloatingSwap::results* res = dynamic_cast<const ConstNotionalCrossCurrencyFixedVsFloatingSwap::results*>(r)) {
92✔
136
        // If we have ConstNotionalCrossCurrencyFixedVsFloatingSwap::results from the pricing engine
137
        fairFixedRate_ = res->fairFixedRate;
×
138
        fairSpread_ = res->fairSpread;
×
139
    } else {
140
        // If not, set them to Null to indicate a calculation is needed below
141
        fairFixedRate_ = Null<Rate>();
92✔
142
        fairSpread_ = Null<Spread>();
92✔
143
    }
144

145
    // Calculate fair rate and spread if they are still Null here
146
    static Spread basisPoint = 1.0e-4;
147

148
    Size idxFixed = type_ == Payer ? 0 : 1;
92✔
149
    if (fairFixedRate_ == Null<Rate>() && legBPS_[idxFixed] != Null<Real>())
92✔
150
        fairFixedRate_ = fixedRate_ - NPV_ / (legBPS_[idxFixed] / basisPoint);
92✔
151

152
    Size idxFloat = type_ == Payer ? 1 : 0;
92✔
153
    if (fairSpread_ == Null<Spread>() && legBPS_[idxFloat] != Null<Real>())
92✔
154
        fairSpread_ = floatSpread_ - NPV_ / (legBPS_[idxFloat] / basisPoint);
92✔
155
}
92✔
156

157
void ConstNotionalCrossCurrencyFixedVsFloatingSwap::setupExpired() const {
×
158
    ConstNotionalCrossCurrencySwap::setupExpired();
×
159
    fairFixedRate_ = Null<Rate>();
×
160
    fairSpread_ = Null<Spread>();
×
161
}
×
162

163
void ConstNotionalCrossCurrencyFixedVsFloatingSwap::arguments::validate() const {
×
164
    ConstNotionalCrossCurrencySwap::arguments::validate();
×
165
    QL_REQUIRE(fixedRate != Null<Rate>(), "Fixed rate cannot be null");
×
166
    QL_REQUIRE(spread != Null<Spread>(), "Spread cannot be null");
×
167
}
×
168

169
void ConstNotionalCrossCurrencyFixedVsFloatingSwap::results::reset() {
×
170
    ConstNotionalCrossCurrencySwap::results::reset();
×
171
    fairFixedRate = Null<Rate>();
×
172
    fairSpread = Null<Spread>();
×
173
}
×
174

175
} // namespace QuantLib
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