1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
5 Copyright (C) 2003, 2004, 2005, 2006, 2007 StatPro Italia srl
6 Copyright (C) 2007 Ferdinando Ametrano
7
8 This file is part of QuantLib, a free-software/open-source library
9 for financial quantitative analysts and developers - http://quantlib.org/
10
11 QuantLib is free software: you can redistribute it and/or modify it
12 under the terms of the QuantLib license. You should have received a
13 copy of the license along with this program; if not, please email
14 <quantlib-dev@lists.sf.net>. The license is also available online at
15 <http://quantlib.org/license.shtml>.
16
17 This program is distributed in the hope that it will be useful, but WITHOUT
18 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 FOR A PARTICULAR PURPOSE. See the license for more details.
20*/
21
22#include <ql/cashflows/cashflows.hpp>
23#include <ql/cashflows/cashflowvectors.hpp>
24#include <ql/cashflows/couponpricer.hpp>
25#include <ql/cashflows/fixedratecoupon.hpp>
26#include <ql/indexes/iborindex.hpp>
27#include <ql/instruments/fixedvsfloatingswap.hpp>
28#include <ql/termstructures/yieldtermstructure.hpp>
29#include <utility>
30
31namespace QuantLib {
32
33 FixedVsFloatingSwap::FixedVsFloatingSwap(Type type,
34 std::vector<Real> fixedNominals,
35 Schedule fixedSchedule,
36 Rate fixedRate,
37 DayCounter fixedDayCount,
38 std::vector<Real> floatingNominals,
39 Schedule floatingSchedule,
40 ext::shared_ptr<IborIndex> iborIndex,
41 Spread spread,
42 DayCounter floatingDayCount,
43 ext::optional<BusinessDayConvention> paymentConvention,
44 Natural paymentLag,
45 const Calendar& paymentCalendar)
46 : Swap(2), type_(type), fixedNominals_(std::move(fixedNominals)), fixedSchedule_(std::move(fixedSchedule)),
47 fixedRate_(fixedRate), fixedDayCount_(std::move(fixedDayCount)),
48 floatingNominals_(std::move(floatingNominals)), floatingSchedule_(std::move(floatingSchedule)),
49 iborIndex_(std::move(iborIndex)), spread_(spread), floatingDayCount_(std::move(floatingDayCount)) {
50
51 QL_REQUIRE(iborIndex_, "null floating index provided");
52
53 if (fixedDayCount_ == DayCounter())
54 fixedDayCount_ = iborIndex_->dayCounter();
55
56 if (paymentConvention) // NOLINT(readability-implicit-bool-conversion)
57 paymentConvention_ = *paymentConvention;
58 else
59 paymentConvention_ = floatingSchedule_.businessDayConvention();
60
61 legs_[0] = FixedRateLeg(fixedSchedule_)
62 .withNotionals(fixedNominals_)
63 .withCouponRates(fixedRate_, paymentDayCounter: fixedDayCount_)
64 .withPaymentAdjustment(paymentConvention_)
65 .withPaymentLag(lag: paymentLag)
66 .withPaymentCalendar(paymentCalendar.empty() ?
67 fixedSchedule_.calendar() :
68 paymentCalendar);
69
70 // legs_[1] to be built by derived class constructor
71
72 switch (type_) {
73 case Payer:
74 payer_[0] = -1.0;
75 payer_[1] = +1.0;
76 break;
77 case Receiver:
78 payer_[0] = +1.0;
79 payer_[1] = -1.0;
80 break;
81 default:
82 QL_FAIL("Unknown vanilla-swap type");
83 }
84
85
86 // These bools tell us if we can support the old methods nominal() and nominals().
87 // There might be false negatives (i.e., if we pass constant vectors of different lengths
88 // as fixedNominals and floatingNominals) but we're going to assume that whoever uses the
89 // constructor with two vectors is mostly going to use the new methods instead.
90 sameNominals_ = std::equal(first1: fixedNominals_.begin(), last1: fixedNominals_.end(),
91 first2: floatingNominals_.begin(), last2: floatingNominals_.end());
92 if (!sameNominals_) {
93 constantNominals_ = false;
94 } else {
95 constantNominals_ = true;
96 Real front = fixedNominals_[0];
97 for (auto x : fixedNominals_) {
98 if (x != front) {
99 constantNominals_ = false;
100 break;
101 }
102 }
103 }
104 }
105
106 void FixedVsFloatingSwap::setupArguments(PricingEngine::arguments* args) const {
107
108 Swap::setupArguments(args);
109
110 auto* arguments = dynamic_cast<FixedVsFloatingSwap::arguments*>(args);
111
112 if (arguments == nullptr) // it's a swap engine...
113 return;
114
115 arguments->type = type_;
116
117 if (constantNominals_)
118 arguments->nominal = nominal();
119 else
120 arguments->nominal = Null<Real>();
121
122 const Leg& fixedCoupons = fixedLeg();
123 Size n = fixedCoupons.size();
124
125 arguments->fixedResetDates = arguments->fixedPayDates = std::vector<Date>(n);
126 arguments->fixedNominals = arguments->fixedCoupons = std::vector<Real>(n);
127
128 for (Size i=0; i<n; ++i) {
129 auto coupon = ext::dynamic_pointer_cast<FixedRateCoupon>(r: fixedCoupons[i]);
130
131 arguments->fixedPayDates[i] = coupon->date();
132 arguments->fixedResetDates[i] = coupon->accrualStartDate();
133 arguments->fixedCoupons[i] = coupon->amount();
134 arguments->fixedNominals[i] = coupon->nominal();
135 }
136
137 setupFloatingArguments(arguments);
138 }
139
140 Rate FixedVsFloatingSwap::fairRate() const {
141 calculate();
142 QL_REQUIRE(fairRate_ != Null<Rate>(), "result not available");
143 return fairRate_;
144 }
145
146 Spread FixedVsFloatingSwap::fairSpread() const {
147 calculate();
148 QL_REQUIRE(fairSpread_ != Null<Spread>(), "result not available");
149 return fairSpread_;
150 }
151
152 Real FixedVsFloatingSwap::fixedLegBPS() const {
153 calculate();
154 QL_REQUIRE(legBPS_[0] != Null<Real>(), "result not available");
155 return legBPS_[0];
156 }
157
158 Real FixedVsFloatingSwap::floatingLegBPS() const {
159 calculate();
160 QL_REQUIRE(legBPS_[1] != Null<Real>(), "result not available");
161 return legBPS_[1];
162 }
163
164 Real FixedVsFloatingSwap::fixedLegNPV() const {
165 calculate();
166 QL_REQUIRE(legNPV_[0] != Null<Real>(), "result not available");
167 return legNPV_[0];
168 }
169
170 Real FixedVsFloatingSwap::floatingLegNPV() const {
171 calculate();
172 QL_REQUIRE(legNPV_[1] != Null<Real>(), "result not available");
173 return legNPV_[1];
174 }
175
176 void FixedVsFloatingSwap::setupExpired() const {
177 Swap::setupExpired();
178 legBPS_[0] = legBPS_[1] = 0.0;
179 fairRate_ = Null<Rate>();
180 fairSpread_ = Null<Spread>();
181 }
182
183 void FixedVsFloatingSwap::fetchResults(const PricingEngine::results* r) const {
184 static const Spread basisPoint = 1.0e-4;
185
186 Swap::fetchResults(r);
187
188 const auto* results = dynamic_cast<const FixedVsFloatingSwap::results*>(r);
189 if (results != nullptr) { // might be a swap engine, so no error is thrown
190 fairRate_ = results->fairRate;
191 fairSpread_ = results->fairSpread;
192 } else {
193 fairRate_ = Null<Rate>();
194 fairSpread_ = Null<Spread>();
195 }
196
197 if (fairRate_ == Null<Rate>()) {
198 // calculate it from other results
199 if (legBPS_[0] != Null<Real>())
200 fairRate_ = fixedRate_ - NPV_/(legBPS_[0]/basisPoint);
201 }
202 if (fairSpread_ == Null<Spread>()) {
203 // ditto
204 if (legBPS_[1] != Null<Real>())
205 fairSpread_ = spread_ - NPV_/(legBPS_[1]/basisPoint);
206 }
207 }
208
209 void FixedVsFloatingSwap::arguments::validate() const {
210 Swap::arguments::validate();
211 QL_REQUIRE(fixedNominals.size() == fixedPayDates.size(),
212 "number of fixed nominals different from "
213 "number of fixed payment dates");
214 QL_REQUIRE(fixedResetDates.size() == fixedPayDates.size(),
215 "number of fixed start dates different from "
216 "number of fixed payment dates");
217 QL_REQUIRE(fixedPayDates.size() == fixedCoupons.size(),
218 "number of fixed payment dates different from "
219 "number of fixed coupon amounts");
220 QL_REQUIRE(floatingNominals.size() == floatingPayDates.size(),
221 "number of floating nominals different from "
222 "number of floating payment dates");
223 QL_REQUIRE(floatingResetDates.size() == floatingPayDates.size(),
224 "number of floating start dates different from "
225 "number of floating payment dates");
226 QL_REQUIRE(floatingFixingDates.size() == floatingPayDates.size(),
227 "number of floating fixing dates different from "
228 "number of floating payment dates");
229 QL_REQUIRE(floatingAccrualTimes.size() == floatingPayDates.size(),
230 "number of floating accrual Times different from "
231 "number of floating payment dates");
232 QL_REQUIRE(floatingSpreads.size() == floatingPayDates.size(),
233 "number of floating spreads different from "
234 "number of floating payment dates");
235 QL_REQUIRE(floatingPayDates.size() == floatingCoupons.size(),
236 "number of floating payment dates different from "
237 "number of floating coupon amounts");
238 }
239
240 void FixedVsFloatingSwap::results::reset() {
241 Swap::results::reset();
242 fairRate = Null<Rate>();
243 fairSpread = Null<Spread>();
244 }
245
246}
247

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

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