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