/src/quantlib/ql/instruments/nonstandardswap.cpp
Line | Count | Source |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | Copyright (C) 2013, 2016 Peter Caspers |
5 | | |
6 | | This file is part of QuantLib, a free-software/open-source library |
7 | | for financial quantitative analysts and developers - http://quantlib.org/ |
8 | | |
9 | | QuantLib is free software: you can redistribute it and/or modify it |
10 | | under the terms of the QuantLib license. You should have received a |
11 | | copy of the license along with this program; if not, please email |
12 | | <quantlib-dev@lists.sf.net>. The license is also available online at |
13 | | <https://www.quantlib.org/license.shtml>. |
14 | | |
15 | | This program is distributed in the hope that it will be useful, but WITHOUT |
16 | | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
17 | | FOR A PARTICULAR PURPOSE. See the license for more details. |
18 | | */ |
19 | | |
20 | | #include <ql/cashflows/capflooredcoupon.hpp> |
21 | | #include <ql/cashflows/cashflows.hpp> |
22 | | #include <ql/cashflows/cashflowvectors.hpp> |
23 | | #include <ql/cashflows/cmscoupon.hpp> |
24 | | #include <ql/cashflows/couponpricer.hpp> |
25 | | #include <ql/cashflows/iborcoupon.hpp> |
26 | | #include <ql/cashflows/simplecashflow.hpp> |
27 | | #include <ql/indexes/iborindex.hpp> |
28 | | #include <ql/indexes/swapindex.hpp> |
29 | | #include <ql/instruments/nonstandardswap.hpp> |
30 | | #include <ql/termstructures/yieldtermstructure.hpp> |
31 | | #include <ql/optional.hpp> |
32 | | #include <utility> |
33 | | |
34 | | namespace QuantLib { |
35 | | |
36 | | NonstandardSwap::NonstandardSwap(const FixedVsFloatingSwap &fromVanilla) |
37 | 0 | : Swap(2), type_(fromVanilla.type()), |
38 | 0 | fixedNominal_(std::vector<Real>(fromVanilla.fixedLeg().size(), |
39 | 0 | fromVanilla.nominal())), |
40 | 0 | floatingNominal_(std::vector<Real>(fromVanilla.floatingLeg().size(), |
41 | 0 | fromVanilla.nominal())), |
42 | 0 | fixedSchedule_(fromVanilla.fixedSchedule()), |
43 | 0 | fixedRate_(std::vector<Real>(fromVanilla.fixedLeg().size(), |
44 | 0 | fromVanilla.fixedRate())), |
45 | 0 | fixedDayCount_(fromVanilla.fixedDayCount()), |
46 | 0 | floatingSchedule_(fromVanilla.floatingSchedule()), |
47 | 0 | iborIndex_(fromVanilla.iborIndex()), |
48 | 0 | spread_(std::vector<Real>(fromVanilla.floatingLeg().size(), fromVanilla.spread())), |
49 | 0 | gearing_(std::vector<Real>(fromVanilla.floatingLeg().size(), 1.0)), |
50 | 0 | singleSpreadAndGearing_(true), |
51 | 0 | floatingDayCount_(fromVanilla.floatingDayCount()), |
52 | 0 | paymentConvention_(fromVanilla.paymentConvention()), |
53 | 0 | intermediateCapitalExchange_(false), finalCapitalExchange_(false) { |
54 | |
|
55 | 0 | init(); |
56 | 0 | } Unexecuted instantiation: QuantLib::NonstandardSwap::NonstandardSwap(QuantLib::FixedVsFloatingSwap const&) Unexecuted instantiation: QuantLib::NonstandardSwap::NonstandardSwap(QuantLib::FixedVsFloatingSwap const&) |
57 | | |
58 | | NonstandardSwap::NonstandardSwap(const Swap::Type type, |
59 | | std::vector<Real> fixedNominal, |
60 | | const std::vector<Real>& floatingNominal, |
61 | | Schedule fixedSchedule, |
62 | | std::vector<Real> fixedRate, |
63 | | DayCounter fixedDayCount, |
64 | | Schedule floatingSchedule, |
65 | | ext::shared_ptr<IborIndex> iborIndex, |
66 | | const Real gearing, |
67 | | const Spread spread, |
68 | | DayCounter floatingDayCount, |
69 | | const bool intermediateCapitalExchange, |
70 | | const bool finalCapitalExchange, |
71 | | ext::optional<BusinessDayConvention> paymentConvention) |
72 | 0 | : Swap(2), type_(type), fixedNominal_(std::move(fixedNominal)), |
73 | 0 | floatingNominal_(floatingNominal), fixedSchedule_(std::move(fixedSchedule)), |
74 | 0 | fixedRate_(std::move(fixedRate)), fixedDayCount_(std::move(fixedDayCount)), |
75 | 0 | floatingSchedule_(std::move(floatingSchedule)), iborIndex_(std::move(iborIndex)), |
76 | 0 | spread_(std::vector<Real>(floatingNominal.size(), spread)), |
77 | 0 | gearing_(std::vector<Real>(floatingNominal.size(), gearing)), singleSpreadAndGearing_(true), |
78 | 0 | floatingDayCount_(std::move(floatingDayCount)), |
79 | 0 | intermediateCapitalExchange_(intermediateCapitalExchange), |
80 | 0 | finalCapitalExchange_(finalCapitalExchange) { |
81 | |
|
82 | 0 | if (paymentConvention) // NOLINT(readability-implicit-bool-conversion) |
83 | 0 | paymentConvention_ = *paymentConvention; |
84 | 0 | else |
85 | 0 | paymentConvention_ = floatingSchedule_.businessDayConvention(); |
86 | 0 | init(); |
87 | 0 | } Unexecuted instantiation: QuantLib::NonstandardSwap::NonstandardSwap(QuantLib::Swap::Type, std::__1::vector<double, std::__1::allocator<double> >, std::__1::vector<double, std::__1::allocator<double> > const&, QuantLib::Schedule, std::__1::vector<double, std::__1::allocator<double> >, QuantLib::DayCounter, QuantLib::Schedule, boost::shared_ptr<QuantLib::IborIndex>, double, double, QuantLib::DayCounter, bool, bool, std::__1::optional<QuantLib::BusinessDayConvention>) Unexecuted instantiation: QuantLib::NonstandardSwap::NonstandardSwap(QuantLib::Swap::Type, std::__1::vector<double, std::__1::allocator<double> >, std::__1::vector<double, std::__1::allocator<double> > const&, QuantLib::Schedule, std::__1::vector<double, std::__1::allocator<double> >, QuantLib::DayCounter, QuantLib::Schedule, boost::shared_ptr<QuantLib::IborIndex>, double, double, QuantLib::DayCounter, bool, bool, std::__1::optional<QuantLib::BusinessDayConvention>) |
88 | | |
89 | | NonstandardSwap::NonstandardSwap(const Swap::Type type, |
90 | | std::vector<Real> fixedNominal, |
91 | | std::vector<Real> floatingNominal, |
92 | | Schedule fixedSchedule, |
93 | | std::vector<Real> fixedRate, |
94 | | DayCounter fixedDayCount, |
95 | | Schedule floatingSchedule, |
96 | | ext::shared_ptr<IborIndex> iborIndex, |
97 | | std::vector<Real> gearing, |
98 | | std::vector<Spread> spread, |
99 | | DayCounter floatingDayCount, |
100 | | const bool intermediateCapitalExchange, |
101 | | const bool finalCapitalExchange, |
102 | | ext::optional<BusinessDayConvention> paymentConvention) |
103 | 0 | : Swap(2), type_(type), fixedNominal_(std::move(fixedNominal)), |
104 | 0 | floatingNominal_(std::move(floatingNominal)), fixedSchedule_(std::move(fixedSchedule)), |
105 | 0 | fixedRate_(std::move(fixedRate)), fixedDayCount_(std::move(fixedDayCount)), |
106 | 0 | floatingSchedule_(std::move(floatingSchedule)), iborIndex_(std::move(iborIndex)), |
107 | 0 | spread_(std::move(spread)), gearing_(std::move(gearing)), singleSpreadAndGearing_(false), |
108 | 0 | floatingDayCount_(std::move(floatingDayCount)), |
109 | 0 | intermediateCapitalExchange_(intermediateCapitalExchange), |
110 | 0 | finalCapitalExchange_(finalCapitalExchange) { |
111 | |
|
112 | 0 | if (paymentConvention) // NOLINT(readability-implicit-bool-conversion) |
113 | 0 | paymentConvention_ = *paymentConvention; |
114 | 0 | else |
115 | 0 | paymentConvention_ = floatingSchedule_.businessDayConvention(); |
116 | 0 | init(); |
117 | 0 | } Unexecuted instantiation: QuantLib::NonstandardSwap::NonstandardSwap(QuantLib::Swap::Type, std::__1::vector<double, std::__1::allocator<double> >, std::__1::vector<double, std::__1::allocator<double> >, QuantLib::Schedule, std::__1::vector<double, std::__1::allocator<double> >, QuantLib::DayCounter, QuantLib::Schedule, boost::shared_ptr<QuantLib::IborIndex>, std::__1::vector<double, std::__1::allocator<double> >, std::__1::vector<double, std::__1::allocator<double> >, QuantLib::DayCounter, bool, bool, std::__1::optional<QuantLib::BusinessDayConvention>) Unexecuted instantiation: QuantLib::NonstandardSwap::NonstandardSwap(QuantLib::Swap::Type, std::__1::vector<double, std::__1::allocator<double> >, std::__1::vector<double, std::__1::allocator<double> >, QuantLib::Schedule, std::__1::vector<double, std::__1::allocator<double> >, QuantLib::DayCounter, QuantLib::Schedule, boost::shared_ptr<QuantLib::IborIndex>, std::__1::vector<double, std::__1::allocator<double> >, std::__1::vector<double, std::__1::allocator<double> >, QuantLib::DayCounter, bool, bool, std::__1::optional<QuantLib::BusinessDayConvention>) |
118 | | |
119 | 0 | void NonstandardSwap::init() { |
120 | |
|
121 | 0 | QL_REQUIRE(fixedNominal_.size() == fixedRate_.size(), |
122 | 0 | "Fixed nominal size (" |
123 | 0 | << fixedNominal_.size() |
124 | 0 | << ") does not match fixed rate size (" |
125 | 0 | << fixedRate_.size() << ")"); |
126 | | |
127 | 0 | QL_REQUIRE(fixedNominal_.size() == fixedSchedule_.size() - 1, |
128 | 0 | "Fixed nominal size (" << fixedNominal_.size() |
129 | 0 | << ") does not match schedule size (" |
130 | 0 | << fixedSchedule_.size() << ") - 1"); |
131 | | |
132 | 0 | QL_REQUIRE(floatingNominal_.size() == floatingSchedule_.size() - 1, |
133 | 0 | "Floating nominal size (" |
134 | 0 | << floatingNominal_.size() |
135 | 0 | << ") does not match schedule size (" |
136 | 0 | << floatingSchedule_.size() << ") - 1"); |
137 | | |
138 | 0 | QL_REQUIRE(floatingNominal_.size() == spread_.size(), |
139 | 0 | "Floating nominal size (" << floatingNominal_.size() |
140 | 0 | << ") does not match spread size (" |
141 | 0 | << spread_.size() << ")"); |
142 | | |
143 | 0 | QL_REQUIRE(floatingNominal_.size() == gearing_.size(), |
144 | 0 | "Floating nominal size (" |
145 | 0 | << floatingNominal_.size() |
146 | 0 | << ") does not match gearing size (" << gearing_.size() |
147 | 0 | << ")"); |
148 | | |
149 | | // if the gearing is zero then the ibor leg will be set up with fixed |
150 | | // coupons which makes trouble here in this context. We therefore use |
151 | | // a dirty trick and enforce the gearing to be non zero. |
152 | 0 | for (Real& i : gearing_) { |
153 | 0 | if (close(i, 0.0)) |
154 | 0 | i = QL_EPSILON; |
155 | 0 | } |
156 | |
|
157 | 0 | legs_[0] = FixedRateLeg(fixedSchedule_) |
158 | 0 | .withNotionals(fixedNominal_) |
159 | 0 | .withCouponRates(fixedRate_, fixedDayCount_) |
160 | 0 | .withPaymentAdjustment(paymentConvention_); |
161 | |
|
162 | 0 | legs_[1] = IborLeg(floatingSchedule_, iborIndex_) |
163 | 0 | .withNotionals(floatingNominal_) |
164 | 0 | .withPaymentDayCounter(floatingDayCount_) |
165 | 0 | .withPaymentAdjustment(paymentConvention_) |
166 | 0 | .withSpreads(spread_) |
167 | 0 | .withGearings(gearing_); |
168 | |
|
169 | 0 | if (intermediateCapitalExchange_) { |
170 | 0 | for (Size i = 0; i < legs_[0].size() - 1; i++) { |
171 | 0 | Real cap = fixedNominal_[i] - fixedNominal_[i + 1]; |
172 | 0 | if (!close(cap, 0.0)) { |
173 | 0 | auto it1 = legs_[0].begin(); |
174 | 0 | std::advance(it1, i + 1); |
175 | 0 | legs_[0].insert( |
176 | 0 | it1, ext::shared_ptr<CashFlow>( |
177 | 0 | new Redemption(cap, legs_[0][i]->date()))); |
178 | 0 | auto it2 = fixedNominal_.begin(); |
179 | 0 | std::advance(it2, i + 1); |
180 | 0 | fixedNominal_.insert(it2, fixedNominal_[i]); |
181 | 0 | auto it3 = fixedRate_.begin(); |
182 | 0 | std::advance(it3, i + 1); |
183 | 0 | fixedRate_.insert(it3, 0.0); |
184 | 0 | i++; |
185 | 0 | } |
186 | 0 | } |
187 | 0 | for (Size i = 0; i < legs_[1].size() - 1; i++) { |
188 | 0 | Real cap = floatingNominal_[i] - floatingNominal_[i + 1]; |
189 | 0 | if (!close(cap, 0.0)) { |
190 | 0 | auto it1 = legs_[1].begin(); |
191 | 0 | std::advance(it1, i + 1); |
192 | 0 | legs_[1].insert( |
193 | 0 | it1, ext::shared_ptr<CashFlow>( |
194 | 0 | new Redemption(cap, legs_[1][i]->date()))); |
195 | 0 | auto it2 = floatingNominal_.begin(); |
196 | 0 | std::advance(it2, i + 1); |
197 | 0 | floatingNominal_.insert(it2, floatingNominal_[i]); |
198 | 0 | i++; |
199 | 0 | } |
200 | 0 | } |
201 | 0 | } |
202 | |
|
203 | 0 | if (finalCapitalExchange_) { |
204 | 0 | legs_[0].push_back(ext::shared_ptr<CashFlow>( |
205 | 0 | new Redemption(fixedNominal_.back(), legs_[0].back()->date()))); |
206 | 0 | fixedNominal_.push_back(fixedNominal_.back()); |
207 | 0 | fixedRate_.push_back(0.0); |
208 | 0 | legs_[1].push_back(ext::shared_ptr<CashFlow>(new Redemption( |
209 | 0 | floatingNominal_.back(), legs_[1].back()->date()))); |
210 | 0 | floatingNominal_.push_back(floatingNominal_.back()); |
211 | 0 | } |
212 | |
|
213 | 0 | for (auto i = legs_[1].begin(); i < legs_[1].end(); ++i) |
214 | 0 | registerWith(*i); |
215 | |
|
216 | 0 | switch (type_) { |
217 | 0 | case Swap::Payer: |
218 | 0 | payer_[0] = -1.0; |
219 | 0 | payer_[1] = +1.0; |
220 | 0 | break; |
221 | 0 | case Swap::Receiver: |
222 | 0 | payer_[0] = +1.0; |
223 | 0 | payer_[1] = -1.0; |
224 | 0 | break; |
225 | 0 | default: |
226 | 0 | QL_FAIL("Unknown nonstandard-swap type"); |
227 | 0 | } |
228 | 0 | } |
229 | | |
230 | 0 | void NonstandardSwap::setupArguments(PricingEngine::arguments *args) const { |
231 | |
|
232 | 0 | Swap::setupArguments(args); |
233 | |
|
234 | 0 | auto* arguments = dynamic_cast<NonstandardSwap::arguments*>(args); |
235 | |
|
236 | 0 | if (arguments == nullptr) |
237 | 0 | return; // swap engine ... |
238 | | |
239 | 0 | arguments->type = type_; |
240 | 0 | arguments->fixedNominal = fixedNominal_; |
241 | 0 | arguments->floatingNominal = floatingNominal_; |
242 | 0 | arguments->fixedRate = fixedRate_; |
243 | |
|
244 | 0 | const Leg &fixedCoupons = fixedLeg(); |
245 | |
|
246 | 0 | arguments->fixedResetDates = arguments->fixedPayDates = |
247 | 0 | std::vector<Date>(fixedCoupons.size()); |
248 | 0 | arguments->fixedCoupons = std::vector<Real>(fixedCoupons.size()); |
249 | 0 | arguments->fixedIsRedemptionFlow = |
250 | 0 | std::vector<bool>(fixedCoupons.size(), false); |
251 | |
|
252 | 0 | for (Size i = 0; i < fixedCoupons.size(); ++i) { |
253 | 0 | ext::shared_ptr<FixedRateCoupon> coupon = |
254 | 0 | ext::dynamic_pointer_cast<FixedRateCoupon>(fixedCoupons[i]); |
255 | 0 | if (coupon != nullptr) { |
256 | 0 | arguments->fixedPayDates[i] = coupon->date(); |
257 | 0 | arguments->fixedResetDates[i] = coupon->accrualStartDate(); |
258 | 0 | arguments->fixedCoupons[i] = coupon->amount(); |
259 | 0 | } else { |
260 | 0 | ext::shared_ptr<CashFlow> cashflow = |
261 | 0 | ext::dynamic_pointer_cast<CashFlow>(fixedCoupons[i]); |
262 | 0 | auto j = |
263 | 0 | std::find(arguments->fixedPayDates.begin(), |
264 | 0 | arguments->fixedPayDates.end(), cashflow->date()); |
265 | 0 | QL_REQUIRE(j != arguments->fixedPayDates.end(), |
266 | 0 | "nominal redemption on " |
267 | 0 | << cashflow->date() |
268 | 0 | << "has no corresponding coupon"); |
269 | 0 | Size jIdx = j - arguments->fixedPayDates.begin(); |
270 | 0 | arguments->fixedIsRedemptionFlow[i] = true; |
271 | 0 | arguments->fixedCoupons[i] = cashflow->amount(); |
272 | 0 | arguments->fixedResetDates[i] = |
273 | 0 | arguments->fixedResetDates[jIdx]; |
274 | 0 | arguments->fixedPayDates[i] = cashflow->date(); |
275 | 0 | } |
276 | 0 | } |
277 | | |
278 | 0 | const Leg &floatingCoupons = floatingLeg(); |
279 | |
|
280 | 0 | arguments->floatingResetDates = arguments->floatingPayDates = |
281 | 0 | arguments->floatingFixingDates = |
282 | 0 | std::vector<Date>(floatingCoupons.size()); |
283 | 0 | arguments->floatingAccrualTimes = |
284 | 0 | std::vector<Time>(floatingCoupons.size()); |
285 | 0 | arguments->floatingSpreads = |
286 | 0 | std::vector<Spread>(floatingCoupons.size()); |
287 | 0 | arguments->floatingGearings = std::vector<Real>(floatingCoupons.size()); |
288 | 0 | arguments->floatingCoupons = std::vector<Real>(floatingCoupons.size()); |
289 | 0 | arguments->floatingIsRedemptionFlow = |
290 | 0 | std::vector<bool>(floatingCoupons.size(), false); |
291 | |
|
292 | 0 | for (Size i = 0; i < floatingCoupons.size(); ++i) { |
293 | 0 | ext::shared_ptr<IborCoupon> coupon = |
294 | 0 | ext::dynamic_pointer_cast<IborCoupon>(floatingCoupons[i]); |
295 | 0 | if (coupon != nullptr) { |
296 | 0 | arguments->floatingResetDates[i] = coupon->accrualStartDate(); |
297 | 0 | arguments->floatingPayDates[i] = coupon->date(); |
298 | 0 | arguments->floatingFixingDates[i] = coupon->fixingDate(); |
299 | 0 | arguments->floatingAccrualTimes[i] = coupon->accrualPeriod(); |
300 | 0 | arguments->floatingSpreads[i] = coupon->spread(); |
301 | 0 | arguments->floatingGearings[i] = coupon->gearing(); |
302 | 0 | try { |
303 | 0 | arguments->floatingCoupons[i] = coupon->amount(); |
304 | 0 | } |
305 | 0 | catch (Error &) { |
306 | 0 | arguments->floatingCoupons[i] = Null<Real>(); |
307 | 0 | } |
308 | 0 | } else { |
309 | 0 | ext::shared_ptr<CashFlow> cashflow = |
310 | 0 | ext::dynamic_pointer_cast<CashFlow>(floatingCoupons[i]); |
311 | 0 | auto j = std::find( |
312 | 0 | arguments->floatingPayDates.begin(), |
313 | 0 | arguments->floatingPayDates.end(), cashflow->date()); |
314 | 0 | QL_REQUIRE(j != arguments->floatingPayDates.end(), |
315 | 0 | "nominal redemption on " |
316 | 0 | << cashflow->date() |
317 | 0 | << "has no corresponding coupon"); |
318 | 0 | Size jIdx = j - arguments->floatingPayDates.begin(); |
319 | 0 | arguments->floatingIsRedemptionFlow[i] = true; |
320 | 0 | arguments->floatingCoupons[i] = cashflow->amount(); |
321 | 0 | arguments->floatingResetDates[i] = |
322 | 0 | arguments->floatingResetDates[jIdx]; |
323 | 0 | arguments->floatingFixingDates[i] = |
324 | 0 | arguments->floatingFixingDates[jIdx]; |
325 | 0 | arguments->floatingAccrualTimes[i] = 0.0; |
326 | 0 | arguments->floatingSpreads[i] = 0.0; |
327 | 0 | arguments->floatingGearings[i] = 1.0; |
328 | 0 | arguments->floatingPayDates[i] = cashflow->date(); |
329 | 0 | } |
330 | 0 | } |
331 | | |
332 | 0 | arguments->iborIndex = iborIndex(); |
333 | 0 | } |
334 | | |
335 | 0 | void NonstandardSwap::setupExpired() const { Swap::setupExpired(); } |
336 | | |
337 | 0 | void NonstandardSwap::fetchResults(const PricingEngine::results *r) const { |
338 | |
|
339 | 0 | Swap::fetchResults(r); |
340 | 0 | } |
341 | | |
342 | 0 | void NonstandardSwap::arguments::validate() const { |
343 | 0 | Swap::arguments::validate(); |
344 | 0 | QL_REQUIRE(fixedNominal.size() == fixedPayDates.size(), |
345 | 0 | "number of fixed leg nominals plus redemption flows " |
346 | 0 | "different from number of payment dates"); |
347 | 0 | QL_REQUIRE(fixedRate.size() == fixedPayDates.size(), |
348 | 0 | "number of fixed rates plus redemption flows different from " |
349 | 0 | "number of payment dates"); |
350 | 0 | QL_REQUIRE(floatingNominal.size() == floatingPayDates.size(), |
351 | 0 | "number of float leg nominals different from number of " |
352 | 0 | "payment dates"); |
353 | 0 | QL_REQUIRE(fixedResetDates.size() == fixedPayDates.size(), |
354 | 0 | "number of fixed start dates different from " |
355 | 0 | "number of fixed payment dates"); |
356 | 0 | QL_REQUIRE(fixedPayDates.size() == fixedCoupons.size(), |
357 | 0 | "number of fixed payment dates different from " |
358 | 0 | "number of fixed coupon amounts"); |
359 | 0 | QL_REQUIRE(floatingResetDates.size() == floatingPayDates.size(), |
360 | 0 | "number of floating start dates different from " |
361 | 0 | "number of floating payment dates"); |
362 | 0 | QL_REQUIRE(floatingFixingDates.size() == floatingPayDates.size(), |
363 | 0 | "number of floating fixing dates different from " |
364 | 0 | "number of floating payment dates"); |
365 | 0 | QL_REQUIRE(floatingAccrualTimes.size() == floatingPayDates.size(), |
366 | 0 | "number of floating accrual Times different from " |
367 | 0 | "number of floating payment dates"); |
368 | 0 | QL_REQUIRE(floatingSpreads.size() == floatingPayDates.size(), |
369 | 0 | "number of floating spreads different from " |
370 | 0 | "number of floating payment dates"); |
371 | 0 | QL_REQUIRE(floatingPayDates.size() == floatingCoupons.size(), |
372 | 0 | "number of floating payment dates different from " |
373 | 0 | "number of floating coupon amounts"); |
374 | 0 | } |
375 | | |
376 | 0 | void NonstandardSwap::results::reset() { Swap::results::reset(); } |
377 | | } |