1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2006 Roland Lichters
5 Copyright (C) 2006, 2008, 2014 StatPro Italia srl
6 Copyright (C) 2010 Robert Philipp
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 <http://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 piecewisezerospreadedtermstructure.hpp
23 \brief Piecewise-zero-spreaded term structure
24*/
25
26#ifndef quantlib_piecewise_zero_spreaded_term_structure_hpp
27#define quantlib_piecewise_zero_spreaded_term_structure_hpp
28
29#include <ql/math/interpolations/linearinterpolation.hpp>
30#include <ql/quote.hpp>
31#include <ql/termstructures/yield/zeroyieldstructure.hpp>
32#include <utility>
33#include <vector>
34
35namespace QuantLib {
36
37 //! Yield curve with an added vector of spreads on the zero-yield rate
38 /*! The zero-yield spread at any given date is interpolated
39 between the input data.
40
41 \note This term structure will remain linked to the original
42 structure, i.e., any changes in the latter will be
43 reflected in this structure as well.
44
45 \ingroup yieldtermstructures
46 */
47
48 template <class Interpolator>
49 class InterpolatedPiecewiseZeroSpreadedTermStructure : public ZeroYieldStructure {
50 public:
51 InterpolatedPiecewiseZeroSpreadedTermStructure(Handle<YieldTermStructure>,
52 std::vector<Handle<Quote> > spreads,
53 const std::vector<Date>& dates,
54 Compounding comp = Continuous,
55 Frequency freq = NoFrequency,
56 DayCounter dc = DayCounter(),
57 const Interpolator& factory = Interpolator());
58 //! \name YieldTermStructure interface
59 //@{
60 DayCounter dayCounter() const override;
61 Natural settlementDays() const override;
62 Calendar calendar() const override;
63 const Date& referenceDate() const override;
64 Date maxDate() const override;
65 //@}
66 protected:
67 //! returns the spreaded zero yield rate
68 Rate zeroYieldImpl(Time) const override;
69 void update() override;
70
71 private:
72 void updateInterpolation();
73 Real calcSpread(Time t) const;
74 Handle<YieldTermStructure> originalCurve_;
75 std::vector<Handle<Quote> > spreads_;
76 std::vector<Date> dates_;
77 std::vector<Time> times_;
78 std::vector<Spread> spreadValues_;
79 Compounding comp_;
80 Frequency freq_;
81 DayCounter dc_;
82 Interpolator factory_;
83 Interpolation interpolator_;
84 };
85
86 //! Piecewise zero-spreaded yield curve based on linear interpolation of zero rates
87 /*! \ingroup yieldtermstructures */
88
89 typedef InterpolatedPiecewiseZeroSpreadedTermStructure<Linear> PiecewiseZeroSpreadedTermStructure;
90
91
92 // inline definitions
93
94 template <class T>
95 inline InterpolatedPiecewiseZeroSpreadedTermStructure<
96 T>::InterpolatedPiecewiseZeroSpreadedTermStructure(Handle<YieldTermStructure> h,
97 std::vector<Handle<Quote> > spreads,
98 const std::vector<Date>& dates,
99 Compounding comp,
100 Frequency freq,
101 DayCounter dc,
102 const T& factory)
103 : originalCurve_(std::move(h)), spreads_(std::move(spreads)), dates_(dates),
104 times_(dates.size()), spreadValues_(dates.size()), comp_(comp), freq_(freq),
105 dc_(std::move(dc)), factory_(factory) {
106 QL_REQUIRE(!spreads_.empty(), "no spreads given");
107 QL_REQUIRE(spreads_.size() == dates_.size(),
108 "spread and date vector have different sizes");
109 registerWith(h: originalCurve_);
110 for (auto& spread : spreads_)
111 registerWith(h: spread);
112 if (!originalCurve_.empty())
113 updateInterpolation();
114 }
115
116 template <class T>
117 inline DayCounter InterpolatedPiecewiseZeroSpreadedTermStructure<T>::dayCounter() const {
118 return originalCurve_->dayCounter();
119 }
120
121 template <class T>
122 inline Calendar InterpolatedPiecewiseZeroSpreadedTermStructure<T>::calendar() const {
123 return originalCurve_->calendar();
124 }
125
126 template <class T>
127 inline Natural InterpolatedPiecewiseZeroSpreadedTermStructure<T>::settlementDays() const {
128 return originalCurve_->settlementDays();
129 }
130
131 template <class T>
132 inline const Date&
133 InterpolatedPiecewiseZeroSpreadedTermStructure<T>::referenceDate() const {
134 return originalCurve_->referenceDate();
135 }
136
137 template <class T>
138 inline Date InterpolatedPiecewiseZeroSpreadedTermStructure<T>::maxDate() const {
139 return std::min(a: originalCurve_->maxDate(), b: dates_.back());
140 }
141
142 template <class T>
143 inline Rate
144 InterpolatedPiecewiseZeroSpreadedTermStructure<T>::zeroYieldImpl(Time t) const {
145 Spread spread = calcSpread(t);
146 InterestRate zeroRate = originalCurve_->zeroRate(t, comp: comp_, freq: freq_, extrapolate: true);
147 InterestRate spreadedRate(zeroRate + spread,
148 zeroRate.dayCounter(),
149 zeroRate.compounding(),
150 zeroRate.frequency());
151 return spreadedRate.equivalentRate(comp: Continuous, freq: NoFrequency, t);
152 }
153
154 template <class T>
155 inline Spread
156 InterpolatedPiecewiseZeroSpreadedTermStructure<T>::calcSpread(Time t) const {
157 if (t <= times_.front()) {
158 return spreads_.front()->value();
159 } else if (t >= times_.back()) {
160 return spreads_.back()->value();
161 } else {
162 return interpolator_(t, true);
163 }
164 }
165
166 template <class T>
167 inline void InterpolatedPiecewiseZeroSpreadedTermStructure<T>::update() {
168 if (!originalCurve_.empty()) {
169 updateInterpolation();
170 ZeroYieldStructure::update();
171 } else {
172 /* The implementation inherited from YieldTermStructure
173 asks for our reference date, which we don't have since
174 the original curve is still not set. Therefore, we skip
175 over that and just call the base-class behavior. */
176 // NOLINTNEXTLINE(bugprone-parent-virtual-call)
177 TermStructure::update();
178 }
179 }
180
181 template <class T>
182 inline void InterpolatedPiecewiseZeroSpreadedTermStructure<T>::updateInterpolation() {
183 for (Size i = 0; i < dates_.size(); i++) {
184 times_[i] = timeFromReference(d: dates_[i]);
185 spreadValues_[i] = spreads_[i]->value();
186 }
187 interpolator_ = factory_.interpolate(times_.begin(),
188 times_.end(),
189 spreadValues_.begin());
190 }
191
192}
193
194
195#endif
196
197

source code of quantlib/ql/termstructures/yield/piecewisezerospreadedtermstructure.hpp