1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*
4  Copyright (C) 2009 Chris Kenyon
5 
6  This file is part of QuantLib, a free-software/open-source library
7  for financial quantitative analysts and developers - http://quantlib.org/
8 
9  QuantLib is free software: you can redistribute it and/or modify it
10  under the terms of the QuantLib license.  You should have received a
11  copy of the license along with this program; if not, please email
12  <quantlib-dev@lists.sf.net>. The license is also available online at
13  <http://quantlib.org/license.shtml>.
14 
15  This program is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  FOR A PARTICULAR PURPOSE.  See the license for more details.
18  */
19 
20 
21 #include <ql/cashflows/inflationcouponpricer.hpp>
22 #include <ql/cashflows/inflationcoupon.hpp>
23 #include <ql/cashflows/capflooredinflationcoupon.hpp>
24 #include <ql/cashflows/cashflowvectors.hpp>
25 
26 namespace QuantLib {
27 
28     YoYInflationCoupon::
YoYInflationCoupon(const Date & paymentDate,Real nominal,const Date & startDate,const Date & endDate,Natural fixingDays,const ext::shared_ptr<YoYInflationIndex> & yoyIndex,const Period & observationLag,const DayCounter & dayCounter,Real gearing,Spread spread,const Date & refPeriodStart,const Date & refPeriodEnd)29     YoYInflationCoupon(const Date& paymentDate,
30                    Real nominal,
31                    const Date& startDate,
32                    const Date& endDate,
33                    Natural fixingDays,
34                    const ext::shared_ptr<YoYInflationIndex>& yoyIndex,
35                    const Period& observationLag,
36                    const DayCounter& dayCounter,
37                    Real gearing,
38                    Spread spread,
39                    const Date& refPeriodStart,
40                    const Date& refPeriodEnd)
41     : InflationCoupon(paymentDate, nominal, startDate, endDate,
42                   fixingDays, yoyIndex, observationLag,
43                   dayCounter, refPeriodStart, refPeriodEnd),
44     yoyIndex_(yoyIndex), gearing_(gearing), spread_(spread) {}
45 
46 
accept(AcyclicVisitor & v)47     void YoYInflationCoupon::accept(AcyclicVisitor& v) {
48         Visitor<YoYInflationCoupon>* v1 =
49         dynamic_cast<Visitor<YoYInflationCoupon>*>(&v);
50         if (v1 != 0)
51             v1->visit(*this);
52         else
53             InflationCoupon::accept(v);
54     }
55 
56 
checkPricerImpl(const ext::shared_ptr<InflationCouponPricer> & pricer) const57     bool YoYInflationCoupon::checkPricerImpl(
58             const ext::shared_ptr<InflationCouponPricer>&pricer) const {
59         return static_cast<bool>(
60                ext::dynamic_pointer_cast<YoYInflationCouponPricer>(pricer));
61     }
62 
63 
64 
65     yoyInflationLeg::
yoyInflationLeg(const Schedule & schedule,const Calendar & paymentCalendar,const ext::shared_ptr<YoYInflationIndex> & index,const Period & observationLag)66     yoyInflationLeg(const Schedule& schedule, const Calendar& paymentCalendar,
67                     const ext::shared_ptr<YoYInflationIndex>& index,
68                     const Period& observationLag)
69     : schedule_(schedule), index_(index),
70       observationLag_(observationLag),
71       paymentAdjustment_(ModifiedFollowing),
72       paymentCalendar_(paymentCalendar) {}
73 
74 
withNotionals(Real notional)75     yoyInflationLeg& yoyInflationLeg::withNotionals(Real notional) {
76         notionals_ = std::vector<Real>(1,notional);
77         return *this;
78     }
79 
withNotionals(const std::vector<Real> & notionals)80     yoyInflationLeg& yoyInflationLeg::withNotionals(const std::vector<Real>& notionals) {
81         notionals_ = notionals;
82         return *this;
83     }
84 
withPaymentDayCounter(const DayCounter & dayCounter)85     yoyInflationLeg& yoyInflationLeg::withPaymentDayCounter(const DayCounter& dayCounter) {
86         paymentDayCounter_ = dayCounter;
87         return *this;
88     }
89 
withPaymentAdjustment(BusinessDayConvention convention)90     yoyInflationLeg& yoyInflationLeg::withPaymentAdjustment(BusinessDayConvention convention) {
91         paymentAdjustment_ = convention;
92         return *this;
93     }
94 
withFixingDays(Natural fixingDays)95     yoyInflationLeg& yoyInflationLeg::withFixingDays(Natural fixingDays) {
96         fixingDays_ = std::vector<Natural>(1,fixingDays);
97         return *this;
98     }
99 
withFixingDays(const std::vector<Natural> & fixingDays)100     yoyInflationLeg& yoyInflationLeg::withFixingDays(const std::vector<Natural>& fixingDays) {
101         fixingDays_ = fixingDays;
102         return *this;
103     }
104 
withGearings(Real gearing)105     yoyInflationLeg& yoyInflationLeg::withGearings(Real gearing) {
106         gearings_ = std::vector<Real>(1,gearing);
107         return *this;
108     }
109 
withGearings(const std::vector<Real> & gearings)110     yoyInflationLeg& yoyInflationLeg::withGearings(const std::vector<Real>& gearings) {
111         gearings_ = gearings;
112         return *this;
113     }
114 
withSpreads(Spread spread)115     yoyInflationLeg& yoyInflationLeg::withSpreads(Spread spread) {
116         spreads_ = std::vector<Spread>(1,spread);
117         return *this;
118     }
119 
withSpreads(const std::vector<Spread> & spreads)120     yoyInflationLeg& yoyInflationLeg::withSpreads(const std::vector<Spread>& spreads) {
121         spreads_ = spreads;
122         return *this;
123     }
124 
withCaps(Rate cap)125     yoyInflationLeg& yoyInflationLeg::withCaps(Rate cap) {
126         caps_ = std::vector<Rate>(1,cap);
127         return *this;
128     }
129 
withCaps(const std::vector<Rate> & caps)130     yoyInflationLeg& yoyInflationLeg::withCaps(const std::vector<Rate>& caps) {
131         caps_ = caps;
132         return *this;
133     }
134 
withFloors(Rate floor)135     yoyInflationLeg& yoyInflationLeg::withFloors(Rate floor) {
136         floors_ = std::vector<Rate>(1,floor);
137         return *this;
138     }
139 
withFloors(const std::vector<Rate> & floors)140     yoyInflationLeg& yoyInflationLeg::withFloors(const std::vector<Rate>& floors) {
141         floors_ = floors;
142         return *this;
143     }
144 
145 
operator Leg() const146     yoyInflationLeg::operator Leg() const {
147 
148         Size n = schedule_.size()-1;
149         QL_REQUIRE(!paymentDayCounter_.empty(), "no payment daycounter given");
150         QL_REQUIRE(!notionals_.empty(), "no notional given");
151         QL_REQUIRE(notionals_.size() <= n,
152                    "too many nominals (" << notionals_.size() <<
153                    "), only " << n << " required");
154         QL_REQUIRE(gearings_.size()<=n,
155                    "too many gearings (" << gearings_.size() <<
156                    "), only " << n << " required");
157         QL_REQUIRE(spreads_.size()<=n,
158                    "too many spreads (" << spreads_.size() <<
159                    "), only " << n << " required");
160         QL_REQUIRE(caps_.size()<=n,
161                    "too many caps (" << caps_.size() <<
162                    "), only " << n << " required");
163         QL_REQUIRE(floors_.size()<=n,
164                    "too many floors (" << floors_.size() <<
165                    "), only " << n << " required");
166 
167         Leg leg; leg.reserve(n);
168 
169         Calendar calendar = paymentCalendar_;
170 
171         Date refStart, start, refEnd, end;
172 
173         for (Size i=0; i<n; ++i) {
174             refStart = start = schedule_.date(i);
175             refEnd   =   end = schedule_.date(i+1);
176             Date paymentDate = calendar.adjust(end, paymentAdjustment_);
177             if (i==0 && schedule_.hasIsRegular() && !schedule_.isRegular(i+1)) {
178                 BusinessDayConvention bdc = schedule_.businessDayConvention();
179                 refStart = schedule_.calendar().adjust(end - schedule_.tenor(), bdc);
180             }
181             if (i==n-1 && schedule_.hasIsRegular() && !schedule_.isRegular(i+1)) {
182                 BusinessDayConvention bdc = schedule_.businessDayConvention();
183                 refEnd = schedule_.calendar().adjust(start + schedule_.tenor(), bdc);
184             }
185             if (detail::get(gearings_, i, 1.0) == 0.0) { // fixed coupon
186                 leg.push_back(ext::shared_ptr<CashFlow>(new
187                             FixedRateCoupon(paymentDate,
188                             detail::get(notionals_, i, 1.0),
189                             detail::effectiveFixedRate(spreads_,caps_,
190                                     floors_,i),
191                                     paymentDayCounter_,
192                                     start, end, refStart, refEnd)));
193             } else { // yoy inflation coupon
194                 if (detail::noOption(caps_, floors_, i)) { // just swaplet
195                     ext::shared_ptr<YoYInflationCoupon> coup(new
196                             YoYInflationCoupon(
197                             paymentDate,
198                             detail::get(notionals_, i, 1.0),
199                             start, end,
200                             detail::get(fixingDays_, i, 0),
201                             index_,
202                             observationLag_,
203                             paymentDayCounter_,
204                             detail::get(gearings_, i, 1.0),
205                             detail::get(spreads_, i, 0.0),
206                             refStart, refEnd));
207 
208                     // in this case you can set a pricer
209                     // straight away because it only provides computation - not data
210                     ext::shared_ptr<YoYInflationCouponPricer> pricer =
211                         ext::make_shared<YoYInflationCouponPricer>(Handle<YoYOptionletVolatilitySurface>(),
212                                                                    Handle<YieldTermStructure>());
213                     coup->setPricer(pricer);
214                     leg.push_back(ext::dynamic_pointer_cast<CashFlow>(coup));
215 
216 
217 
218                 } else {    // cap/floorlet
219                     leg.push_back(ext::shared_ptr<CashFlow>(new
220                             CappedFlooredYoYInflationCoupon(
221                             paymentDate,
222                             detail::get(notionals_, i, 1.0),
223                             start, end,
224                             detail::get(fixingDays_, i, 0),
225                             index_,
226                             observationLag_,
227                             paymentDayCounter_,
228                             detail::get(gearings_, i, 1.0),
229                             detail::get(spreads_, i, 0.0),
230                             detail::get(caps_,   i, Null<Rate>()),
231                             detail::get(floors_, i, Null<Rate>()),
232                             refStart, refEnd)));
233                 }
234             }
235         }
236 
237         return leg;
238     }
239 
240 
241 
242 
243 
244 
245 }
246 
247