Coverage Report

Created: 2025-12-08 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/experimental/callablebonds/callablebond.hpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2008 Allen Kuo
5
 Copyright (C) 2017 BN Algorithms Ltd
6
7
 This file is part of QuantLib, a free-software/open-source library
8
 for financial quantitative analysts and developers - http://quantlib.org/
9
10
 QuantLib is free software: you can redistribute it and/or modify it
11
 under the terms of the QuantLib license.  You should have received a
12
 copy of the license along with this program; if not, please email
13
 <quantlib-dev@lists.sf.net>. The license is also available online at
14
 <https://www.quantlib.org/license.shtml>.
15
16
 This program is distributed in the hope that it will be useful, but WITHOUT
17
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
 FOR A PARTICULAR PURPOSE.  See the license for more details.
19
*/
20
21
/*! \file callablebond.hpp
22
    \brief callable bond classes
23
*/
24
25
#ifndef quantlib_callable_bond_hpp
26
#define quantlib_callable_bond_hpp
27
28
#include <ql/instruments/bond.hpp>
29
#include <ql/pricingengine.hpp>
30
#include <ql/instruments/callabilityschedule.hpp>
31
#include <ql/termstructures/yieldtermstructure.hpp>
32
#include <ql/handle.hpp>
33
#include <ql/quotes/simplequote.hpp>
34
35
namespace QuantLib {
36
37
    class Schedule;
38
    class DayCounter;
39
40
    //! Callable bond base class
41
    /*! Base callable bond class for fixed and zero coupon bonds.
42
        Defines commonalities between fixed and zero coupon callable
43
        bonds. At present, only European and Bermudan put/call schedules
44
        supported (no American optionality), as defined by the Callability
45
        class.
46
47
        \todo models/shortrate/calibrationHelpers
48
        \todo OAS/OAD
49
        \todo floating rate callable bonds ?
50
51
        \ingroup instruments
52
    */
53
    class CallableBond : public Bond {
54
      public:
55
        class arguments;
56
        class results;
57
        class engine;
58
59
        //! \name Inspectors
60
        //@{
61
        //! return the bond's put/call schedule
62
0
        const CallabilitySchedule& callability() const {
63
0
            return putCallSchedule_;
64
0
        }
65
        //@}
66
67
        //! \name Calculations
68
        //@{
69
        //! returns the Black implied forward yield volatility
70
        /*! the forward yield volatility, see Hull, Fourth Edition,
71
            Chapter 20, pg 536). Relevant only to European put/call
72
            schedules
73
        */
74
        Volatility impliedVolatility(
75
                              const Bond::Price& targetPrice,
76
                              const Handle<YieldTermStructure>& discountCurve,
77
                              Real accuracy,
78
                              Size maxEvaluations,
79
                              Volatility minVol,
80
                              Volatility maxVol) const;
81
82
        //! Calculate the Option Adjusted Spread (OAS)
83
        /*! Calculates the spread that needs to be added to the
84
            reference curve so that the theoretical model value
85
            matches the marketPrice.
86
87
         */
88
        Spread OAS(Real cleanPrice,
89
                   const Handle<YieldTermStructure>& engineTS,
90
                   const DayCounter& dayCounter,
91
                   Compounding compounding,
92
                   Frequency frequency,
93
                   Date settlementDate = Date(),
94
                   Real accuracy = 1.0e-10,
95
                   Size maxIterations = 100,
96
                   Rate guess = 0.0);
97
98
        //! Calculate the clean price based on the given
99
        //! option-adjust-spread (oas) over the given yield term
100
        //! structure (engineTS)
101
        Real cleanPriceOAS(Real oas,
102
                           const Handle<YieldTermStructure>& engineTS,
103
                           const DayCounter& dayCounter,
104
                           Compounding compounding,
105
                           Frequency frequency,
106
                           Date settlementDate = Date());
107
108
        //! Calculate the effective duration, i.e., the first
109
        //! differential of the dirty price w.r.t. a parallel shift of
110
        //! the yield term structure divided by current dirty price
111
        Real effectiveDuration(Real oas,
112
                               const Handle<YieldTermStructure>& engineTS,
113
                               const DayCounter& dayCounter,
114
                               Compounding compounding,
115
                               Frequency frequency,
116
                               Real bump=2e-4);
117
118
        //! Calculate the effective convexity, i.e., the second
119
        //! differential of the dirty price w.r.t. a parallel shift of
120
        //! the yield term structure divided by current dirty price
121
        Real effectiveConvexity(Real oas,
122
                                const Handle<YieldTermStructure>& engineTS,
123
                                const DayCounter& dayCounter,
124
                                Compounding compounding,
125
                                Frequency frequency,
126
                                Real bump=2e-4);
127
        //@}
128
129
        void setupArguments(PricingEngine::arguments* args) const override;
130
131
      protected:
132
        CallableBond(Natural settlementDays,
133
                     const Date& maturityDate,
134
                     const Calendar& calendar,
135
                     DayCounter paymentDayCounter,
136
                     Real faceAmount,
137
                     const Date& issueDate = Date(),
138
                     CallabilitySchedule putCallSchedule = CallabilitySchedule());
139
140
        DayCounter paymentDayCounter_;
141
        Frequency frequency_;
142
        CallabilitySchedule putCallSchedule_;
143
        Real faceAmount_;
144
        // helper class for Black implied volatility calculation
145
        class ImpliedVolHelper;
146
        // helper class for option adjusted spread calculations
147
        class NPVSpreadHelper;
148
149
      private:
150
        /*  Used internally.
151
            same as Bond::accruedAmount() but with enable early
152
            payments true.  Forces accrued to be calculated in a
153
            consistent way for future put/ call dates, which can be
154
            problematic in lattice engines when option dates are also
155
            coupon dates.
156
        */
157
        Real accrued(Date settlement) const;
158
    };
159
160
    class CallableBond::arguments : public Bond::arguments {
161
      public:
162
0
        arguments() = default;
163
        std::vector<Date> couponDates;
164
        std::vector<Real> couponAmounts;
165
        Real faceAmount;
166
        //! redemption = face amount * redemption / 100.
167
        Real redemption;
168
        Date redemptionDate;
169
        DayCounter paymentDayCounter;
170
        Frequency frequency;
171
        CallabilitySchedule putCallSchedule;
172
        //! bond full/dirty/cash prices
173
        std::vector<Real> callabilityPrices;
174
        std::vector<Date> callabilityDates;
175
        //! Spread to apply to the valuation. This is a continuously
176
        //! componded rate added to the model. Currently only applied
177
        //! by the TreeCallableFixedRateBondEngine
178
        Real spread;
179
        void validate() const override;
180
    };
181
182
    //! results for a callable bond calculation
183
    class CallableBond::results : public Bond::results {
184
      public:
185
        // no extra results set yet
186
    };
187
188
    //! base class for callable fixed rate bond engine
189
    class CallableBond::engine
190
        : public GenericEngine<CallableBond::arguments,
191
                               CallableBond::results> {};
192
193
194
    //! callable/puttable fixed rate bond
195
    /*! Callable fixed rate bond class.
196
197
        \ingroup instruments
198
    */
199
    class CallableFixedRateBond : public CallableBond {
200
      public:
201
        CallableFixedRateBond(Natural settlementDays,
202
                              Real faceAmount,
203
                              Schedule schedule,
204
                              const std::vector<Rate>& coupons,
205
                              const DayCounter& accrualDayCounter,
206
                              BusinessDayConvention paymentConvention = Following,
207
                              Real redemption = 100.0,
208
                              const Date& issueDate = Date(),
209
                              const CallabilitySchedule& putCallSchedule = {},
210
                              const Period& exCouponPeriod = Period(),
211
                              const Calendar& exCouponCalendar = Calendar(),
212
                              BusinessDayConvention exCouponConvention = Unadjusted,
213
                              bool exCouponEndOfMonth = false);
214
    };
215
216
    //! callable/puttable zero coupon bond
217
    /*! Callable zero coupon bond class.
218
219
        \ingroup instruments
220
    */
221
    class CallableZeroCouponBond : public CallableBond {
222
      public:
223
        CallableZeroCouponBond(Natural settlementDays,
224
                               Real faceAmount,
225
                               const Calendar& calendar,
226
                               const Date& maturityDate,
227
                               const DayCounter& dayCounter,
228
                               BusinessDayConvention paymentConvention = Following,
229
                               Real redemption = 100.0,
230
                               const Date& issueDate = Date(),
231
                               const CallabilitySchedule& putCallSchedule = {});
232
    };
233
234
}
235
236
#endif