/src/quantlib/ql/cashflows/rangeaccrual.hpp
Line | Count | Source |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | |
5 | | Copyright (C) 2006, 2007 Giorgio Facchinetti |
6 | | Copyright (C) 2006, 2007 Mario Pucci |
7 | | |
8 | | This file is part of QuantLib, a free-software/open-source library |
9 | | for financial quantitative analysts and developers - http://quantlib.org/ |
10 | | |
11 | | QuantLib is free software: you can redistribute it and/or modify it |
12 | | under the terms of the QuantLib license. You should have received a |
13 | | copy of the license along with this program; if not, please email |
14 | | <quantlib-dev@lists.sf.net>. The license is also available online at |
15 | | <https://www.quantlib.org/license.shtml>. |
16 | | |
17 | | This program is distributed in the hope that it will be useful, but WITHOUT |
18 | | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
19 | | FOR A PARTICULAR PURPOSE. See the license for more details. |
20 | | */ |
21 | | |
22 | | /*! \file rangeaccrual.hpp |
23 | | \brief range-accrual coupon |
24 | | */ |
25 | | |
26 | | #ifndef quantlib_range_accrual_h |
27 | | #define quantlib_range_accrual_h |
28 | | |
29 | | #include <ql/termstructures/volatility/smilesection.hpp> |
30 | | #include <ql/cashflows/couponpricer.hpp> |
31 | | #include <ql/cashflows/floatingratecoupon.hpp> |
32 | | #include <ql/time/schedule.hpp> |
33 | | #include <vector> |
34 | | |
35 | | namespace QuantLib { |
36 | | |
37 | | class IborIndex; |
38 | | |
39 | | class RangeAccrualFloatersCoupon : public FloatingRateCoupon { |
40 | | |
41 | | public: |
42 | | RangeAccrualFloatersCoupon(const Date& paymentDate, |
43 | | Real nominal, |
44 | | const ext::shared_ptr<IborIndex>& index, |
45 | | const Date& startDate, |
46 | | const Date& endDate, |
47 | | Natural fixingDays, |
48 | | const DayCounter& dayCounter, |
49 | | Real gearing, |
50 | | Rate spread, |
51 | | const Date& refPeriodStart, |
52 | | const Date& refPeriodEnd, |
53 | | Schedule observationsSchedule, |
54 | | Real lowerTrigger, |
55 | | Real upperTrigger); |
56 | | |
57 | | /*! \deprecated Use the overload taking a Schedule instead. |
58 | | Deprecated in version 1.40. |
59 | | */ |
60 | | [[deprecated("Use the overload taking a Schedule instead")]] |
61 | | RangeAccrualFloatersCoupon(const Date& paymentDate, |
62 | | Real nominal, |
63 | | const ext::shared_ptr<IborIndex>& index, |
64 | | const Date& startDate, |
65 | | const Date& endDate, |
66 | | Natural fixingDays, |
67 | | const DayCounter& dayCounter, |
68 | | Real gearing, |
69 | | Rate spread, |
70 | | const Date& refPeriodStart, |
71 | | const Date& refPeriodEnd, |
72 | | const ext::shared_ptr<Schedule>& observationsSchedule, |
73 | | Real lowerTrigger, |
74 | | Real upperTrigger) |
75 | | : RangeAccrualFloatersCoupon(paymentDate, nominal, index, startDate, endDate, |
76 | | fixingDays, dayCounter, gearing, spread, |
77 | | refPeriodStart, refPeriodEnd, |
78 | | *observationsSchedule, |
79 | 0 | lowerTrigger, upperTrigger) {} |
80 | | |
81 | 0 | Real startTime() const {return startTime_; } |
82 | 0 | Real endTime() const {return endTime_; } |
83 | 0 | Real lowerTrigger() const {return lowerTrigger_; } |
84 | 0 | Real upperTrigger() const {return upperTrigger_; } |
85 | 0 | Size observationsNo() const {return observationsNo_; } |
86 | 0 | const std::vector<Date>& observationDates() const { |
87 | 0 | return observationDates_; |
88 | 0 | } |
89 | 0 | const std::vector<Real>& observationTimes() const { |
90 | 0 | return observationTimes_; |
91 | 0 | } |
92 | 0 | const Schedule& observationSchedule() const { return observationSchedule_; } |
93 | | /*! \deprecated Use observationSchedule instead. |
94 | | Deprecated in version 1.40. |
95 | | */ |
96 | | [[deprecated("Use observationSchedule instead")]] |
97 | 0 | ext::shared_ptr<Schedule> observationsSchedule() const { |
98 | 0 | return ext::make_shared<Schedule>(observationSchedule_); |
99 | 0 | } |
100 | | |
101 | | Real priceWithoutOptionality( |
102 | | const Handle<YieldTermStructure>& discountCurve) const; |
103 | | //! \name Visitability |
104 | | //@{ |
105 | | void accept(AcyclicVisitor&) override; |
106 | | //@} |
107 | | private: |
108 | | |
109 | | Real startTime_; // S |
110 | | Real endTime_; // T |
111 | | |
112 | | Schedule observationSchedule_; |
113 | | std::vector<Date> observationDates_; |
114 | | std::vector<Real> observationTimes_; |
115 | | Size observationsNo_; |
116 | | |
117 | | Real lowerTrigger_; |
118 | | Real upperTrigger_; |
119 | | }; |
120 | | |
121 | | class RangeAccrualPricer: public FloatingRateCouponPricer { |
122 | | public: |
123 | | //! \name Observer interface |
124 | | //@{ |
125 | | Rate swapletRate() const override; |
126 | | Real capletPrice(Rate effectiveCap) const override; |
127 | | Rate capletRate(Rate effectiveCap) const override; |
128 | | Real floorletPrice(Rate effectiveFloor) const override; |
129 | | Rate floorletRate(Rate effectiveFloor) const override; |
130 | | void initialize(const FloatingRateCoupon& coupon) override; |
131 | | //@} |
132 | | |
133 | | protected: |
134 | | const RangeAccrualFloatersCoupon* coupon_; |
135 | | Real startTime_; // S |
136 | | Real endTime_; // T |
137 | | Real accrualFactor_; // T-S |
138 | | std::vector<Real> observationTimeLags_; // d |
139 | | std::vector<Real> observationTimes_; // U |
140 | | std::vector<Real> initialValues_; |
141 | | Size observationsNo_; |
142 | | Real lowerTrigger_; |
143 | | Real upperTrigger_; |
144 | | Real discount_; |
145 | | Real gearing_; |
146 | | Spread spread_; |
147 | | Real spreadLegValue_; |
148 | | |
149 | | }; |
150 | | |
151 | | class RangeAccrualPricerByBgm : public RangeAccrualPricer { |
152 | | |
153 | | public: |
154 | | RangeAccrualPricerByBgm(Real correlation, |
155 | | ext::shared_ptr<SmileSection> smilesOnExpiry, |
156 | | ext::shared_ptr<SmileSection> smilesOnPayment, |
157 | | bool withSmile, |
158 | | bool byCallSpread); |
159 | | //! \name Observer interface |
160 | | //@{ |
161 | | Real swapletPrice() const override; |
162 | | //@} |
163 | | |
164 | | protected: |
165 | | |
166 | | Real drift(Real U, Real lambdaS, Real lambdaT, Real correlation) const; |
167 | | Real derDriftDerLambdaS(Real U, Real lambdaS, Real lambdaT, |
168 | | Real correlation) const; |
169 | | Real derDriftDerLambdaT(Real U, Real lambdaS, Real lambdaT, |
170 | | Real correlation) const; |
171 | | |
172 | | Real lambda(Real U, Real lambdaS, Real lambdaT) const; |
173 | | Real derLambdaDerLambdaS(Real U) const; |
174 | | Real derLambdaDerLambdaT(Real U) const; |
175 | | |
176 | | std::vector<Real> driftsOverPeriod(Real U, Real lambdaS, Real lambdaT, |
177 | | Real correlation) const; |
178 | | std::vector<Real> lambdasOverPeriod(Real U, Real lambdaS, |
179 | | Real lambdaT) const; |
180 | | |
181 | | Real digitalRangePrice(Real lowerTrigger, |
182 | | Real upperTrigger, |
183 | | Real initialValue, |
184 | | Real expiry, |
185 | | Real deflator) const; |
186 | | |
187 | | Real digitalPrice(Real strike, |
188 | | Real initialValue, |
189 | | Real expiry, |
190 | | Real deflator) const; |
191 | | |
192 | | Real digitalPriceWithoutSmile(Real strike, |
193 | | Real initialValue, |
194 | | Real expiry, |
195 | | Real deflator) const; |
196 | | |
197 | | Real digitalPriceWithSmile(Real strike, |
198 | | Real initialValue, |
199 | | Real expiry, |
200 | | Real deflator) const; |
201 | | |
202 | | Real callSpreadPrice(Real previousInitialValue, |
203 | | Real nextInitialValue, |
204 | | Real previousStrike, |
205 | | Real nextStrike, |
206 | | Real deflator, |
207 | | Real previousVariance, |
208 | | Real nextVariance) const; |
209 | | |
210 | | Real smileCorrection(Real strike, |
211 | | Real initialValue, |
212 | | Real expiry, |
213 | | Real deflator) const; |
214 | | |
215 | | private: |
216 | | Real correlation_; // correlation between L(S) and L(T) |
217 | | bool withSmile_; |
218 | | bool byCallSpread_; |
219 | | |
220 | | ext::shared_ptr<SmileSection> smilesOnExpiry_; |
221 | | ext::shared_ptr<SmileSection> smilesOnPayment_; |
222 | | Real eps_ = 1.0e-8; |
223 | | }; |
224 | | |
225 | | |
226 | | //! helper class building a sequence of range-accrual floating-rate coupons |
227 | | class RangeAccrualLeg { |
228 | | public: |
229 | | RangeAccrualLeg(Schedule schedule, ext::shared_ptr<IborIndex> index); |
230 | | RangeAccrualLeg& withNotionals(Real notional); |
231 | | RangeAccrualLeg& withNotionals(const std::vector<Real>& notionals); |
232 | | RangeAccrualLeg& withPaymentDayCounter(const DayCounter&); |
233 | | RangeAccrualLeg& withPaymentAdjustment(BusinessDayConvention); |
234 | | RangeAccrualLeg& withFixingDays(Natural fixingDays); |
235 | | RangeAccrualLeg& withFixingDays(const std::vector<Natural>& fixingDays); |
236 | | RangeAccrualLeg& withGearings(Real gearing); |
237 | | RangeAccrualLeg& withGearings(const std::vector<Real>& gearings); |
238 | | RangeAccrualLeg& withSpreads(Spread spread); |
239 | | RangeAccrualLeg& withSpreads(const std::vector<Spread>& spreads); |
240 | | RangeAccrualLeg& withLowerTriggers(Rate trigger); |
241 | | RangeAccrualLeg& withLowerTriggers(const std::vector<Rate>& triggers); |
242 | | RangeAccrualLeg& withUpperTriggers(Rate trigger); |
243 | | RangeAccrualLeg& withUpperTriggers(const std::vector<Rate>& triggers); |
244 | | RangeAccrualLeg& withObservationTenor(const Period&); |
245 | | RangeAccrualLeg& withObservationConvention(BusinessDayConvention); |
246 | | operator Leg() const; |
247 | | private: |
248 | | Schedule schedule_; |
249 | | ext::shared_ptr<IborIndex> index_; |
250 | | std::vector<Real> notionals_; |
251 | | DayCounter paymentDayCounter_; |
252 | | BusinessDayConvention paymentAdjustment_ = Following; |
253 | | std::vector<Natural> fixingDays_; |
254 | | std::vector<Real> gearings_; |
255 | | std::vector<Spread> spreads_; |
256 | | std::vector<Rate> lowerTriggers_, upperTriggers_; |
257 | | Period observationTenor_; |
258 | | BusinessDayConvention observationConvention_ = ModifiedFollowing; |
259 | | }; |
260 | | |
261 | | } |
262 | | |
263 | | |
264 | | #endif |