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#include <ql/cashflows/cashflows.hpp>
21#include <ql/instruments/inflationcapfloor.hpp>
22#include <ql/math/solvers1d/newtonsafe.hpp>
23#include <ql/quotes/simplequote.hpp>
24#include <ql/utilities/dataformatters.hpp>
25#include <utility>
26
27namespace QuantLib {
28
29
30 std::ostream& operator<<(std::ostream& out,
31 YoYInflationCapFloor::Type t) {
32 switch (t) {
33 case YoYInflationCapFloor::Cap:
34 return out << "YoYInflationCap";
35 case YoYInflationCapFloor::Floor:
36 return out << "YoYInflationFloor";
37 case YoYInflationCapFloor::Collar:
38 return out << "YoYInflationCollar";
39 default:
40 QL_FAIL("unknown YoYInflationCapFloor::Type (" << Integer(t) << ")");
41 }
42 }
43
44 YoYInflationCapFloor::YoYInflationCapFloor(YoYInflationCapFloor::Type type,
45 Leg yoyLeg,
46 std::vector<Rate> capRates,
47 std::vector<Rate> floorRates)
48 : type_(type), yoyLeg_(std::move(yoyLeg)), capRates_(std::move(capRates)),
49 floorRates_(std::move(floorRates)) {
50 if (type_ == Cap || type_ == Collar) {
51 QL_REQUIRE(!capRates_.empty(), "no cap rates given");
52 capRates_.reserve(n: yoyLeg_.size());
53 while (capRates_.size() < yoyLeg_.size())
54 capRates_.push_back(x: capRates_.back());
55 }
56 if (type_ == Floor || type_ == Collar) {
57 QL_REQUIRE(!floorRates_.empty(), "no floor rates given");
58 floorRates_.reserve(n: yoyLeg_.size());
59 while (floorRates_.size() < yoyLeg_.size())
60 floorRates_.push_back(x: floorRates_.back());
61 }
62 Leg::const_iterator i;
63 for (i = yoyLeg_.begin(); i != yoyLeg_.end(); ++i)
64 registerWith(h: *i);
65
66 registerWith(h: Settings::instance().evaluationDate());
67 }
68
69 YoYInflationCapFloor::YoYInflationCapFloor(YoYInflationCapFloor::Type type,
70 Leg yoyLeg,
71 const std::vector<Rate>& strikes)
72 : type_(type), yoyLeg_(std::move(yoyLeg)) {
73 QL_REQUIRE(!strikes.empty(), "no strikes given");
74 if (type_ == Cap) {
75 capRates_ = strikes;
76 capRates_.reserve(n: yoyLeg_.size());
77 while (capRates_.size() < yoyLeg_.size())
78 capRates_.push_back(x: capRates_.back());
79 } else if (type_ == Floor) {
80 floorRates_ = strikes;
81 floorRates_.reserve(n: yoyLeg_.size());
82 while (floorRates_.size() < yoyLeg_.size())
83 floorRates_.push_back(x: floorRates_.back());
84 } else
85 QL_FAIL("only Cap/Floor types allowed in this constructor");
86
87 Leg::const_iterator i;
88 for (i = yoyLeg_.begin(); i != yoyLeg_.end(); ++i)
89 registerWith(h: *i);
90
91 registerWith(h: Settings::instance().evaluationDate());
92 }
93
94 bool YoYInflationCapFloor::isExpired() const {
95 for (Size i=yoyLeg_.size(); i>0; --i)
96 if (!yoyLeg_[i-1]->hasOccurred())
97 return false;
98 return true;
99 }
100
101 Date YoYInflationCapFloor::startDate() const {
102 return CashFlows::startDate(leg: yoyLeg_);
103 }
104
105 Date YoYInflationCapFloor::maturityDate() const {
106 return CashFlows::maturityDate(leg: yoyLeg_);
107 }
108
109 ext::shared_ptr<YoYInflationCoupon>
110 YoYInflationCapFloor::lastYoYInflationCoupon() const {
111 ext::shared_ptr<CashFlow> lastCF(yoyLeg_.back());
112 ext::shared_ptr<YoYInflationCoupon> lastYoYInflationCoupon =
113 ext::dynamic_pointer_cast<YoYInflationCoupon>(r: lastCF);
114 return lastYoYInflationCoupon;
115 }
116
117 ext::shared_ptr<YoYInflationCapFloor> YoYInflationCapFloor::optionlet(const Size i) const {
118 QL_REQUIRE(i < yoyLeg().size(),
119 io::ordinal(i+1) << " optionlet does not exist, only " <<
120 yoyLeg().size());
121 Leg cf(1, yoyLeg()[i]);
122
123 std::vector<Rate> cap, floor;
124 if (type() == Cap || type() == Collar)
125 cap.push_back(x: capRates()[i]);
126 if (type() == Floor || type() == Collar)
127 floor.push_back(x: floorRates()[i]);
128
129 return ext::make_shared<YoYInflationCapFloor>(args: type(),
130 args&: cf, args&: cap, args&: floor);
131 }
132
133 void YoYInflationCapFloor::setupArguments(PricingEngine::arguments* args) const {
134 auto* arguments = dynamic_cast<YoYInflationCapFloor::arguments*>(args);
135 QL_REQUIRE(arguments != nullptr, "wrong argument type");
136
137 Size n = yoyLeg_.size();
138
139 arguments->startDates.resize(new_size: n);
140 arguments->fixingDates.resize(new_size: n);
141 arguments->payDates.resize(new_size: n);
142 arguments->accrualTimes.resize(new_size: n);
143 arguments->nominals.resize(new_size: n);
144 arguments->gearings.resize(new_size: n);
145 arguments->capRates.resize(new_size: n);
146 arguments->floorRates.resize(new_size: n);
147 arguments->spreads.resize(new_size: n);
148
149 arguments->type = type_;
150
151 for (Size i=0; i<n; ++i) {
152 ext::shared_ptr<YoYInflationCoupon> coupon =
153 ext::dynamic_pointer_cast<YoYInflationCoupon>(
154 r: yoyLeg_[i]);
155 QL_REQUIRE(coupon, "non-YoYInflationCoupon given");
156 arguments->startDates[i] = coupon->accrualStartDate();
157 arguments->fixingDates[i] = coupon->fixingDate();
158 arguments->payDates[i] = coupon->date();
159
160 // this is passed explicitly for precision
161 arguments->accrualTimes[i] = coupon->accrualPeriod();
162
163 arguments->nominals[i] = coupon->nominal();
164 Spread spread = coupon->spread();
165 Real gearing = coupon->gearing();
166 arguments->gearings[i] = gearing;
167 arguments->spreads[i] = spread;
168
169 if (type_ == Cap || type_ == Collar)
170 arguments->capRates[i] = (capRates_[i]-spread)/gearing;
171 else
172 arguments->capRates[i] = Null<Rate>();
173
174 if (type_ == Floor || type_ == Collar)
175 arguments->floorRates[i] = (floorRates_[i]-spread)/gearing;
176 else
177 arguments->floorRates[i] = Null<Rate>();
178 }
179 }
180
181 void YoYInflationCapFloor::arguments::validate() const {
182 QL_REQUIRE(payDates.size() == startDates.size(),
183 "number of start dates (" << startDates.size()
184 << ") different from that of pay dates ("
185 << payDates.size() << ")");
186 QL_REQUIRE(accrualTimes.size() == startDates.size(),
187 "number of start dates (" << startDates.size()
188 << ") different from that of accrual times ("
189 << accrualTimes.size() << ")");
190 QL_REQUIRE(type == YoYInflationCapFloor::Floor ||
191 capRates.size() == startDates.size(),
192 "number of start dates (" << startDates.size()
193 << ") different from that of cap rates ("
194 << capRates.size() << ")");
195 QL_REQUIRE(type == YoYInflationCapFloor::Cap ||
196 floorRates.size() == startDates.size(),
197 "number of start dates (" << startDates.size()
198 << ") different from that of floor rates ("
199 << floorRates.size() << ")");
200 QL_REQUIRE(gearings.size() == startDates.size(),
201 "number of start dates (" << startDates.size()
202 << ") different from that of gearings ("
203 << gearings.size() << ")");
204 QL_REQUIRE(spreads.size() == startDates.size(),
205 "number of start dates (" << startDates.size()
206 << ") different from that of spreads ("
207 << spreads.size() << ")");
208 QL_REQUIRE(nominals.size() == startDates.size(),
209 "number of start dates (" << startDates.size()
210 << ") different from that of nominals ("
211 << nominals.size() << ")");
212 }
213
214 Rate YoYInflationCapFloor::atmRate(const YieldTermStructure& discountCurve) const {
215 return CashFlows::atmRate(leg: yoyLeg_, discountCurve,
216 includeSettlementDateFlows: false, settlementDate: discountCurve.referenceDate());
217 }
218
219
220}
221

source code of quantlib/ql/instruments/inflationcapfloor.cpp

Morty Proxy This is a proxified and sanitized view of the page, visit original site.