EquityOption.cpp
This example evaluates European, American and Bermudan options using different methods
00001
00002
00020
00021 #define BOOST_LIB_DIAGNOSTIC
00022 # include <ql/quantlib.hpp>
00023 #undef BOOST_LIB_DIAGNOSTIC
00024
00025 #ifdef BOOST_MSVC
00026
00027
00028
00029
00030
00031
00032
00033
00034 #endif
00035
00036 #include <boost/timer.hpp>
00037 #include <iostream>
00038 #include <iomanip>
00039
00040 using namespace QuantLib;
00041
00042 #if defined(QL_ENABLE_SESSIONS)
00043 namespace QuantLib {
00044
00045 Integer sessionId() { return 0; }
00046
00047 }
00048 #endif
00049
00050
00051 int main(int, char* []) {
00052
00053 try {
00054
00055 boost::timer timer;
00056 std::cout << std::endl;
00057
00058
00059 Option::Type type(Option::Put);
00060 Real underlying = 36;
00061 Real strike = 40;
00062 Spread dividendYield = 0.00;
00063 Rate riskFreeRate = 0.06;
00064 Volatility volatility = 0.20;
00065
00066 Date todaysDate(15, May, 1998);
00067 Date settlementDate(17, May, 1998);
00068 Settings::instance().evaluationDate() = todaysDate;
00069
00070 Date maturity(17, May, 1999);
00071 DayCounter dayCounter = Actual365Fixed();
00072
00073 std::cout << "Option type = " << type << std::endl;
00074 std::cout << "Maturity = " << maturity << std::endl;
00075 std::cout << "Underlying price = " << underlying << std::endl;
00076 std::cout << "Strike = " << strike << std::endl;
00077 std::cout << "Risk-free interest rate = " << io::rate(riskFreeRate)
00078 << std::endl;
00079 std::cout << "Dividend yield = " << io::rate(dividendYield)
00080 << std::endl;
00081 std::cout << "Volatility = " << io::volatility(volatility)
00082 << std::endl;
00083 std::cout << std::endl;
00084
00085 std::string method;
00086
00087 std::cout << std::endl ;
00088
00089
00090 Size widths[] = { 35, 14, 14, 14 };
00091 std::cout << std::setw(widths[0]) << std::left << "Method"
00092 << std::setw(widths[1]) << std::left << "European"
00093 << std::setw(widths[2]) << std::left << "Bermudan"
00094 << std::setw(widths[3]) << std::left << "American"
00095 << std::endl;
00096
00097 std::vector<Date> exerciseDates;
00098 for (Integer i=1; i<=4; i++)
00099 exerciseDates.push_back(settlementDate + 3*i*Months);
00100
00101 boost::shared_ptr<Exercise> europeanExercise(
00102 new EuropeanExercise(maturity));
00103
00104 boost::shared_ptr<Exercise> bermudanExercise(
00105 new BermudanExercise(exerciseDates));
00106
00107 boost::shared_ptr<Exercise> americanExercise(
00108 new AmericanExercise(settlementDate,
00109 maturity));
00110
00111 Handle<Quote> underlyingH(
00112 boost::shared_ptr<Quote>(new SimpleQuote(underlying)));
00113
00114
00115 Handle<YieldTermStructure> flatTermStructure(
00116 boost::shared_ptr<YieldTermStructure>(
00117 new FlatForward(settlementDate, riskFreeRate, dayCounter)));
00118 Handle<YieldTermStructure> flatDividendTS(
00119 boost::shared_ptr<YieldTermStructure>(
00120 new FlatForward(settlementDate, dividendYield, dayCounter)));
00121 Handle<BlackVolTermStructure> flatVolTS(
00122 boost::shared_ptr<BlackVolTermStructure>(
00123 new BlackConstantVol(settlementDate, volatility, dayCounter)));
00124
00125 boost::shared_ptr<StrikedTypePayoff> payoff(
00126 new PlainVanillaPayoff(type, strike));
00127
00128 boost::shared_ptr<StochasticProcess> stochasticProcess(
00129 new BlackScholesMertonProcess(underlyingH, flatDividendTS,
00130 flatTermStructure, flatVolTS));
00131
00132
00133
00134 VanillaOption europeanOption(stochasticProcess, payoff,
00135 europeanExercise);
00136
00137 VanillaOption bermudanOption(stochasticProcess, payoff,
00138 bermudanExercise);
00139
00140 VanillaOption americanOption(stochasticProcess, payoff,
00141 americanExercise);
00142
00143
00144
00145
00146 method = "Black-Scholes";
00147 europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00148 new AnalyticEuropeanEngine));
00149 std::cout << std::setw(widths[0]) << std::left << method
00150 << std::fixed
00151 << std::setw(widths[1]) << std::left << europeanOption.NPV()
00152 << std::setw(widths[2]) << std::left << "N/A"
00153 << std::setw(widths[3]) << std::left << "N/A"
00154 << std::endl;
00155
00156
00157 method = "Barone-Adesi/Whaley";
00158 americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00159 new BaroneAdesiWhaleyApproximationEngine));
00160 std::cout << std::setw(widths[0]) << std::left << method
00161 << std::fixed
00162 << std::setw(widths[1]) << std::left << "N/A"
00163 << std::setw(widths[2]) << std::left << "N/A"
00164 << std::setw(widths[3]) << std::left << americanOption.NPV()
00165 << std::endl;
00166
00167
00168 method = "Bjerksund/Stensland";
00169 americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00170 new BjerksundStenslandApproximationEngine));
00171 std::cout << std::setw(widths[0]) << std::left << method
00172 << std::fixed
00173 << std::setw(widths[1]) << std::left << "N/A"
00174 << std::setw(widths[2]) << std::left << "N/A"
00175 << std::setw(widths[3]) << std::left << americanOption.NPV()
00176 << std::endl;
00177
00178
00179
00180 method = "Integral";
00181 europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00182 new IntegralEngine));
00183 std::cout << std::setw(widths[0]) << std::left << method
00184 << std::fixed
00185 << std::setw(widths[1]) << std::left << europeanOption.NPV()
00186 << std::setw(widths[2]) << std::left << "N/A"
00187 << std::setw(widths[3]) << std::left << "N/A"
00188 << std::endl;
00189
00190
00191
00192 Size timeSteps = 801;
00193
00194 method = "Finite differences";
00195 europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00196 new FDEuropeanEngine(timeSteps,timeSteps-1)));
00197 bermudanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00198 new FDBermudanEngine(timeSteps,timeSteps-1)));
00199 americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00200 new FDAmericanEngine(timeSteps,timeSteps-1)));
00201 std::cout << std::setw(widths[0]) << std::left << method
00202 << std::fixed
00203 << std::setw(widths[1]) << std::left << europeanOption.NPV()
00204 << std::setw(widths[2]) << std::left << bermudanOption.NPV()
00205 << std::setw(widths[3]) << std::left << americanOption.NPV()
00206 << std::endl;
00207
00208
00209
00210 method = "Binomial Jarrow-Rudd";
00211 europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00212 new BinomialVanillaEngine<JarrowRudd>(timeSteps)));
00213 bermudanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00214 new BinomialVanillaEngine<JarrowRudd>(timeSteps)));
00215 americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00216 new BinomialVanillaEngine<JarrowRudd>(timeSteps)));
00217 std::cout << std::setw(widths[0]) << std::left << method
00218 << std::fixed
00219 << std::setw(widths[1]) << std::left << europeanOption.NPV()
00220 << std::setw(widths[2]) << std::left << bermudanOption.NPV()
00221 << std::setw(widths[3]) << std::left << americanOption.NPV()
00222 << std::endl;
00223
00224 method = "Binomial Cox-Ross-Rubinstein";
00225 europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00226 new BinomialVanillaEngine<CoxRossRubinstein>(timeSteps)));
00227 bermudanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00228 new BinomialVanillaEngine<CoxRossRubinstein>(timeSteps)));
00229 americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00230 new BinomialVanillaEngine<CoxRossRubinstein>(timeSteps)));
00231 std::cout << std::setw(widths[0]) << std::left << method
00232 << std::fixed
00233 << std::setw(widths[1]) << std::left << europeanOption.NPV()
00234 << std::setw(widths[2]) << std::left << bermudanOption.NPV()
00235 << std::setw(widths[3]) << std::left << americanOption.NPV()
00236 << std::endl;
00237
00238 method = "Additive equiprobabilities";
00239 europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00240 new BinomialVanillaEngine<AdditiveEQPBinomialTree>(timeSteps)));
00241 bermudanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00242 new BinomialVanillaEngine<AdditiveEQPBinomialTree>(timeSteps)));
00243 americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00244 new BinomialVanillaEngine<AdditiveEQPBinomialTree>(timeSteps)));
00245 std::cout << std::setw(widths[0]) << std::left << method
00246 << std::fixed
00247 << std::setw(widths[1]) << std::left << europeanOption.NPV()
00248 << std::setw(widths[2]) << std::left << bermudanOption.NPV()
00249 << std::setw(widths[3]) << std::left << americanOption.NPV()
00250 << std::endl;
00251
00252 method = "Binomial Trigeorgis";
00253 europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00254 new BinomialVanillaEngine<Trigeorgis>(timeSteps)));
00255 bermudanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00256 new BinomialVanillaEngine<Trigeorgis>(timeSteps)));
00257 americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00258 new BinomialVanillaEngine<Trigeorgis>(timeSteps)));
00259 std::cout << std::setw(widths[0]) << std::left << method
00260 << std::fixed
00261 << std::setw(widths[1]) << std::left << europeanOption.NPV()
00262 << std::setw(widths[2]) << std::left << bermudanOption.NPV()
00263 << std::setw(widths[3]) << std::left << americanOption.NPV()
00264 << std::endl;
00265
00266 method = "Binomial Tian";
00267 europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00268 new BinomialVanillaEngine<Tian>(timeSteps)));
00269 bermudanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00270 new BinomialVanillaEngine<Tian>(timeSteps)));
00271 americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00272 new BinomialVanillaEngine<Tian>(timeSteps)));
00273 std::cout << std::setw(widths[0]) << std::left << method
00274 << std::fixed
00275 << std::setw(widths[1]) << std::left << europeanOption.NPV()
00276 << std::setw(widths[2]) << std::left << bermudanOption.NPV()
00277 << std::setw(widths[3]) << std::left << americanOption.NPV()
00278 << std::endl;
00279
00280 method = "Binomial Leisen-Reimer";
00281 europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00282 new BinomialVanillaEngine<LeisenReimer>(timeSteps)));
00283 bermudanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00284 new BinomialVanillaEngine<LeisenReimer>(timeSteps)));
00285 americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00286 new BinomialVanillaEngine<LeisenReimer>(timeSteps)));
00287 std::cout << std::setw(widths[0]) << std::left << method
00288 << std::fixed
00289 << std::setw(widths[1]) << std::left << europeanOption.NPV()
00290 << std::setw(widths[2]) << std::left << bermudanOption.NPV()
00291 << std::setw(widths[3]) << std::left << americanOption.NPV()
00292 << std::endl;
00293
00294 method = "Binomial Joshi";
00295 europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00296 new BinomialVanillaEngine<Joshi4>(timeSteps)));
00297 bermudanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00298 new BinomialVanillaEngine<Joshi4>(timeSteps)));
00299 americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00300 new BinomialVanillaEngine<Joshi4>(timeSteps)));
00301 std::cout << std::setw(widths[0]) << std::left << method
00302 << std::fixed
00303 << std::setw(widths[1]) << std::left << europeanOption.NPV()
00304 << std::setw(widths[2]) << std::left << bermudanOption.NPV()
00305 << std::setw(widths[3]) << std::left << americanOption.NPV()
00306 << std::endl;
00307
00308
00309
00310 timeSteps = 1;
00311
00312 method = "MC (crude)";
00313 Size mcSeed = 42;
00314
00315 boost::shared_ptr<PricingEngine> mcengine1;
00316 mcengine1 =
00317 MakeMCEuropeanEngine<PseudoRandom>().withSteps(timeSteps)
00318 .withTolerance(0.02)
00319 .withSeed(mcSeed);
00320 europeanOption.setPricingEngine(mcengine1);
00321
00322 std::cout << std::setw(widths[0]) << std::left << method
00323 << std::fixed
00324 << std::setw(widths[1]) << std::left << europeanOption.NPV()
00325 << std::setw(widths[2]) << std::left << "N/A"
00326 << std::setw(widths[3]) << std::left << "N/A"
00327 << std::endl;
00328
00329 method = "MC (Sobol)";
00330 Size nSamples = 32768;
00331
00332 boost::shared_ptr<PricingEngine> mcengine2;
00333 mcengine2 =
00334 MakeMCEuropeanEngine<LowDiscrepancy>().withSteps(timeSteps)
00335 .withSamples(nSamples);
00336 europeanOption.setPricingEngine(mcengine2);
00337 std::cout << std::setw(widths[0]) << std::left << method
00338 << std::fixed
00339 << std::setw(widths[1]) << std::left << europeanOption.NPV()
00340 << std::setw(widths[2]) << std::left << "N/A"
00341 << std::setw(widths[3]) << std::left << "N/A"
00342 << std::endl;
00343
00344 method = "MC (Longstaff Schwartz)";
00345 boost::shared_ptr<PricingEngine> mcengine3;
00346 mcengine3 =
00347 MakeMCAmericanEngine<PseudoRandom>().withSteps(100)
00348 .withAntitheticVariate()
00349 .withCalibrationSamples(4096)
00350 .withTolerance(0.02)
00351 .withSeed(mcSeed);
00352 americanOption.setPricingEngine(mcengine3);
00353 std::cout << std::setw(widths[0]) << std::left << method
00354 << std::fixed
00355 << std::setw(widths[1]) << std::left << "N/A"
00356 << std::setw(widths[2]) << std::left << "N/A"
00357 << std::setw(widths[3]) << std::left << americanOption.NPV()
00358 << std::endl;
00359
00360 Real seconds = timer.elapsed();
00361 Integer hours = int(seconds/3600);
00362 seconds -= hours * 3600;
00363 Integer minutes = int(seconds/60);
00364 seconds -= minutes * 60;
00365 std::cout << " \nRun completed in ";
00366 if (hours > 0)
00367 std::cout << hours << " h ";
00368 if (hours > 0 || minutes > 0)
00369 std::cout << minutes << " m ";
00370 std::cout << std::fixed << std::setprecision(0)
00371 << seconds << " s\n" << std::endl;
00372
00373 return 0;
00374 } catch (std::exception& e) {
00375 std::cout << e.what() << std::endl;
00376 return 1;
00377 } catch (...) {
00378 std::cout << "unknown error" << std::endl;
00379 return 1;
00380 }
00381 }