1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2013 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 <http://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/experimental/coupons/cmsspreadcoupon.hpp> // internal
28#include <ql/indexes/iborindex.hpp>
29#include <ql/indexes/swapindex.hpp>
30#include <ql/instruments/floatfloatswap.hpp>
31#include <ql/termstructures/yieldtermstructure.hpp>
32#include <ql/optional.hpp>
33#include <utility>
34
35namespace QuantLib {
36
37 FloatFloatSwap::FloatFloatSwap(const Swap::Type type,
38 const Real nominal1,
39 const Real nominal2,
40 const Schedule& schedule1,
41 ext::shared_ptr<InterestRateIndex> index1,
42 DayCounter dayCount1,
43 const Schedule& schedule2,
44 ext::shared_ptr<InterestRateIndex> index2,
45 DayCounter dayCount2,
46 const bool intermediateCapitalExchange,
47 const bool finalCapitalExchange,
48 const Real gearing1,
49 const Real spread1,
50 const Real cappedRate1,
51 const Real flooredRate1,
52 const Real gearing2,
53 const Real spread2,
54 const Real cappedRate2,
55 const Real flooredRate2,
56 const ext::optional<BusinessDayConvention>& paymentConvention1,
57 const ext::optional<BusinessDayConvention>& paymentConvention2)
58 : Swap(2), type_(type), nominal1_(std::vector<Real>(schedule1.size() - 1, nominal1)),
59 nominal2_(std::vector<Real>(schedule2.size() - 1, nominal2)), schedule1_(schedule1),
60 schedule2_(schedule2), index1_(std::move(index1)), index2_(std::move(index2)),
61 gearing1_(std::vector<Real>(schedule1.size() - 1, gearing1)),
62 gearing2_(std::vector<Real>(schedule2.size() - 1, gearing2)),
63 spread1_(std::vector<Real>(schedule1.size() - 1, spread1)),
64 spread2_(std::vector<Real>(schedule2.size() - 1, spread2)),
65 cappedRate1_(std::vector<Real>(schedule1.size() - 1, cappedRate1)),
66 flooredRate1_(std::vector<Real>(schedule1.size() - 1, flooredRate1)),
67 cappedRate2_(std::vector<Real>(schedule2.size() - 1, cappedRate2)),
68 flooredRate2_(std::vector<Real>(schedule2.size() - 1, flooredRate2)),
69 dayCount1_(std::move(dayCount1)), dayCount2_(std::move(dayCount2)),
70 intermediateCapitalExchange_(intermediateCapitalExchange),
71 finalCapitalExchange_(finalCapitalExchange) {
72
73 init(paymentConvention1, paymentConvention2);
74 }
75
76 FloatFloatSwap::FloatFloatSwap(const Swap::Type type,
77 std::vector<Real> nominal1,
78 std::vector<Real> nominal2,
79 Schedule schedule1,
80 ext::shared_ptr<InterestRateIndex> index1,
81 DayCounter dayCount1,
82 Schedule schedule2,
83 ext::shared_ptr<InterestRateIndex> index2,
84 DayCounter dayCount2,
85 const bool intermediateCapitalExchange,
86 const bool finalCapitalExchange,
87 std::vector<Real> gearing1,
88 std::vector<Real> spread1,
89 std::vector<Real> cappedRate1,
90 std::vector<Real> flooredRate1,
91 std::vector<Real> gearing2,
92 std::vector<Real> spread2,
93 std::vector<Real> cappedRate2,
94 std::vector<Real> flooredRate2,
95 const ext::optional<BusinessDayConvention>& paymentConvention1,
96 const ext::optional<BusinessDayConvention>& paymentConvention2)
97 : Swap(2), type_(type), nominal1_(std::move(nominal1)), nominal2_(std::move(nominal2)),
98 schedule1_(std::move(schedule1)), schedule2_(std::move(schedule2)),
99 index1_(std::move(index1)), index2_(std::move(index2)), gearing1_(std::move(gearing1)),
100 gearing2_(std::move(gearing2)), spread1_(std::move(spread1)), spread2_(std::move(spread2)),
101 cappedRate1_(std::move(cappedRate1)), flooredRate1_(std::move(flooredRate1)),
102 cappedRate2_(std::move(cappedRate2)), flooredRate2_(std::move(flooredRate2)),
103 dayCount1_(std::move(dayCount1)), dayCount2_(std::move(dayCount2)),
104 intermediateCapitalExchange_(intermediateCapitalExchange),
105 finalCapitalExchange_(finalCapitalExchange) {
106
107 init(paymentConvention1, paymentConvention2);
108 }
109
110 void FloatFloatSwap::init(
111 ext::optional<BusinessDayConvention> paymentConvention1,
112 ext::optional<BusinessDayConvention> paymentConvention2) {
113
114 QL_REQUIRE(nominal1_.size() == schedule1_.size() - 1,
115 "nominal1 size (" << nominal1_.size()
116 << ") does not match schedule1 size ("
117 << schedule1_.size() << ")");
118 QL_REQUIRE(nominal2_.size() == schedule2_.size() - 1,
119 "nominal2 size (" << nominal2_.size()
120 << ") does not match schedule2 size ("
121 << nominal2_.size() << ")");
122 QL_REQUIRE(gearing1_.empty() || gearing1_.size() == nominal1_.size(),
123 "nominal1 size (" << nominal1_.size() << ") does not match gearing1 size ("
124 << gearing1_.size() << ")");
125 QL_REQUIRE(gearing2_.empty() || gearing2_.size() == nominal2_.size(),
126 "nominal2 size (" << nominal2_.size() << ") does not match gearing2 size ("
127 << gearing2_.size() << ")");
128 QL_REQUIRE(cappedRate1_.empty() || cappedRate1_.size() == nominal1_.size(),
129 "nominal1 size (" << nominal1_.size() << ") does not match cappedRate1 size ("
130 << cappedRate1_.size() << ")");
131 QL_REQUIRE(cappedRate2_.empty() || cappedRate2_.size() == nominal2_.size(),
132 "nominal2 size (" << nominal2_.size() << ") does not match cappedRate2 size ("
133 << cappedRate2_.size() << ")");
134 QL_REQUIRE(flooredRate1_.empty() || flooredRate1_.size() == nominal1_.size(),
135 "nominal1 size (" << nominal1_.size() << ") does not match flooredRate1 size ("
136 << flooredRate1_.size() << ")");
137 QL_REQUIRE(flooredRate2_.empty() || flooredRate2_.size() == nominal2_.size(),
138 "nominal2 size (" << nominal2_.size() << ") does not match flooredRate2 size ("
139 << flooredRate2_.size() << ")");
140
141 if (paymentConvention1) // NOLINT(readability-implicit-bool-conversion)
142 paymentConvention1_ = *paymentConvention1;
143 else
144 paymentConvention1_ = schedule1_.businessDayConvention();
145
146 if (paymentConvention2) // NOLINT(readability-implicit-bool-conversion)
147 paymentConvention2_ = *paymentConvention2;
148 else
149 paymentConvention2_ = schedule2_.businessDayConvention();
150
151 if (gearing1_.empty())
152 gearing1_ = std::vector<Real>(nominal1_.size(), 1.0);
153 if (gearing2_.empty())
154 gearing2_ = std::vector<Real>(nominal2_.size(), 1.0);
155 if (spread1_.empty())
156 spread1_ = std::vector<Real>(nominal1_.size(), 0.0);
157 if (spread2_.empty())
158 spread2_ = std::vector<Real>(nominal2_.size(), 0.0);
159 if (cappedRate1_.empty())
160 cappedRate1_ = std::vector<Real>(nominal1_.size(), Null<Real>());
161 if (cappedRate2_.empty())
162 cappedRate2_ = std::vector<Real>(nominal2_.size(), Null<Real>());
163 if (flooredRate1_.empty())
164 flooredRate1_ = std::vector<Real>(nominal1_.size(), Null<Real>());
165 if (flooredRate2_.empty())
166 flooredRate2_ = std::vector<Real>(nominal2_.size(), Null<Real>());
167
168 bool isNull;
169 isNull = cappedRate1_[0] == Null<Real>();
170 for (Size i = 0; i < cappedRate1_.size(); i++) {
171 if (isNull)
172 QL_REQUIRE(cappedRate1_[i] == Null<Real>(),
173 "cappedRate1 must be null for all or none entry ("
174 << (i + 1) << "th is " << cappedRate1_[i]
175 << ")");
176 else
177 QL_REQUIRE(cappedRate1_[i] != Null<Real>(),
178 "cappedRate 1 must be null for all or none entry ("
179 << "1st is " << cappedRate1_[0] << ")");
180 }
181 isNull = cappedRate2_[0] == Null<Real>();
182 for (Size i = 0; i < cappedRate2_.size(); i++) {
183 if (isNull)
184 QL_REQUIRE(cappedRate2_[i] == Null<Real>(),
185 "cappedRate2 must be null for all or none entry ("
186 << (i + 1) << "th is " << cappedRate2_[i]
187 << ")");
188 else
189 QL_REQUIRE(cappedRate2_[i] != Null<Real>(),
190 "cappedRate2 must be null for all or none entry ("
191 << "1st is " << cappedRate2_[0] << ")");
192 }
193 isNull = flooredRate1_[0] == Null<Real>();
194 for (Size i = 0; i < flooredRate1_.size(); i++) {
195 if (isNull)
196 QL_REQUIRE(flooredRate1_[i] == Null<Real>(),
197 "flooredRate1 must be null for all or none entry ("
198 << (i + 1) << "th is " << flooredRate1_[i]
199 << ")");
200 else
201 QL_REQUIRE(flooredRate1_[i] != Null<Real>(),
202 "flooredRate 1 must be null for all or none entry ("
203 << "1st is " << flooredRate1_[0] << ")");
204 }
205 isNull = flooredRate2_[0] == Null<Real>();
206 for (Size i = 0; i < flooredRate2_.size(); i++) {
207 if (isNull)
208 QL_REQUIRE(flooredRate2_[i] == Null<Real>(),
209 "flooredRate2 must be null for all or none entry ("
210 << (i + 1) << "th is " << flooredRate2_[i]
211 << ")");
212 else
213 QL_REQUIRE(flooredRate2_[i] != Null<Real>(),
214 "flooredRate2 must be null for all or none entry ("
215 << "1st is " << flooredRate2_[0] << ")");
216 }
217
218 // if the gearing is zero then the ibor / cms leg will be set up with
219 // fixed coupons which makes trouble here in this context. We therefore
220 // use a dirty trick and enforce the gearing to be non zero.
221 for (Real& i : gearing1_)
222 if (close(x: i, y: 0.0))
223 i = QL_EPSILON;
224 for (Real& i : gearing2_)
225 if (close(x: i, y: 0.0))
226 i = QL_EPSILON;
227
228 ext::shared_ptr<IborIndex> ibor1 =
229 ext::dynamic_pointer_cast<IborIndex>(r: index1_);
230 ext::shared_ptr<IborIndex> ibor2 =
231 ext::dynamic_pointer_cast<IborIndex>(r: index2_);
232 ext::shared_ptr<SwapIndex> cms1 =
233 ext::dynamic_pointer_cast<SwapIndex>(r: index1_);
234 ext::shared_ptr<SwapIndex> cms2 =
235 ext::dynamic_pointer_cast<SwapIndex>(r: index2_);
236 ext::shared_ptr<SwapSpreadIndex> cmsspread1 =
237 ext::dynamic_pointer_cast<SwapSpreadIndex>(r: index1_);
238 ext::shared_ptr<SwapSpreadIndex> cmsspread2 =
239 ext::dynamic_pointer_cast<SwapSpreadIndex>(r: index2_);
240
241 QL_REQUIRE(ibor1 != nullptr || cms1 != nullptr || cmsspread1 != nullptr,
242 "index1 must be ibor or cms or cms spread");
243 QL_REQUIRE(ibor2 != nullptr || cms2 != nullptr || cmsspread2 != nullptr,
244 "index2 must be ibor or cms");
245
246 if (ibor1 != nullptr) {
247 IborLeg leg(schedule1_, ibor1);
248 leg = leg.withNotionals(notionals: nominal1_)
249 .withPaymentDayCounter(dayCount1_)
250 .withPaymentAdjustment(paymentConvention1_)
251 .withSpreads(spreads: spread1_)
252 .withGearings(gearings: gearing1_);
253 if (cappedRate1_[0] != Null<Real>())
254 leg = leg.withCaps(caps: cappedRate1_);
255 if (flooredRate1_[0] != Null<Real>())
256 leg = leg.withFloors(floors: flooredRate1_);
257 legs_[0] = leg;
258 }
259
260 if (ibor2 != nullptr) {
261 IborLeg leg(schedule2_, ibor2);
262 leg = leg.withNotionals(notionals: nominal2_)
263 .withPaymentDayCounter(dayCount2_)
264 .withPaymentAdjustment(paymentConvention2_)
265 .withSpreads(spreads: spread2_)
266 .withGearings(gearings: gearing2_);
267 if (cappedRate2_[0] != Null<Real>())
268 leg = leg.withCaps(caps: cappedRate2_);
269 if (flooredRate2_[0] != Null<Real>())
270 leg = leg.withFloors(floors: flooredRate2_);
271 legs_[1] = leg;
272 }
273
274 if (cms1 != nullptr) {
275 CmsLeg leg(schedule1_, cms1);
276 leg = leg.withNotionals(notionals: nominal1_)
277 .withPaymentDayCounter(dayCount1_)
278 .withPaymentAdjustment(paymentConvention1_)
279 .withSpreads(spreads: spread1_)
280 .withGearings(gearings: gearing1_);
281 if (cappedRate1_[0] != Null<Real>())
282 leg = leg.withCaps(caps: cappedRate1_);
283 if (flooredRate1_[0] != Null<Real>())
284 leg = leg.withFloors(floors: flooredRate1_);
285 legs_[0] = leg;
286 }
287
288 if (cms2 != nullptr) {
289 CmsLeg leg(schedule2_, cms2);
290 leg = leg.withNotionals(notionals: nominal2_)
291 .withPaymentDayCounter(dayCount2_)
292 .withPaymentAdjustment(paymentConvention2_)
293 .withSpreads(spreads: spread2_)
294 .withGearings(gearings: gearing2_);
295 if (cappedRate2_[0] != Null<Real>())
296 leg = leg.withCaps(caps: cappedRate2_);
297 if (flooredRate2_[0] != Null<Real>())
298 leg = leg.withFloors(floors: flooredRate2_);
299 legs_[1] = leg;
300 }
301
302 if (cmsspread1 != nullptr) {
303 CmsSpreadLeg leg(schedule1_, cmsspread1);
304 leg = leg.withNotionals(notionals: nominal1_)
305 .withPaymentDayCounter(dayCount1_)
306 .withPaymentAdjustment(paymentConvention1_)
307 .withSpreads(spreads: spread1_)
308 .withGearings(gearings: gearing1_);
309 if (cappedRate1_[0] != Null<Real>())
310 leg = leg.withCaps(caps: cappedRate1_);
311 if (flooredRate1_[0] != Null<Real>())
312 leg = leg.withFloors(floors: flooredRate1_);
313 legs_[0] = leg;
314 }
315
316 if (cmsspread2 != nullptr) {
317 CmsSpreadLeg leg(schedule2_, cmsspread2);
318 leg = leg.withNotionals(notionals: nominal2_)
319 .withPaymentDayCounter(dayCount2_)
320 .withPaymentAdjustment(paymentConvention2_)
321 .withSpreads(spreads: spread2_)
322 .withGearings(gearings: gearing2_);
323 if (cappedRate2_[0] != Null<Real>())
324 leg = leg.withCaps(caps: cappedRate2_);
325 if (flooredRate2_[0] != Null<Real>())
326 leg = leg.withFloors(floors: flooredRate2_);
327 legs_[1] = leg;
328 }
329
330 if (intermediateCapitalExchange_) {
331 for (Size i = 0; i < legs_[0].size() - 1; i++) {
332 Real cap = nominal1_[i] - nominal1_[i + 1];
333 if (!close(x: cap, y: 0.0)) {
334 auto it1 = legs_[0].begin();
335 std::advance(i&: it1, n: i + 1);
336 legs_[0].insert(
337 position: it1, x: ext::shared_ptr<CashFlow>(
338 new Redemption(cap, legs_[0][i]->date())));
339 auto it2 = nominal1_.begin();
340 std::advance(i&: it2, n: i + 1);
341 nominal1_.insert(position: it2, x: nominal1_[i]);
342 i++;
343 }
344 }
345 for (Size i = 0; i < legs_[1].size() - 1; i++) {
346 Real cap = nominal2_[i] - nominal2_[i + 1];
347 if (!close(x: cap, y: 0.0)) {
348 auto it1 = legs_[1].begin();
349 std::advance(i&: it1, n: i + 1);
350 legs_[1].insert(
351 position: it1, x: ext::shared_ptr<CashFlow>(
352 new Redemption(cap, legs_[1][i]->date())));
353 auto it2 = nominal2_.begin();
354 std::advance(i&: it2, n: i + 1);
355 nominal2_.insert(position: it2, x: nominal2_[i]);
356 i++;
357 }
358 }
359 }
360
361 if (finalCapitalExchange_) {
362 legs_[0].push_back(x: ext::shared_ptr<CashFlow>(
363 new Redemption(nominal1_.back(), legs_[0].back()->date())));
364 nominal1_.push_back(x: nominal1_.back());
365 legs_[1].push_back(x: ext::shared_ptr<CashFlow>(
366 new Redemption(nominal2_.back(), legs_[1].back()->date())));
367 nominal2_.push_back(x: nominal2_.back());
368 }
369
370 for (Leg::const_iterator i = legs_[0].begin(); i < legs_[0].end(); ++i)
371 registerWith(h: *i);
372
373 for (Leg::const_iterator i = legs_[1].begin(); i < legs_[1].end(); ++i)
374 registerWith(h: *i);
375
376 switch (type_) {
377 case Swap::Payer:
378 payer_[0] = -1.0;
379 payer_[1] = +1.0;
380 break;
381 case Swap::Receiver:
382 payer_[0] = +1.0;
383 payer_[1] = -1.0;
384 break;
385 default:
386 QL_FAIL("Unknown float float - swap type");
387 }
388 }
389
390 void FloatFloatSwap::setupArguments(PricingEngine::arguments *args) const {
391
392 Swap::setupArguments(args);
393
394 auto* arguments = dynamic_cast<FloatFloatSwap::arguments*>(args);
395
396 if (arguments == nullptr)
397 return; // swap engine ... // QL_REQUIRE(arguments != 0, "argument type does not match");
398
399 arguments->type = type_;
400 arguments->nominal1 = nominal1_;
401 arguments->nominal2 = nominal2_;
402 arguments->index1 = index1_;
403 arguments->index2 = index2_;
404
405 const Leg &leg1Coupons = leg1();
406 const Leg &leg2Coupons = leg2();
407
408 arguments->leg1ResetDates = arguments->leg1PayDates =
409 arguments->leg1FixingDates = std::vector<Date>(leg1Coupons.size());
410 arguments->leg2ResetDates = arguments->leg2PayDates =
411 arguments->leg2FixingDates = std::vector<Date>(leg2Coupons.size());
412
413 arguments->leg1Spreads = arguments->leg1AccrualTimes =
414 arguments->leg1Gearings = std::vector<Real>(leg1Coupons.size());
415 arguments->leg2Spreads = arguments->leg2AccrualTimes =
416 arguments->leg2Gearings = std::vector<Real>(leg2Coupons.size());
417
418 arguments->leg1Coupons =
419 std::vector<Real>(leg1Coupons.size(), Null<Real>());
420 arguments->leg2Coupons =
421 std::vector<Real>(leg2Coupons.size(), Null<Real>());
422
423 arguments->leg1IsRedemptionFlow =
424 std::vector<bool>(leg1Coupons.size(), false);
425 arguments->leg2IsRedemptionFlow =
426 std::vector<bool>(leg2Coupons.size(), false);
427
428 arguments->leg1CappedRates = arguments->leg1FlooredRates =
429 std::vector<Real>(leg1Coupons.size(), Null<Real>());
430 arguments->leg2CappedRates = arguments->leg2FlooredRates =
431 std::vector<Real>(leg2Coupons.size(), Null<Real>());
432
433 for (Size i = 0; i < leg1Coupons.size(); ++i) {
434 ext::shared_ptr<FloatingRateCoupon> coupon =
435 ext::dynamic_pointer_cast<FloatingRateCoupon>(r: leg1Coupons[i]);
436 if (coupon != nullptr) {
437 arguments->leg1AccrualTimes[i] = coupon->accrualPeriod();
438 arguments->leg1PayDates[i] = coupon->date();
439 arguments->leg1ResetDates[i] = coupon->accrualStartDate();
440 arguments->leg1FixingDates[i] = coupon->fixingDate();
441 arguments->leg1Spreads[i] = coupon->spread();
442 arguments->leg1Gearings[i] = coupon->gearing();
443 try {
444 arguments->leg1Coupons[i] = coupon->amount();
445 }
446 catch (Error &) {
447 arguments->leg1Coupons[i] = Null<Real>();
448 }
449 ext::shared_ptr<CappedFlooredCoupon> cfcoupon =
450 ext::dynamic_pointer_cast<CappedFlooredCoupon>(
451 r: leg1Coupons[i]);
452 if (cfcoupon != nullptr) {
453 arguments->leg1CappedRates[i] = cfcoupon->cap();
454 arguments->leg1FlooredRates[i] = cfcoupon->floor();
455 }
456 } else {
457 ext::shared_ptr<CashFlow> cashflow =
458 ext::dynamic_pointer_cast<CashFlow>(r: leg1Coupons[i]);
459 std::vector<Date>::const_iterator j =
460 std::find(first: arguments->leg1PayDates.begin(),
461 last: arguments->leg1PayDates.end(), val: cashflow->date());
462 QL_REQUIRE(j != arguments->leg1PayDates.end(),
463 "nominal redemption on "
464 << cashflow->date()
465 << "has no corresponding coupon");
466 Size jIdx = j - arguments->leg1PayDates.begin();
467 arguments->leg1IsRedemptionFlow[i] = true;
468 arguments->leg1Coupons[i] = cashflow->amount();
469 arguments->leg1ResetDates[i] = arguments->leg1ResetDates[jIdx];
470 arguments->leg1FixingDates[i] =
471 arguments->leg1FixingDates[jIdx];
472 arguments->leg1AccrualTimes[i] = 0.0;
473 arguments->leg1Spreads[i] = 0.0;
474 arguments->leg1Gearings[i] = 1.0;
475 arguments->leg1PayDates[i] = cashflow->date();
476 }
477 }
478
479 for (Size i = 0; i < leg2Coupons.size(); ++i) {
480 ext::shared_ptr<FloatingRateCoupon> coupon =
481 ext::dynamic_pointer_cast<FloatingRateCoupon>(r: leg2Coupons[i]);
482 if (coupon != nullptr) {
483 arguments->leg2AccrualTimes[i] = coupon->accrualPeriod();
484 arguments->leg2PayDates[i] = coupon->date();
485 arguments->leg2ResetDates[i] = coupon->accrualStartDate();
486 arguments->leg2FixingDates[i] = coupon->fixingDate();
487 arguments->leg2Spreads[i] = coupon->spread();
488 arguments->leg2Gearings[i] = coupon->gearing();
489 try {
490 arguments->leg2Coupons[i] = coupon->amount();
491 }
492 catch (Error &) {
493 arguments->leg2Coupons[i] = Null<Real>();
494 }
495 ext::shared_ptr<CappedFlooredCoupon> cfcoupon =
496 ext::dynamic_pointer_cast<CappedFlooredCoupon>(
497 r: leg2Coupons[i]);
498 if (cfcoupon != nullptr) {
499 arguments->leg2CappedRates[i] = cfcoupon->cap();
500 arguments->leg2FlooredRates[i] = cfcoupon->floor();
501 }
502 } else {
503 ext::shared_ptr<CashFlow> cashflow =
504 ext::dynamic_pointer_cast<CashFlow>(r: leg2Coupons[i]);
505 std::vector<Date>::const_iterator j =
506 std::find(first: arguments->leg2PayDates.begin(),
507 last: arguments->leg2PayDates.end(), val: cashflow->date());
508 QL_REQUIRE(j != arguments->leg2PayDates.end(),
509 "nominal redemption on "
510 << cashflow->date()
511 << "has no corresponding coupon");
512 Size jIdx = j - arguments->leg2PayDates.begin();
513 arguments->leg2IsRedemptionFlow[i] = true;
514 arguments->leg2Coupons[i] = cashflow->amount();
515 arguments->leg2ResetDates[i] = arguments->leg2ResetDates[jIdx];
516 arguments->leg2FixingDates[i] =
517 arguments->leg2FixingDates[jIdx];
518 arguments->leg2AccrualTimes[i] = 0.0;
519 arguments->leg2Spreads[i] = 0.0;
520 arguments->leg2Gearings[i] = 1.0;
521 arguments->leg2PayDates[i] = cashflow->date();
522 }
523 }
524 }
525
526 void FloatFloatSwap::setupExpired() const { Swap::setupExpired(); }
527
528 void FloatFloatSwap::fetchResults(const PricingEngine::results *r) const {
529 Swap::fetchResults(r);
530 }
531
532 void FloatFloatSwap::arguments::validate() const {
533
534 Swap::arguments::validate();
535
536 QL_REQUIRE(nominal1.size() == leg1ResetDates.size(),
537 "nominal1 size is different from resetDates1 size");
538 QL_REQUIRE(nominal1.size() == leg1FixingDates.size(),
539 "nominal1 size is different from fixingDates1 size");
540 QL_REQUIRE(nominal1.size() == leg1PayDates.size(),
541 "nominal1 size is different from payDates1 size");
542 QL_REQUIRE(nominal1.size() == leg1Spreads.size(),
543 "nominal1 size is different from spreads1 size");
544 QL_REQUIRE(nominal1.size() == leg1Gearings.size(),
545 "nominal1 size is different from gearings1 size");
546 QL_REQUIRE(nominal1.size() == leg1CappedRates.size(),
547 "nominal1 size is different from cappedRates1 size");
548 QL_REQUIRE(nominal1.size() == leg1FlooredRates.size(),
549 "nominal1 size is different from flooredRates1 size");
550 QL_REQUIRE(nominal1.size() == leg1Coupons.size(),
551 "nominal1 size is different from coupons1 size");
552 QL_REQUIRE(nominal1.size() == leg1AccrualTimes.size(),
553 "nominal1 size is different from accrualTimes1 size");
554 QL_REQUIRE(nominal1.size() == leg1IsRedemptionFlow.size(),
555 "nominal1 size is different from redemption1 size");
556
557 QL_REQUIRE(nominal2.size() == leg2ResetDates.size(),
558 "nominal2 size is different from resetDates2 size");
559 QL_REQUIRE(nominal2.size() == leg2FixingDates.size(),
560 "nominal2 size is different from fixingDates2 size");
561 QL_REQUIRE(nominal2.size() == leg2PayDates.size(),
562 "nominal2 size is different from payDates2 size");
563 QL_REQUIRE(nominal2.size() == leg2Spreads.size(),
564 "nominal2 size is different from spreads2 size");
565 QL_REQUIRE(nominal2.size() == leg2Gearings.size(),
566 "nominal2 size is different from gearings2 size");
567 QL_REQUIRE(nominal2.size() == leg2CappedRates.size(),
568 "nominal2 size is different from cappedRates2 size");
569 QL_REQUIRE(nominal2.size() == leg2FlooredRates.size(),
570 "nominal2 size is different from flooredRates2 size");
571 QL_REQUIRE(nominal2.size() == leg2Coupons.size(),
572 "nominal2 size is different from coupons2 size");
573 QL_REQUIRE(nominal2.size() == leg2AccrualTimes.size(),
574 "nominal2 size is different from accrualTimes2 size");
575 QL_REQUIRE(nominal2.size() == leg2IsRedemptionFlow.size(),
576 "nominal2 size is different from redemption2 size");
577
578 QL_REQUIRE(index1 != nullptr, "index1 is null");
579 QL_REQUIRE(index2 != nullptr, "index2 is null");
580 }
581
582 void FloatFloatSwap::results::reset() { Swap::results::reset(); }
583}
584

source code of quantlib/ql/instruments/floatfloatswap.cpp

Morty Proxy This is a proxified and sanitized view of the page, visit original site.