1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*!
4 Copyright (C) 2005, 2006 Theo Boafo
5 Copyright (C) 2006, 2007 StatPro Italia srl
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#include <ql/qldefines.hpp>
22#if !defined(BOOST_ALL_NO_LIB) && defined(BOOST_MSVC)
23# include <ql/auto_link.hpp>
24#endif
25#include <ql/instruments/bonds/convertiblebonds.hpp>
26#include <ql/pricingengines/bond/binomialconvertibleengine.hpp>
27#include <ql/time/calendars/target.hpp>
28#include <ql/time/daycounters/thirty360.hpp>
29#include <ql/utilities/dataformatters.hpp>
30
31#include <iostream>
32#include <iomanip>
33
34#define LENGTH(a) (sizeof(a)/sizeof(a[0]))
35
36using namespace QuantLib;
37
38int main(int, char* []) {
39
40 try {
41
42 std::cout << std::endl;
43
44 Option::Type type(Option::Put);
45 Real underlying = 36.0;
46 Real spreadRate = 0.005;
47
48 Spread dividendYield = 0.02;
49 Rate riskFreeRate = 0.06;
50 Volatility volatility = 0.20;
51
52 Integer settlementDays = 3;
53 Integer length = 5;
54 Real redemption = 100.0;
55 Real conversionRatio = redemption/underlying; // at the money
56
57 // set up dates/schedules
58 Calendar calendar = TARGET();
59 Date today = calendar.adjust(Date::todaysDate());
60
61 Settings::instance().evaluationDate() = today;
62 Date settlementDate = calendar.advance(today, n: settlementDays, unit: Days);
63 Date exerciseDate = calendar.advance(settlementDate, n: length, unit: Years);
64 Date issueDate = calendar.advance(exerciseDate, n: -length, unit: Years);
65
66 BusinessDayConvention convention = ModifiedFollowing;
67
68 Frequency frequency = Annual;
69
70 Schedule schedule(issueDate, exerciseDate,
71 Period(frequency), calendar,
72 convention, convention,
73 DateGeneration::Backward, false);
74
75 DividendSchedule dividends;
76 CallabilitySchedule callability;
77
78 std::vector<Real> coupons(1, 0.05);
79
80 DayCounter bondDayCount = Thirty360(Thirty360::BondBasis);
81
82 Integer callLength[] = { 2, 4 }; // Call dates, years 2, 4.
83 Integer putLength[] = { 3 }; // Put dates year 3
84
85 Real callPrices[] = { 101.5, 100.85 };
86 Real putPrices[]= { 105.0 };
87
88 // Load call schedules
89 for (Size i=0; i<LENGTH(callLength); i++) {
90 callability.push_back(
91 x: ext::make_shared<SoftCallability>(args: Bond::Price(callPrices[i],
92 Bond::Price::Clean),
93 args: schedule.date(i: callLength[i]),
94 args: 1.20));
95 }
96
97 for (Size j=0; j<LENGTH(putLength); j++) {
98 callability.push_back(
99 x: ext::make_shared<Callability>(args: Bond::Price(putPrices[j],
100 Bond::Price::Clean),
101 args: Callability::Put,
102 args: schedule.date(i: putLength[j])));
103 }
104
105 // Assume dividends are paid every 6 months.
106 for (Date d = today + 6*Months; d < exerciseDate; d += 6*Months) {
107 dividends.push_back(x: ext::make_shared<FixedDividend>(args: 1.0, args&: d));
108 }
109
110 DayCounter dayCounter = Actual365Fixed();
111 Time maturity = dayCounter.yearFraction(d1: settlementDate,
112 d2: exerciseDate);
113
114 std::cout << "option type = " << type << std::endl;
115 std::cout << "Time to maturity = " << maturity
116 << std::endl;
117 std::cout << "Underlying price = " << underlying
118 << std::endl;
119 std::cout << "Risk-free interest rate = " << io::rate(r: riskFreeRate)
120 << std::endl;
121 std::cout << "Dividend yield = " << io::rate(r: dividendYield)
122 << std::endl;
123 std::cout << "Volatility = " << io::volatility(v: volatility)
124 << std::endl;
125 std::cout << std::endl;
126
127 std::string method;
128 std::cout << std::endl ;
129
130 // write column headings
131 Size widths[] = { 35, 14, 14 };
132 Size totalWidth = widths[0] + widths[1] + widths[2];
133 std::string rule(totalWidth, '-'), dblrule(totalWidth, '=');
134
135 std::cout << dblrule << std::endl;
136 std::cout << "Tsiveriotis-Fernandes method" << std::endl;
137 std::cout << dblrule << std::endl;
138 std::cout << std::setw(widths[0]) << std::left << "Tree type"
139 << std::setw(widths[1]) << std::left << "European"
140 << std::setw(widths[1]) << std::left << "American"
141 << std::endl;
142 std::cout << rule << std::endl;
143
144 auto exercise = ext::make_shared<EuropeanExercise>(args&: exerciseDate);
145 auto amExercise = ext::make_shared<AmericanExercise>(args&: settlementDate, args&: exerciseDate);
146
147 Handle<Quote> underlyingH(ext::make_shared<SimpleQuote>(args&: underlying));
148
149 Handle<YieldTermStructure> flatTermStructure(
150 ext::make_shared<FlatForward>(args&: settlementDate, args&: riskFreeRate, args&: dayCounter));
151
152 Handle<YieldTermStructure> flatDividendTS(
153 ext::make_shared<FlatForward>(args&: settlementDate, args&: dividendYield, args&: dayCounter));
154
155 Handle<BlackVolTermStructure> flatVolTS(
156 ext::make_shared<BlackConstantVol>(args&: settlementDate, args&: calendar, args&: volatility, args&: dayCounter));
157
158 auto stochasticProcess = ext::make_shared<BlackScholesMertonProcess>(
159 args&: underlyingH, args&: flatDividendTS, args&: flatTermStructure, args&: flatVolTS);
160
161 Size timeSteps = 801;
162
163 Handle<Quote> creditSpread(ext::make_shared<SimpleQuote>(args&: spreadRate));
164
165 auto rate = ext::make_shared<SimpleQuote>(args&: riskFreeRate);
166
167 Handle<YieldTermStructure> discountCurve(
168 ext::make_shared<FlatForward>(args&: today, args: Handle<Quote>(rate), args&: dayCounter));
169
170 ConvertibleFixedCouponBond europeanBond(
171 exercise, conversionRatio, callability,
172 issueDate, settlementDays,
173 coupons, bondDayCount, schedule, redemption);
174
175 ConvertibleFixedCouponBond americanBond(
176 amExercise, conversionRatio, callability,
177 issueDate, settlementDays,
178 coupons, bondDayCount, schedule, redemption);
179
180 method = "Jarrow-Rudd";
181 auto jrEngine = ext::make_shared<BinomialConvertibleEngine<JarrowRudd>>(args&: stochasticProcess, args&: timeSteps, args&: creditSpread, args&: dividends);
182 europeanBond.setPricingEngine(jrEngine);
183 americanBond.setPricingEngine(jrEngine);
184 std::cout << std::setw(widths[0]) << std::left << method
185 << std::fixed
186 << std::setw(widths[1]) << std::left << europeanBond.NPV()
187 << std::setw(widths[2]) << std::left << americanBond.NPV()
188 << std::endl;
189
190 method = "Cox-Ross-Rubinstein";
191 auto crrEngine = ext::make_shared<BinomialConvertibleEngine<CoxRossRubinstein>>(args&: stochasticProcess, args&: timeSteps, args&: creditSpread, args&: dividends);
192 europeanBond.setPricingEngine(crrEngine);
193 americanBond.setPricingEngine(crrEngine);
194 std::cout << std::setw(widths[0]) << std::left << method
195 << std::fixed
196 << std::setw(widths[1]) << std::left << europeanBond.NPV()
197 << std::setw(widths[2]) << std::left << americanBond.NPV()
198 << std::endl;
199
200 method = "Additive equiprobabilities";
201 auto aeqpEngine = ext::make_shared<BinomialConvertibleEngine<AdditiveEQPBinomialTree>>(args&: stochasticProcess, args&: timeSteps, args&: creditSpread, args&: dividends);
202 europeanBond.setPricingEngine(aeqpEngine);
203 americanBond.setPricingEngine(aeqpEngine);
204 std::cout << std::setw(widths[0]) << std::left << method
205 << std::fixed
206 << std::setw(widths[1]) << std::left << europeanBond.NPV()
207 << std::setw(widths[2]) << std::left << americanBond.NPV()
208 << std::endl;
209
210 method = "Trigeorgis";
211 auto trEngine = ext::make_shared<BinomialConvertibleEngine<Trigeorgis>>(args&: stochasticProcess, args&: timeSteps, args&: creditSpread, args&: dividends);
212 europeanBond.setPricingEngine(trEngine);
213 americanBond.setPricingEngine(trEngine);
214 std::cout << std::setw(widths[0]) << std::left << method
215 << std::fixed
216 << std::setw(widths[1]) << std::left << europeanBond.NPV()
217 << std::setw(widths[2]) << std::left << americanBond.NPV()
218 << std::endl;
219
220 method = "Tian";
221 auto tianEngine = ext::make_shared<BinomialConvertibleEngine<Tian>>(args&: stochasticProcess, args&: timeSteps, args&: creditSpread, args&: dividends);
222 europeanBond.setPricingEngine(tianEngine);
223 americanBond.setPricingEngine(tianEngine);
224 std::cout << std::setw(widths[0]) << std::left << method
225 << std::fixed
226 << std::setw(widths[1]) << std::left << europeanBond.NPV()
227 << std::setw(widths[2]) << std::left << americanBond.NPV()
228 << std::endl;
229
230 method = "Leisen-Reimer";
231 auto lrEngine = ext::make_shared<BinomialConvertibleEngine<LeisenReimer>>(args&: stochasticProcess, args&: timeSteps, args&: creditSpread, args&: dividends);
232 europeanBond.setPricingEngine(lrEngine);
233 americanBond.setPricingEngine(lrEngine);
234 std::cout << std::setw(widths[0]) << std::left << method
235 << std::fixed
236 << std::setw(widths[1]) << std::left << europeanBond.NPV()
237 << std::setw(widths[2]) << std::left << americanBond.NPV()
238 << std::endl;
239
240 method = "Joshi";
241 auto joshiEngine = ext::make_shared<BinomialConvertibleEngine<Joshi4>>(args&: stochasticProcess, args&: timeSteps, args&: creditSpread, args&: dividends);
242 europeanBond.setPricingEngine(joshiEngine);
243 americanBond.setPricingEngine(joshiEngine);
244 std::cout << std::setw(widths[0]) << std::left << method
245 << std::fixed
246 << std::setw(widths[1]) << std::left << europeanBond.NPV()
247 << std::setw(widths[2]) << std::left << americanBond.NPV()
248 << std::endl;
249
250 std::cout << dblrule << std::endl;
251
252 return 0;
253 } catch (std::exception& e) {
254 std::cerr << e.what() << std::endl;
255 return 1;
256 } catch (...) {
257 std::cerr << "unknown error" << std::endl;
258 return 1;
259 }
260
261}
262
263

source code of quantlib/Examples/ConvertibleBonds/ConvertibleBonds.cpp