QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
rangeaccrual.cpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2006, 2007 Giorgio Facchinetti
5 Copyright (C) 2006, 2007 Mario Pucci
6
7 This file is part of QuantLib, a free-software/open-source library
8 for financial quantitative analysts and developers - http://quantlib.org/
9
10 QuantLib is free software: you can redistribute it and/or modify it
11 under the terms of the QuantLib license. You should have received a
12 copy of the license along with this program; if not, please email
13 <quantlib-dev@lists.sf.net>. The license is also available online at
14 <http://quantlib.org/license.shtml>.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the license for more details.
19*/
20
21
22#include <ql/cashflows/cashflowvectors.hpp>
23#include <ql/cashflows/rangeaccrual.hpp>
24#include <ql/indexes/iborindex.hpp>
25#include <ql/math/distributions/normaldistribution.hpp>
26#include <ql/pricingengines/blackformula.hpp>
27#include <ql/termstructures/yieldtermstructure.hpp>
28#include <ql/time/schedule.hpp>
29#include <cmath>
30#include <utility>
31
32namespace QuantLib {
33
34 //===========================================================================//
35 // RangeAccrualFloatersCoupon //
36 //===========================================================================//
37
39 const Date& paymentDate,
40 Real nominal,
41 const ext::shared_ptr<IborIndex>& index,
42 const Date& startDate, // S
43 const Date& endDate, // T
44 Natural fixingDays,
45 const DayCounter& dayCounter,
46 Real gearing,
47 Rate spread,
48 const Date& refPeriodStart,
49 const Date& refPeriodEnd,
50 ext::shared_ptr<Schedule> observationsSchedule,
51 Real lowerTrigger, // l
52 Real upperTrigger // u
53 )
54 : FloatingRateCoupon(paymentDate,
55 nominal,
56 startDate,
57 endDate,
58 fixingDays,
59 index,
60 gearing,
61 spread,
62 refPeriodStart,
63 refPeriodEnd,
64 dayCounter),
65 observationsSchedule_(std::move(observationsSchedule)), lowerTrigger_(lowerTrigger),
66 upperTrigger_(upperTrigger) {
67
68 QL_REQUIRE(lowerTrigger_<upperTrigger,
69 "lowerTrigger_>=upperTrigger");
70 QL_REQUIRE(observationsSchedule_->startDate()==startDate,
71 "incompatible start date");
72 QL_REQUIRE(observationsSchedule_->endDate()==endDate,
73 "incompatible end date");
74
76 observationDates_.pop_back(); //remove end date
77 observationDates_.erase(observationDates_.begin()); //remove start date
79
80 const Handle<YieldTermStructure>& rateCurve =
81 index->forwardingTermStructure();
82 Date referenceDate = rateCurve->referenceDate();
83
84 startTime_ = dayCounter.yearFraction(referenceDate, startDate);
85 endTime_ = dayCounter.yearFraction(referenceDate, endDate);
86 for(Size i=0;i<observationsNo_;i++) {
87 observationTimes_.push_back(
88 dayCounter.yearFraction(referenceDate, observationDates_[i]));
89 }
90 }
91
93 auto* v1 = dynamic_cast<Visitor<RangeAccrualFloatersCoupon>*>(&v);
94 if (v1 != nullptr)
95 v1->visit(*this);
96 else
98 }
99
101 const Handle<YieldTermStructure>& discountingCurve) const {
103 nominal() * discountingCurve->discount(date());
104 }
105
106
107 //=======================================================================//
108 // RangeAccrualPricer //
109 //=======================================================================//
110
112 coupon_ = dynamic_cast<const RangeAccrualFloatersCoupon*>(&coupon);
113 QL_REQUIRE(coupon_, "range-accrual coupon required");
116
117 Date paymentDate = coupon_->date();
118
119 ext::shared_ptr<IborIndex> index =
120 ext::dynamic_pointer_cast<IborIndex>(coupon_->index());
121 const Handle<YieldTermStructure>& rateCurve =
122 index->forwardingTermStructure();
123 discount_ = rateCurve->discount(paymentDate);
126
133
134 const std::vector<Date> &observationDates =
135 coupon_->observationsSchedule()->dates();
136 QL_REQUIRE(observationDates.size()==observationsNo_+2,
137 "incompatible size of initialValues vector");
138 initialValues_= std::vector<Real>(observationDates.size(),0.);
139
140 Calendar calendar = index->fixingCalendar();
141 for(Size i=0; i<observationDates.size(); i++) {
142 initialValues_[i]=index->fixing(
143 calendar.advance(observationDates[i],
144 -static_cast<Integer>(coupon_->fixingDays()),
145 Days));
146 }
147
148 }
149
152 }
153
155 QL_FAIL("RangeAccrualPricer::capletPrice not implemented");
156 }
157
159 QL_FAIL("RangeAccrualPricer::capletRate not implemented");
160 }
161
163 QL_FAIL("RangeAccrualPricer::floorletPrice not implemented");
164 }
165
167 QL_FAIL("RangeAccrualPricer::floorletRate not implemented");
168 }
169
170 //===========================================================================//
171 // RangeAccrualPricerByBgm //
172 //===========================================================================//
174 ext::shared_ptr<SmileSection> smilesOnExpiry,
175 ext::shared_ptr<SmileSection> smilesOnPayment,
176 bool withSmile,
177 bool byCallSpread)
178 : correlation_(correlation), withSmile_(withSmile), byCallSpread_(byCallSpread),
179 smilesOnExpiry_(std::move(smilesOnExpiry)), smilesOnPayment_(std::move(smilesOnPayment)) {}
181
182 Real result = 0.;
183 const Real deflator = discount_*initialValues_[0];
184 for(Size i=0;i<observationsNo_;i++){
186 observationTimes_[i], deflator);
187 result += digitalFloater;
188 }
190 }
191
193 Real lambdaS,
194 Real lambdaT,
195 Real correlation) const{
196 std::vector<Real> result;
197
198 const Real p = (U-startTime_)/accrualFactor_;
199 const Real q = (endTime_-U)/accrualFactor_;
200 const Real L0T = initialValues_.back();
201
202 const Real driftBeforeFixing =
203 p*accrualFactor_*L0T/(1.+L0T*accrualFactor_)*(p*lambdaT*lambdaT + q*lambdaS*lambdaT*correlation) +
204 q*lambdaS*lambdaS + p*lambdaS*lambdaT*correlation
205 -0.5*lambda(U,lambdaS,lambdaT)*lambda(U,lambdaS,lambdaT);
206 const Real driftAfterFixing = (p*accrualFactor_*L0T/(1.+L0T*accrualFactor_)-0.5)*lambdaT*lambdaT;
207
208 result.push_back(driftBeforeFixing);
209 result.push_back(driftAfterFixing);
210
211 return result;
212 }
213
215 Real lambdaS,
216 Real lambdaT) const{
217 std::vector<Real> result;
218
219 const Real p = (U-startTime_)/accrualFactor_;
220 const Real q = (endTime_-U)/accrualFactor_;
221
222 const Real lambdaBeforeFixing = q*lambdaS + p*lambdaT;
223 const Real lambdaAfterFixing = lambdaT;
224
225 result.push_back(lambdaBeforeFixing);
226 result.push_back(lambdaAfterFixing);
227
228 return result;
229 }
231 Real lambdaS,
232 Real lambdaT,
233 Real correlation) const{
234 Real result;
235
236 const Real p = (U-startTime_)/accrualFactor_;
237 const Real q = (endTime_-U)/accrualFactor_;
238 const Real L0T = initialValues_.back();
239
240 const Real driftBeforeFixing =
241 p*accrualFactor_*L0T/(1.+L0T*accrualFactor_)*(p*lambdaT*lambdaT + q*lambdaS*lambdaT*correlation) +
242 q*lambdaS*lambdaS + p*lambdaS*lambdaT*correlation;
243 const Real driftAfterFixing = (p*accrualFactor_*L0T/(1.+L0T*accrualFactor_)-0.5)*lambdaT*lambdaT;
244
245 if(startTime_ > 0){result = driftBeforeFixing;}
246 else {result = driftAfterFixing;}
247
248 return result;
249 }
250
252 Real lambdaS,
253 Real lambdaT) const{
254 Real result;
255
256 const Real p = (U-startTime_)/accrualFactor_;
257 const Real q = (endTime_-U)/accrualFactor_;
258
259 if(startTime_ > 0){result = q*lambdaS + p*lambdaT;}
260 else {result = lambdaT;}
261
262 return result;
263 }
264
265
267 Real lambdaS,
268 Real lambdaT,
269 Real correlation) const{
270 Real result;
271
272 const Real p = (U-startTime_)/accrualFactor_;
273 const Real q = (endTime_-U)/accrualFactor_;
274 const Real L0T = initialValues_.back();
275
276 const Real driftBeforeFixing =
277 p*accrualFactor_*L0T/(1.+L0T*accrualFactor_)*(q*lambdaT*correlation) +
278 2*q*lambdaS + p*lambdaT*correlation;
279 const Real driftAfterFixing = 0.;
280
281 if(startTime_ > 0){result = driftBeforeFixing;}
282 else {result = driftAfterFixing;}
283
284 return result;
285 }
286
288
289 if (startTime_>0) {
291 return q;
292 } else
293 return 0.0;
294
295 }
296
298 Real lambdaS,
299 Real lambdaT,
300 Real correlation) const{
301 Real result;
302
303 const Real p = (U-startTime_)/accrualFactor_;
304 const Real q = (endTime_-U)/accrualFactor_;
305 const Real L0T = initialValues_.back();
306
307 const Real driftBeforeFixing =
308 p*accrualFactor_*L0T/(1.+L0T*accrualFactor_)*(2*p*lambdaT + q*lambdaS*correlation) +
309 + p*lambdaS*correlation;
310 const Real driftAfterFixing = (p*accrualFactor_*L0T/(1.+L0T*accrualFactor_)-0.5)*2*lambdaT;
311
312 if(startTime_ > 0){result = driftBeforeFixing;}
313 else {result = driftAfterFixing;}
314
315 return result;
316 }
317
319
320 if (startTime_>0) {
322 return p;
323 } else
324 return 0.0;
325
326 }
327
329 Real upperTrigger,
330 Real initialValue,
331 Real expiry,
332 Real deflator) const{
333 const Real lowerPrice = digitalPrice(lowerTrigger, initialValue, expiry, deflator);
334 const Real upperPrice = digitalPrice(upperTrigger, initialValue, expiry, deflator);
335 const Real result = lowerPrice - upperPrice;
336 QL_REQUIRE(result >=0.,
337 "RangeAccrualPricerByBgm::digitalRangePrice:\n digitalPrice("<<upperTrigger<<
338 "): "<<upperPrice<<" > digitalPrice("<<lowerTrigger<<"): "<<lowerPrice);
339 return result;
340
341 }
343 Real initialValue,
344 Real expiry,
345 Real deflator) const {
346 Real result = deflator;
347 if(strike>eps_/2){
348 if(withSmile_)
349 result = digitalPriceWithSmile(strike, initialValue, expiry, deflator);
350 else
351 result = digitalPriceWithoutSmile(strike, initialValue, expiry, deflator);
352 }
353 return result;
354 }
355
357 Real initialValue,
358 Real expiry,
359 Real deflator) const {
360
361 Real lambdaS = smilesOnExpiry_->volatility(strike);
362 Real lambdaT = smilesOnPayment_->volatility(strike);
363
364 std::vector<Real> lambdaU = lambdasOverPeriod(expiry, lambdaS, lambdaT);
365 const Real variance =
366 startTime_*lambdaU[0]*lambdaU[0]+(expiry-startTime_)*lambdaU[1]*lambdaU[1];
367
368 Real lambdaSATM = smilesOnExpiry_->volatility(initialValue);
369 Real lambdaTATM = smilesOnPayment_->volatility(initialValue);
370 //drift of Lognormal process (of Libor) "a_U()" nel paper
371 std::vector<Real> muU = driftsOverPeriod(expiry, lambdaSATM, lambdaTATM, correlation_);
372 const Real adjustment = (startTime_*muU[0]+(expiry-startTime_)*muU[1]);
373
374
375 Real d2 = (std::log(initialValue/strike) + adjustment - 0.5*variance)/std::sqrt(variance);
376
378 const Real result = deflator*phi(d2);
379
380 QL_REQUIRE(result > 0.,
381 "RangeAccrualPricerByBgm::digitalPriceWithoutSmile: result< 0. Result:"<<result);
382 QL_REQUIRE(result/deflator <= 1.,
383 "RangeAccrualPricerByBgm::digitalPriceWithoutSmile: result/deflator > 1. Ratio: "
384 << result/deflator << " result: " << result<< " deflator: " << deflator);
385
386 return result;
387 }
388
390 Real initialValue,
391 Real expiry,
392 Real deflator) const {
393 Real result;
394 if (byCallSpread_) {
395
396 // Previous strike
397 const Real previousStrike = strike - eps_/2;
398 Real lambdaS = smilesOnExpiry_->volatility(previousStrike);
399 Real lambdaT = smilesOnPayment_->volatility(previousStrike);
400
401 //drift of Lognormal process (of Libor) "a_U()" nel paper
402 std::vector<Real> lambdaU = lambdasOverPeriod(expiry, lambdaS, lambdaT);
403 const Real previousVariance = std::max(startTime_, 0.)*lambdaU[0]*lambdaU[0]+
404 std::min(expiry-startTime_, expiry)*lambdaU[1]*lambdaU[1];
405
406 Real lambdaSATM = smilesOnExpiry_->volatility(initialValue);
407 Real lambdaTATM = smilesOnPayment_->volatility(initialValue);
408 std::vector<Real> muU = driftsOverPeriod(expiry, lambdaSATM, lambdaTATM, correlation_);
409 const Real previousAdjustment = std::exp(std::max(startTime_, 0.)*muU[0] +
410 std::min(expiry-startTime_, expiry)*muU[1]);
411 const Real previousForward = initialValue * previousAdjustment ;
412
413 // Next strike
414 const Real nextStrike = strike + eps_/2;
415 lambdaS = smilesOnExpiry_->volatility(nextStrike);
416 lambdaT = smilesOnPayment_->volatility(nextStrike);
417
418 lambdaU = lambdasOverPeriod(expiry, lambdaS, lambdaT);
419 const Real nextVariance = std::max(startTime_, 0.)*lambdaU[0]*lambdaU[0]+
420 std::min(expiry-startTime_, expiry)*lambdaU[1]*lambdaU[1];
421 //drift of Lognormal process (of Libor) "a_U()" nel paper
422 muU = driftsOverPeriod(expiry, lambdaSATM, lambdaTATM, correlation_);
423 const Real nextAdjustment = std::exp(std::max(startTime_, 0.)*muU[0] +
424 std::min(expiry-startTime_, expiry)*muU[1]);
425 const Real nextForward = initialValue * nextAdjustment ;
426
427 result = callSpreadPrice(previousForward,nextForward,previousStrike, nextStrike,
428 deflator, previousVariance, nextVariance);
429
430 }
431 else{
432 result = digitalPriceWithoutSmile(strike, initialValue, expiry, deflator)+
433 smileCorrection(strike, initialValue, expiry, deflator);
434 }
435
436 QL_REQUIRE(result > -std::pow(eps_,.5),
437 "RangeAccrualPricerByBgm::digitalPriceWithSmile: result< 0 Result:"<<result);
438 QL_REQUIRE(result/deflator <= 1.0 + std::pow(eps_,.2),
439 "RangeAccrualPricerByBgm::digitalPriceWithSmile: result/deflator > 1. Ratio: "
440 << result/deflator << " result: " << result<< " deflator: " << deflator);
441
442 return result;
443 }
444
446 Real forward,
447 Real expiry,
448 Real deflator) const {
449
450 const Real previousStrike = strike - eps_/2;
451 const Real nextStrike = strike + eps_/2;
452
453 const Real derSmileS = (smilesOnExpiry_->volatility(nextStrike)-
454 smilesOnExpiry_->volatility(previousStrike))/eps_;
455 const Real derSmileT = (smilesOnPayment_->volatility(nextStrike)-
456 smilesOnPayment_->volatility(previousStrike))/eps_;
457
458 Real lambdaS = smilesOnExpiry_->volatility(strike);
459 Real lambdaT = smilesOnPayment_->volatility(strike);
460 //Real lambdaU = lambda(expiry, lambdaS, lambdaT);
461
462 Real derLambdaDerK = derLambdaDerLambdaS(expiry) * derSmileS +
463 derLambdaDerLambdaT(expiry) * derSmileT;
464 //Real derDriftDerK = derDriftDerLambdaS(expiry, lambdaS, lambdaT, correlation_)*derSmileS +
465 // derDriftDerLambdaT(expiry, lambdaS, lambdaT, correlation_)*derSmileT +
466 // lambdaU * derLambdaDerK;
467
468 Real lambdaSATM = smilesOnExpiry_->volatility(forward);
469 Real lambdaTATM = smilesOnPayment_->volatility(forward);
470 std::vector<Real> lambdasOverPeriodU = lambdasOverPeriod(expiry, lambdaS, lambdaT);
471 //drift of Lognormal process (of Libor) "a_U()" nel paper
472 std::vector<Real> muU = driftsOverPeriod(expiry, lambdaSATM, lambdaTATM, correlation_);
473
474 const Real variance = std::max(startTime_, 0.)*lambdasOverPeriodU[0]*lambdasOverPeriodU[0] +
475 std::min(expiry-startTime_, expiry)*lambdasOverPeriodU[1]*lambdasOverPeriodU[1];
476
477 const Real forwardAdjustment = std::exp(std::max(startTime_, 0.)*muU[0] +
478 std::min(expiry-startTime_, expiry)*muU[1]);
479 const Real forwardAdjusted = forward * forwardAdjustment;
480
481 const Real d1 = (std::log(forwardAdjusted/strike)+0.5*variance)/std::sqrt(variance);
482
483 const Real sqrtOfTimeToExpiry = (std::max(startTime_, 0.)*lambdasOverPeriodU[0] +
484 std::min(expiry-startTime_, expiry)*lambdasOverPeriodU[1])*
485 (1./std::sqrt(variance));
486
489 Real result = - forwardAdjusted*psi(d1)*sqrtOfTimeToExpiry*derLambdaDerK ;
490 // - forwardAdjusted*phi(d1)*expiry*derDriftDerK;
491
492 result *= deflator;
493
494 QL_REQUIRE(std::fabs(result/deflator) <= 1.0 + std::pow(eps_,.2),
495 "RangeAccrualPricerByBgm::smileCorrection: abs(result/deflator) > 1. Ratio: "
496 << result/deflator << " result: " << result<< " deflator: " << deflator);
497
498 return result;
499 }
500
502 Real previousForward,
503 Real nextForward,
504 Real previousStrike,
505 Real nextStrike,
506 Real deflator,
507 Real previousVariance,
508 Real nextVariance) const{
509 const Real nextCall =
510 blackFormula(Option::Call, nextStrike, nextForward, std::sqrt(nextVariance), deflator);
511 const Real previousCall =
512 blackFormula(Option::Call, previousStrike, previousForward, std::sqrt(previousVariance), deflator);
513
514 QL_ENSURE(nextCall <previousCall,"RangeAccrualPricerByBgm::callSpreadPrice: nextCall > previousCall"
515 "\n nextCall: strike :" << nextStrike << "; variance: " << nextVariance <<
516 " adjusted initial value " << nextForward <<
517 "\n previousCall: strike :" << previousStrike << "; variance: " << previousVariance <<
518 " adjusted initial value " << previousForward );
519
520 const Real result = (previousCall-nextCall)/(nextStrike-previousStrike);
521
522 return result;
523 }
524
525
526 RangeAccrualLeg::RangeAccrualLeg(Schedule schedule, ext::shared_ptr<IborIndex> index)
527 : schedule_(std::move(schedule)), index_(std::move(index)) {}
528
529 RangeAccrualLeg& RangeAccrualLeg::withNotionals(Real notional) {
530 notionals_ = std::vector<Real>(1,notional);
531 return *this;
532 }
533
534 RangeAccrualLeg& RangeAccrualLeg::withNotionals(
535 const std::vector<Real>& notionals) {
536 notionals_ = notionals;
537 return *this;
538 }
539
540 RangeAccrualLeg& RangeAccrualLeg::withPaymentDayCounter(
541 const DayCounter& dayCounter) {
542 paymentDayCounter_ = dayCounter;
543 return *this;
544 }
545
546 RangeAccrualLeg& RangeAccrualLeg::withPaymentAdjustment(
547 BusinessDayConvention convention) {
548 paymentAdjustment_ = convention;
549 return *this;
550 }
551
552 RangeAccrualLeg& RangeAccrualLeg::withFixingDays(Natural fixingDays) {
553 fixingDays_ = std::vector<Natural>(1,fixingDays);
554 return *this;
555 }
556
557 RangeAccrualLeg& RangeAccrualLeg::withFixingDays(
558 const std::vector<Natural>& fixingDays) {
559 fixingDays_ = fixingDays;
560 return *this;
561 }
562
563 RangeAccrualLeg& RangeAccrualLeg::withGearings(Real gearing) {
564 gearings_ = std::vector<Real>(1,gearing);
565 return *this;
566 }
567
568 RangeAccrualLeg& RangeAccrualLeg::withGearings(
569 const std::vector<Real>& gearings) {
570 gearings_ = gearings;
571 return *this;
572 }
573
574 RangeAccrualLeg& RangeAccrualLeg::withSpreads(Spread spread) {
575 spreads_ = std::vector<Spread>(1,spread);
576 return *this;
577 }
578
579 RangeAccrualLeg& RangeAccrualLeg::withSpreads(
580 const std::vector<Spread>& spreads) {
581 spreads_ = spreads;
582 return *this;
583 }
584
585 RangeAccrualLeg& RangeAccrualLeg::withLowerTriggers(Rate trigger) {
586 lowerTriggers_ = std::vector<Rate>(1,trigger);
587 return *this;
588 }
589
590 RangeAccrualLeg& RangeAccrualLeg::withLowerTriggers(
591 const std::vector<Rate>& triggers) {
592 lowerTriggers_ = triggers;
593 return *this;
594 }
595
596 RangeAccrualLeg& RangeAccrualLeg::withUpperTriggers(Rate trigger) {
597 upperTriggers_ = std::vector<Rate>(1,trigger);
598 return *this;
599 }
600
601 RangeAccrualLeg& RangeAccrualLeg::withUpperTriggers(
602 const std::vector<Rate>& triggers) {
603 upperTriggers_ = triggers;
604 return *this;
605 }
606
607 RangeAccrualLeg& RangeAccrualLeg::withObservationTenor(
608 const Period& tenor) {
609 observationTenor_ = tenor;
610 return *this;
611 }
612
613 RangeAccrualLeg& RangeAccrualLeg::withObservationConvention(
614 BusinessDayConvention convention) {
615 observationConvention_ = convention;
616 return *this;
617 }
618
619 RangeAccrualLeg::operator Leg() const {
620
621 QL_REQUIRE(!notionals_.empty(), "no notional given");
622
623 Size n = schedule_.size()-1;
624 QL_REQUIRE(notionals_.size() <= n,
625 "too many nominals (" << notionals_.size() <<
626 "), only " << n << " required");
627 QL_REQUIRE(fixingDays_.size() <= n,
628 "too many fixingDays (" << fixingDays_.size() <<
629 "), only " << n << " required");
630 QL_REQUIRE(gearings_.size()<=n,
631 "too many gearings (" << gearings_.size() <<
632 "), only " << n << " required");
633 QL_REQUIRE(spreads_.size()<=n,
634 "too many spreads (" << spreads_.size() <<
635 "), only " << n << " required");
636 QL_REQUIRE(lowerTriggers_.size()<=n,
637 "too many lowerTriggers (" << lowerTriggers_.size() <<
638 "), only " << n << " required");
639 QL_REQUIRE(upperTriggers_.size()<=n,
640 "too many upperTriggers (" << upperTriggers_.size() <<
641 "), only " << n << " required");
642
643 Leg leg(n);
644
645 // the following is not always correct
646 Calendar calendar = schedule_.calendar();
647
648 Date refStart, start, refEnd, end;
649 Date paymentDate;
650 std::vector<ext::shared_ptr<Schedule> > observationsSchedules;
651
652 for (Size i=0; i<n; ++i) {
653 refStart = start = schedule_.date(i);
654 refEnd = end = schedule_.date(i+1);
655 paymentDate = calendar.adjust(end, paymentAdjustment_);
656 if (i==0 && schedule_.hasIsRegular() && !schedule_.isRegular(i+1)) {
657 BusinessDayConvention bdc = schedule_.businessDayConvention();
658 refStart = calendar.adjust(end - schedule_.tenor(), bdc);
659 }
660 if (i==n-1 && schedule_.hasIsRegular() && !schedule_.isRegular(i+1)) {
661 BusinessDayConvention bdc = schedule_.businessDayConvention();
662 refEnd = calendar.adjust(start + schedule_.tenor(), bdc);
663 }
664 if (detail::get(gearings_, i, 1.0) == 0.0) { // fixed coupon
665 leg.push_back(ext::shared_ptr<CashFlow>(new
666 FixedRateCoupon(paymentDate,
667 detail::get(notionals_, i, Null<Real>()),
668 detail::get(spreads_, i, 0.0),
669 paymentDayCounter_,
670 start, end, refStart, refEnd)));
671 } else { // floating coupon
672 observationsSchedules.push_back(
673 ext::make_shared<Schedule>(start, end,
674 observationTenor_, calendar,
675 observationConvention_,
676 observationConvention_,
677 DateGeneration::Forward, false));
678
679 leg.push_back(ext::shared_ptr<CashFlow>(new
680 RangeAccrualFloatersCoupon(
681 paymentDate,
682 detail::get(notionals_, i, Null<Real>()),
683 index_,
684 start, end,
685 detail::get(fixingDays_, i, 2),
686 paymentDayCounter_,
687 detail::get(gearings_, i, 1.0),
688 detail::get(spreads_, i, 0.0),
689 refStart, refEnd,
690 observationsSchedules.back(),
691 detail::get(lowerTriggers_, i, Null<Rate>()),
692 detail::get(upperTriggers_, i, Null<Rate>()))));
693 }
694 }
695 return leg;
696 }
697
698}
degenerate base class for the Acyclic Visitor pattern
Definition: visitor.hpp:33
calendar class
Definition: calendar.hpp:61
Date advance(const Date &, Integer n, TimeUnit unit, BusinessDayConvention convention=Following, bool endOfMonth=false) const
Definition: calendar.cpp:130
virtual Real nominal() const
Definition: coupon.hpp:100
Date date() const override
Definition: coupon.hpp:53
Time accrualPeriod() const
accrual period as fraction of year
Definition: coupon.cpp:44
Cumulative normal distribution function.
Concrete date class.
Definition: date.hpp:125
day counter class
Definition: daycounter.hpp:44
Time yearFraction(const Date &, const Date &, const Date &refPeriodStart=Date(), const Date &refPeriodEnd=Date()) const
Returns the period between two dates as a fraction of year.
Definition: daycounter.hpp:128
base floating-rate coupon class
Natural fixingDays() const
fixing days
void accept(AcyclicVisitor &) override
Real gearing() const
index gearing, i.e. multiplicative coefficient for the index
DayCounter dayCounter() const override
day counter for accrual calculation
virtual Rate indexFixing() const
fixing of the underlying index
const ext::shared_ptr< InterestRateIndex > & index() const
floating index
Spread spread() const
spread paid over the fixing of the underlying index
virtual Real swapletPrice() const =0
Shared handle to an observable.
Definition: handle.hpp:41
Normal distribution function.
const std::vector< Real > & observationTimes() const
Real priceWithoutOptionality(const Handle< YieldTermStructure > &discountCurve) const
void accept(AcyclicVisitor &) override
ext::shared_ptr< Schedule > observationsSchedule() const
const ext::shared_ptr< Schedule > observationsSchedule_
RangeAccrualFloatersCoupon(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 spread, const Date &refPeriodStart, const Date &refPeriodEnd, ext::shared_ptr< Schedule > observationsSchedule, Real lowerTrigger, Real upperTrigger)
RangeAccrualPricerByBgm(Real correlation, ext::shared_ptr< SmileSection > smilesOnExpiry, ext::shared_ptr< SmileSection > smilesOnPayment, bool withSmile, bool byCallSpread)
Real drift(Real U, Real lambdaS, Real lambdaT, Real correlation) const
std::vector< Real > driftsOverPeriod(Real U, Real lambdaS, Real lambdaT, Real correlation) const
Real derDriftDerLambdaS(Real U, Real lambdaS, Real lambdaT, Real correlation) const
Real digitalRangePrice(Real lowerTrigger, Real upperTrigger, Real initialValue, Real expiry, Real deflator) const
Real derDriftDerLambdaT(Real U, Real lambdaS, Real lambdaT, Real correlation) const
Real callSpreadPrice(Real previousInitialValue, Real nextInitialValue, Real previousStrike, Real nextStrike, Real deflator, Real previousVariance, Real nextVariance) const
ext::shared_ptr< SmileSection > smilesOnPayment_
Real derLambdaDerLambdaT(Real U) const
Real lambda(Real U, Real lambdaS, Real lambdaT) const
Real derLambdaDerLambdaS(Real U) const
std::vector< Real > lambdasOverPeriod(Real U, Real lambdaS, Real lambdaT) const
ext::shared_ptr< SmileSection > smilesOnExpiry_
Real digitalPriceWithSmile(Real strike, Real initialValue, Real expiry, Real deflator) const
Real smileCorrection(Real strike, Real initialValue, Real expiry, Real deflator) const
Real digitalPriceWithoutSmile(Real strike, Real initialValue, Real expiry, Real deflator) const
Real swapletPrice() const override
Real digitalPrice(Real strike, Real initialValue, Real expiry, Real deflator) const
std::vector< Real > observationTimes_
Real capletPrice(Rate effectiveCap) const override
Rate floorletRate(Rate effectiveFloor) const override
std::vector< Real > initialValues_
void initialize(const FloatingRateCoupon &coupon) override
const RangeAccrualFloatersCoupon * coupon_
Real floorletPrice(Rate effectiveFloor) const override
Rate swapletRate() const override
Rate capletRate(Rate effectiveCap) const override
Visitor for a specific class
Definition: visitor.hpp:40
virtual void visit(T &)=0
QL_REAL Real
real number
Definition: types.hpp:50
unsigned QL_INTEGER Natural
positive integer
Definition: types.hpp:43
QL_INTEGER Integer
integer number
Definition: types.hpp:35
Real Rate
interest rates
Definition: types.hpp:70
std::size_t Size
size of a container
Definition: types.hpp:58
Definition: any.hpp:35
Real blackFormula(Option::Type optionType, Real strike, Real forward, Real stdDev, Real discount, Real displacement)
STL namespace.