AmericanOption.cpp

This example calculates American options using different methods

00001 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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         // our option
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         // write column headings
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         // bootstrap the yield/dividend/vol curves
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         // European option
00153         VanillaOption euroOption(stochasticProcess, payoff, exercise,
00154             boost::shared_ptr<PricingEngine>(new AnalyticEuropeanEngine()));
00155 
00156         // method: Black Scholes Engine
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         // American option
00167         VanillaOption option(stochasticProcess, payoff, amExercise);
00168 
00169         // target value
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         // Finite differences
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         // Binomial Method (JR)
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         // Binomial Method (CRR)
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         // Equal Probability Additive Binomial Tree (EQP)
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         // Equal Jumps Additive Binomial Tree (Trigeorgis)
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         // Tian Binomial Tree (third moment matching)
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         // Leisen-Reimer Binomial Tree
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         // Barone-Adesi and Whaley approximation
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         // Bjerksund and Stensland approximation
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 }

QuantLib.org
QuantLib
Hosted by
SourceForge.net Logo
Documentation generated by
doxygen