AmericanOption.cppThis example calculates American options using different methods
00001
00002
00022 #include <ql/quantlib.hpp>
00023 #include <iostream>
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 std::cout << "Using " << QL_VERSION << std::endl << std::endl;
00042
00043
00044 Option::Type type(Option::Put);
00045 Real underlying = 36;
00046 Real strike = 40;
00047 Spread dividendYield = 0.00;
00048 Rate riskFreeRate = 0.06;
00049 Volatility volatility = 0.20;
00050
00051 Date todaysDate(15, May, 1998);
00052 Date settlementDate(17, May, 1998);
00053 Settings::instance().evaluationDate() = todaysDate;
00054
00055 Date exerciseDate(17, May, 1999);
00056 DayCounter dayCounter = Actual365Fixed();
00057 Time maturity = dayCounter.yearFraction(settlementDate,
00058 exerciseDate);
00059
00060 std::cout << "option type = " << type << std::endl;
00061 std::cout << "Time to maturity = " << maturity
00062 << std::endl;
00063 std::cout << "Underlying price = " << underlying
00064 << std::endl;
00065 std::cout << "Strike = " << strike
00066 << std::endl;
00067 std::cout << "Risk-free interest rate = " << io::rate(riskFreeRate)
00068 << std::endl;
00069 std::cout << "Dividend yield = " << io::rate(dividendYield)
00070 << std::endl;
00071 std::cout << "Volatility = " << io::volatility(volatility)
00072 << std::endl;
00073 std::cout << std::endl;
00074
00075 std::string method;
00076
00077 Real value, discrepancy, rightValue, relativeDiscrepancy;
00078 rightValue = (type == Option::Put ? 4.48667344 : 2.17372645);
00079
00080 std::cout << std::endl ;
00081
00082
00083 Size widths[] = { 35, 14, 14, 14 };
00084 std::cout << std::setw(widths[0]) << std::left << "Method"
00085 << std::setw(widths[1]) << std::left << "Value"
00086 << std::setw(widths[2]) << std::left << "Discrepancy"
00087 << std::setw(widths[3]) << std::left << "Rel. Discr."
00088 << std::endl;
00089
00090 Date midlifeDate(19, November, 1998);
00091 std::vector<Date> exDates(2);
00092 exDates[0]=midlifeDate;
00093 exDates[1]=exerciseDate;
00094
00095 boost::shared_ptr<Exercise> exercise(
00096 new EuropeanExercise(exerciseDate));
00097 boost::shared_ptr<Exercise> amExercise(
00098 new AmericanExercise(settlementDate,
00099 exerciseDate));
00100 boost::shared_ptr<Exercise> berExercise(new BermudanExercise(exDates));
00101
00102
00103 Handle<Quote> underlyingH(
00104 boost::shared_ptr<Quote>(new SimpleQuote(underlying)));
00105
00106
00107 Handle<YieldTermStructure> flatTermStructure(
00108 boost::shared_ptr<YieldTermStructure>(
00109 new FlatForward(settlementDate, riskFreeRate, dayCounter)));
00110 Handle<YieldTermStructure> flatDividendTS(
00111 boost::shared_ptr<YieldTermStructure>(
00112 new FlatForward(settlementDate, dividendYield, dayCounter)));
00113 Handle<BlackVolTermStructure> flatVolTS(
00114 boost::shared_ptr<BlackVolTermStructure>(
00115 new BlackConstantVol(settlementDate, volatility, dayCounter)));
00116
00117 std::vector<Date> dates(4);
00118 dates[0] = settlementDate + 1*Months;
00119 dates[1] = exerciseDate;
00120 dates[2] = exerciseDate + 6*Months;
00121 dates[3] = exerciseDate + 12*Months;
00122 std::vector<Real> strikes(4);
00123 strikes[0] = underlying*0.9;
00124 strikes[1] = underlying;
00125 strikes[2] = underlying*1.1;
00126 strikes[3] = underlying*1.2;
00127
00128 Matrix vols(4,4);
00129 vols[0][0] = volatility*1.1; vols[0][1] = volatility;
00130 vols[0][2] = volatility*0.9; vols[0][3] = volatility*0.8;
00131 vols[1][0] = volatility*1.1; vols[1][1] = volatility;
00132 vols[1][2] = volatility*0.9; vols[1][3] = volatility*0.8;
00133 vols[2][0] = volatility*1.1; vols[2][1] = volatility;
00134 vols[2][2] = volatility*0.9; vols[2][3] = volatility*0.8;
00135 vols[3][0] = volatility*1.1; vols[3][1] = volatility;
00136 vols[3][2] = volatility*0.9; vols[3][3] = volatility*0.8;
00137 Handle<BlackVolTermStructure> blackSurface(
00138 boost::shared_ptr<BlackVolTermStructure>(new
00139 BlackVarianceSurface(settlementDate, dates,
00140 strikes, vols, dayCounter)));
00141
00142 boost::shared_ptr<StrikedTypePayoff> payoff(new
00143 PlainVanillaPayoff(type, strike));
00144
00145 boost::shared_ptr<BlackScholesProcess> stochasticProcess(new
00146 BlackScholesProcess(
00147 underlyingH,
00148 flatDividendTS,
00149 flatTermStructure,
00150 flatVolTS));
00151
00152
00153 VanillaOption euroOption(stochasticProcess, payoff, exercise,
00154 boost::shared_ptr<PricingEngine>(new AnalyticEuropeanEngine()));
00155
00156
00157 method = "equivalent European option";
00158 value = euroOption.NPV();
00159 std::cout << std::setw(widths[0]) << std::left << method
00160 << std::fixed
00161 << std::setw(widths[1]) << std::left << value
00162 << std::setw(widths[2]) << std::left << "N/A"
00163 << std::setw(widths[3]) << std::left << "N/A"
00164 << std::endl;
00165
00166
00167 VanillaOption option(stochasticProcess, payoff, amExercise);
00168
00169
00170 method = "reference value";
00171 std::cout << std::setw(widths[0]) << std::left << method
00172 << std::fixed
00173 << std::setw(widths[1]) << std::left << rightValue
00174 << std::setw(widths[2]) << std::left << "N/A"
00175 << std::setw(widths[3]) << std::left << "N/A"
00176 << std::endl;
00177
00178 Size timeSteps = 801;
00179
00180
00181 method = "Finite differences";
00182 option.setPricingEngine(boost::shared_ptr<PricingEngine>(
00183 new FDAmericanEngine(timeSteps,timeSteps-1)));
00184 value = option.NPV();
00185 discrepancy = std::fabs(value-rightValue);
00186 relativeDiscrepancy = discrepancy/rightValue;
00187 std::cout << std::setw(widths[0]) << std::left << method
00188 << std::fixed
00189 << std::setw(widths[1]) << std::left << value
00190 << std::setw(widths[2]) << std::left << discrepancy
00191 << std::scientific
00192 << std::setw(widths[3]) << std::left << relativeDiscrepancy
00193 << std::endl;
00194
00195
00196 method = "Binomial Jarrow-Rudd";
00197 option.setPricingEngine(boost::shared_ptr<PricingEngine>(
00198 new BinomialVanillaEngine<JarrowRudd>(timeSteps)));
00199 value = option.NPV();
00200 discrepancy = std::fabs(value-rightValue);
00201 relativeDiscrepancy = discrepancy/rightValue;
00202 std::cout << std::setw(widths[0]) << std::left << method
00203 << std::fixed
00204 << std::setw(widths[1]) << std::left << value
00205 << std::setw(widths[2]) << std::left << discrepancy
00206 << std::scientific
00207 << std::setw(widths[3]) << std::left << relativeDiscrepancy
00208 << std::endl;
00209
00210
00211 method = "Binomial Cox-Ross-Rubinstein";
00212 option.setPricingEngine(boost::shared_ptr<PricingEngine>(
00213 new BinomialVanillaEngine<CoxRossRubinstein>(timeSteps)));
00214 value = option.NPV();
00215 discrepancy = std::fabs(value-rightValue);
00216 relativeDiscrepancy = discrepancy/rightValue;
00217 std::cout << std::setw(widths[0]) << std::left << method
00218 << std::fixed
00219 << std::setw(widths[1]) << std::left << value
00220 << std::setw(widths[2]) << std::left << discrepancy
00221 << std::scientific
00222 << std::setw(widths[3]) << std::left << relativeDiscrepancy
00223 << std::endl;
00224
00225
00226 method = "Additive equiprobabilities";
00227 option.setPricingEngine(boost::shared_ptr<PricingEngine>(
00228 new BinomialVanillaEngine<AdditiveEQPBinomialTree>(timeSteps)));
00229 value = option.NPV();
00230 discrepancy = std::fabs(value-rightValue);
00231 relativeDiscrepancy = discrepancy/rightValue;
00232 std::cout << std::setw(widths[0]) << std::left << method
00233 << std::fixed
00234 << std::setw(widths[1]) << std::left << value
00235 << std::setw(widths[2]) << std::left << discrepancy
00236 << std::scientific
00237 << std::setw(widths[3]) << std::left << relativeDiscrepancy
00238 << std::endl;
00239
00240
00241 method = "Binomial Trigeorgis";
00242 option.setPricingEngine(boost::shared_ptr<PricingEngine>(
00243 new BinomialVanillaEngine<Trigeorgis>(timeSteps)));
00244 value = option.NPV();
00245 discrepancy = std::fabs(value-rightValue);
00246 relativeDiscrepancy = discrepancy/rightValue;
00247 std::cout << std::setw(widths[0]) << std::left << method
00248 << std::fixed
00249 << std::setw(widths[1]) << std::left << value
00250 << std::setw(widths[2]) << std::left << discrepancy
00251 << std::scientific
00252 << std::setw(widths[3]) << std::left << relativeDiscrepancy
00253 << std::endl;
00254
00255
00256 method = "Binomial Tian";
00257 option.setPricingEngine(boost::shared_ptr<PricingEngine>(
00258 new BinomialVanillaEngine<Tian>(timeSteps)));
00259 value = option.NPV();
00260 discrepancy = std::fabs(value-rightValue);
00261 relativeDiscrepancy = discrepancy/rightValue;
00262 std::cout << std::setw(widths[0]) << std::left << method
00263 << std::fixed
00264 << std::setw(widths[1]) << std::left << value
00265 << std::setw(widths[2]) << std::left << discrepancy
00266 << std::scientific
00267 << std::setw(widths[3]) << std::left << relativeDiscrepancy
00268 << std::endl;
00269
00270
00271 method = "Binomial Leisen-Reimer";
00272 option.setPricingEngine(boost::shared_ptr<PricingEngine>(
00273 new BinomialVanillaEngine<LeisenReimer>(timeSteps)));
00274 value = option.NPV();
00275 discrepancy = std::fabs(value-rightValue);
00276 relativeDiscrepancy = discrepancy/rightValue;
00277 std::cout << std::setw(widths[0]) << std::left << method
00278 << std::fixed
00279 << std::setw(widths[1]) << std::left << value
00280 << std::setw(widths[2]) << std::left << discrepancy
00281 << std::scientific
00282 << std::setw(widths[3]) << std::left << relativeDiscrepancy
00283 << std::endl;
00284
00285
00286 method = "Barone-Adesi and Whaley approx.";
00287 option.setPricingEngine(boost::shared_ptr<PricingEngine>(
00288 new BaroneAdesiWhaleyApproximationEngine));
00289 value = option.NPV();
00290 discrepancy = std::fabs(value-rightValue);
00291 relativeDiscrepancy = discrepancy/rightValue;
00292 std::cout << std::setw(widths[0]) << std::left << method
00293 << std::fixed
00294 << std::setw(widths[1]) << std::left << value
00295 << std::setw(widths[2]) << std::left << discrepancy
00296 << std::scientific
00297 << std::setw(widths[3]) << std::left << relativeDiscrepancy
00298 << std::endl;
00299
00300
00301 method = "Bjerksund and Stensland approx.";
00302 option.setPricingEngine(boost::shared_ptr<PricingEngine>(
00303 new BjerksundStenslandApproximationEngine));
00304 value = option.NPV();
00305 discrepancy = std::fabs(value-rightValue);
00306 relativeDiscrepancy = discrepancy/rightValue;
00307 std::cout << std::setw(widths[0]) << std::left << method
00308 << std::fixed
00309 << std::setw(widths[1]) << std::left << value
00310 << std::setw(widths[2]) << std::left << discrepancy
00311 << std::scientific
00312 << std::setw(widths[3]) << std::left << relativeDiscrepancy
00313 << std::endl;
00314
00315 return 0;
00316 } catch (std::exception& e) {
00317 std::cout << e.what() << std::endl;
00318 return 1;
00319 } catch (...) {
00320 std::cout << "unknown error" << std::endl;
00321 return 1;
00322 }
00323 }
|