1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2006, 2007, 2010, 2014, 2015 Ferdinando Ametrano
5 Copyright (C) 2006 Katiuscia Manzoni
6 Copyright (C) 2006 StatPro Italia srl
7 Copyright (C) 2015 Paolo Mazzocchi
8 Copyright (C) 2018 Matthias Groncki
9
10 This file is part of QuantLib, a free-software/open-source library
11 for financial quantitative analysts and developers - http://quantlib.org/
12
13 QuantLib is free software: you can redistribute it and/or modify it
14 under the terms of the QuantLib license. You should have received a
15 copy of the license along with this program; if not, please email
16 <quantlib-dev@lists.sf.net>. The license is also available online at
17 <http://quantlib.org/license.shtml>.
18
19 This program is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21 FOR A PARTICULAR PURPOSE. See the license for more details.
22*/
23
24#include <ql/instruments/makevanillaswap.hpp>
25#include <ql/pricingengines/swap/discountingswapengine.hpp>
26#include <ql/time/daycounters/thirty360.hpp>
27#include <ql/time/daycounters/actual360.hpp>
28#include <ql/time/daycounters/actual365fixed.hpp>
29#include <ql/indexes/iborindex.hpp>
30#include <ql/time/schedule.hpp>
31#include <ql/currencies/america.hpp>
32#include <ql/currencies/asia.hpp>
33#include <ql/currencies/europe.hpp>
34#include <ql/currencies/oceania.hpp>
35#include <ql/utilities/null.hpp>
36#include <ql/optional.hpp>
37
38namespace QuantLib {
39
40 MakeVanillaSwap::MakeVanillaSwap(const Period& swapTenor,
41 const ext::shared_ptr<IborIndex>& index,
42 Rate fixedRate,
43 const Period& forwardStart)
44 : swapTenor_(swapTenor), iborIndex_(index), fixedRate_(fixedRate), forwardStart_(forwardStart),
45 settlementDays_(Null<Natural>()), fixedCalendar_(index->fixingCalendar()),
46 floatCalendar_(index->fixingCalendar()),
47
48 floatTenor_(index->tenor()),
49
50 floatConvention_(index->businessDayConvention()),
51 floatTerminationDateConvention_(index->businessDayConvention()),
52
53 floatDayCount_(index->dayCounter()) {}
54
55 MakeVanillaSwap::operator VanillaSwap() const {
56 ext::shared_ptr<VanillaSwap> swap = *this;
57 return *swap;
58 }
59
60 MakeVanillaSwap::operator ext::shared_ptr<VanillaSwap>() const {
61
62 Date startDate;
63 if (effectiveDate_ != Date())
64 startDate = effectiveDate_;
65 else {
66 Date refDate = Settings::instance().evaluationDate();
67 // if the evaluation date is not a business day
68 // then move to the next business day
69 refDate = floatCalendar_.adjust(refDate);
70 // use index valueDate interface wherever possible to estimate spot date.
71 // Unless we pass an explicit settlementDays_ which does not match the index-defined number of fixing days.
72 Date spotDate;
73 if (settlementDays_ == Null<Natural>())
74 spotDate = iborIndex_->valueDate(fixingDate: refDate);
75 else
76 spotDate = floatCalendar_.advance(date: refDate, period: settlementDays_ * Days);
77 startDate = spotDate+forwardStart_;
78 if (forwardStart_.length()<0)
79 startDate = floatCalendar_.adjust(startDate,
80 convention: Preceding);
81 else if (forwardStart_.length()>0)
82 startDate = floatCalendar_.adjust(startDate,
83 convention: Following);
84 // no explicit date adjustment needed for forwardStart_.length()==0 (already handled by spotDate arithmetic above)
85 }
86
87 Date endDate = terminationDate_;
88 if (endDate == Date()) {
89 if (floatEndOfMonth_)
90 endDate = floatCalendar_.advance(date: startDate,
91 period: swapTenor_,
92 convention: ModifiedFollowing,
93 endOfMonth: floatEndOfMonth_);
94 else
95 endDate = startDate + swapTenor_;
96 }
97
98 const Currency& curr = iborIndex_->currency();
99 Period fixedTenor;
100 if (fixedTenor_ != Period())
101 fixedTenor = fixedTenor_;
102 else {
103 if ((curr == EURCurrency()) ||
104 (curr == USDCurrency()) ||
105 (curr == CHFCurrency()) ||
106 (curr == SEKCurrency()) ||
107 (curr == GBPCurrency() && swapTenor_ <= 1 * Years))
108 fixedTenor = Period(1, Years);
109 else if ((curr == GBPCurrency() && swapTenor_ > 1 * Years) ||
110 (curr == JPYCurrency()) ||
111 (curr == AUDCurrency() && swapTenor_ >= 4 * Years))
112 fixedTenor = Period(6, Months);
113 else if ((curr == HKDCurrency() ||
114 (curr == AUDCurrency() && swapTenor_ < 4 * Years)))
115 fixedTenor = Period(3, Months);
116 else
117 QL_FAIL("unknown fixed leg default tenor for " << curr);
118 }
119
120 Schedule fixedSchedule(startDate, endDate,
121 fixedTenor, fixedCalendar_,
122 fixedConvention_,
123 fixedTerminationDateConvention_,
124 fixedRule_, fixedEndOfMonth_,
125 fixedFirstDate_, fixedNextToLastDate_);
126
127 Schedule floatSchedule(startDate, endDate,
128 floatTenor_, floatCalendar_,
129 floatConvention_,
130 floatTerminationDateConvention_,
131 floatRule_, floatEndOfMonth_,
132 floatFirstDate_, floatNextToLastDate_);
133
134 DayCounter fixedDayCount;
135 if (fixedDayCount_ != DayCounter())
136 fixedDayCount = fixedDayCount_;
137 else {
138 if (curr == USDCurrency())
139 fixedDayCount = Actual360();
140 else if (curr == EURCurrency() || curr == CHFCurrency() ||
141 curr == SEKCurrency())
142 fixedDayCount = Thirty360(Thirty360::BondBasis);
143 else if (curr == GBPCurrency() || curr == JPYCurrency() ||
144 curr == AUDCurrency() || curr == HKDCurrency() ||
145 curr == THBCurrency())
146 fixedDayCount = Actual365Fixed();
147 else
148 QL_FAIL("unknown fixed leg day counter for " << curr);
149 }
150
151 Rate usedFixedRate = fixedRate_;
152 if (fixedRate_ == Null<Rate>()) {
153 VanillaSwap temp(type_, 100.00, fixedSchedule,
154 0.0, // fixed rate
155 fixedDayCount, floatSchedule, iborIndex_, floatSpread_, floatDayCount_,
156 ext::nullopt, useIndexedCoupons_);
157 if (engine_ == nullptr) {
158 Handle<YieldTermStructure> disc =
159 iborIndex_->forwardingTermStructure();
160 QL_REQUIRE(!disc.empty(),
161 "null term structure set to this instance of " <<
162 iborIndex_->name());
163 bool includeSettlementDateFlows = false;
164 ext::shared_ptr<PricingEngine> engine(new
165 DiscountingSwapEngine(disc, includeSettlementDateFlows));
166 temp.setPricingEngine(engine);
167 } else
168 temp.setPricingEngine(engine_);
169
170 usedFixedRate = temp.fairRate();
171 }
172
173 ext::shared_ptr<VanillaSwap> swap(new VanillaSwap(
174 type_, nominal_, fixedSchedule, usedFixedRate, fixedDayCount, floatSchedule, iborIndex_,
175 floatSpread_, floatDayCount_, ext::nullopt, useIndexedCoupons_));
176
177 if (engine_ == nullptr) {
178 Handle<YieldTermStructure> disc =
179 iborIndex_->forwardingTermStructure();
180 bool includeSettlementDateFlows = false;
181 ext::shared_ptr<PricingEngine> engine(new
182 DiscountingSwapEngine(disc, includeSettlementDateFlows));
183 swap->setPricingEngine(engine);
184 } else
185 swap->setPricingEngine(engine_);
186
187 return swap;
188 }
189
190 MakeVanillaSwap& MakeVanillaSwap::receiveFixed(bool flag) {
191 type_ = flag ? Swap::Receiver : Swap::Payer ;
192 return *this;
193 }
194
195 MakeVanillaSwap& MakeVanillaSwap::withType(Swap::Type type) {
196 type_ = type;
197 return *this;
198 }
199
200 MakeVanillaSwap& MakeVanillaSwap::withNominal(Real n) {
201 nominal_ = n;
202 return *this;
203 }
204
205 MakeVanillaSwap& MakeVanillaSwap::withSettlementDays(Natural settlementDays) {
206 settlementDays_ = settlementDays;
207 effectiveDate_ = Date();
208 return *this;
209 }
210
211 MakeVanillaSwap&
212 MakeVanillaSwap::withEffectiveDate(const Date& effectiveDate) {
213 effectiveDate_ = effectiveDate;
214 return *this;
215 }
216
217 MakeVanillaSwap&
218 MakeVanillaSwap::withTerminationDate(const Date& terminationDate) {
219 terminationDate_ = terminationDate;
220 swapTenor_ = Period();
221 return *this;
222 }
223
224 MakeVanillaSwap& MakeVanillaSwap::withRule(DateGeneration::Rule r) {
225 fixedRule_ = r;
226 floatRule_ = r;
227 return *this;
228 }
229
230 MakeVanillaSwap& MakeVanillaSwap::withDiscountingTermStructure(
231 const Handle<YieldTermStructure>& d) {
232 bool includeSettlementDateFlows = false;
233 engine_ = ext::shared_ptr<PricingEngine>(new
234 DiscountingSwapEngine(d, includeSettlementDateFlows));
235 return *this;
236 }
237
238 MakeVanillaSwap& MakeVanillaSwap::withPricingEngine(
239 const ext::shared_ptr<PricingEngine>& engine) {
240 engine_ = engine;
241 return *this;
242 }
243
244 MakeVanillaSwap& MakeVanillaSwap::withFixedLegTenor(const Period& t) {
245 fixedTenor_ = t;
246 return *this;
247 }
248
249 MakeVanillaSwap&
250 MakeVanillaSwap::withFixedLegCalendar(const Calendar& cal) {
251 fixedCalendar_ = cal;
252 return *this;
253 }
254
255 MakeVanillaSwap&
256 MakeVanillaSwap::withFixedLegConvention(BusinessDayConvention bdc) {
257 fixedConvention_ = bdc;
258 return *this;
259 }
260
261 MakeVanillaSwap&
262 MakeVanillaSwap::withFixedLegTerminationDateConvention(BusinessDayConvention bdc) {
263 fixedTerminationDateConvention_ = bdc;
264 return *this;
265 }
266
267 MakeVanillaSwap& MakeVanillaSwap::withFixedLegRule(DateGeneration::Rule r) {
268 fixedRule_ = r;
269 return *this;
270 }
271
272 MakeVanillaSwap& MakeVanillaSwap::withFixedLegEndOfMonth(bool flag) {
273 fixedEndOfMonth_ = flag;
274 return *this;
275 }
276
277 MakeVanillaSwap& MakeVanillaSwap::withFixedLegFirstDate(const Date& d) {
278 fixedFirstDate_ = d;
279 return *this;
280 }
281
282 MakeVanillaSwap&
283 MakeVanillaSwap::withFixedLegNextToLastDate(const Date& d) {
284 fixedNextToLastDate_ = d;
285 return *this;
286 }
287
288 MakeVanillaSwap&
289 MakeVanillaSwap::withFixedLegDayCount(const DayCounter& dc) {
290 fixedDayCount_ = dc;
291 return *this;
292 }
293
294 MakeVanillaSwap& MakeVanillaSwap::withFloatingLegTenor(const Period& t) {
295 floatTenor_ = t;
296 return *this;
297 }
298
299 MakeVanillaSwap&
300 MakeVanillaSwap::withFloatingLegCalendar(const Calendar& cal) {
301 floatCalendar_ = cal;
302 return *this;
303 }
304
305 MakeVanillaSwap&
306 MakeVanillaSwap::withFloatingLegConvention(BusinessDayConvention bdc) {
307 floatConvention_ = bdc;
308 return *this;
309 }
310
311 MakeVanillaSwap&
312 MakeVanillaSwap::withFloatingLegTerminationDateConvention(BusinessDayConvention bdc) {
313 floatTerminationDateConvention_ = bdc;
314 return *this;
315 }
316
317 MakeVanillaSwap& MakeVanillaSwap::withFloatingLegRule(DateGeneration::Rule r) {
318 floatRule_ = r;
319 return *this;
320 }
321
322 MakeVanillaSwap& MakeVanillaSwap::withFloatingLegEndOfMonth(bool flag) {
323 floatEndOfMonth_ = flag;
324 return *this;
325 }
326
327 MakeVanillaSwap&
328 MakeVanillaSwap::withFloatingLegFirstDate(const Date& d) {
329 floatFirstDate_ = d;
330 return *this;
331 }
332
333 MakeVanillaSwap&
334 MakeVanillaSwap::withFloatingLegNextToLastDate(const Date& d) {
335 floatNextToLastDate_ = d;
336 return *this;
337 }
338
339 MakeVanillaSwap&
340 MakeVanillaSwap::withFloatingLegDayCount(const DayCounter& dc) {
341 floatDayCount_ = dc;
342 return *this;
343 }
344
345 MakeVanillaSwap& MakeVanillaSwap::withFloatingLegSpread(Spread sp) {
346 floatSpread_ = sp;
347 return *this;
348 }
349
350 MakeVanillaSwap& MakeVanillaSwap::withIndexedCoupons(const ext::optional<bool>& b) {
351 useIndexedCoupons_ = b;
352 return *this;
353 }
354
355 MakeVanillaSwap& MakeVanillaSwap::withAtParCoupons(bool b) {
356 useIndexedCoupons_ = !b;
357 return *this;
358 }
359
360}
361

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