1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2006, 2011 Ferdinando Ametrano
5 Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
6 Copyright (C) 2003, 2004, 2005, 2007, 2008 StatPro Italia srl
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/instruments/swap.hpp>
23#include <ql/cashflows/cashflows.hpp>
24#include <ql/cashflows/floatingratecoupon.hpp>
25#include <ql/termstructures/yieldtermstructure.hpp>
26#include <ostream>
27
28namespace QuantLib {
29
30 Swap::Swap(const Leg& firstLeg,
31 const Leg& secondLeg)
32 : legs_(2), payer_(2),
33 legNPV_(2, 0.0), legBPS_(2, 0.0),
34 startDiscounts_(2, 0.0), endDiscounts_(2, 0.0),
35 npvDateDiscount_(0.0) {
36 legs_[0] = firstLeg;
37 legs_[1] = secondLeg;
38 payer_[0] = -1.0;
39 payer_[1] = 1.0;
40 for (auto& i : legs_[0])
41 registerWith(h: i);
42 for (auto& i : legs_[1])
43 registerWith(h: i);
44 }
45
46 Swap::Swap(const std::vector<Leg>& legs,
47 const std::vector<bool>& payer)
48 : legs_(legs), payer_(legs.size(), 1.0),
49 legNPV_(legs.size(), 0.0), legBPS_(legs.size(), 0.0),
50 startDiscounts_(legs.size(), 0.0), endDiscounts_(legs.size(), 0.0),
51 npvDateDiscount_(0.0) {
52 QL_REQUIRE(payer.size()==legs_.size(),
53 "size mismatch between payer (" << payer.size() <<
54 ") and legs (" << legs_.size() << ")");
55 for (Size j=0; j<legs_.size(); ++j) {
56 if (payer[j]) payer_[j]=-1.0;
57 for (auto& i : legs_[j])
58 registerWith(h: i);
59 }
60 }
61
62 Swap::Swap(Size legs)
63 : legs_(legs), payer_(legs),
64 legNPV_(legs, 0.0), legBPS_(legs, 0.0),
65 startDiscounts_(legs, 0.0), endDiscounts_(legs, 0.0),
66 npvDateDiscount_(0.0) {}
67
68 bool Swap::isExpired() const {
69 for (const auto& leg : legs_) {
70 Leg::const_iterator i;
71 for (i = leg.begin(); i != leg.end(); ++i)
72 if (!(*i)->hasOccurred())
73 return false;
74 }
75 return true;
76 }
77
78 void Swap::setupExpired() const {
79 Instrument::setupExpired();
80 std::fill(first: legBPS_.begin(), last: legBPS_.end(), value: 0.0);
81 std::fill(first: legNPV_.begin(), last: legNPV_.end(), value: 0.0);
82 std::fill(first: startDiscounts_.begin(), last: startDiscounts_.end(), value: 0.0);
83 std::fill(first: endDiscounts_.begin(), last: endDiscounts_.end(), value: 0.0);
84 npvDateDiscount_ = 0.0;
85 }
86
87 void Swap::setupArguments(PricingEngine::arguments* args) const {
88 auto* arguments = dynamic_cast<Swap::arguments*>(args);
89 QL_REQUIRE(arguments != nullptr, "wrong argument type");
90
91 arguments->legs = legs_;
92 arguments->payer = payer_;
93 }
94
95 void Swap::fetchResults(const PricingEngine::results* r) const {
96 Instrument::fetchResults(r);
97
98 const auto* results = dynamic_cast<const Swap::results*>(r);
99 QL_REQUIRE(results != nullptr, "wrong result type");
100
101 if (!results->legNPV.empty()) {
102 QL_REQUIRE(results->legNPV.size() == legNPV_.size(),
103 "wrong number of leg NPV returned");
104 legNPV_ = results->legNPV;
105 } else {
106 std::fill(first: legNPV_.begin(), last: legNPV_.end(), value: Null<Real>());
107 }
108
109 if (!results->legBPS.empty()) {
110 QL_REQUIRE(results->legBPS.size() == legBPS_.size(),
111 "wrong number of leg BPS returned");
112 legBPS_ = results->legBPS;
113 } else {
114 std::fill(first: legBPS_.begin(), last: legBPS_.end(), value: Null<Real>());
115 }
116
117 if (!results->startDiscounts.empty()) {
118 QL_REQUIRE(results->startDiscounts.size() == startDiscounts_.size(),
119 "wrong number of leg start discounts returned");
120 startDiscounts_ = results->startDiscounts;
121 } else {
122 std::fill(first: startDiscounts_.begin(), last: startDiscounts_.end(),
123 value: Null<DiscountFactor>());
124 }
125
126 if (!results->endDiscounts.empty()) {
127 QL_REQUIRE(results->endDiscounts.size() == endDiscounts_.size(),
128 "wrong number of leg end discounts returned");
129 endDiscounts_ = results->endDiscounts;
130 } else {
131 std::fill(first: endDiscounts_.begin(), last: endDiscounts_.end(),
132 value: Null<DiscountFactor>());
133 }
134
135 if (results->npvDateDiscount != Null<DiscountFactor>()) {
136 npvDateDiscount_ = results->npvDateDiscount;
137 } else {
138 npvDateDiscount_ = Null<DiscountFactor>();
139 }
140 }
141
142 Size Swap::numberOfLegs() const { return legs_.size(); }
143
144 const std::vector<Leg>& Swap::legs() const { return legs_; }
145
146 Date Swap::startDate() const {
147 QL_REQUIRE(!legs_.empty(), "no legs given");
148 Date d = CashFlows::startDate(leg: legs_[0]);
149 for (Size j=1; j<legs_.size(); ++j)
150 d = std::min(a: d, b: CashFlows::startDate(leg: legs_[j]));
151 return d;
152 }
153
154 Date Swap::maturityDate() const {
155 QL_REQUIRE(!legs_.empty(), "no legs given");
156 Date d = CashFlows::maturityDate(leg: legs_[0]);
157 for (Size j=1; j<legs_.size(); ++j)
158 d = std::max(a: d, b: CashFlows::maturityDate(leg: legs_[j]));
159 return d;
160 }
161
162 void Swap::deepUpdate() {
163 for (auto& leg : legs_) {
164 for (auto& k : leg) {
165 k->deepUpdate();
166 }
167 }
168 update();
169 }
170
171 void Swap::arguments::validate() const {
172 QL_REQUIRE(legs.size() == payer.size(),
173 "number of legs and multipliers differ");
174 }
175
176 void Swap::results::reset() {
177 Instrument::results::reset();
178 legNPV.clear();
179 legBPS.clear();
180 startDiscounts.clear();
181 endDiscounts.clear();
182 npvDateDiscount = Null<DiscountFactor>();
183 }
184
185 std::ostream& operator<<(std::ostream& out, Swap::Type t) {
186 switch (t) {
187 case Swap::Payer:
188 return out << "Payer";
189 case Swap::Receiver:
190 return out << "Receiver";
191 default:
192 QL_FAIL("unknown Swap::Type(" << Integer(t) << ")");
193 }
194 }
195
196}
197

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

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