/src/quantlib/ql/instruments/bonds/btp.cpp
Line | Count | Source |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | Copyright (C) 2010, 2011 Ferdinando Ametrano |
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 | | <https://www.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/instruments/bonds/btp.hpp> |
21 | | #include <ql/instruments/makevanillaswap.hpp> |
22 | | #include <ql/pricingengines/bond/bondfunctions.hpp> |
23 | | #include <ql/time/calendars/nullcalendar.hpp> |
24 | | #include <ql/time/calendars/target.hpp> |
25 | | #include <ql/time/daycounters/actual360.hpp> |
26 | | #include <ql/time/daycounters/actualactual.hpp> |
27 | | #include <ql/time/schedule.hpp> |
28 | | #include <ql/utilities/dataformatters.hpp> |
29 | | #include <utility> |
30 | | |
31 | | namespace QuantLib { |
32 | | |
33 | | CCTEU::CCTEU(const Date& maturityDate, |
34 | | Spread spread, |
35 | | const Handle<YieldTermStructure>& fwdCurve, |
36 | | const Date& startDate, |
37 | | const Date& issueDate) |
38 | 0 | : FloatingRateBond(2, 100.0, |
39 | 0 | Schedule(startDate, |
40 | 0 | maturityDate, 6*Months, |
41 | 0 | NullCalendar(), Unadjusted, Unadjusted, |
42 | 0 | DateGeneration::Backward, true), |
43 | 0 | ext::make_shared<Euribor6M>(fwdCurve), |
44 | 0 | Actual360(), |
45 | 0 | Following, |
46 | 0 | Euribor6M().fixingDays(), |
47 | 0 | std::vector<Real>(1, 1.0), // gearing |
48 | 0 | std::vector<Spread>(1, spread), |
49 | 0 | std::vector<Rate>(), // caps |
50 | 0 | std::vector<Rate>(), // floors |
51 | 0 | false, // in arrears |
52 | 0 | 100.0, // redemption |
53 | 0 | issueDate) {}Unexecuted instantiation: QuantLib::CCTEU::CCTEU(QuantLib::Date const&, double, QuantLib::Handle<QuantLib::YieldTermStructure> const&, QuantLib::Date const&, QuantLib::Date const&) Unexecuted instantiation: QuantLib::CCTEU::CCTEU(QuantLib::Date const&, double, QuantLib::Handle<QuantLib::YieldTermStructure> const&, QuantLib::Date const&, QuantLib::Date const&) |
54 | | |
55 | | BTP::BTP(const Date& maturityDate, |
56 | | Rate fixedRate, |
57 | | const Date& startDate, |
58 | | const Date& issueDate) |
59 | 0 | : FixedRateBond(2, 100.0, |
60 | 0 | Schedule(startDate, |
61 | 0 | maturityDate, 6*Months, |
62 | 0 | NullCalendar(), Unadjusted, Unadjusted, |
63 | 0 | DateGeneration::Backward, true), |
64 | 0 | std::vector<Rate>(1, fixedRate), |
65 | 0 | ActualActual(ActualActual::ISMA), |
66 | 0 | ModifiedFollowing, 100.0, issueDate, TARGET()) {}Unexecuted instantiation: QuantLib::BTP::BTP(QuantLib::Date const&, double, QuantLib::Date const&, QuantLib::Date const&) Unexecuted instantiation: QuantLib::BTP::BTP(QuantLib::Date const&, double, QuantLib::Date const&, QuantLib::Date const&) |
67 | | |
68 | | BTP::BTP(const Date& maturityDate, |
69 | | Rate fixedRate, |
70 | | Real redemption, |
71 | | const Date& startDate, |
72 | | const Date& issueDate) |
73 | 0 | : FixedRateBond(2, 100.0, |
74 | 0 | Schedule(startDate, |
75 | 0 | maturityDate, 6*Months, |
76 | 0 | NullCalendar(), Unadjusted, Unadjusted, |
77 | 0 | DateGeneration::Backward, true), |
78 | 0 | std::vector<Rate>(1, fixedRate), |
79 | 0 | ActualActual(ActualActual::ISMA), |
80 | 0 | ModifiedFollowing, redemption, issueDate, TARGET()) {}Unexecuted instantiation: QuantLib::BTP::BTP(QuantLib::Date const&, double, double, QuantLib::Date const&, QuantLib::Date const&) Unexecuted instantiation: QuantLib::BTP::BTP(QuantLib::Date const&, double, double, QuantLib::Date const&, QuantLib::Date const&) |
81 | | |
82 | | Rate BTP::yield(Real cleanPrice, |
83 | | Date settlementDate, |
84 | | Real accuracy, |
85 | 0 | Size maxEvaluations) const { |
86 | 0 | return Bond::yield({cleanPrice, Bond::Price::Clean}, |
87 | 0 | ActualActual(ActualActual::ISMA), Compounded, Annual, settlementDate, |
88 | 0 | accuracy, maxEvaluations); |
89 | 0 | } |
90 | | |
91 | | |
92 | | RendistatoBasket::RendistatoBasket(const std::vector<ext::shared_ptr<BTP> >& btps, |
93 | | const std::vector<Real>& outstandings, |
94 | | std::vector<Handle<Quote> > cleanPriceQuotes) |
95 | 0 | : btps_(btps), outstandings_(outstandings), quotes_(std::move(cleanPriceQuotes)) { |
96 | |
|
97 | 0 | QL_REQUIRE(!btps_.empty(), "empty RendistatoCalculator Basket"); |
98 | 0 | Size k = btps_.size(); |
99 | |
|
100 | 0 | QL_REQUIRE(outstandings_.size()==k, |
101 | 0 | "mismatch between number of BTPs (" << k << |
102 | 0 | ") and number of outstandings (" << |
103 | 0 | outstandings_.size() << ")"); |
104 | 0 | QL_REQUIRE(quotes_.size()==k, |
105 | 0 | "mismatch between number of BTPs (" << k << |
106 | 0 | ") and number of clean prices quotes (" << |
107 | 0 | quotes_.size() << ")"); |
108 | | |
109 | | // require non-negative outstanding |
110 | 0 | for (Size i=0; i<k; ++i) { |
111 | 0 | QL_REQUIRE(outstandings[i]>=0, |
112 | 0 | "negative outstanding for " << io::ordinal(i) << |
113 | 0 | " bond, maturity " << btps[i]->maturityDate()); |
114 | | // add check for prices ?? |
115 | 0 | } |
116 | | |
117 | | // TODO: filter out expired bonds, zero outstanding bond, etc |
118 | | |
119 | 0 | QL_REQUIRE(!btps_.empty(), "invalid bonds only in RendistatoCalculator Basket"); |
120 | 0 | n_ = btps_.size(); |
121 | |
|
122 | 0 | outstanding_ = 0.0; |
123 | 0 | for (Size i=0; i<n_; ++i) |
124 | 0 | outstanding_ += outstandings[i]; |
125 | |
|
126 | 0 | weights_.resize(n_); |
127 | 0 | for (Size i=0; i<n_; ++i) { |
128 | 0 | weights_[i] = outstandings[i]/outstanding_; |
129 | 0 | registerWith(quotes_[i]); |
130 | 0 | } |
131 | 0 | } |
132 | | |
133 | | |
134 | | RendistatoCalculator::RendistatoCalculator(ext::shared_ptr<RendistatoBasket> basket, |
135 | | ext::shared_ptr<Euribor> euriborIndex, |
136 | | Handle<YieldTermStructure> discountCurve) |
137 | 0 | : basket_(std::move(basket)), euriborIndex_(std::move(euriborIndex)), |
138 | 0 | discountCurve_(std::move(discountCurve)), yields_(basket_->size(), 0.05), |
139 | 0 | durations_(basket_->size()), |
140 | | // TODO: generalize number of swaps and their lengths |
141 | 0 | swaps_(nSwaps_), swapLengths_(nSwaps_), swapBondDurations_(nSwaps_, Null<Time>()), |
142 | 0 | swapBondYields_(nSwaps_, 0.05), swapRates_(nSwaps_, Null<Rate>()) { |
143 | 0 | registerWith(basket_); |
144 | 0 | registerWith(euriborIndex_); |
145 | 0 | registerWith(discountCurve_); |
146 | |
|
147 | 0 | Rate dummyRate = 0.05; |
148 | 0 | for (Size i=0; i<nSwaps_; ++i) { |
149 | 0 | swapLengths_[i] = static_cast<Real>(i+1); |
150 | 0 | swaps_[i] = MakeVanillaSwap( |
151 | 0 | swapLengths_[i]*Years, euriborIndex_, dummyRate, 1*Days) |
152 | 0 | .withDiscountingTermStructure(discountCurve_); |
153 | 0 | } |
154 | 0 | } Unexecuted instantiation: QuantLib::RendistatoCalculator::RendistatoCalculator(boost::shared_ptr<QuantLib::RendistatoBasket>, boost::shared_ptr<QuantLib::Euribor>, QuantLib::Handle<QuantLib::YieldTermStructure>) Unexecuted instantiation: QuantLib::RendistatoCalculator::RendistatoCalculator(boost::shared_ptr<QuantLib::RendistatoBasket>, boost::shared_ptr<QuantLib::Euribor>, QuantLib::Handle<QuantLib::YieldTermStructure>) |
155 | | |
156 | 0 | void RendistatoCalculator::performCalculations() const { |
157 | |
|
158 | 0 | const std::vector<ext::shared_ptr<BTP> >& btps = basket_->btps(); |
159 | 0 | const std::vector<Handle<Quote> >& quotes = basket_->cleanPriceQuotes(); |
160 | 0 | Date bondSettlementDate = btps[0]->settlementDate(); |
161 | 0 | for (Size i=0; i<basket_->size(); ++i) { |
162 | 0 | yields_[i] = BondFunctions::yield( |
163 | 0 | *btps[i], {quotes[i]->value(), Bond::Price::Clean}, |
164 | 0 | ActualActual(ActualActual::ISMA), Compounded, Annual, bondSettlementDate, |
165 | | // accuracy, maxIterations, guess |
166 | 0 | 1.0e-10, 100, yields_[i]); |
167 | 0 | durations_[i] = BondFunctions::duration( |
168 | 0 | *btps[i], yields_[i], |
169 | 0 | ActualActual(ActualActual::ISMA), Compounded, Annual, |
170 | 0 | Duration::Modified, bondSettlementDate); |
171 | 0 | } |
172 | 0 | duration_ = std::inner_product(basket_->weights().begin(), |
173 | 0 | basket_->weights().end(), |
174 | 0 | durations_.begin(), Real(0.0)); |
175 | |
|
176 | 0 | Natural settlDays = 2; |
177 | 0 | DayCounter fixedDayCount = swaps_[0]->fixedDayCount(); |
178 | 0 | equivalentSwapIndex_ = nSwaps_-1; |
179 | 0 | swapRates_[0]= swaps_[0]->fairRate(); |
180 | 0 | FixedRateBond swapBond(settlDays, |
181 | 0 | 100.0, // faceAmount |
182 | 0 | swaps_[0]->fixedSchedule(), |
183 | 0 | std::vector<Rate>(1, swapRates_[0]), |
184 | 0 | fixedDayCount, |
185 | 0 | Following, // paymentConvention |
186 | 0 | 100.0); // redemption |
187 | 0 | swapBondYields_[0] = BondFunctions::yield(swapBond, |
188 | 0 | {100.0, Bond::Price::Clean}, // floating leg NPV including end payment |
189 | 0 | ActualActual(ActualActual::ISMA), Compounded, Annual, |
190 | 0 | bondSettlementDate, |
191 | | // accuracy, maxIterations, guess |
192 | 0 | 1.0e-10, 100, swapBondYields_[0]); |
193 | 0 | swapBondDurations_[0] = BondFunctions::duration( |
194 | 0 | swapBond, swapBondYields_[0], |
195 | 0 | ActualActual(ActualActual::ISMA), Compounded, Annual, |
196 | 0 | Duration::Modified, bondSettlementDate); |
197 | 0 | for (Size i=1; i<nSwaps_; ++i) { |
198 | 0 | swapRates_[i]= swaps_[i]->fairRate(); |
199 | 0 | FixedRateBond swapBond(settlDays, |
200 | 0 | 100.0, // faceAmount |
201 | 0 | swaps_[i]->fixedSchedule(), |
202 | 0 | std::vector<Rate>(1, swapRates_[i]), |
203 | 0 | fixedDayCount, |
204 | 0 | Following, // paymentConvention |
205 | 0 | 100.0); // redemption |
206 | 0 | swapBondYields_[i] = BondFunctions::yield(swapBond, |
207 | 0 | {100.0, Bond::Price::Clean}, // floating leg NPV including end payment |
208 | 0 | ActualActual(ActualActual::ISMA), Compounded, Annual, |
209 | 0 | bondSettlementDate, |
210 | | // accuracy, maxIterations, guess |
211 | 0 | 1.0e-10, 100, swapBondYields_[i]); |
212 | 0 | swapBondDurations_[i] = BondFunctions::duration( |
213 | 0 | swapBond, swapBondYields_[i], |
214 | 0 | ActualActual(ActualActual::ISMA), Compounded, Annual, |
215 | 0 | Duration::Modified, bondSettlementDate); |
216 | 0 | if (swapBondDurations_[i] > duration_) { |
217 | 0 | equivalentSwapIndex_ = i-1; |
218 | 0 | break; // exit the loop |
219 | 0 | } |
220 | 0 | } |
221 | 0 | } |
222 | | |
223 | | RendistatoEquivalentSwapLengthQuote::RendistatoEquivalentSwapLengthQuote( |
224 | | ext::shared_ptr<RendistatoCalculator> r) |
225 | 0 | : r_(std::move(r)) {}Unexecuted instantiation: QuantLib::RendistatoEquivalentSwapLengthQuote::RendistatoEquivalentSwapLengthQuote(boost::shared_ptr<QuantLib::RendistatoCalculator>) Unexecuted instantiation: QuantLib::RendistatoEquivalentSwapLengthQuote::RendistatoEquivalentSwapLengthQuote(boost::shared_ptr<QuantLib::RendistatoCalculator>) |
226 | | |
227 | 0 | bool RendistatoEquivalentSwapLengthQuote::isValid() const { |
228 | 0 | try { |
229 | 0 | value(); |
230 | 0 | return true; |
231 | 0 | } catch (...) { |
232 | 0 | return false; |
233 | 0 | } |
234 | 0 | } |
235 | | |
236 | | RendistatoEquivalentSwapSpreadQuote::RendistatoEquivalentSwapSpreadQuote( |
237 | | ext::shared_ptr<RendistatoCalculator> r) |
238 | 0 | : r_(std::move(r)) {}Unexecuted instantiation: QuantLib::RendistatoEquivalentSwapSpreadQuote::RendistatoEquivalentSwapSpreadQuote(boost::shared_ptr<QuantLib::RendistatoCalculator>) Unexecuted instantiation: QuantLib::RendistatoEquivalentSwapSpreadQuote::RendistatoEquivalentSwapSpreadQuote(boost::shared_ptr<QuantLib::RendistatoCalculator>) |
239 | | |
240 | 0 | bool RendistatoEquivalentSwapSpreadQuote::isValid() const { |
241 | 0 | try { |
242 | 0 | value(); |
243 | 0 | return true; |
244 | 0 | } catch (...) { |
245 | 0 | return false; |
246 | 0 | } |
247 | 0 | } |
248 | | } |