103 {
104
106 "BlackAverageONIndexedCouponPricer::optionletRateLocal() does not support effective volatility input.");
107
108
109
110
111
112
113
114
115
116
117
118
119
121
122
123
124
125
126 ext::shared_ptr<OvernightIndex> index = ext::dynamic_pointer_cast<OvernightIndex>(
coupon_->index());
127
130
131 Size n = dt.size();
132 Size i = 0;
135 << ") must be less than number of fixings in period (" << n << ")");
137
138 Real compoundFactor = 1.0, compoundFactorRaw = 1.0;
139
140
141 Date today = Settings::instance().evaluationDate();
142 while (i < n && fixingDates[std::min(i, nCutoff)] < today) {
143
144 Rate pastFixing = index->pastFixing(fixingDates[std::min(i, nCutoff)]);
145 QL_REQUIRE(pastFixing != Null<Real>(),
146 "Missing " << index->name() << " fixing for " << fixingDates[std::min(i, nCutoff)]);
148 pastFixing +=
coupon_->spread();
149 }
150 compoundFactor *= 1.0 + cappedFlooredRate(pastFixing, optionType, absStrike) * dt[i];
151 compoundFactorRaw *= 1.0 + pastFixing * dt[i];
152 ++i;
153 }
154
155
156 if (i < n && fixingDates[std::min(i, nCutoff)] == today) {
157
158 try {
159 Rate pastFixing = index->pastFixing(today);
160 if (pastFixing != Null<Real>()) {
162 pastFixing +=
coupon_->spread();
163 }
164 compoundFactor *= 1.0 + cappedFlooredRate(pastFixing, optionType, absStrike) * dt[i];
165 compoundFactorRaw *= 1.0 + pastFixing * dt[i];
166 ++i;
167 } else {
168 ;
169 }
170 } catch (Error&) {
171 ;
172 }
173 }
174
175
177 if (i < n) {
178 Handle<YieldTermStructure> curve = index->forwardingTermStructure();
179 QL_REQUIRE(!curve.empty(), "null term structure set to this instance of " << index->name());
180
181 DiscountFactor startDiscount = curve->discount(dates[i]);
182 DiscountFactor endDiscount = curve->discount(dates[std::max(nCutoff, i)]);
183
184
185 if (nCutoff < n) {
186
187 DiscountFactor discountCutoffDate = curve->discount(dates[nCutoff] + 1) / curve->discount(dates[nCutoff]);
188
189 endDiscount *= std::pow(discountCutoffDate, dates[n] - dates[nCutoff]);
190 }
191
192
193 Real tau =
coupon_->dayCounter().yearFraction(dates[i], dates.back());
194 Real averageRate = -std::log(endDiscount / startDiscount) / tau;
195
196
197
198 Time midPoint =
200 2.0;
201 Real stdDev =
capletVolatility()->volatility(midPoint, effStrike) * std::sqrt(midPoint);
204 Rate cfValue = shiftedLn ? blackFormula(optionType, effStrike, averageRate, stdDev, 1.0, shift)
205 : bachelierBlackFormula(optionType, effStrike, averageRate, stdDev, 1.0);
206 Real effectiveTime =
capletVolatility()->timeFromReference(fixingDates.back());
207 if (optionType == Option::Type::Call)
209 else
211
212
215 }
216
217
218 Real averageRateRaw = averageRate;
219 averageRate += optionType == Option::Call ? (-cfValue) : cfValue;
220
221
222
223 Real dailyTau =
224 coupon_->
underlying()->dayCounter().yearFraction(dates[i], dates.back()) / (dates.back() - dates[i]);
225
226 compoundFactor *= std::pow(1.0 + dailyTau * averageRate, static_cast<int>(dates.back() - dates[i]));
227 compoundFactorRaw *= std::pow(1.0 + dailyTau * averageRateRaw, static_cast<int>(dates.back() - dates[i]));
228 }
229
232 :
coupon_->dayCounter().yearFraction(dates.front(), dates.back());
233 Rate rate = (compoundFactor - 1.0) / tau;
234 Rate rawRate = (compoundFactorRaw - 1.0) / tau;
235
238
242 }
243
244
245
246
247 return (optionType == Option::Call ? -1.0 : 1.0) * (rate - rawRate);
248}