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