This example evaluates convertible bond prices.
00001
00002
00021
00022 #define BOOST_LIB_DIAGNOSTIC
00023 # include <ql/quantlib.hpp>
00024 #undef BOOST_LIB_DIAGNOSTIC
00025
00026 #ifdef BOOST_MSVC
00027
00028
00029
00030
00031
00032
00033
00034
00035 #endif
00036
00037 #include <boost/timer.hpp>
00038 #include <iostream>
00039 #include <iomanip>
00040
00041 #define LENGTH(a) (sizeof(a)/sizeof(a[0]))
00042
00043 using namespace QuantLib;
00044
00045 #if defined(QL_ENABLE_SESSIONS)
00046 namespace QuantLib {
00047
00048 Integer sessionId() { return 0; }
00049
00050 }
00051 #endif
00052
00053
00054 int main()
00055 {
00056 try {
00057
00058 QL_IO_INIT
00059
00060 boost::timer timer;
00061 std::cout << std::endl;
00062
00063 Option::Type type(Option::Put);
00064 Real underlying = 36.0;
00065 Real spreadRate = 0.005;
00066
00067 Spread dividendYield = 0.02;
00068 Rate riskFreeRate = 0.06;
00069 Volatility volatility = 0.20;
00070
00071 Integer settlementDays = 3;
00072 Integer length = 5;
00073 Real redemption = 100.0;
00074 Real conversionRatio = redemption/underlying;
00075
00076
00077 Calendar calendar = TARGET();
00078 Date today = calendar.adjust(Date::todaysDate());
00079
00080 Settings::instance().evaluationDate() = today;
00081 Date settlementDate = calendar.advance(today, settlementDays, Days);
00082 Date exerciseDate = calendar.advance(settlementDate, length, Years);
00083 Date issueDate = calendar.advance(exerciseDate, -length, Years);
00084
00085 BusinessDayConvention convention = ModifiedFollowing;
00086
00087 Frequency frequency = Annual;
00088
00089 Schedule schedule(issueDate,exerciseDate,Period(frequency),calendar,
00090 convention, convention, true, false);
00091
00092 DividendSchedule dividends;
00093 CallabilitySchedule callability;
00094
00095 std::vector<Real> coupons(1, 0.05);
00096
00097 DayCounter bondDayCount = Thirty360();
00098
00099 Integer callLength[] = { 2, 4 };
00100 Integer putLength[] = { 3 };
00101
00102 Real callPrices[] = { 101.5, 100.85 };
00103 Real putPrices[]= { 105.0 };
00104
00105
00106 for (Size i=0; i<LENGTH(callLength); i++) {
00107 callability.push_back(
00108 boost::shared_ptr<Callability>(
00109 new SoftCallability(Callability::Price(
00110 callPrices[i],
00111 Callability::Price::Clean),
00112 schedule.date(callLength[i]),
00113 1.20)));
00114 }
00115
00116 for (Size j=0; j<LENGTH(putLength); j++) {
00117 callability.push_back(
00118 boost::shared_ptr<Callability>(
00119 new Callability(Callability::Price(
00120 putPrices[j],
00121 Callability::Price::Clean),
00122 Callability::Put,
00123 schedule.date(putLength[j]))));
00124 }
00125
00126
00127 for (Date d = today + 6*Months; d < exerciseDate; d += 6*Months) {
00128 dividends.push_back(
00129 boost::shared_ptr<Dividend>(new FixedDividend(1.0, d)));
00130 }
00131
00132 DayCounter dayCounter = Actual365Fixed();
00133 Time maturity = dayCounter.yearFraction(settlementDate,
00134 exerciseDate);
00135
00136 std::cout << "option type = " << type << std::endl;
00137 std::cout << "Time to maturity = " << maturity
00138 << std::endl;
00139 std::cout << "Underlying price = " << underlying
00140 << std::endl;
00141 std::cout << "Risk-free interest rate = " << io::rate(riskFreeRate)
00142 << std::endl;
00143 std::cout << "Dividend yield = " << io::rate(dividendYield)
00144 << std::endl;
00145 std::cout << "Volatility = " << io::volatility(volatility)
00146 << std::endl;
00147 std::cout << std::endl;
00148
00149 std::string method;
00150 std::cout << std::endl ;
00151
00152
00153 Size widths[] = { 35, 14, 14 };
00154 Size totalWidth = widths[0] + widths[1] + widths[2];
00155 std::string rule(totalWidth, '-'), dblrule(totalWidth, '=');
00156
00157 std::cout << dblrule << std::endl;
00158 std::cout << "Tsiveriotis-Fernandes method" << std::endl;
00159 std::cout << dblrule << std::endl;
00160 std::cout << std::setw(widths[0]) << std::left << "Tree type"
00161 << std::setw(widths[1]) << std::left << "European"
00162 << std::setw(widths[1]) << std::left << "American"
00163 << std::endl;
00164 std::cout << rule << std::endl;
00165
00166 boost::shared_ptr<Exercise> exercise(
00167 new EuropeanExercise(exerciseDate));
00168 boost::shared_ptr<Exercise> amExercise(
00169 new AmericanExercise(settlementDate,
00170 exerciseDate));
00171
00172 Handle<Quote> underlyingH(
00173 boost::shared_ptr<Quote>(new SimpleQuote(underlying)));
00174
00175 Handle<YieldTermStructure> flatTermStructure(
00176 boost::shared_ptr<YieldTermStructure>(
00177 new FlatForward(settlementDate, riskFreeRate, dayCounter)));
00178
00179 Handle<YieldTermStructure> flatDividendTS(
00180 boost::shared_ptr<YieldTermStructure>(
00181 new FlatForward(settlementDate, dividendYield, dayCounter)));
00182
00183 Handle<BlackVolTermStructure> flatVolTS(
00184 boost::shared_ptr<BlackVolTermStructure>(
00185 new BlackConstantVol(settlementDate, volatility, dayCounter)));
00186
00187
00188 boost::shared_ptr<StochasticProcess> stochasticProcess(
00189 new BlackScholesMertonProcess(underlyingH,
00190 flatDividendTS,
00191 flatTermStructure,
00192 flatVolTS));
00193
00194 Size timeSteps = 801;
00195
00196 Handle<Quote> creditSpread(
00197 boost::shared_ptr<Quote>(new SimpleQuote(spreadRate)));
00198
00199 boost::shared_ptr<Quote> rate(new SimpleQuote(riskFreeRate));
00200
00201 Handle<YieldTermStructure> discountCurve(
00202 boost::shared_ptr<YieldTermStructure>(
00203 new FlatForward(today, Handle<Quote>(rate), dayCounter)));
00204
00205 boost::shared_ptr<PricingEngine> engine(
00206 new BinomialConvertibleEngine<JarrowRudd>(timeSteps));
00207
00208 ConvertibleFixedCouponBond europeanBond(
00209 stochasticProcess, exercise, engine,
00210 conversionRatio, dividends, callability,
00211 creditSpread, issueDate, settlementDays,
00212 coupons, bondDayCount, schedule, redemption);
00213
00214 ConvertibleFixedCouponBond americanBond(
00215 stochasticProcess, amExercise, engine,
00216 conversionRatio, dividends, callability,
00217 creditSpread, issueDate, settlementDays,
00218 coupons, bondDayCount, schedule, redemption);
00219
00220 method = "Jarrow-Rudd";
00221 europeanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
00222 new BinomialConvertibleEngine<JarrowRudd>(timeSteps)));
00223 americanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
00224 new BinomialConvertibleEngine<JarrowRudd>(timeSteps)));
00225 std::cout << std::setw(widths[0]) << std::left << method
00226 << std::fixed
00227 << std::setw(widths[1]) << std::left << europeanBond.NPV()
00228 << std::setw(widths[2]) << std::left << americanBond.NPV()
00229 << std::endl;
00230
00231 method = "Cox-Ross-Rubinstein";
00232 europeanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
00233 new BinomialConvertibleEngine<CoxRossRubinstein>(timeSteps)));
00234 americanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
00235 new BinomialConvertibleEngine<CoxRossRubinstein>(timeSteps)));
00236 std::cout << std::setw(widths[0]) << std::left << method
00237 << std::fixed
00238 << std::setw(widths[1]) << std::left << europeanBond.NPV()
00239 << std::setw(widths[2]) << std::left << americanBond.NPV()
00240 << std::endl;
00241
00242 method = "Additive equiprobabilities";
00243 europeanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
00244 new BinomialConvertibleEngine<AdditiveEQPBinomialTree>(timeSteps)));
00245 americanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
00246 new BinomialConvertibleEngine<AdditiveEQPBinomialTree>(timeSteps)));
00247 std::cout << std::setw(widths[0]) << std::left << method
00248 << std::fixed
00249 << std::setw(widths[1]) << std::left << europeanBond.NPV()
00250 << std::setw(widths[2]) << std::left << americanBond.NPV()
00251 << std::endl;
00252
00253 method = "Trigeorgis";
00254 europeanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
00255 new BinomialConvertibleEngine<Trigeorgis>(timeSteps)));
00256 americanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
00257 new BinomialConvertibleEngine<Trigeorgis>(timeSteps)));
00258 std::cout << std::setw(widths[0]) << std::left << method
00259 << std::fixed
00260 << std::setw(widths[1]) << std::left << europeanBond.NPV()
00261 << std::setw(widths[2]) << std::left << americanBond.NPV()
00262 << std::endl;
00263
00264 method = "Tian";
00265 europeanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
00266 new BinomialConvertibleEngine<Tian>(timeSteps)));
00267 americanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
00268 new BinomialConvertibleEngine<Tian>(timeSteps)));
00269 std::cout << std::setw(widths[0]) << std::left << method
00270 << std::fixed
00271 << std::setw(widths[1]) << std::left << europeanBond.NPV()
00272 << std::setw(widths[2]) << std::left << americanBond.NPV()
00273 << std::endl;
00274
00275 method = "Leisen-Reimer";
00276 europeanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
00277 new BinomialConvertibleEngine<LeisenReimer>(timeSteps)));
00278 americanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
00279 new BinomialConvertibleEngine<LeisenReimer>(timeSteps)));
00280 std::cout << std::setw(widths[0]) << std::left << method
00281 << std::fixed
00282 << std::setw(widths[1]) << std::left << europeanBond.NPV()
00283 << std::setw(widths[2]) << std::left << americanBond.NPV()
00284 << std::endl;
00285
00286 std::cout << dblrule << std::endl;
00287
00288 Real seconds = timer.elapsed();
00289 Integer hours = int(seconds/3600);
00290 seconds -= hours * 3600;
00291 Integer minutes = int(seconds/60);
00292 seconds -= minutes * 60;
00293 std::cout << " \nRun completed in ";
00294 if (hours > 0)
00295 std::cout << hours << " h ";
00296 if (hours > 0 || minutes > 0)
00297 std::cout << minutes << " m ";
00298 std::cout << std::fixed << std::setprecision(0)
00299 << seconds << " s\n" << std::endl;
00300
00301 return 0;
00302 } catch (std::exception& e) {
00303 std::cout << e.what() << std::endl;
00304 return 1;
00305 } catch (...) {
00306 std::cout << "unknown error" << std::endl;
00307 return 1;
00308 }
00309
00310 }
00311