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 Copyright (C) 2017 Francois Botha
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 compositezeroyieldstructure.hpp
23 \brief Composite zero term structure
24 */
25 
26 #ifndef quantlib_composite_zero_yield_structure
27 #define quantlib_composite_zero_yield_structure
28 
29 
30 #include <ql/termstructures/yield/zeroyieldstructure.hpp>
31 
32 namespace QuantLib {
33     template <class BinaryFunction>
34     class CompositeZeroYieldStructure : public ZeroYieldStructure {
35       public:
36           CompositeZeroYieldStructure(const Handle<YieldTermStructure>& h1,
37                                       const Handle<YieldTermStructure>& h2,
38                                       const BinaryFunction& f,
39                                       Compounding comp = Continuous,
40                                       Frequency freq = NoFrequency);
41 
42           //! \name YieldTermStructure interface
43           //@{
44           DayCounter dayCounter() const;
45           Calendar calendar() const;
46           Natural settlementDays() const;
47           const Date& referenceDate() const;
48           Date maxDate() const;
49           Time maxTime() const;
50           //@}
51           //! \name Observer interface
52           //@{
53           void update();
54           //@}
55       protected:
56         //! returns the composite zero yield rate
57         Rate zeroYieldImpl(Time) const;
58       private:
59         Handle<YieldTermStructure> curve1_;
60         Handle<YieldTermStructure> curve2_;
61         BinaryFunction f_;
62         Compounding comp_;
63         Frequency freq_;
64     };
65 
66     // inline definitions
67 
68     template <class BinaryFunction>
CompositeZeroYieldStructure(const Handle<YieldTermStructure> & h1,const Handle<YieldTermStructure> & h2,const BinaryFunction & f,Compounding comp,Frequency freq)69     inline CompositeZeroYieldStructure<BinaryFunction>::CompositeZeroYieldStructure(
70         const Handle<YieldTermStructure>& h1,
71         const Handle<YieldTermStructure>& h2,
72         const BinaryFunction& f,
73         Compounding comp,
74         Frequency freq)
75     : curve1_(h1), curve2_(h2), f_(f), comp_(comp), freq_(freq) {
76         if (!curve1_.empty() && !curve2_.empty())
77             enableExtrapolation(curve1_->allowsExtrapolation() && curve2_->allowsExtrapolation());
78 
79         registerWith(curve1_);
80         registerWith(curve2_);
81     }
82 
83     template <class BinaryFunction>
dayCounter() const84     inline DayCounter CompositeZeroYieldStructure<BinaryFunction>::dayCounter() const {
85         return curve1_->dayCounter();
86     }
87 
88     template <class BinaryFunction>
calendar() const89     inline Calendar CompositeZeroYieldStructure<BinaryFunction>::calendar() const {
90         return curve1_->calendar();
91     }
92 
93     template <class BinaryFunction>
settlementDays() const94     inline Natural CompositeZeroYieldStructure<BinaryFunction>::settlementDays() const {
95         return curve1_->settlementDays();
96     }
97 
98     template <class BinaryFunction>
referenceDate() const99     inline const Date& CompositeZeroYieldStructure<BinaryFunction>::referenceDate() const {
100         return curve1_->referenceDate();
101     }
102 
103     template <class BinaryFunction>
maxDate() const104     inline Date CompositeZeroYieldStructure<BinaryFunction>::maxDate() const {
105         return curve1_->maxDate();
106     }
107 
108     template <class BinaryFunction>
maxTime() const109     inline Time CompositeZeroYieldStructure<BinaryFunction>::maxTime() const {
110         return curve1_->maxTime();
111     }
112 
113     template <class BinaryFunction>
update()114     inline void CompositeZeroYieldStructure<BinaryFunction>::update() {
115         if (!curve1_.empty() && !curve2_.empty()) {
116             YieldTermStructure::update();
117             enableExtrapolation(curve1_->allowsExtrapolation() && curve2_->allowsExtrapolation());
118         }
119         else {
120             /* The implementation inherited from YieldTermStructure
121             asks for our reference date, which we don't have since
122             the original curve is still not set. Therefore, we skip
123             over that and just call the base-class behavior. */
124             // NOLINTNEXTLINE(bugprone-parent-virtual-call)
125             TermStructure::update();
126         }
127     }
128 
129     template <class BinaryFunction>
zeroYieldImpl(Time t) const130     inline Rate CompositeZeroYieldStructure<BinaryFunction>::zeroYieldImpl(Time t) const {
131         Rate zeroRate1 =
132             curve1_->zeroRate(t, comp_, freq_, true);
133 
134         InterestRate zeroRate2 =
135             curve2_->zeroRate(t, comp_, freq_, true);
136 
137         InterestRate compositeRate(f_(zeroRate1, zeroRate2), dayCounter(), comp_, freq_);
138         return compositeRate.equivalentRate(Continuous, NoFrequency, t);
139     }
140 }
141 #endif
142