QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
cashflows.cpp
Go to the documentation of this file.
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2005, 2006 StatPro Italia srl
5 Copyright (C) 2005 Charles Whitmore
6 Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Ferdinando Ametrano
7 Copyright (C) 2008 Toyin Akin
8
9 This file is part of QuantLib, a free-software/open-source library
10 for financial quantitative analysts and developers - http://quantlib.org/
11
12 QuantLib is free software: you can redistribute it and/or modify it
13 under the terms of the QuantLib license. You should have received a
14 copy of the license along with this program; if not, please email
15 <quantlib-dev@lists.sf.net>. The license is also available online at
16 <http://quantlib.org/license.shtml>.
17
18 This program is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20 FOR A PARTICULAR PURPOSE. See the license for more details.
21*/
22
32#include <utility>
33
34namespace QuantLib {
35
36 // Date inspectors
37
39 QL_REQUIRE(!leg.empty(), "empty leg");
40
42 for (const auto& i : leg) {
43 ext::shared_ptr<Coupon> c = ext::dynamic_pointer_cast<Coupon>(i);
44 if (c != nullptr)
45 d = std::min(d, c->accrualStartDate());
46 else
47 d = std::min(d, i->date());
48 }
49 return d;
50 }
51
53 QL_REQUIRE(!leg.empty(), "empty leg");
54
56 for (const auto& i : leg) {
57 ext::shared_ptr<Coupon> c = ext::dynamic_pointer_cast<Coupon>(i);
58 if (c != nullptr)
59 d = std::max(d, c->accrualEndDate());
60 else
61 d = std::max(d, i->date());
62 }
63 return d;
64 }
65
66 bool CashFlows::isExpired(const Leg& leg,
67 bool includeSettlementDateFlows,
68 Date settlementDate)
69 {
70 if (leg.empty())
71 return true;
72
73 if (settlementDate == Date())
74 settlementDate = Settings::instance().evaluationDate();
75
76 for (Size i=leg.size(); i>0; --i)
77 if (!leg[i-1]->hasOccurred(settlementDate,
78 includeSettlementDateFlows))
79 return false;
80 return true;
81 }
82
83 Leg::const_reverse_iterator
85 bool includeSettlementDateFlows,
86 Date settlementDate) {
87 if (leg.empty())
88 return leg.rend();
89
90 if (settlementDate == Date())
91 settlementDate = Settings::instance().evaluationDate();
92
93 Leg::const_reverse_iterator i;
94 for (i = leg.rbegin(); i<leg.rend(); ++i) {
95 if ( (*i)->hasOccurred(settlementDate, includeSettlementDateFlows) )
96 return i;
97 }
98 return leg.rend();
99 }
100
101 Leg::const_iterator
103 bool includeSettlementDateFlows,
104 Date settlementDate) {
105 if (leg.empty())
106 return leg.end();
107
108 if (settlementDate == Date())
109 settlementDate = Settings::instance().evaluationDate();
110
111 Leg::const_iterator i;
112 for (i = leg.begin(); i<leg.end(); ++i) {
113 if ( ! (*i)->hasOccurred(settlementDate, includeSettlementDateFlows) )
114 return i;
115 }
116 return leg.end();
117 }
118
120 bool includeSettlementDateFlows,
121 Date settlementDate) {
122 Leg::const_reverse_iterator cf;
123 cf = previousCashFlow(leg, includeSettlementDateFlows, settlementDate);
124
125 if (cf==leg.rend())
126 return {};
127
128 return (*cf)->date();
129 }
130
132 bool includeSettlementDateFlows,
133 Date settlementDate) {
134 Leg::const_iterator cf;
135 cf = nextCashFlow(leg, includeSettlementDateFlows, settlementDate);
136
137 if (cf==leg.end())
138 return {};
139
140 return (*cf)->date();
141 }
142
144 bool includeSettlementDateFlows,
145 Date settlementDate) {
146 Leg::const_reverse_iterator cf;
147 cf = previousCashFlow(leg, includeSettlementDateFlows, settlementDate);
148
149 if (cf==leg.rend())
150 return Real();
151
152 Date paymentDate = (*cf)->date();
153 Real result = 0.0;
154 for (; cf<leg.rend() && (*cf)->date()==paymentDate; ++cf)
155 result += (*cf)->amount();
156 return result;
157 }
158
160 bool includeSettlementDateFlows,
161 Date settlementDate) {
162 Leg::const_iterator cf;
163 cf = nextCashFlow(leg, includeSettlementDateFlows, settlementDate);
164
165 if (cf==leg.end())
166 return Real();
167
168 Date paymentDate = (*cf)->date();
169 Real result = 0.0;
170 for (; cf<leg.end() && (*cf)->date()==paymentDate; ++cf)
171 result += (*cf)->amount();
172 return result;
173 }
174
175 // Coupon utility functions
176 namespace {
177
178 template<typename Iter>
179 Rate aggregateRate(const Leg& leg,
180 Iter first,
181 Iter last) {
182 if (first==last) return 0.0;
183
184 Date paymentDate = (*first)->date();
185 bool firstCouponFound = false;
186 Real nominal = 0.0;
187 Time accrualPeriod = 0.0;
188 DayCounter dc;
189 Rate result = 0.0;
190 for (; first<last && (*first)->date()==paymentDate; ++first) {
191 ext::shared_ptr<Coupon> cp = ext::dynamic_pointer_cast<Coupon>(*first);
192 if (cp) {
193 if (firstCouponFound) {
194 QL_REQUIRE(nominal == cp->nominal() &&
195 accrualPeriod == cp->accrualPeriod() &&
196 dc == cp->dayCounter(),
197 "cannot aggregate two different coupons on "
198 << paymentDate);
199 } else {
200 firstCouponFound = true;
201 nominal = cp->nominal();
202 accrualPeriod = cp->accrualPeriod();
203 dc = cp->dayCounter();
204 }
205 result += cp->rate();
206 }
207 }
208 QL_ENSURE(firstCouponFound,
209 "no coupon paid at cashflow date " << paymentDate);
210 return result;
211 }
212
213 } // anonymous namespace ends here
214
216 bool includeSettlementDateFlows,
217 Date settlementDate) {
218 Leg::const_reverse_iterator cf;
219 cf = previousCashFlow(leg, includeSettlementDateFlows, settlementDate);
220
221 return aggregateRate<Leg::const_reverse_iterator>(leg, cf, leg.rend());
222 }
223
225 bool includeSettlementDateFlows,
226 Date settlementDate) {
227 Leg::const_iterator cf;
228 cf = nextCashFlow(leg, includeSettlementDateFlows, settlementDate);
229 return aggregateRate<Leg::const_iterator>(leg, cf, leg.end());
230 }
231
233 bool includeSettlementDateFlows,
234 Date settlementDate) {
235 auto cf = nextCashFlow(leg, includeSettlementDateFlows, settlementDate);
236 if (cf==leg.end()) return 0.0;
237
238 Date paymentDate = (*cf)->date();
239 for (; cf<leg.end() && (*cf)->date()==paymentDate; ++cf) {
240 ext::shared_ptr<Coupon> cp = ext::dynamic_pointer_cast<Coupon>(*cf);
241 if (cp != nullptr)
242 return cp->nominal();
243 }
244 return 0.0;
245 }
246
248 bool includeSettlementDateFlows,
249 Date settlementDate) {
250 auto cf = nextCashFlow(leg, includeSettlementDateFlows, settlementDate);
251 if (cf==leg.end())
252 return {};
253
254 Date paymentDate = (*cf)->date();
255 for (; cf<leg.end() && (*cf)->date()==paymentDate; ++cf) {
256 ext::shared_ptr<Coupon> cp = ext::dynamic_pointer_cast<Coupon>(*cf);
257 if (cp != nullptr)
258 return cp->accrualStartDate();
259 }
260 return {};
261 }
262
264 bool includeSettlementDateFlows,
265 Date settlementDate) {
266 auto cf = nextCashFlow(leg, includeSettlementDateFlows, settlementDate);
267 if (cf==leg.end())
268 return {};
269
270 Date paymentDate = (*cf)->date();
271 for (; cf<leg.end() && (*cf)->date()==paymentDate; ++cf) {
272 ext::shared_ptr<Coupon> cp = ext::dynamic_pointer_cast<Coupon>(*cf);
273 if (cp != nullptr)
274 return cp->accrualEndDate();
275 }
276 return {};
277 }
278
280 bool includeSettlementDateFlows,
281 Date settlementDate) {
282 auto cf = nextCashFlow(leg, includeSettlementDateFlows, settlementDate);
283 if (cf==leg.end())
284 return {};
285
286 Date paymentDate = (*cf)->date();
287 for (; cf<leg.end() && (*cf)->date()==paymentDate; ++cf) {
288 ext::shared_ptr<Coupon> cp = ext::dynamic_pointer_cast<Coupon>(*cf);
289 if (cp != nullptr)
290 return cp->referencePeriodStart();
291 }
292 return {};
293 }
294
296 bool includeSettlementDateFlows,
297 Date settlementDate) {
298 auto cf = nextCashFlow(leg, includeSettlementDateFlows, settlementDate);
299 if (cf==leg.end())
300 return {};
301
302 Date paymentDate = (*cf)->date();
303 for (; cf<leg.end() && (*cf)->date()==paymentDate; ++cf) {
304 ext::shared_ptr<Coupon> cp = ext::dynamic_pointer_cast<Coupon>(*cf);
305 if (cp != nullptr)
306 return cp->referencePeriodEnd();
307 }
308 return {};
309 }
310
312 bool includeSettlementDateFlows,
313 Date settlementDate) {
314 auto cf = nextCashFlow(leg, includeSettlementDateFlows, settlementDate);
315 if (cf==leg.end()) return 0;
316
317 Date paymentDate = (*cf)->date();
318 for (; cf<leg.end() && (*cf)->date()==paymentDate; ++cf) {
319 ext::shared_ptr<Coupon> cp = ext::dynamic_pointer_cast<Coupon>(*cf);
320 if (cp != nullptr)
321 return cp->accrualPeriod();
322 }
323 return 0;
324 }
325
327 bool includeSettlementDateFlows,
328 Date settlementDate) {
329 auto cf = nextCashFlow(leg, includeSettlementDateFlows, settlementDate);
330 if (cf==leg.end()) return 0;
331
332 Date paymentDate = (*cf)->date();
333 for (; cf<leg.end() && (*cf)->date()==paymentDate; ++cf) {
334 ext::shared_ptr<Coupon> cp = ext::dynamic_pointer_cast<Coupon>(*cf);
335 if (cp != nullptr)
336 return cp->accrualDays();
337 }
338 return 0;
339 }
340
342 bool includeSettlementDateFlows,
343 Date settlementDate) {
344 if (settlementDate == Date())
345 settlementDate = Settings::instance().evaluationDate();
346
347 auto cf = nextCashFlow(leg, includeSettlementDateFlows, settlementDate);
348 if (cf==leg.end()) return 0;
349
350 Date paymentDate = (*cf)->date();
351 for (; cf<leg.end() && (*cf)->date()==paymentDate; ++cf) {
352 ext::shared_ptr<Coupon> cp = ext::dynamic_pointer_cast<Coupon>(*cf);
353 if (cp != nullptr)
354 return cp->accruedPeriod(settlementDate);
355 }
356 return 0;
357 }
358
360 bool includeSettlementDateFlows,
361 Date settlementDate) {
362 if (settlementDate == Date())
363 settlementDate = Settings::instance().evaluationDate();
364
365 auto cf = nextCashFlow(leg, includeSettlementDateFlows, settlementDate);
366 if (cf==leg.end()) return 0;
367
368 Date paymentDate = (*cf)->date();
369 for (; cf<leg.end() && (*cf)->date()==paymentDate; ++cf) {
370 ext::shared_ptr<Coupon> cp = ext::dynamic_pointer_cast<Coupon>(*cf);
371 if (cp != nullptr)
372 return cp->accruedDays(settlementDate);
373 }
374 return 0;
375 }
376
378 bool includeSettlementDateFlows,
379 Date settlementDate) {
380 if (settlementDate == Date())
381 settlementDate = Settings::instance().evaluationDate();
382
383 auto cf = nextCashFlow(leg, includeSettlementDateFlows, settlementDate);
384 if (cf==leg.end()) return 0.0;
385
386 Date paymentDate = (*cf)->date();
387 Real result = 0.0;
388 for (; cf<leg.end() && (*cf)->date()==paymentDate; ++cf) {
389 ext::shared_ptr<Coupon> cp = ext::dynamic_pointer_cast<Coupon>(*cf);
390 if (cp != nullptr)
391 result += cp->accruedAmount(settlementDate);
392 }
393 return result;
394 }
395
396 // YieldTermStructure utility functions
397 namespace {
398
399 class BPSCalculator : public AcyclicVisitor,
400 public Visitor<CashFlow>,
401 public Visitor<Coupon> {
402 public:
403 explicit BPSCalculator(const YieldTermStructure& discountCurve)
404 : discountCurve_(discountCurve) {}
405 void visit(Coupon& c) override {
406 Real bps = c.nominal() *
407 c.accrualPeriod() *
408 discountCurve_.discount(c.date());
409 bps_ += bps;
410 }
411 void visit(CashFlow& cf) override {
412 nonSensNPV_ += cf.amount() *
413 discountCurve_.discount(cf.date());
414 }
415 Real bps() const { return bps_; }
416 Real nonSensNPV() const { return nonSensNPV_; }
417 private:
418 const YieldTermStructure& discountCurve_;
419 Real bps_ = 0.0, nonSensNPV_ = 0.0;
420 };
421
422 const Spread basisPoint_ = 1.0e-4;
423 } // anonymous namespace ends here
424
426 const YieldTermStructure& discountCurve,
427 bool includeSettlementDateFlows,
428 Date settlementDate,
429 Date npvDate) {
430
431 if (leg.empty())
432 return 0.0;
433
434 if (settlementDate == Date())
435 settlementDate = Settings::instance().evaluationDate();
436
437 if (npvDate == Date())
438 npvDate = settlementDate;
439
440 Real totalNPV = 0.0;
441 for (const auto& i : leg) {
442 if (!i->hasOccurred(settlementDate, includeSettlementDateFlows) &&
443 !i->tradingExCoupon(settlementDate))
444 totalNPV += i->amount() * discountCurve.discount(i->date());
445 }
446
447 return totalNPV/discountCurve.discount(npvDate);
448 }
449
451 const YieldTermStructure& discountCurve,
452 bool includeSettlementDateFlows,
453 Date settlementDate,
454 Date npvDate) {
455 if (leg.empty())
456 return 0.0;
457
458 if (settlementDate == Date())
459 settlementDate = Settings::instance().evaluationDate();
460
461 if (npvDate == Date())
462 npvDate = settlementDate;
463
464 BPSCalculator calc(discountCurve);
465 for (const auto& i : leg) {
466 if (!i->hasOccurred(settlementDate, includeSettlementDateFlows) &&
467 !i->tradingExCoupon(settlementDate))
468 i->accept(calc);
469 }
470 return basisPoint_*calc.bps()/discountCurve.discount(npvDate);
471 }
472
473 std::pair<Real, Real> CashFlows::npvbps(const Leg& leg,
474 const YieldTermStructure& discountCurve,
475 bool includeSettlementDateFlows,
476 Date settlementDate,
477 Date npvDate) {
478 Real npv = 0.0;
479 Real bps = 0.0;
480
481 if (leg.empty()) {
482 return { npv, bps };
483 }
484
485 if (settlementDate == Date())
486 settlementDate = Settings::instance().evaluationDate();
487
488 if (npvDate == Date())
489 npvDate = settlementDate;
490
491 for (const auto& i : leg) {
492 CashFlow& cf = *i;
493 if (!cf.hasOccurred(settlementDate,
494 includeSettlementDateFlows) &&
495 !cf.tradingExCoupon(settlementDate)) {
496 ext::shared_ptr<Coupon> cp = ext::dynamic_pointer_cast<Coupon>(i);
497 Real df = discountCurve.discount(cf.date());
498 npv += cf.amount() * df;
499 if (cp != nullptr)
500 bps += cp->nominal() * cp->accrualPeriod() * df;
501 }
502 }
503 DiscountFactor d = discountCurve.discount(npvDate);
504 npv /= d;
505 bps = basisPoint_ * bps / d;
506
507 return { npv, bps };
508 }
509
511 const YieldTermStructure& discountCurve,
512 bool includeSettlementDateFlows,
513 Date settlementDate,
514 Date npvDate,
515 Real targetNpv) {
516 if (leg.empty())
517 return 0.0;
518
519 if (settlementDate == Date())
520 settlementDate = Settings::instance().evaluationDate();
521
522 if (npvDate == Date())
523 npvDate = settlementDate;
524
525 Real npv = 0.0;
526 BPSCalculator calc(discountCurve);
527 for (const auto& i : leg) {
528 CashFlow& cf = *i;
529 if (!cf.hasOccurred(settlementDate,
530 includeSettlementDateFlows) &&
531 !cf.tradingExCoupon(settlementDate)) {
532 npv += cf.amount() *
533 discountCurve.discount(cf.date());
534 cf.accept(calc);
535 }
536 }
537
538 if (targetNpv==Null<Real>())
539 targetNpv = npv - calc.nonSensNPV();
540 else {
541 targetNpv *= discountCurve.discount(npvDate);
542 targetNpv -= calc.nonSensNPV();
543 }
544
545 if (targetNpv==0.0)
546 return 0.0;
547
548 Real bps = calc.bps();
549 QL_REQUIRE(bps!=0.0, "null bps: impossible atm rate");
550
551 return targetNpv/bps;
552 }
553
554 // IRR utility functions
555 namespace {
556
557 template <class T>
558 Integer sign(T x) {
559 static T zero = T();
560 if (x == zero)
561 return 0;
562 else if (x > zero)
563 return 1;
564 else
565 return -1;
566 }
567
568 // helper fucntion used to calculate Time-To-Discount for each stage when calculating discount factor stepwisely
569 Time getStepwiseDiscountTime(const ext::shared_ptr<QuantLib::CashFlow>& cashFlow,
570 const DayCounter& dc,
571 Date npvDate,
572 Date lastDate) {
573 Date cashFlowDate = cashFlow->date();
574 Date refStartDate, refEndDate;
575 ext::shared_ptr<Coupon> coupon =
576 ext::dynamic_pointer_cast<Coupon>(cashFlow);
577 if (coupon != nullptr) {
578 refStartDate = coupon->referencePeriodStart();
579 refEndDate = coupon->referencePeriodEnd();
580 } else {
581 if (lastDate == npvDate) {
582 // we don't have a previous coupon date,
583 // so we fake it
584 refStartDate = cashFlowDate - 1*Years;
585 } else {
586 refStartDate = lastDate;
587 }
588 refEndDate = cashFlowDate;
589 }
590
591 if ((coupon != nullptr) && lastDate != coupon->accrualStartDate()) {
592 Time couponPeriod = dc.yearFraction(coupon->accrualStartDate(),
593 cashFlowDate, refStartDate, refEndDate);
594 Time accruedPeriod = dc.yearFraction(coupon->accrualStartDate(),
595 lastDate, refStartDate, refEndDate);
596 return couponPeriod - accruedPeriod;
597 } else {
598 return dc.yearFraction(lastDate, cashFlowDate,
599 refStartDate, refEndDate);
600 }
601 }
602
603 Real simpleDuration(const Leg& leg,
604 const InterestRate& y,
605 bool includeSettlementDateFlows,
606 Date settlementDate,
607 Date npvDate) {
608 if (leg.empty())
609 return 0.0;
610
611 if (settlementDate == Date())
612 settlementDate = Settings::instance().evaluationDate();
613
614 if (npvDate == Date())
615 npvDate = settlementDate;
616
617 Real P = 0.0;
618 Real dPdy = 0.0;
619 Time t = 0.0;
620 Date lastDate = npvDate;
621 const DayCounter& dc = y.dayCounter();
622 for (const auto& i : leg) {
623 if (i->hasOccurred(settlementDate, includeSettlementDateFlows))
624 continue;
625
626 Real c = i->amount();
627 if (i->tradingExCoupon(settlementDate)) {
628 c = 0.0;
629 }
630
631 t += getStepwiseDiscountTime(i, dc, npvDate, lastDate);
632 DiscountFactor B = y.discountFactor(t);
633 P += c * B;
634 dPdy += t * c * B;
635
636 lastDate = i->date();
637 }
638 if (P == 0.0) // no cashflows
639 return 0.0;
640 return dPdy/P;
641 }
642
643 Real modifiedDuration(const Leg& leg,
644 const InterestRate& y,
645 bool includeSettlementDateFlows,
646 Date settlementDate,
647 Date npvDate) {
648 if (leg.empty())
649 return 0.0;
650
651 if (settlementDate == Date())
652 settlementDate = Settings::instance().evaluationDate();
653
654 if (npvDate == Date())
655 npvDate = settlementDate;
656
657 Real P = 0.0;
658 Time t = 0.0;
659 Real dPdy = 0.0;
660 Rate r = y.rate();
661 Natural N = y.frequency();
662 Date lastDate = npvDate;
663 const DayCounter& dc = y.dayCounter();
664 for (const auto& i : leg) {
665 if (i->hasOccurred(settlementDate, includeSettlementDateFlows))
666 continue;
667
668 Real c = i->amount();
669 if (i->tradingExCoupon(settlementDate)) {
670 c = 0.0;
671 }
672
673 t += getStepwiseDiscountTime(i, dc, npvDate, lastDate);
674 DiscountFactor B = y.discountFactor(t);
675 P += c * B;
676 switch (y.compounding()) {
677 case Simple:
678 dPdy -= c * B*B * t;
679 break;
680 case Compounded:
681 dPdy -= c * t * B/(1+r/N);
682 break;
683 case Continuous:
684 dPdy -= c * B * t;
685 break;
687 if (t<=1.0/N)
688 dPdy -= c * B*B * t;
689 else
690 dPdy -= c * t * B/(1+r/N);
691 break;
693 if (t>1.0/N)
694 dPdy -= c * B*B * t;
695 else
696 dPdy -= c * t * B/(1+r/N);
697 break;
698 default:
699 QL_FAIL("unknown compounding convention (" <<
700 Integer(y.compounding()) << ")");
701 }
702 lastDate = i->date();
703 }
704
705 if (P == 0.0) // no cashflows
706 return 0.0;
707 return -dPdy/P; // reverse derivative sign
708 }
709
710 Real macaulayDuration(const Leg& leg,
711 const InterestRate& y,
712 bool includeSettlementDateFlows,
713 Date settlementDate,
714 Date npvDate) {
715
716 QL_REQUIRE(y.compounding() == Compounded,
717 "compounded rate required");
718
719 return (1.0+y.rate()/Integer(y.frequency())) *
720 modifiedDuration(leg, y,
721 includeSettlementDateFlows,
722 settlementDate, npvDate);
723 }
724
725 struct CashFlowLater {
726 bool operator()(const ext::shared_ptr<CashFlow> &c,
727 const ext::shared_ptr<CashFlow> &d) {
728 return c->date() > d->date();
729 }
730 };
731
732 } // anonymous namespace ends here
733
735 Real npv,
736 DayCounter dayCounter,
737 Compounding comp,
738 Frequency freq,
739 bool includeSettlementDateFlows,
740 Date settlementDate,
741 Date npvDate)
742 : leg_(leg), npv_(npv), dayCounter_(std::move(dayCounter)), compounding_(comp),
743 frequency_(freq), includeSettlementDateFlows_(includeSettlementDateFlows),
744 settlementDate_(settlementDate), npvDate_(npvDate) {
745
746 if (settlementDate_ == Date())
748
749 if (npvDate_ == Date())
751
752 checkSign();
753 }
754
756 InterestRate yield(y, dayCounter_, compounding_, frequency_);
760 return npv_ - NPV;
761 }
762
764 InterestRate yield(y, dayCounter_, compounding_, frequency_);
765 return modifiedDuration(leg_, yield,
768 }
769
771 // depending on the sign of the market price, check that cash
772 // flows of the opposite sign have been specified (otherwise
773 // IRR is nonsensical.)
774
775 Integer lastSign = sign(Real(-npv_)),
776 signChanges = 0;
777 for (const auto& i : leg_) {
778 if (!i->hasOccurred(settlementDate_, includeSettlementDateFlows_) &&
779 !i->tradingExCoupon(settlementDate_)) {
780 Integer thisSign = sign(i->amount());
781 if (lastSign * thisSign < 0) // sign change
782 signChanges++;
783
784 if (thisSign != 0)
785 lastSign = thisSign;
786 }
787 }
788 QL_REQUIRE(signChanges > 0,
789 "the given cash flows cannot result in the given market "
790 "price due to their sign");
791
792 /* The following is commented out due to the lack of a QL_WARN macro
793 if (signChanges > 1) { // Danger of non-unique solution
794 // Check the aggregate cash flows (Norstrom)
795 Real aggregateCashFlow = npv;
796 signChanges = 0;
797 for (Size i = 0; i < leg.size(); ++i) {
798 Real nextAggregateCashFlow =
799 aggregateCashFlow + leg[i]->amount();
800
801 if (aggregateCashFlow * nextAggregateCashFlow < 0.0)
802 signChanges++;
803
804 aggregateCashFlow = nextAggregateCashFlow;
805 }
806 if (signChanges > 1)
807 QL_WARN( "danger of non-unique solution");
808 };
809 */
810 }
811
813 const InterestRate& y,
814 bool includeSettlementDateFlows,
815 Date settlementDate,
816 Date npvDate) {
817
818 if (leg.empty())
819 return 0.0;
820
821 if (settlementDate == Date())
822 settlementDate = Settings::instance().evaluationDate();
823
824 if (npvDate == Date())
825 npvDate = settlementDate;
826
827#if defined(QL_EXTRA_SAFETY_CHECKS)
828 QL_REQUIRE(std::adjacent_find(leg.begin(), leg.end(),
829 CashFlowLater()) == leg.end(),
830 "cashflows must be sorted in ascending order w.r.t. their payment dates");
831#endif
832
833 Real npv = 0.0;
834 DiscountFactor discount = 1.0;
835 Date lastDate = npvDate;
836 const DayCounter& dc = y.dayCounter();
837 for (const auto& i : leg) {
838 if (i->hasOccurred(settlementDate, includeSettlementDateFlows))
839 continue;
840
841 Real amount = i->amount();
842 if (i->tradingExCoupon(settlementDate)) {
843 amount = 0.0;
844 }
845
846 DiscountFactor b = y.discountFactor(getStepwiseDiscountTime(i, dc, npvDate, lastDate));
847 discount *= b;
848 lastDate = i->date();
849
850 npv += amount * discount;
851 }
852
853 return npv;
854 }
855
857 Rate yield,
858 const DayCounter& dc,
859 Compounding comp,
860 Frequency freq,
861 bool includeSettlementDateFlows,
862 Date settlementDate,
863 Date npvDate) {
864 return npv(leg, InterestRate(yield, dc, comp, freq),
865 includeSettlementDateFlows,
866 settlementDate, npvDate);
867 }
868
870 const InterestRate& yield,
871 bool includeSettlementDateFlows,
872 Date settlementDate,
873 Date npvDate) {
874
875 if (leg.empty())
876 return 0.0;
877
878 if (settlementDate == Date())
879 settlementDate = Settings::instance().evaluationDate();
880
881 if (npvDate == Date())
882 npvDate = settlementDate;
883
884 FlatForward flatRate(settlementDate, yield.rate(), yield.dayCounter(),
885 yield.compounding(), yield.frequency());
886 return bps(leg, flatRate,
887 includeSettlementDateFlows,
888 settlementDate, npvDate);
889 }
890
892 Rate yield,
893 const DayCounter& dc,
894 Compounding comp,
895 Frequency freq,
896 bool includeSettlementDateFlows,
897 Date settlementDate,
898 Date npvDate) {
899 return bps(leg, InterestRate(yield, dc, comp, freq),
900 includeSettlementDateFlows,
901 settlementDate, npvDate);
902 }
903
905 Real npv,
906 const DayCounter& dayCounter,
907 Compounding compounding,
908 Frequency frequency,
909 bool includeSettlementDateFlows,
910 Date settlementDate,
911 Date npvDate,
912 Real accuracy,
913 Size maxIterations,
914 Rate guess) {
915 NewtonSafe solver;
916 solver.setMaxEvaluations(maxIterations);
917 return CashFlows::yield<NewtonSafe>(solver, leg, npv, dayCounter,
918 compounding, frequency,
919 includeSettlementDateFlows,
920 settlementDate, npvDate,
921 accuracy, guess);
922 }
923
924
926 const InterestRate& rate,
927 Duration::Type type,
928 bool includeSettlementDateFlows,
929 Date settlementDate,
930 Date npvDate) {
931
932 if (leg.empty())
933 return 0.0;
934
935 if (settlementDate == Date())
936 settlementDate = Settings::instance().evaluationDate();
937
938 if (npvDate == Date())
939 npvDate = settlementDate;
940
941 switch (type) {
942 case Duration::Simple:
943 return simpleDuration(leg, rate,
944 includeSettlementDateFlows,
945 settlementDate, npvDate);
947 return modifiedDuration(leg, rate,
948 includeSettlementDateFlows,
949 settlementDate, npvDate);
951 return macaulayDuration(leg, rate,
952 includeSettlementDateFlows,
953 settlementDate, npvDate);
954 default:
955 QL_FAIL("unknown duration type");
956 }
957 }
958
960 Rate yield,
961 const DayCounter& dc,
962 Compounding comp,
963 Frequency freq,
964 Duration::Type type,
965 bool includeSettlementDateFlows,
966 Date settlementDate,
967 Date npvDate) {
968 return duration(leg, InterestRate(yield, dc, comp, freq),
969 type,
970 includeSettlementDateFlows,
971 settlementDate, npvDate);
972 }
973
975 const InterestRate& y,
976 bool includeSettlementDateFlows,
977 Date settlementDate,
978 Date npvDate) {
979 if (leg.empty())
980 return 0.0;
981
982 if (settlementDate == Date())
983 settlementDate = Settings::instance().evaluationDate();
984
985 if (npvDate == Date())
986 npvDate = settlementDate;
987
988 const DayCounter& dc = y.dayCounter();
989
990 Real P = 0.0;
991 Time t = 0.0;
992 Real d2Pdy2 = 0.0;
993 Rate r = y.rate();
994 Natural N = y.frequency();
995 Date lastDate = npvDate;
996 for (const auto& i : leg) {
997 if (i->hasOccurred(settlementDate, includeSettlementDateFlows))
998 continue;
999
1000 Real c = i->amount();
1001 if (i->tradingExCoupon(settlementDate)) {
1002 c = 0.0;
1003 }
1004
1005 t += getStepwiseDiscountTime(i, dc, npvDate, lastDate);
1006 DiscountFactor B = y.discountFactor(t);
1007 P += c * B;
1008 switch (y.compounding()) {
1009 case Simple:
1010 d2Pdy2 += c * 2.0*B*B*B*t*t;
1011 break;
1012 case Compounded:
1013 d2Pdy2 += c * B*t*(N*t+1)/(N*(1+r/N)*(1+r/N));
1014 break;
1015 case Continuous:
1016 d2Pdy2 += c * B*t*t;
1017 break;
1019 if (t<=1.0/N)
1020 d2Pdy2 += c * 2.0*B*B*B*t*t;
1021 else
1022 d2Pdy2 += c * B*t*(N*t+1)/(N*(1+r/N)*(1+r/N));
1023 break;
1025 if (t>1.0/N)
1026 d2Pdy2 += c * 2.0*B*B*B*t*t;
1027 else
1028 d2Pdy2 += c * B*t*(N*t+1)/(N*(1+r/N)*(1+r/N));
1029 break;
1030 default:
1031 QL_FAIL("unknown compounding convention (" <<
1032 Integer(y.compounding()) << ")");
1033 }
1034 lastDate = i->date();
1035 }
1036
1037 if (P == 0.0)
1038 // no cashflows
1039 return 0.0;
1040
1041 return d2Pdy2/P;
1042 }
1043
1044
1046 Rate yield,
1047 const DayCounter& dc,
1048 Compounding comp,
1049 Frequency freq,
1050 bool includeSettlementDateFlows,
1051 Date settlementDate,
1052 Date npvDate) {
1053 return convexity(leg, InterestRate(yield, dc, comp, freq),
1054 includeSettlementDateFlows,
1055 settlementDate, npvDate);
1056 }
1057
1059 const InterestRate& y,
1060 bool includeSettlementDateFlows,
1061 Date settlementDate,
1062 Date npvDate) {
1063 if (leg.empty())
1064 return 0.0;
1065
1066 if (settlementDate == Date())
1067 settlementDate = Settings::instance().evaluationDate();
1068
1069 if (npvDate == Date())
1070 npvDate = settlementDate;
1071
1072 Real npv = CashFlows::npv(leg, y,
1073 includeSettlementDateFlows,
1074 settlementDate, npvDate);
1075 Real modifiedDuration = CashFlows::duration(leg, y,
1077 includeSettlementDateFlows,
1078 settlementDate, npvDate);
1080 includeSettlementDateFlows,
1081 settlementDate, npvDate);
1082 Real delta = -modifiedDuration*npv;
1083 Real gamma = (convexity/100.0)*npv;
1084
1085 Real shift = 0.0001;
1086 delta *= shift;
1087 gamma *= shift*shift;
1088
1089 return delta + 0.5*gamma;
1090 }
1091
1093 Rate yield,
1094 const DayCounter& dc,
1095 Compounding comp,
1096 Frequency freq,
1097 bool includeSettlementDateFlows,
1098 Date settlementDate,
1099 Date npvDate) {
1100 return basisPointValue(leg, InterestRate(yield, dc, comp, freq),
1101 includeSettlementDateFlows,
1102 settlementDate, npvDate);
1103 }
1104
1106 const InterestRate& y,
1107 bool includeSettlementDateFlows,
1108 Date settlementDate,
1109 Date npvDate) {
1110 if (leg.empty())
1111 return 0.0;
1112
1113 if (settlementDate == Date())
1114 settlementDate = Settings::instance().evaluationDate();
1115
1116 if (npvDate == Date())
1117 npvDate = settlementDate;
1118
1119 Real npv = CashFlows::npv(leg, y,
1120 includeSettlementDateFlows,
1121 settlementDate, npvDate);
1122 Real modifiedDuration = CashFlows::duration(leg, y,
1124 includeSettlementDateFlows,
1125 settlementDate, npvDate);
1126
1127 Real shift = 0.01;
1128 return (1.0/(-npv*modifiedDuration))*shift;
1129 }
1130
1132 Rate yield,
1133 const DayCounter& dc,
1134 Compounding comp,
1135 Frequency freq,
1136 bool includeSettlementDateFlows,
1137 Date settlementDate,
1138 Date npvDate) {
1139 return yieldValueBasisPoint(leg, InterestRate(yield, dc, comp, freq),
1140 includeSettlementDateFlows,
1141 settlementDate, npvDate);
1142 }
1143
1144 // Z-spread utility functions
1145 namespace {
1146
1147 class ZSpreadFinder {
1148 public:
1149 ZSpreadFinder(const Leg& leg,
1150 const ext::shared_ptr<YieldTermStructure>& discountCurve,
1151 Real npv,
1152 const DayCounter& dc,
1153 Compounding comp,
1154 Frequency freq,
1155 bool includeSettlementDateFlows,
1156 Date settlementDate,
1157 Date npvDate)
1158 : leg_(leg), npv_(npv), zSpread_(new SimpleQuote(0.0)),
1159 curve_(Handle<YieldTermStructure>(discountCurve),
1160 Handle<Quote>(zSpread_), comp, freq, dc),
1161 includeSettlementDateFlows_(includeSettlementDateFlows),
1162 settlementDate_(settlementDate),
1163 npvDate_(npvDate) {
1164
1165 if (settlementDate_ == Date())
1166 settlementDate_ = Settings::instance().evaluationDate();
1167
1168 if (npvDate_ == Date())
1170
1171 // if the discount curve allows extrapolation, let's
1172 // the spreaded curve do too.
1173 curve_.enableExtrapolation(
1174 discountCurve->allowsExtrapolation());
1175 }
1176 Real operator()(Rate zSpread) const {
1177 zSpread_->setValue(zSpread);
1178 Real NPV = CashFlows::npv(leg_, curve_,
1181 return npv_ - NPV;
1182 }
1183 private:
1184 const Leg& leg_;
1185 Real npv_;
1186 ext::shared_ptr<SimpleQuote> zSpread_;
1187 ZeroSpreadedTermStructure curve_;
1190 };
1191
1192 } // anonymous namespace ends here
1193
1195 const ext::shared_ptr<YieldTermStructure>& discountCurve,
1197 const DayCounter& dc,
1198 Compounding comp,
1199 Frequency freq,
1200 bool includeSettlementDateFlows,
1201 Date settlementDate,
1202 Date npvDate) {
1203
1204 if (leg.empty())
1205 return 0.0;
1206
1207 if (settlementDate == Date())
1208 settlementDate = Settings::instance().evaluationDate();
1209
1210 if (npvDate == Date())
1211 npvDate = settlementDate;
1212
1213 Handle<YieldTermStructure> discountCurveHandle(discountCurve);
1214 Handle<Quote> zSpreadQuoteHandle(ext::shared_ptr<Quote>(new
1216
1217 ZeroSpreadedTermStructure spreadedCurve(discountCurveHandle,
1218 zSpreadQuoteHandle,
1219 comp, freq, dc);
1220
1221 spreadedCurve.enableExtrapolation(discountCurveHandle->allowsExtrapolation());
1222
1223 return npv(leg, spreadedCurve,
1224 includeSettlementDateFlows,
1225 settlementDate, npvDate);
1226 }
1227
1229 Real npv,
1230 const ext::shared_ptr<YieldTermStructure>& discount,
1231 const DayCounter& dayCounter,
1232 Compounding compounding,
1233 Frequency frequency,
1234 bool includeSettlementDateFlows,
1235 Date settlementDate,
1236 Date npvDate,
1237 Real accuracy,
1238 Size maxIterations,
1239 Rate guess) {
1240
1241 if (settlementDate == Date())
1242 settlementDate = Settings::instance().evaluationDate();
1243
1244 if (npvDate == Date())
1245 npvDate = settlementDate;
1246
1247 Brent solver;
1248 solver.setMaxEvaluations(maxIterations);
1249 ZSpreadFinder objFunction(leg,
1250 discount,
1251 npv,
1252 dayCounter, compounding, frequency, includeSettlementDateFlows,
1253 settlementDate, npvDate);
1254 Real step = 0.01;
1255 return solver.solve(objFunction, accuracy, guess, step);
1256 }
1257
1258}
Brent 1-D solver.
ext::shared_ptr< SimpleQuote > zSpread_
Definition: cashflows.cpp:1186
const Leg & leg_
Definition: cashflows.cpp:1184
Real nonSensNPV_
Definition: cashflows.cpp:419
Real bps_
Definition: cashflows.cpp:419
Real npv_
Definition: cashflows.cpp:1185
Date npvDate_
Definition: cashflows.cpp:1189
bool includeSettlementDateFlows_
Definition: cashflows.cpp:1188
const YieldTermStructure & discountCurve_
Definition: cashflows.cpp:418
Date settlementDate_
Definition: cashflows.cpp:1189
ZeroSpreadedTermStructure curve_
Definition: cashflows.cpp:1187
Cash-flow analysis functions.
degenerate base class for the Acyclic Visitor pattern
Definition: visitor.hpp:33
Brent 1-D solver
Definition: brent.hpp:37
Base class for cash flows.
Definition: cashflow.hpp:40
bool hasOccurred(const Date &refDate=Date(), ext::optional< bool > includeRefDate=ext::nullopt) const override
returns true if an event has already occurred before a date
Definition: cashflow.cpp:27
bool tradingExCoupon(const Date &refDate=Date()) const
returns true if the cashflow is trading ex-coupon on the refDate
Definition: cashflow.cpp:51
void accept(AcyclicVisitor &) override
Definition: cashflow.cpp:63
Date date() const override=0
virtual Real amount() const =0
returns the amount of the cash flow
IrrFinder(const Leg &leg, Real npv, DayCounter dayCounter, Compounding comp, Frequency freq, bool includeSettlementDateFlows, Date settlementDate, Date npvDate)
Definition: cashflows.cpp:734
Real derivative(Rate y) const
Definition: cashflows.cpp:763
Real operator()(Rate y) const
Definition: cashflows.cpp:755
static Date::serial_type accruedDays(const Leg &leg, bool includeSettlementDateFlows, Date settlementDate=Date())
Definition: cashflows.cpp:359
static Real previousCashFlowAmount(const Leg &leg, bool includeSettlementDateFlows, Date settlementDate=Date())
Definition: cashflows.cpp:143
static Rate previousCouponRate(const Leg &leg, bool includeSettlementDateFlows, Date settlementDate=Date())
Definition: cashflows.cpp:215
static Rate nextCouponRate(const Leg &leg, bool includeSettlementDateFlows, Date settlementDate=Date())
Definition: cashflows.cpp:224
static Date referencePeriodStart(const Leg &leg, bool includeSettlementDateFlows, Date settlDate=Date())
Definition: cashflows.cpp:279
static Real nextCashFlowAmount(const Leg &leg, bool includeSettlementDateFlows, Date settlementDate=Date())
Definition: cashflows.cpp:159
static Real yieldValueBasisPoint(const Leg &leg, const InterestRate &yield, bool includeSettlementDateFlows, Date settlementDate=Date(), Date npvDate=Date())
Yield value of a basis point.
Definition: cashflows.cpp:1105
static Real accruedAmount(const Leg &leg, bool includeSettlementDateFlows, Date settlementDate=Date())
Definition: cashflows.cpp:377
static Real basisPointValue(const Leg &leg, const InterestRate &yield, bool includeSettlementDateFlows, Date settlementDate=Date(), Date npvDate=Date())
Basis-point value.
Definition: cashflows.cpp:1058
static Leg::const_iterator nextCashFlow(const Leg &leg, bool includeSettlementDateFlows, Date settlementDate=Date())
the first cashflow paying after the given date
Definition: cashflows.cpp:102
static Spread zSpread(const Leg &leg, Real npv, const ext::shared_ptr< YieldTermStructure > &, const DayCounter &dayCounter, Compounding compounding, Frequency frequency, bool includeSettlementDateFlows, Date settlementDate=Date(), Date npvDate=Date(), Real accuracy=1.0e-10, Size maxIterations=100, Rate guess=0.0)
implied Z-spread.
Definition: cashflows.cpp:1228
static Real npv(const Leg &leg, const YieldTermStructure &discountCurve, bool includeSettlementDateFlows, Date settlementDate=Date(), Date npvDate=Date())
NPV of the cash flows.
Definition: cashflows.cpp:425
static Date accrualEndDate(const Leg &leg, bool includeSettlementDateFlows, Date settlementDate=Date())
Definition: cashflows.cpp:263
static Date accrualStartDate(const Leg &leg, bool includeSettlementDateFlows, Date settlDate=Date())
Definition: cashflows.cpp:247
static Leg::const_reverse_iterator previousCashFlow(const Leg &leg, bool includeSettlementDateFlows, Date settlementDate=Date())
the last cashflow paying before or at the given date
Definition: cashflows.cpp:84
static Date nextCashFlowDate(const Leg &leg, bool includeSettlementDateFlows, Date settlementDate=Date())
Definition: cashflows.cpp:131
static Rate yield(const Leg &leg, Real npv, const DayCounter &dayCounter, Compounding compounding, Frequency frequency, bool includeSettlementDateFlows, Date settlementDate=Date(), Date npvDate=Date(), Real accuracy=1.0e-10, Size maxIterations=100, Rate guess=0.05)
Implied internal rate of return.
Definition: cashflows.cpp:904
static Time accrualPeriod(const Leg &leg, bool includeSettlementDateFlows, Date settlementDate=Date())
Definition: cashflows.cpp:311
static Date::serial_type accrualDays(const Leg &leg, bool includeSettlementDateFlows, Date settlementDate=Date())
Definition: cashflows.cpp:326
static Date maturityDate(const Leg &leg)
Definition: cashflows.cpp:52
static Time duration(const Leg &leg, const InterestRate &yield, Duration::Type type, bool includeSettlementDateFlows, Date settlementDate=Date(), Date npvDate=Date())
Cash-flow duration.
Definition: cashflows.cpp:925
static Date startDate(const Leg &leg)
Definition: cashflows.cpp:38
static Real nominal(const Leg &leg, bool includeSettlementDateFlows, Date settlDate=Date())
Definition: cashflows.cpp:232
static Date previousCashFlowDate(const Leg &leg, bool includeSettlementDateFlows, Date settlementDate=Date())
Definition: cashflows.cpp:119
static Rate atmRate(const Leg &leg, const YieldTermStructure &discountCurve, bool includeSettlementDateFlows, Date settlementDate=Date(), Date npvDate=Date(), Real npv=Null< Real >())
At-the-money rate of the cash flows.
Definition: cashflows.cpp:510
static bool isExpired(const Leg &leg, bool includeSettlementDateFlows, Date settlementDate=Date())
Definition: cashflows.cpp:66
static Real bps(const Leg &leg, const YieldTermStructure &discountCurve, bool includeSettlementDateFlows, Date settlementDate=Date(), Date npvDate=Date())
Basis-point sensitivity of the cash flows.
Definition: cashflows.cpp:450
static std::pair< Real, Real > npvbps(const Leg &leg, const YieldTermStructure &discountCurve, bool includeSettlementDateFlows, Date settlementDate=Date(), Date npvDate=Date())
NPV and BPS of the cash flows.
Definition: cashflows.cpp:473
static Date referencePeriodEnd(const Leg &leg, bool includeSettlementDateFlows, Date settlDate=Date())
Definition: cashflows.cpp:295
static Time accruedPeriod(const Leg &leg, bool includeSettlementDateFlows, Date settlementDate=Date())
Definition: cashflows.cpp:341
static Real convexity(const Leg &leg, const InterestRate &yield, bool includeSettlementDateFlows, Date settlementDate=Date(), Date npvDate=Date())
Cash-flow convexity.
Definition: cashflows.cpp:974
Concrete date class.
Definition: date.hpp:125
static Date minDate()
earliest allowed date
Definition: date.cpp:766
std::int_fast32_t serial_type
serial number type
Definition: date.hpp:128
static Date maxDate()
latest allowed date
Definition: date.cpp:771
day counter class
Definition: daycounter.hpp:44
void enableExtrapolation(bool b=true)
enable extrapolation in subsequent calls
Flat interest-rate curve.
Definition: flatforward.hpp:37
Shared handle to an observable.
Definition: handle.hpp:41
Concrete interest rate class.
safe Newton 1-D solver
Definition: newtonsafe.hpp:40
template class providing a null value for a given type.
Definition: null.hpp:76
purely virtual base class for market observables
Definition: quote.hpp:37
DateProxy & evaluationDate()
the date at which pricing is to be performed.
Definition: settings.hpp:147
market element returning a stored value
Definition: simplequote.hpp:33
static Settings & instance()
access to the unique instance
Definition: singleton.hpp:104
void setMaxEvaluations(Size evaluations)
Definition: solver1d.hpp:238
Real solve(const F &f, Real accuracy, Real guess, Real step) const
Definition: solver1d.hpp:84
Visitor for a specific class
Definition: visitor.hpp:40
Interest-rate term structure.
DiscountFactor discount(const Date &d, bool extrapolate=false) const
Term structure with an added spread on the zero yield rate.
Coupon accruing over a fixed period.
Coupon pricers.
const DefaultType & t
#define QL_ENSURE(condition, message)
throw an error if the given post-condition is not verified
Definition: errors.hpp:130
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
#define QL_FAIL(message)
throw an error (possibly with file and line information)
Definition: errors.hpp:92
Date d
ext::function< Real(Real)> b
flat forward rate term structure
Frequency
Frequency of events.
Definition: frequency.hpp:37
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
QL_REAL Real
real number
Definition: types.hpp:50
Real DiscountFactor
discount factor between dates
Definition: types.hpp:66
unsigned QL_INTEGER Natural
positive integer
Definition: types.hpp:43
QL_INTEGER Integer
integer number
Definition: types.hpp:35
Real Spread
spreads on interest rates
Definition: types.hpp:74
Real Rate
interest rates
Definition: types.hpp:70
std::size_t Size
size of a container
Definition: types.hpp:58
Definition: any.hpp:35
Compounding
Interest rate coumpounding rule.
Definition: compounding.hpp:32
@ CompoundedThenSimple
Compounded up to the first period then Simple.
Definition: compounding.hpp:36
@ SimpleThenCompounded
Simple up to the first period then Compounded.
Definition: compounding.hpp:35
std::vector< ext::shared_ptr< CashFlow > > Leg
Sequence of cash-flows.
Definition: cashflow.hpp:78
STL namespace.
Safe (bracketed) Newton 1-D solver.
ext::shared_ptr< YieldTermStructure > r
simple quote class
degenerate base class for the Acyclic Visitor pattern
Zero spreaded term structure.