/src/quantlib/ql/instruments/bonds/btp.hpp
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 | | /*! \file btp.hpp |
21 | | \brief Italian BTP (Buoni Poliennali del Tesoro) fixed rate bond |
22 | | */ |
23 | | |
24 | | #ifndef quantlib_btp_hpp |
25 | | #define quantlib_btp_hpp |
26 | | |
27 | | #include <ql/instruments/bonds/fixedratebond.hpp> |
28 | | #include <ql/instruments/bonds/floatingratebond.hpp> |
29 | | #include <ql/indexes/ibor/euribor.hpp> |
30 | | #include <ql/instruments/vanillaswap.hpp> |
31 | | |
32 | | #include <numeric> |
33 | | |
34 | | namespace QuantLib { |
35 | | |
36 | | /*! Italian CCTEU (Certificato di credito del tesoro) |
37 | | Euribor6M indexed floating rate bond |
38 | | |
39 | | \ingroup instruments |
40 | | |
41 | | */ |
42 | | class CCTEU : public FloatingRateBond { |
43 | | public: |
44 | | CCTEU(const Date& maturityDate, |
45 | | Spread spread, |
46 | | const Handle<YieldTermStructure>& fwdCurve = |
47 | | Handle<YieldTermStructure>(), |
48 | | const Date& startDate = Date(), |
49 | | const Date& issueDate = Date()); |
50 | | //! \name Bond interface |
51 | | //@{ |
52 | | //! accrued amount at a given date |
53 | | /*! The default bond settlement is used if no date is given. */ |
54 | | Real accruedAmount(Date d = Date()) const override; |
55 | | //@} |
56 | | }; |
57 | | |
58 | | //! Italian BTP (Buono Poliennali del Tesoro) fixed rate bond |
59 | | /*! \ingroup instruments |
60 | | |
61 | | */ |
62 | | class BTP : public FixedRateBond { |
63 | | public: |
64 | | BTP(const Date& maturityDate, |
65 | | Rate fixedRate, |
66 | | const Date& startDate = Date(), |
67 | | const Date& issueDate = Date()); |
68 | | /*! constructor needed for legacy non-par redemption BTPs. |
69 | | As of today the only remaining one is IT123456789012 |
70 | | that will redeem 99.999 on xx-may-2037 */ |
71 | | BTP(const Date& maturityDate, |
72 | | Rate fixedRate, |
73 | | Real redemption, |
74 | | const Date& startDate = Date(), |
75 | | const Date& issueDate = Date()); |
76 | | //! \name Bond interface |
77 | | //@{ |
78 | | //! accrued amount at a given date |
79 | | /*! The default bond settlement is used if no date is given. */ |
80 | | Real accruedAmount(Date d = Date()) const override; |
81 | | //@} |
82 | | //! BTP yield given a (clean) price and settlement date |
83 | | /*! The default BTP conventions are used: Actual/Actual (ISMA), |
84 | | Compounded, Annual. |
85 | | The default bond settlement is used if no date is given. */ |
86 | | Rate yield(Real cleanPrice, |
87 | | Date settlementDate = Date(), |
88 | | Real accuracy = 1.0e-8, |
89 | | Size maxEvaluations = 100) const; |
90 | | }; |
91 | | |
92 | | class RendistatoBasket : public Observer, |
93 | | public Observable { |
94 | | public: |
95 | | RendistatoBasket(const std::vector<ext::shared_ptr<BTP> >& btps, |
96 | | const std::vector<Real>& outstandings, |
97 | | std::vector<Handle<Quote> > cleanPriceQuotes); |
98 | | //! \name Inspectors |
99 | | //@{ |
100 | 0 | Size size() const { return n_;} |
101 | | const std::vector<ext::shared_ptr<BTP> >& btps() const; |
102 | | const std::vector<Handle<Quote> >& cleanPriceQuotes() const; |
103 | 0 | const std::vector<Real>& outstandings() const { return outstandings_;} |
104 | 0 | const std::vector<Real>& weights() const { return weights_;} |
105 | 0 | Real outstanding() const { return outstanding_;} |
106 | | //@} |
107 | | //! \name Observer interface |
108 | | //@{ |
109 | 0 | void update() override { notifyObservers(); } |
110 | | //@} |
111 | | private: |
112 | | std::vector<ext::shared_ptr<BTP> > btps_; |
113 | | std::vector<Real> outstandings_; |
114 | | std::vector<Handle<Quote> > quotes_; |
115 | | Real outstanding_; |
116 | | Size n_; |
117 | | std::vector<Real> weights_; |
118 | | }; |
119 | | |
120 | | class RendistatoCalculator : public LazyObject { |
121 | | public: |
122 | | RendistatoCalculator(ext::shared_ptr<RendistatoBasket> basket, |
123 | | ext::shared_ptr<Euribor> euriborIndex, |
124 | | Handle<YieldTermStructure> discountCurve); |
125 | | //! \name Calculations |
126 | | //@{ |
127 | | Rate yield() const; |
128 | | Time duration() const; |
129 | | // bonds |
130 | | const std::vector<Rate>& yields() const; |
131 | | const std::vector<Time>& durations() const; |
132 | | // swaps |
133 | | const std::vector<Time>& swapLengths() const; |
134 | | const std::vector<Rate>& swapRates() const; |
135 | | const std::vector<Rate>& swapYields() const; |
136 | | const std::vector<Time>& swapDurations() const; |
137 | | //@} |
138 | | //! \name Equivalent Swap proxy |
139 | | //@{ |
140 | | ext::shared_ptr<VanillaSwap> equivalentSwap() const; |
141 | | Rate equivalentSwapRate() const; |
142 | | Rate equivalentSwapYield() const; |
143 | | Time equivalentSwapDuration() const; |
144 | | Time equivalentSwapLength() const; |
145 | | Spread equivalentSwapSpread() const; |
146 | | //@} |
147 | | protected: |
148 | | //! \name LazyObject interface |
149 | | //@{ |
150 | | void performCalculations() const override; |
151 | | //@} |
152 | | private: |
153 | | ext::shared_ptr<RendistatoBasket> basket_; |
154 | | ext::shared_ptr<Euribor> euriborIndex_; |
155 | | Handle<YieldTermStructure> discountCurve_; |
156 | | |
157 | | mutable std::vector<Rate> yields_; |
158 | | mutable std::vector<Time> durations_; |
159 | | mutable Time duration_; |
160 | | mutable Size equivalentSwapIndex_; |
161 | | |
162 | | Size nSwaps_ = 15; |
163 | | mutable std::vector<ext::shared_ptr<VanillaSwap> > swaps_; |
164 | | std::vector<Time> swapLengths_; |
165 | | mutable std::vector<Time> swapBondDurations_; |
166 | | mutable std::vector<Rate> swapBondYields_, swapRates_; |
167 | | }; |
168 | | |
169 | | //! RendistatoCalculator equivalent swap lenth Quote adapter |
170 | | class RendistatoEquivalentSwapLengthQuote : public Quote { |
171 | | public: |
172 | | RendistatoEquivalentSwapLengthQuote(ext::shared_ptr<RendistatoCalculator> r); |
173 | | Real value() const override; |
174 | | bool isValid() const override; |
175 | | |
176 | | private: |
177 | | ext::shared_ptr<RendistatoCalculator> r_; |
178 | | }; |
179 | | |
180 | | //! RendistatoCalculator equivalent swap spread Quote adapter |
181 | | class RendistatoEquivalentSwapSpreadQuote : public Quote { |
182 | | public: |
183 | | RendistatoEquivalentSwapSpreadQuote(ext::shared_ptr<RendistatoCalculator> r); |
184 | | Real value() const override; |
185 | | bool isValid() const override; |
186 | | |
187 | | private: |
188 | | ext::shared_ptr<RendistatoCalculator> r_; |
189 | | }; |
190 | | |
191 | | // inline |
192 | | |
193 | 0 | inline Real CCTEU::accruedAmount(Date d) const { |
194 | 0 | Real result = FloatingRateBond::accruedAmount(d); |
195 | 0 | return ClosestRounding(5)(result); |
196 | 0 | } |
197 | | |
198 | 0 | inline Real BTP::accruedAmount(Date d) const { |
199 | 0 | Real result = FixedRateBond::accruedAmount(d); |
200 | 0 | return ClosestRounding(5)(result); |
201 | 0 | } |
202 | | |
203 | | inline const std::vector<ext::shared_ptr<BTP> >& |
204 | 0 | RendistatoBasket::btps() const { |
205 | 0 | return btps_; |
206 | 0 | } |
207 | | |
208 | | inline const std::vector<Handle<Quote> >& |
209 | 0 | RendistatoBasket::cleanPriceQuotes() const { |
210 | 0 | return quotes_; |
211 | 0 | } |
212 | | |
213 | 0 | inline Rate RendistatoCalculator::yield() const { |
214 | 0 | return std::inner_product(basket_->weights().begin(), |
215 | 0 | basket_->weights().end(), |
216 | 0 | yields().begin(), Real(0.0)); |
217 | 0 | } |
218 | | |
219 | 0 | inline Time RendistatoCalculator::duration() const { |
220 | 0 | calculate(); |
221 | 0 | return duration_; |
222 | 0 | } |
223 | | |
224 | 0 | inline const std::vector<Rate>& RendistatoCalculator::yields() const { |
225 | 0 | calculate(); |
226 | 0 | return yields_; |
227 | 0 | } |
228 | | |
229 | 0 | inline const std::vector<Time>& RendistatoCalculator::durations() const { |
230 | 0 | calculate(); |
231 | 0 | return durations_; |
232 | 0 | } |
233 | | |
234 | 0 | inline const std::vector<Time>& RendistatoCalculator::swapLengths() const { |
235 | 0 | return swapLengths_; |
236 | 0 | } |
237 | | |
238 | 0 | inline const std::vector<Rate>& RendistatoCalculator::swapRates() const { |
239 | 0 | calculate(); |
240 | 0 | return swapRates_; |
241 | 0 | } |
242 | | |
243 | 0 | inline const std::vector<Rate>& RendistatoCalculator::swapYields() const { |
244 | 0 | calculate(); |
245 | 0 | return swapBondYields_; |
246 | 0 | } |
247 | | |
248 | 0 | inline const std::vector<Time>& RendistatoCalculator::swapDurations() const { |
249 | 0 | calculate(); |
250 | 0 | return swapBondDurations_; |
251 | 0 | } |
252 | | |
253 | | inline ext::shared_ptr<VanillaSwap> |
254 | 0 | RendistatoCalculator::equivalentSwap() const { |
255 | 0 | calculate(); |
256 | 0 | return swaps_[equivalentSwapIndex_]; |
257 | 0 | } |
258 | | |
259 | 0 | inline Rate RendistatoCalculator::equivalentSwapRate() const { |
260 | 0 | calculate(); |
261 | 0 | return swapRates_[equivalentSwapIndex_]; |
262 | 0 | } |
263 | | |
264 | 0 | inline Rate RendistatoCalculator::equivalentSwapYield() const { |
265 | 0 | calculate(); |
266 | 0 | return swapBondYields_[equivalentSwapIndex_]; |
267 | 0 | } |
268 | | |
269 | 0 | inline Time RendistatoCalculator::equivalentSwapDuration() const { |
270 | 0 | calculate(); |
271 | 0 | return swapBondDurations_[equivalentSwapIndex_]; |
272 | 0 | } |
273 | | |
274 | 0 | inline Time RendistatoCalculator::equivalentSwapLength() const { |
275 | 0 | calculate(); |
276 | 0 | return swapLengths_[equivalentSwapIndex_]; |
277 | 0 | } |
278 | | |
279 | 0 | inline Spread RendistatoCalculator::equivalentSwapSpread() const { |
280 | 0 | return yield() - equivalentSwapRate(); |
281 | 0 | } |
282 | | |
283 | 0 | inline Real RendistatoEquivalentSwapLengthQuote::value() const { |
284 | 0 | return r_->equivalentSwapLength(); |
285 | 0 | } |
286 | | |
287 | 0 | inline Real RendistatoEquivalentSwapSpreadQuote::value() const { |
288 | 0 | return r_->equivalentSwapSpread(); |
289 | 0 | } |
290 | | |
291 | | } |
292 | | |
293 | | #endif |