1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*
4  Copyright (C) 2008 Toyin Akin
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 #include <ql/experimental/coupons/subperiodcoupons.hpp>
21 #include <ql/cashflows/cashflowvectors.hpp>
22 #include <ql/time/schedule.hpp>
23 #include <ql/indexes/iborindex.hpp>
24 #include <ql/termstructures/yieldtermstructure.hpp>
25 #include <cmath>
26 
27 namespace QuantLib {
28 
SubPeriodsCoupon(const Date & paymentDate,Real nominal,const ext::shared_ptr<IborIndex> & index,const Date & startDate,const Date & endDate,Natural fixingDays,const DayCounter & dayCounter,Real gearing,Rate couponSpread,Rate rateSpread,const Date & refPeriodStart,const Date & refPeriodEnd)29     SubPeriodsCoupon::SubPeriodsCoupon(
30                                     const Date& paymentDate,
31                                     Real nominal,
32                                     const ext::shared_ptr<IborIndex>& index,
33                                     const Date& startDate,
34                                     const Date& endDate,
35                                     Natural fixingDays,
36                                     const DayCounter& dayCounter,
37                                     Real gearing,
38                                     Rate couponSpread,
39                                     Rate rateSpread,
40                                     const Date& refPeriodStart,
41                                     const Date& refPeriodEnd)
42     : FloatingRateCoupon(paymentDate, nominal, startDate, endDate,
43                          fixingDays, index, gearing, couponSpread,
44                          refPeriodStart, refPeriodEnd, dayCounter),
45       rateSpread_(rateSpread) {
46         const Handle<YieldTermStructure>& rateCurve =
47             index->forwardingTermStructure();
48         const Date& referenceDate = rateCurve->referenceDate();
49 
50         observationsSchedule_ = ext::make_shared<Schedule>(startDate, endDate,
51                      index->tenor(),
52                      NullCalendar(),
53                      Unadjusted,
54                      Unadjusted,
55                      DateGeneration::Forward,
56                      false);
57 
58         observationDates_ = observationsSchedule_->dates();
59         observationDates_.pop_back();                       //remove end date
60         observations_ = observationDates_.size();
61 
62         startTime_ = dayCounter.yearFraction(referenceDate, startDate);
63         endTime_ = dayCounter.yearFraction(referenceDate, endDate);
64 
65         for (Size i=0; i<observations_; ++i) {
66             observationTimes_.push_back(
67                 dayCounter.yearFraction(referenceDate, observationDates_[i]));
68         }
69      }
70 
accept(AcyclicVisitor & v)71     void SubPeriodsCoupon::accept(AcyclicVisitor& v) {
72         Visitor<SubPeriodsCoupon>* v1 =
73             dynamic_cast<Visitor<SubPeriodsCoupon>*>(&v);
74         if (v1 != 0)
75             v1->visit(*this);
76         else
77             FloatingRateCoupon::accept(v);
78     }
79 
80 
initialize(const FloatingRateCoupon & coupon)81     void SubPeriodsPricer::initialize(const FloatingRateCoupon& coupon) {
82         coupon_ =  dynamic_cast<const SubPeriodsCoupon*>(&coupon);
83         QL_REQUIRE(coupon_, "sub-periods coupon required");
84         gearing_ = coupon_->gearing();
85         spread_ = coupon_->spread();
86 
87         Date paymentDate = coupon_->date();
88 
89         ext::shared_ptr<IborIndex> index =
90             ext::dynamic_pointer_cast<IborIndex>(coupon_->index());
91         const Handle<YieldTermStructure>& rateCurve =
92             index->forwardingTermStructure();
93         discount_ = rateCurve->discount(paymentDate);
94         accrualFactor_ = coupon_->accrualPeriod();
95         spreadLegValue_ = spread_ * accrualFactor_* discount_;
96 
97         startTime_ = coupon_->startTime();
98         endTime_ = coupon_->endTime();
99         observationTimes_ = coupon_->observationTimes();
100         observations_ = coupon_->observations();
101 
102         const std::vector<Date>& observationDates =
103             coupon_->observationsSchedule()->dates();
104 
105         QL_REQUIRE(observationDates.size()==observations_+2,
106                    "incompatible size of initialValues vector");
107 
108         initialValues_ = std::vector<Real>(observationDates.size(),0.);
109 
110         observationCvg_ = std::vector<Real>(observationDates.size(),0.);
111 
112         observationIndexStartDates_ =
113             std::vector<Date>(observationDates.size());
114         observationIndexEndDates_ =
115             std::vector<Date>(observationDates.size());
116 
117         Calendar calendar = index->fixingCalendar();
118 
119         for(Size i=0; i<observationDates.size(); i++) {
120             Date fixingDate = calendar.advance(
121                                  observationDates[i],
122                                  -static_cast<Integer>(coupon_->fixingDays()),
123                                  Days);
124 
125             initialValues_[i] =
126                 index->fixing(fixingDate) + coupon_->rateSpread();
127 
128             Date fixingValueDate = index->valueDate(fixingDate);
129             Date endValueDate = index->maturityDate(fixingValueDate);
130 
131             observationIndexStartDates_[i] = fixingValueDate;
132             observationIndexEndDates_[i] = endValueDate;
133 
134             observationCvg_[i] =
135                 index->dayCounter().yearFraction(fixingValueDate, endValueDate);
136         }
137     }
138 
swapletRate() const139     Real SubPeriodsPricer::swapletRate() const {
140         return swapletPrice()/(accrualFactor_*discount_);
141     }
142 
capletPrice(Rate) const143     Real SubPeriodsPricer::capletPrice(Rate) const {
144         QL_FAIL("SubPeriodsPricer::capletPrice not implemented");
145     }
146 
capletRate(Rate) const147     Rate SubPeriodsPricer::capletRate(Rate) const {
148         QL_FAIL("SubPeriodsPricer::capletRate not implemented");
149     }
150 
floorletPrice(Rate) const151     Real SubPeriodsPricer::floorletPrice(Rate) const {
152         QL_FAIL("SubPeriodsPricer::floorletPrice not implemented");
153     }
154 
floorletRate(Rate) const155     Rate SubPeriodsPricer::floorletRate(Rate) const {
156         QL_FAIL("SubPeriodsPricer::floorletRate not implemented");
157     }
158 
swapletPrice() const159     Real AveragingRatePricer::swapletPrice() const {
160         // past or future fixing is managed in InterestRateIndex::fixing()
161 
162         Size nCount = initialValues_.size();
163         Real dAvgRate = 0.0, dTotalCvg = 0.0, dTotalPayment = 0.0;
164         for (Size i=0; i<nCount; i++) {
165             dTotalPayment += initialValues_[i] * observationCvg_[i];
166             dTotalCvg += observationCvg_[i];
167         }
168 
169         dAvgRate =  dTotalPayment/dTotalCvg;
170 
171         Real swapletPrice = dAvgRate*coupon_->accrualPeriod()*discount_;
172         return gearing_ * swapletPrice + spreadLegValue_;
173     }
174 
swapletPrice() const175     Real CompoundingRatePricer::swapletPrice() const {
176         // past or future fixing is managed in InterestRateIndex::fixing()
177 
178         Real dNotional = 1.0;
179 
180         Size nCount = initialValues_.size();
181         Real dCompRate = 0.0, dTotalCvg = 0.0, dTotalPayment = 0.0;
182         for (Size i=0; i<nCount; i++) {
183             dTotalPayment = initialValues_[i] * observationCvg_[i]*dNotional;
184             dNotional += dTotalPayment;
185             dTotalCvg += observationCvg_[i];
186         }
187 
188         dCompRate = (dNotional - 1.0)/dTotalCvg;
189 
190         Real swapletPrice = dCompRate*coupon_->accrualPeriod()*discount_;
191         return gearing_ * swapletPrice + spreadLegValue_;
192     }
193 
194 }
195 
196