QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
blackcallablebondengine.cpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2008 Allen Kuo
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/experimental/callablebonds/blackcallablebondengine.hpp>
22#include <ql/experimental/callablebonds/callablebondconstantvol.hpp>
23#include <ql/experimental/callablebonds/callablebondvolstructure.hpp>
24#include <ql/pricingengines/blackformula.hpp>
25#include <ql/time/calendars/nullcalendar.hpp>
26#include <utility>
27
28using namespace std;
29
30namespace QuantLib {
31
33 const Handle<Quote>& fwdYieldVol, Handle<YieldTermStructure> discountCurve)
34 : volatility_(ext::shared_ptr<CallableBondVolatilityStructure>(
36 discountCurve_(std::move(discountCurve)) {
37 registerWith(volatility_);
38 registerWith(discountCurve_);
39 }
40
44 Handle<YieldTermStructure> discountCurve)
45 : volatility_(std::move(yieldVolStructure)), discountCurve_(std::move(discountCurve)) {
46 registerWith(volatility_);
47 registerWith(discountCurve_);
48 }
49
52 Date settlement = arguments_.settlementDate;
53 Leg cf = arguments_.cashflows;
54 Date optionMaturity = arguments_.putCallSchedule[0]->date();
55
56 /* the following assumes
57 1. cashflows are in ascending order !
58 2. income = coupons paid between settlementDate() and put/call date
59 */
60 Real income = 0.0;
61 for (Size i = 0; i < cf.size() - 1; ++i) {
62 if (!cf[i]->hasOccurred(settlement, false)) {
63 if (cf[i]->hasOccurred(optionMaturity, false)) {
64 income += cf[i]->amount() *
65 discountCurve_->discount(cf[i]->date());
66 } else {
67 break;
68 }
69 }
70 }
71 return income/discountCurve_->discount(settlement);
72 }
73
74
76 const {
77 Date bondMaturity = arguments_.redemptionDate;
78 Date exerciseDate = arguments_.callabilityDates[0];
79 Leg fixedLeg = arguments_.cashflows;
80
81 // value of bond cash flows at option maturity
82 Real fwdNpv = CashFlows::npv(fixedLeg,
84 false, exerciseDate);
85
86 DayCounter dayCounter = arguments_.paymentDayCounter;
87 Frequency frequency = arguments_.frequency;
88
89 // adjust if zero coupon bond (see also bond.cpp)
90 if (frequency == NoFrequency || frequency == Once)
91 frequency = Annual;
92
93 Rate fwdYtm = CashFlows::yield(fixedLeg,
94 fwdNpv,
95 dayCounter,
97 frequency,
98 false, exerciseDate);
99
100 InterestRate fwdRate(fwdYtm,
101 dayCounter,
103 frequency);
104
105 Time fwdDur = CashFlows::duration(fixedLeg,
106 fwdRate,
108 false, exerciseDate);
109
110 Real cashStrike = arguments_.callabilityPrices[0] * arguments_.faceAmount / 100.0;
111 dayCounter = volatility_->dayCounter();
112 Date referenceDate = volatility_->referenceDate();
113 Time exerciseTime = dayCounter.yearFraction(referenceDate,
114 exerciseDate);
115 Time maturityTime = dayCounter.yearFraction(referenceDate,
116 bondMaturity);
117 Volatility yieldVol = volatility_->volatility(exerciseTime,
118 maturityTime-exerciseTime,
119 cashStrike);
120 Volatility fwdPriceVol = yieldVol*fwdDur*fwdYtm;
121 return fwdPriceVol;
122 }
123
124
126 // validate args for Black engine
127 QL_REQUIRE(arguments_.putCallSchedule.size() == 1,
128 "Must have exactly one call/put date to use Black Engine");
129
130 Date settle = arguments_.settlementDate;
131 Date exerciseDate = arguments_.callabilityDates[0];
132 QL_REQUIRE(exerciseDate >= settle,
133 "must have exercise Date >= settlement Date");
134
135 Leg fixedLeg = arguments_.cashflows;
136
137 Real value = CashFlows::npv(fixedLeg,
139 false, settle);
140
141 Real npv = CashFlows::npv(fixedLeg,
143 false, discountCurve_->referenceDate());
144
145 Real fwdCashPrice = (value - spotIncome())/
146 discountCurve_->discount(exerciseDate);
147
148 Real cashStrike = arguments_.callabilityPrices[0] * arguments_.faceAmount / 100.0;
149
150 Option::Type type = (arguments_.putCallSchedule[0]->type() ==
152
154
155 Time exerciseTime = volatility_->dayCounter().yearFraction(
156 volatility_->referenceDate(),
157 exerciseDate);
158 Real embeddedOptionValue =
159 blackFormula(type,
160 cashStrike,
161 fwdCashPrice,
162 priceVol*std::sqrt(exerciseTime));
163
164 if (type == Option::Call) {
165 results_.value = npv - embeddedOptionValue;
166 results_.settlementValue = value - embeddedOptionValue;
167 } else {
168 results_.value = npv + embeddedOptionValue;
169 results_.settlementValue = value + embeddedOptionValue;
170 }
171 }
172
173}
Actual/365 (Fixed) day count convention.
Handle< CallableBondVolatilityStructure > volatility_
BlackCallableFixedRateBondEngine(const Handle< Quote > &fwdYieldVol, Handle< YieldTermStructure > discountCurve)
volatility is the quoted fwd yield volatility, not price vol
Constant callable-bond volatility, no time-strike dependence.
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 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:915
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:936
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
Shared handle to an observable.
Definition: handle.hpp:41
Concrete interest rate class.
Calendar for reproducing theoretical calculations.
Frequency
Frequency of events.
Definition: frequency.hpp:37
@ Annual
once a year
Definition: frequency.hpp:39
@ Once
only once, e.g., a zero-coupon
Definition: frequency.hpp:38
@ NoFrequency
null frequency
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 Volatility
volatility
Definition: types.hpp:78
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)
std::vector< ext::shared_ptr< CashFlow > > Leg
Sequence of cash-flows.
Definition: cashflow.hpp:78
STL namespace.