1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*
4  Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
5  Copyright (C) 2007, 2008 StatPro Italia srl
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  <http://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 zerospreadedtermstructure.hpp
22     \brief Zero spreaded term structure
23 */
24 
25 #ifndef quantlib_zero_spreaded_term_structure_hpp
26 #define quantlib_zero_spreaded_term_structure_hpp
27 
28 #include <ql/termstructures/yield/zeroyieldstructure.hpp>
29 #include <ql/quote.hpp>
30 
31 namespace QuantLib {
32 
33     //! Term structure with an added spread on the zero yield rate
34     /*! \note This term structure will remain linked to the original
35               structure, i.e., any changes in the latter will be
36               reflected in this structure as well.
37 
38         \ingroup yieldtermstructures
39 
40         \test
41         - the correctness of the returned values is tested by
42           checking them against numerical calculations.
43         - observability against changes in the underlying term
44           structure and in the added spread is checked.
45     */
46     class ZeroSpreadedTermStructure : public ZeroYieldStructure {
47       public:
48         ZeroSpreadedTermStructure(const Handle<YieldTermStructure>&,
49                                   const Handle<Quote>& spread,
50                                   Compounding comp = Continuous,
51                                   Frequency freq = NoFrequency,
52                                   const DayCounter& dc = DayCounter());
53         //! \name YieldTermStructure interface
54         //@{
55         DayCounter dayCounter() const;
56         Calendar calendar() const;
57         Natural settlementDays() const;
58         const Date& referenceDate() const;
59         Date maxDate() const;
60         Time maxTime() const;
61         //@}
62         //! \name Observer interface
63         //@{
64         void update();
65         //@}
66       protected:
67         //! returns the spreaded zero yield rate
68         Rate zeroYieldImpl(Time) const;
69         //! returns the spreaded forward rate
70         /* This method must disappear should the spread become a curve */
71         Rate forwardImpl(Time) const;
72       private:
73         Handle<YieldTermStructure> originalCurve_;
74         Handle<Quote> spread_;
75         Compounding comp_;
76         Frequency freq_;
77         DayCounter dc_;
78     };
79 
ZeroSpreadedTermStructure(const Handle<YieldTermStructure> & h,const Handle<Quote> & spread,Compounding comp,Frequency freq,const DayCounter & dc)80     inline ZeroSpreadedTermStructure::ZeroSpreadedTermStructure(
81                                           const Handle<YieldTermStructure>& h,
82                                           const Handle<Quote>& spread,
83                                           Compounding comp,
84                                           Frequency freq,
85                                           const DayCounter& dc)
86     : originalCurve_(h), spread_(spread), comp_(comp), freq_(freq), dc_(dc) {
87         if (!originalCurve_.empty())
88             enableExtrapolation(originalCurve_->allowsExtrapolation());
89         registerWith(originalCurve_);
90         registerWith(spread_);
91     }
92 
dayCounter() const93     inline DayCounter ZeroSpreadedTermStructure::dayCounter() const {
94         return originalCurve_->dayCounter();
95     }
96 
calendar() const97     inline Calendar ZeroSpreadedTermStructure::calendar() const {
98         return originalCurve_->calendar();
99     }
100 
settlementDays() const101     inline Natural ZeroSpreadedTermStructure::settlementDays() const {
102         return originalCurve_->settlementDays();
103     }
104 
referenceDate() const105     inline const Date& ZeroSpreadedTermStructure::referenceDate() const {
106         return originalCurve_->referenceDate();
107     }
108 
maxDate() const109     inline Date ZeroSpreadedTermStructure::maxDate() const {
110         return originalCurve_->maxDate();
111     }
112 
maxTime() const113     inline Time ZeroSpreadedTermStructure::maxTime() const {
114         return originalCurve_->maxTime();
115     }
116 
update()117     inline void ZeroSpreadedTermStructure::update() {
118         if (!originalCurve_.empty()) {
119             YieldTermStructure::update();
120             enableExtrapolation(originalCurve_->allowsExtrapolation());
121         } else {
122             /* The implementation inherited from YieldTermStructure
123                asks for our reference date, which we don't have since
124                the original curve is still not set. Therefore, we skip
125                over that and just call the base-class behavior. */
126             // NOLINTNEXTLINE(bugprone-parent-virtual-call)
127             TermStructure::update();
128         }
129     }
130 
zeroYieldImpl(Time t) const131     inline Rate ZeroSpreadedTermStructure::zeroYieldImpl(Time t) const {
132         // to be fixed: user-defined daycounter should be used
133         InterestRate zeroRate =
134             originalCurve_->zeroRate(t, comp_, freq_, true);
135         InterestRate spreadedRate(zeroRate + spread_->value(),
136                                   zeroRate.dayCounter(),
137                                   zeroRate.compounding(),
138                                   zeroRate.frequency());
139         return spreadedRate.equivalentRate(Continuous, NoFrequency, t);
140     }
141 
forwardImpl(Time t) const142     inline Rate ZeroSpreadedTermStructure::forwardImpl(Time t) const {
143         return originalCurve_->forwardRate(t, t, comp_, freq_, true)
144             + spread_->value();
145     }
146 
147 }
148 
149 #endif
150