/src/quantlib/ql/instruments/bond.hpp
Line | Count | Source |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | Copyright (C) 2004 Jeff Yu |
5 | | Copyright (C) 2004 M-Dimension Consulting Inc. |
6 | | Copyright (C) 2005, 2006, 2007, 2008 StatPro Italia srl |
7 | | Copyright (C) 2007, 2008, 2009 Ferdinando Ametrano |
8 | | Copyright (C) 2007 Chiara Fornarola |
9 | | Copyright (C) 2008 Simon Ibbotson |
10 | | |
11 | | This file is part of QuantLib, a free-software/open-source library |
12 | | for financial quantitative analysts and developers - http://quantlib.org/ |
13 | | |
14 | | QuantLib is free software: you can redistribute it and/or modify it |
15 | | under the terms of the QuantLib license. You should have received a |
16 | | copy of the license along with this program; if not, please email |
17 | | <quantlib-dev@lists.sf.net>. The license is also available online at |
18 | | <https://www.quantlib.org/license.shtml>. |
19 | | |
20 | | This program is distributed in the hope that it will be useful, but WITHOUT |
21 | | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
22 | | FOR A PARTICULAR PURPOSE. See the license for more details. |
23 | | */ |
24 | | |
25 | | /*! \file bond.hpp |
26 | | \brief concrete bond class |
27 | | */ |
28 | | |
29 | | #ifndef quantlib_bond_hpp |
30 | | #define quantlib_bond_hpp |
31 | | |
32 | | #include <ql/instrument.hpp> |
33 | | |
34 | | #include <ql/time/calendar.hpp> |
35 | | #include <ql/cashflow.hpp> |
36 | | #include <ql/compounding.hpp> |
37 | | |
38 | | #include <vector> |
39 | | |
40 | | namespace QuantLib { |
41 | | |
42 | | class DayCounter; |
43 | | |
44 | | //! Base bond class |
45 | | /*! Derived classes must fill the uninitialized data members. |
46 | | |
47 | | \warning Most methods assume that the cash flows are stored |
48 | | sorted by date, the redemption(s) being after any |
49 | | cash flow at the same date. In particular, if there's |
50 | | one single redemption, it must be the last cash flow, |
51 | | |
52 | | \note Pricing methods (cleanPrice, dirtyPrice, settlementValue, etc.) |
53 | | assume and return values as a percentage of par (per 100). |
54 | | For bonds with a face value other than 100 (e.g., 25), the actual |
55 | | cash price must be calculated by the user: `cash price = quote * face / 100`. |
56 | | Yield and Z-spread methods also expect prices to be passed per 100. |
57 | | |
58 | | \ingroup instruments |
59 | | |
60 | | \test |
61 | | - price/yield calculations are cross-checked for consistency. |
62 | | - price/yield calculations are checked against known good |
63 | | values. |
64 | | */ |
65 | | class Bond : public Instrument { |
66 | | public: |
67 | | //! Bond price information |
68 | | class Price { |
69 | | public: |
70 | | enum Type { Dirty, Clean }; |
71 | 0 | Price() : amount_(Null<Real>()), type_(Bond::Price::Clean) {} |
72 | 0 | Price(Real amount, Type type) : amount_(amount), type_(type) {} |
73 | 0 | Real amount() const { |
74 | 0 | QL_REQUIRE(amount_ != Null<Real>(), "no amount given"); |
75 | 0 | return amount_; |
76 | 0 | } Unexecuted instantiation: QuantLib::Bond::Price::amount() const Unexecuted instantiation: QuantLib::Bond::Price::amount() const |
77 | 0 | Type type() const { return type_; } |
78 | 0 | bool isValid() const { return amount_ != Null<Real>(); } |
79 | | private: |
80 | | Real amount_; |
81 | | Type type_; |
82 | | }; |
83 | | |
84 | | //! constructor for amortizing or non-amortizing bonds. |
85 | | /*! Redemptions and maturity are calculated from the coupon |
86 | | data, if available. Therefore, redemptions must not be |
87 | | included in the passed cash flows. |
88 | | */ |
89 | | Bond(Natural settlementDays, |
90 | | Calendar calendar, |
91 | | const Date& issueDate = Date(), |
92 | | const Leg& coupons = Leg()); |
93 | | |
94 | | //! old constructor for non amortizing bonds. |
95 | | /*! \warning The last passed cash flow must be the bond |
96 | | redemption. No other cash flow can have a date |
97 | | later than the redemption date. |
98 | | */ |
99 | | Bond(Natural settlementDays, |
100 | | Calendar calendar, |
101 | | Real faceAmount, |
102 | | const Date& maturityDate, |
103 | | const Date& issueDate = Date(), |
104 | | const Leg& cashflows = Leg()); |
105 | | |
106 | | class arguments; |
107 | | class results; |
108 | | class engine; |
109 | | |
110 | | //! \name Instrument interface |
111 | | //@{ |
112 | | bool isExpired() const override; |
113 | | //@} |
114 | | //! \name Observable interface |
115 | | //@{ |
116 | | void deepUpdate() override; |
117 | | //@} |
118 | | //! \name Inspectors |
119 | | //@{ |
120 | | Natural settlementDays() const; |
121 | | const Calendar& calendar() const; |
122 | | |
123 | | const std::vector<Real>& notionals() const; |
124 | | virtual Real notional(Date d = Date()) const; |
125 | | |
126 | | /*! \note returns all the cashflows, including the redemptions. */ |
127 | | const Leg& cashflows() const; |
128 | | /*! returns just the redemption flows (not interest payments) */ |
129 | | const Leg& redemptions() const; |
130 | | /*! returns the redemption, if only one is defined */ |
131 | | const ext::shared_ptr<CashFlow>& redemption() const; |
132 | | |
133 | | Date startDate() const; |
134 | | Date maturityDate() const; |
135 | | Date issueDate() const; |
136 | | |
137 | | bool isTradable(Date d = Date()) const; |
138 | | Date settlementDate(Date d = Date()) const; |
139 | | //@} |
140 | | |
141 | | //! \name Calculations |
142 | | //@{ |
143 | | |
144 | | //! theoretical clean price |
145 | | /*! The default bond settlement is used for calculation. |
146 | | |
147 | | \warning the theoretical price calculated from a flat term |
148 | | structure might differ slightly from the price |
149 | | calculated from the corresponding yield by means |
150 | | of the other overload of this function. If the |
151 | | price from a constant yield is desired, it is |
152 | | advisable to use such other overload. |
153 | | */ |
154 | | Real cleanPrice() const; |
155 | | |
156 | | //! theoretical dirty price |
157 | | /*! The default bond settlement is used for calculation. |
158 | | |
159 | | \warning the theoretical price calculated from a flat term |
160 | | structure might differ slightly from the price |
161 | | calculated from the corresponding yield by means |
162 | | of the other overload of this function. If the |
163 | | price from a constant yield is desired, it is |
164 | | advisable to use such other overload. |
165 | | */ |
166 | | Real dirtyPrice() const; |
167 | | |
168 | | //! theoretical settlement value |
169 | | /*! The default bond settlement date is used for calculation. */ |
170 | | Real settlementValue() const; |
171 | | |
172 | | //! theoretical bond yield |
173 | | /*! The default bond settlement and theoretical price are used |
174 | | for calculation. |
175 | | */ |
176 | | Rate yield(const DayCounter& dc, |
177 | | Compounding comp, |
178 | | Frequency freq, |
179 | | Real accuracy = 1.0e-8, |
180 | | Size maxEvaluations = 100, |
181 | | Real guess = 0.05, |
182 | | Bond::Price::Type priceType = Bond::Price::Clean) const; |
183 | | |
184 | | //! clean price given a yield and settlement date |
185 | | /*! The default bond settlement is used if no date is given. */ |
186 | | Real cleanPrice(Rate yield, |
187 | | const DayCounter& dc, |
188 | | Compounding comp, |
189 | | Frequency freq, |
190 | | Date settlementDate = Date()) const; |
191 | | |
192 | | //! dirty price given a yield and settlement date |
193 | | /*! The default bond settlement is used if no date is given. */ |
194 | | Real dirtyPrice(Rate yield, |
195 | | const DayCounter& dc, |
196 | | Compounding comp, |
197 | | Frequency freq, |
198 | | Date settlementDate = Date()) const; |
199 | | |
200 | | //! settlement value as a function of the clean price |
201 | | /*! The default bond settlement date is used for calculation. */ |
202 | | Real settlementValue(Real cleanPrice) const; |
203 | | |
204 | | //! yield given a price and settlement date |
205 | | /*! The default bond settlement is used if no date is given. */ |
206 | | Rate yield(Bond::Price price, |
207 | | const DayCounter& dc, |
208 | | Compounding comp, |
209 | | Frequency freq, |
210 | | Date settlementDate = Date(), |
211 | | Real accuracy = 1.0e-8, |
212 | | Size maxEvaluations = 100, |
213 | | Real guess = 0.05) const; |
214 | | |
215 | | //! accrued amount at a given date |
216 | | /*! The default bond settlement is used if no date is given. */ |
217 | | virtual Real accruedAmount(Date d = Date()) const; |
218 | | //@} |
219 | | |
220 | | /*! Expected next coupon: depending on (the bond and) the given date |
221 | | the coupon can be historic, deterministic or expected in a |
222 | | stochastic sense. When the bond settlement date is used the coupon |
223 | | is the already-fixed not-yet-paid one. |
224 | | |
225 | | The current bond settlement is used if no date is given. |
226 | | */ |
227 | | virtual Rate nextCouponRate(Date d = Date()) const; |
228 | | |
229 | | //! Previous coupon already paid at a given date |
230 | | /*! Expected previous coupon: depending on (the bond and) the given |
231 | | date the coupon can be historic, deterministic or expected in a |
232 | | stochastic sense. When the bond settlement date is used the coupon |
233 | | is the last paid one. |
234 | | |
235 | | The current bond settlement is used if no date is given. |
236 | | */ |
237 | | Rate previousCouponRate(Date d = Date()) const; |
238 | | |
239 | | Date nextCashFlowDate(Date d = Date()) const; |
240 | | Date previousCashFlowDate(Date d = Date()) const; |
241 | | |
242 | | protected: |
243 | | void setupExpired() const override; |
244 | | void setupArguments(PricingEngine::arguments*) const override; |
245 | | void fetchResults(const PricingEngine::results*) const override; |
246 | | |
247 | | /*! This method can be called by derived classes in order to |
248 | | build redemption payments from the existing cash flows. |
249 | | It must be called after setting up the cashflows_ vector |
250 | | and will fill the notionalSchedule_, notionals_, and |
251 | | redemptions_ data members. |
252 | | |
253 | | If given, the elements of the redemptions vector will |
254 | | multiply the amount of the redemption cash flow. The |
255 | | elements will be taken in base 100, i.e., a redemption |
256 | | equal to 100 does not modify the amount. |
257 | | |
258 | | \pre The cashflows_ vector must contain at least one |
259 | | coupon and must be sorted by date. |
260 | | */ |
261 | | void addRedemptionsToCashflows(const std::vector<Real>& redemptions |
262 | | = std::vector<Real>()); |
263 | | |
264 | | /*! This method can be called by derived classes in order to |
265 | | build a bond with a single redemption payment. It will |
266 | | fill the notionalSchedule_, notionals_, and redemptions_ |
267 | | data members. |
268 | | */ |
269 | | void setSingleRedemption(Real notional, |
270 | | Real redemption, |
271 | | const Date& date); |
272 | | |
273 | | /*! This method can be called by derived classes in order to |
274 | | build a bond with a single redemption payment. It will |
275 | | fill the notionalSchedule_, notionals_, and redemptions_ |
276 | | data members. |
277 | | */ |
278 | | void setSingleRedemption(Real notional, |
279 | | const ext::shared_ptr<CashFlow>& redemption); |
280 | | |
281 | | /*! used internally to collect notional information from the |
282 | | coupons. It should not be called by derived classes, |
283 | | unless they already provide redemption cash flows (in |
284 | | which case they must set up the redemptions_ data member |
285 | | independently). It will fill the notionalSchedule_ and |
286 | | notionals_ data members. |
287 | | */ |
288 | | void calculateNotionalsFromCashflows(); |
289 | | |
290 | | Natural settlementDays_; |
291 | | Calendar calendar_; |
292 | | std::vector<Date> notionalSchedule_; |
293 | | std::vector<Real> notionals_; |
294 | | Leg cashflows_; // all cashflows |
295 | | Leg redemptions_; // the redemptions |
296 | | |
297 | | Date maturityDate_, issueDate_; |
298 | | mutable Real settlementValue_; |
299 | | }; |
300 | | |
301 | | class Bond::arguments : public PricingEngine::arguments { |
302 | | public: |
303 | | Date settlementDate; |
304 | | Leg cashflows; |
305 | | Calendar calendar; |
306 | | void validate() const override; |
307 | | }; |
308 | | |
309 | | class Bond::results : public Instrument::results { |
310 | | public: |
311 | | Real settlementValue; |
312 | 0 | void reset() override { |
313 | 0 | settlementValue = Null<Real>(); |
314 | 0 | Instrument::results::reset(); |
315 | 0 | } |
316 | | }; |
317 | | |
318 | | class Bond::engine : public GenericEngine<Bond::arguments, |
319 | | Bond::results> {}; |
320 | | |
321 | | |
322 | | // inline definitions |
323 | | |
324 | 0 | inline Natural Bond::settlementDays() const { |
325 | 0 | return settlementDays_; |
326 | 0 | } |
327 | | |
328 | 0 | inline const Calendar& Bond::calendar() const { |
329 | 0 | return calendar_; |
330 | 0 | } |
331 | | |
332 | 0 | inline const std::vector<Real>& Bond::notionals() const { |
333 | 0 | return notionals_; |
334 | 0 | } |
335 | | |
336 | 143k | inline const Leg& Bond::cashflows() const { |
337 | 143k | return cashflows_; |
338 | 143k | } |
339 | | |
340 | 0 | inline const Leg& Bond::redemptions() const { |
341 | 0 | return redemptions_; |
342 | 0 | } |
343 | | |
344 | 0 | inline Date Bond::issueDate() const { |
345 | 0 | return issueDate_; |
346 | 0 | } |
347 | | |
348 | | } |
349 | | |
350 | | #endif |