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