/src/quantlib/ql/experimental/swaptions/irregularswap.cpp
Line | Count | Source |
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 | | Copyright (C) 2010 Andre Miemiec |
8 | | |
9 | | This file is part of QuantLib, a free-software/open-source library |
10 | | for financial quantitative analysts and developers - http://quantlib.org/ |
11 | | |
12 | | QuantLib is free software: you can redistribute it and/or modify it |
13 | | under the terms of the QuantLib license. You should have received a |
14 | | copy of the license along with this program; if not, please email |
15 | | <quantlib-dev@lists.sf.net>. The license is also available online at |
16 | | <https://www.quantlib.org/license.shtml>. |
17 | | |
18 | | This program is distributed in the hope that it will be useful, but WITHOUT |
19 | | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
20 | | FOR A PARTICULAR PURPOSE. See the license for more details. |
21 | | */ |
22 | | |
23 | | #include <ql/experimental/swaptions/irregularswap.hpp> |
24 | | #include <ql/cashflows/fixedratecoupon.hpp> |
25 | | #include <ql/cashflows/iborcoupon.hpp> |
26 | | #include <ql/cashflows/cashflowvectors.hpp> |
27 | | #include <ql/cashflows/cashflows.hpp> |
28 | | #include <ql/cashflows/couponpricer.hpp> |
29 | | #include <ql/indexes/iborindex.hpp> |
30 | | #include <ql/termstructures/yieldtermstructure.hpp> |
31 | | |
32 | | namespace QuantLib { |
33 | | |
34 | | IrregularSwap::IrregularSwap( |
35 | | Type type, |
36 | | const Leg& fixLeg, |
37 | | const Leg& floatLeg) |
38 | 0 | : Swap(2), type_(type) { |
39 | | |
40 | |
|
41 | 0 | switch (type_) { |
42 | 0 | case Payer: |
43 | 0 | payer_[0] = -1.0; |
44 | 0 | payer_[1] = +1.0; |
45 | 0 | break; |
46 | 0 | case Receiver: |
47 | 0 | payer_[0] = +1.0; |
48 | 0 | payer_[1] = -1.0; |
49 | 0 | break; |
50 | 0 | default: |
51 | 0 | QL_FAIL("Unknown Irregular-swap type"); |
52 | 0 | } |
53 | | |
54 | | //Fixed leg |
55 | 0 | legs_[0] = fixLeg; |
56 | |
|
57 | 0 | for (auto i = legs_[0].begin(); i < legs_[0].end(); ++i) |
58 | 0 | registerWith(*i); |
59 | | |
60 | | //Floating Leg |
61 | 0 | legs_[1] = floatLeg; |
62 | |
|
63 | 0 | for (auto i = legs_[1].begin(); i < legs_[1].end(); ++i) |
64 | 0 | registerWith(*i); |
65 | |
|
66 | 0 | } Unexecuted instantiation: QuantLib::IrregularSwap::IrregularSwap(QuantLib::Swap::Type, std::__1::vector<boost::shared_ptr<QuantLib::CashFlow>, std::__1::allocator<boost::shared_ptr<QuantLib::CashFlow> > > const&, std::__1::vector<boost::shared_ptr<QuantLib::CashFlow>, std::__1::allocator<boost::shared_ptr<QuantLib::CashFlow> > > const&) Unexecuted instantiation: QuantLib::IrregularSwap::IrregularSwap(QuantLib::Swap::Type, std::__1::vector<boost::shared_ptr<QuantLib::CashFlow>, std::__1::allocator<boost::shared_ptr<QuantLib::CashFlow> > > const&, std::__1::vector<boost::shared_ptr<QuantLib::CashFlow>, std::__1::allocator<boost::shared_ptr<QuantLib::CashFlow> > > const&) |
67 | | |
68 | | |
69 | 0 | void IrregularSwap::setupArguments(PricingEngine::arguments* args) const { |
70 | | |
71 | | //Debug: to be done |
72 | |
|
73 | 0 | Swap::setupArguments(args); |
74 | |
|
75 | 0 | auto* arguments = dynamic_cast<IrregularSwap::arguments*>(args); |
76 | |
|
77 | 0 | if (arguments == nullptr) // it's a swap engine... |
78 | 0 | return; |
79 | | |
80 | 0 | arguments->type = type_; |
81 | | //arguments->nominal = nominal_; |
82 | | |
83 | | |
84 | 0 | const Leg& fixedCoupons = fixedLeg(); |
85 | |
|
86 | 0 | arguments->fixedResetDates = arguments->fixedPayDates = std::vector<Date>(fixedCoupons.size()); |
87 | 0 | arguments->fixedNominals = arguments->fixedCoupons = std::vector<Real>(fixedCoupons.size()); |
88 | | |
89 | |
|
90 | 0 | for (Size i=0; i<fixedCoupons.size(); ++i) { |
91 | 0 | ext::shared_ptr<FixedRateCoupon> coupon = |
92 | 0 | ext::dynamic_pointer_cast<FixedRateCoupon>(fixedCoupons[i]); |
93 | |
|
94 | 0 | arguments->fixedPayDates[i] = coupon->date(); |
95 | 0 | arguments->fixedResetDates[i] = coupon->accrualStartDate(); |
96 | 0 | arguments->fixedCoupons[i] = coupon->amount(); |
97 | 0 | arguments->fixedNominals[i] = coupon->nominal(); |
98 | 0 | } |
99 | | |
100 | |
|
101 | 0 | const Leg& floatingCoupons = floatingLeg(); |
102 | |
|
103 | 0 | arguments->floatingResetDates = arguments->floatingPayDates |
104 | 0 | = arguments->floatingFixingDates = std::vector<Date>(floatingCoupons.size()); |
105 | 0 | arguments->floatingAccrualTimes = std::vector<Time>(floatingCoupons.size()); |
106 | 0 | arguments->floatingSpreads = std::vector<Spread>(floatingCoupons.size()); |
107 | 0 | arguments->floatingNominals = arguments->floatingCoupons = std::vector<Real>(floatingCoupons.size()); |
108 | |
|
109 | 0 | for (Size i=0; i<floatingCoupons.size(); ++i) { |
110 | 0 | ext::shared_ptr<IborCoupon> coupon = |
111 | 0 | ext::dynamic_pointer_cast<IborCoupon>(floatingCoupons[i]); |
112 | |
|
113 | 0 | arguments->floatingResetDates[i] = coupon->accrualStartDate(); |
114 | 0 | arguments->floatingPayDates[i] = coupon->date(); |
115 | |
|
116 | 0 | arguments->floatingFixingDates[i] = coupon->fixingDate(); |
117 | 0 | arguments->floatingAccrualTimes[i] = coupon->accrualPeriod(); |
118 | 0 | arguments->floatingSpreads[i] = coupon->spread(); |
119 | 0 | arguments->floatingNominals[i] = coupon->nominal(); |
120 | |
|
121 | 0 | try { |
122 | 0 | arguments->floatingCoupons[i] = coupon->amount(); |
123 | 0 | } catch (Error&) { |
124 | 0 | arguments->floatingCoupons[i] = Null<Real>(); |
125 | 0 | } |
126 | 0 | } |
127 | | |
128 | 0 | } |
129 | | |
130 | | |
131 | 0 | Rate IrregularSwap::fairRate() const { |
132 | 0 | calculate(); |
133 | 0 | QL_REQUIRE(fairRate_ != Null<Rate>(), "result not available"); |
134 | 0 | return fairRate_; |
135 | 0 | } |
136 | | |
137 | 0 | Spread IrregularSwap::fairSpread() const { |
138 | 0 | calculate(); |
139 | 0 | QL_REQUIRE(fairSpread_ != Null<Spread>(), "result not available"); |
140 | 0 | return fairSpread_; |
141 | 0 | } |
142 | | |
143 | 0 | Real IrregularSwap::fixedLegBPS() const { |
144 | 0 | calculate(); |
145 | 0 | QL_REQUIRE(legBPS_[0] != Null<Real>(), "result not available"); |
146 | 0 | return legBPS_[0]; |
147 | 0 | } |
148 | | |
149 | 0 | Real IrregularSwap::floatingLegBPS() const { |
150 | 0 | calculate(); |
151 | 0 | QL_REQUIRE(legBPS_[1] != Null<Real>(), "result not available"); |
152 | 0 | return legBPS_[1]; |
153 | 0 | } |
154 | | |
155 | 0 | Real IrregularSwap::fixedLegNPV() const { |
156 | 0 | calculate(); |
157 | 0 | QL_REQUIRE(legNPV_[0] != Null<Real>(), "result not available"); |
158 | 0 | return legNPV_[0]; |
159 | 0 | } |
160 | | |
161 | 0 | Real IrregularSwap::floatingLegNPV() const { |
162 | 0 | calculate(); |
163 | 0 | QL_REQUIRE(legNPV_[1] != Null<Real>(), "result not available"); |
164 | 0 | return legNPV_[1]; |
165 | 0 | } |
166 | | |
167 | 0 | void IrregularSwap::setupExpired() const { |
168 | 0 | Swap::setupExpired(); |
169 | 0 | legBPS_[0] = legBPS_[1] = 0.0; |
170 | 0 | fairRate_ = Null<Rate>(); |
171 | 0 | fairSpread_ = Null<Spread>(); |
172 | 0 | } |
173 | | |
174 | 0 | void IrregularSwap::fetchResults(const PricingEngine::results* r) const { |
175 | 0 | Swap::fetchResults(r); |
176 | |
|
177 | 0 | const auto* results = dynamic_cast<const IrregularSwap::results*>(r); |
178 | 0 | if (results != nullptr) { // might be a swap engine, so no error is thrown |
179 | 0 | fairRate_ = results->fairRate; |
180 | 0 | fairSpread_ = results->fairSpread; |
181 | 0 | } else { |
182 | 0 | fairRate_ = Null<Rate>(); |
183 | 0 | fairSpread_ = Null<Spread>(); |
184 | 0 | } |
185 | |
|
186 | 0 | if (fairRate_ == Null<Rate>()) { |
187 | | // calculate it from other results |
188 | 0 | if (legBPS_[0] != Null<Real>()) |
189 | 0 | fairRate_ = 0.0; // Debug: legs_[0]->fixedRate_ - NPV_/(legBPS_[0]/basisPoint); |
190 | 0 | } |
191 | 0 | if (fairSpread_ == Null<Spread>()) { |
192 | | // ditto |
193 | 0 | if (legBPS_[1] != Null<Real>()) |
194 | 0 | fairSpread_ = 0.0; //DEBUG: spread_ - NPV_/(legBPS_[1]/basisPoint); |
195 | 0 | } |
196 | 0 | } |
197 | | |
198 | 0 | void IrregularSwap::arguments::validate() const { |
199 | |
|
200 | 0 | Swap::arguments::validate(); |
201 | |
|
202 | 0 | QL_REQUIRE(fixedResetDates.size() == fixedPayDates.size(), |
203 | 0 | "number of fixed start dates different from " |
204 | 0 | "number of fixed payment dates"); |
205 | 0 | QL_REQUIRE(fixedPayDates.size() == fixedCoupons.size(), |
206 | 0 | "number of fixed payment dates different from " |
207 | 0 | "number of fixed coupon amounts"); |
208 | 0 | QL_REQUIRE(floatingResetDates.size() == floatingPayDates.size(), |
209 | 0 | "number of floating start dates different from " |
210 | 0 | "number of floating payment dates"); |
211 | 0 | QL_REQUIRE(floatingFixingDates.size() == floatingPayDates.size(), |
212 | 0 | "number of floating fixing dates different from " |
213 | 0 | "number of floating payment dates"); |
214 | 0 | QL_REQUIRE(floatingAccrualTimes.size() == floatingPayDates.size(), |
215 | 0 | "number of floating accrual Times different from " |
216 | 0 | "number of floating payment dates"); |
217 | 0 | QL_REQUIRE(floatingSpreads.size() == floatingPayDates.size(), |
218 | 0 | "number of floating spreads different from " |
219 | 0 | "number of floating payment dates"); |
220 | 0 | QL_REQUIRE(floatingPayDates.size() == floatingCoupons.size(), |
221 | 0 | "number of floating payment dates different from " |
222 | 0 | "number of floating coupon amounts"); |
223 | 0 | } |
224 | | |
225 | 0 | void IrregularSwap::results::reset() { |
226 | 0 | Swap::results::reset(); |
227 | 0 | fairRate = Null<Rate>(); |
228 | 0 | fairSpread = Null<Spread>(); |
229 | 0 | } |
230 | | |
231 | | } |