AmericanOption.cpp

This example calculates American options using different methods
#include <ql/quantlib.hpp> using namespace QuantLib; int main(int, char* []) { try { QL_IO_INIT std::cout << "Using " << QL_VERSION << std::endl << std::endl; // our option Option::Type type(Option::Put); Real underlying = 36; Real strike = 40; Spread dividendYield = 0.00; Rate riskFreeRate = 0.06; Volatility volatility = 0.20; Date todaysDate(15, May, 1998); Date settlementDate(17, May, 1998); Date exerciseDate(17, May, 1999); DayCounter rateDayCounter = Actual365(); Time maturity = rateDayCounter.yearFraction(settlementDate, exerciseDate); std::cout << "option type = " << OptionTypeFormatter::toString(type) << std::endl; std::cout << "Time to maturity = " << maturity << std::endl; std::cout << "Underlying price = " << underlying << std::endl; std::cout << "Strike = " << strike << std::endl; std::cout << "Risk-free interest rate = " << riskFreeRate << std::endl; std::cout << "dividend yield = " << dividendYield << std::endl; std::cout << "Volatility = " << volatility << std::endl; std::cout << std::endl; std::string method; Real value, discrepancy, rightValue, relativeDiscrepancy; rightValue = (type == Option::Put ? 4.48667344 : 2.17372645); std::cout << std::endl ; // write column headings std::cout << "Method\t\t\t\t Value\t\tDiscrepancy" "\tRel. Discr." << std::endl; Date midlifeDate(19, November, 1998); std::vector<Date> exDates(2); exDates[0]=midlifeDate; exDates[1]=exerciseDate; boost::shared_ptr<Exercise> exercise( new EuropeanExercise(exerciseDate)); boost::shared_ptr<Exercise> amExercise( new AmericanExercise(settlementDate, exerciseDate)); boost::shared_ptr<Exercise> berExercise(new BermudanExercise(exDates)); RelinkableHandle<Quote> underlyingH( boost::shared_ptr<Quote>(new SimpleQuote(underlying))); // bootstrap the yield/dividend/vol curves RelinkableHandle<TermStructure> flatTermStructure( boost::shared_ptr<TermStructure>( new FlatForward(todaysDate, settlementDate, riskFreeRate, rateDayCounter))); RelinkableHandle<TermStructure> flatDividendTS( boost::shared_ptr<TermStructure>( new FlatForward(todaysDate, settlementDate, dividendYield, rateDayCounter))); RelinkableHandle<BlackVolTermStructure> flatVolTS( boost::shared_ptr<BlackVolTermStructure>( new BlackConstantVol(settlementDate, volatility))); std::vector<Date> dates(4); dates[0] = settlementDate.plusMonths(1); dates[1] = exerciseDate; dates[2] = exerciseDate.plusMonths(6); dates[3] = exerciseDate.plusMonths(12); std::vector<Real> strikes(4); strikes[0] = underlying*0.9; strikes[1] = underlying; strikes[2] = underlying*1.1; strikes[3] = underlying*1.2; Matrix vols(4,4); vols[0][0] = volatility*1.1; vols[0][1] = volatility; vols[0][2] = volatility*0.9; vols[0][3] = volatility*0.8; vols[1][0] = volatility*1.1; vols[1][1] = volatility; vols[1][2] = volatility*0.9; vols[1][3] = volatility*0.8; vols[2][0] = volatility*1.1; vols[2][1] = volatility; vols[2][2] = volatility*0.9; vols[2][3] = volatility*0.8; vols[3][0] = volatility*1.1; vols[3][1] = volatility; vols[3][2] = volatility*0.9; vols[3][3] = volatility*0.8; RelinkableHandle<BlackVolTermStructure> blackSurface( boost::shared_ptr<BlackVolTermStructure>( new BlackVarianceSurface(settlementDate, dates, strikes, vols))); boost::shared_ptr<StrikedTypePayoff> payoff(new PlainVanillaPayoff(type, strike)); boost::shared_ptr<BlackScholesProcess> stochasticProcess(new BlackScholesProcess( underlyingH, flatDividendTS, flatTermStructure, flatVolTS)); // European option VanillaOption euroOption(stochasticProcess, payoff, exercise, boost::shared_ptr<PricingEngine>(new AnalyticEuropeanEngine())); // method: Black Scholes Engine method = "equivalent European option "; value = euroOption.NPV(); std::cout << method << " " << DecimalFormatter::toString(value, 6) << "\t" << "N/A\t\t" << "N/A\t\t" << std::endl; // American option VanillaOption option(stochasticProcess, payoff, amExercise); Size timeSteps = 801; // Binomial Method (JR) method = "Binomial Jarrow-Rudd "; option.setPricingEngine(boost::shared_ptr<PricingEngine>( new BinomialVanillaEngine<JarrowRudd>(timeSteps))); value = option.NPV(); discrepancy = QL_FABS(value-rightValue); relativeDiscrepancy = discrepancy/rightValue; std::cout << method << " " << DecimalFormatter::toString(value, 6) << "\t" << DecimalFormatter::toString(discrepancy, 6) << "\t" << DecimalFormatter::toString(relativeDiscrepancy, 6) << std::endl; // Binomial Method (CRR) method = "Binomial Cox-Ross-Rubinstein "; option.setPricingEngine(boost::shared_ptr<PricingEngine>( new BinomialVanillaEngine<CoxRossRubinstein>(timeSteps))); value = option.NPV(); discrepancy = QL_FABS(value-rightValue); relativeDiscrepancy = discrepancy/rightValue; std::cout << method << " " << DecimalFormatter::toString(value, 6) << "\t" << DecimalFormatter::toString(discrepancy, 6) << "\t" << DecimalFormatter::toString(relativeDiscrepancy, 6) << std::endl; // Equal Probability Additive Binomial Tree (EQP) method = "Additive equiprobabilities "; option.setPricingEngine(boost::shared_ptr<PricingEngine>( new BinomialVanillaEngine<AdditiveEQPBinomialTree>(timeSteps))); value = option.NPV(); discrepancy = QL_FABS(value-rightValue); relativeDiscrepancy = discrepancy/rightValue; std::cout << method << " " << DecimalFormatter::toString(value, 6) << "\t" << DecimalFormatter::toString(discrepancy, 6) << "\t" << DecimalFormatter::toString(relativeDiscrepancy, 6) << std::endl; // Equal Jumps Additive Binomial Tree (Trigeorgis) method = "Binomial Trigeorgis "; option.setPricingEngine(boost::shared_ptr<PricingEngine>( new BinomialVanillaEngine<Trigeorgis>(timeSteps))); value = option.NPV(); discrepancy = QL_FABS(value-rightValue); relativeDiscrepancy = discrepancy/rightValue; std::cout << method << " " << DecimalFormatter::toString(value, 6) << "\t" << DecimalFormatter::toString(discrepancy, 6) << "\t" << DecimalFormatter::toString(relativeDiscrepancy, 6) << std::endl; // Tian Binomial Tree (third moment matching) method = "Binomial Tian "; option.setPricingEngine(boost::shared_ptr<PricingEngine>( new BinomialVanillaEngine<Tian>(timeSteps))); value = option.NPV(); discrepancy = QL_FABS(value-rightValue); relativeDiscrepancy = discrepancy/rightValue; std::cout << method << " " << DecimalFormatter::toString(value, 6) << "\t" << DecimalFormatter::toString(discrepancy, 6) << "\t" << DecimalFormatter::toString(relativeDiscrepancy, 6) << std::endl; // Leisen-Reimer Binomial Tree method = "Binomial Leisen-Reimer "; option.setPricingEngine(boost::shared_ptr<PricingEngine>( new BinomialVanillaEngine<LeisenReimer>(timeSteps))); value = option.NPV(); discrepancy = QL_FABS(value-rightValue); relativeDiscrepancy = discrepancy/rightValue; std::cout << method << " " << DecimalFormatter::toString(value, 6) << "\t" << DecimalFormatter::toString(discrepancy, 6) << "\t" << DecimalFormatter::toString(relativeDiscrepancy, 6) << std::endl; // Barone-Adesi and Whaley approximation method = "Barone-Adesi and Whaley approx. "; option.setPricingEngine(boost::shared_ptr<PricingEngine>( new BaroneAdesiWhaleyApproximationEngine)); value = option.NPV(); discrepancy = QL_FABS(value-rightValue); relativeDiscrepancy = discrepancy/rightValue; std::cout << method << " " << DecimalFormatter::toString(value, 6) << "\t" << DecimalFormatter::toString(discrepancy, 6) << "\t" << DecimalFormatter::toString(relativeDiscrepancy, 6) << std::endl; // Bjerksund and Stensland approximation method = "Bjerksund and Stensland approx. "; option.setPricingEngine(boost::shared_ptr<PricingEngine>( new BjerksundStenslandApproximationEngine)); value = option.NPV(); discrepancy = QL_FABS(value-rightValue); relativeDiscrepancy = discrepancy/rightValue; std::cout << method << " " << DecimalFormatter::toString(value, 6) << "\t" << DecimalFormatter::toString(discrepancy, 6) << "\t" << DecimalFormatter::toString(relativeDiscrepancy, 6) << std::endl; return 0; } catch (std::exception& e) { std::cout << e.what() << std::endl; return 1; } catch (...) { std::cout << "unknown error" << std::endl; return 1; } }
00001 00020 #include <ql/quantlib.hpp> 00021 00022 using namespace QuantLib; 00023 00024 00025 int main(int, char* []) 00026 { 00027 try { 00028 QL_IO_INIT 00029 00030 std::cout << "Using " << QL_VERSION << std::endl << std::endl; 00031 00032 // our option 00033 Option::Type type(Option::Put); 00034 Real underlying = 36; 00035 Real strike = 40; 00036 Spread dividendYield = 0.00; 00037 Rate riskFreeRate = 0.06; 00038 Volatility volatility = 0.20; 00039 00040 Date todaysDate(15, May, 1998); 00041 Date settlementDate(17, May, 1998); 00042 Date exerciseDate(17, May, 1999); 00043 DayCounter rateDayCounter = Actual365(); 00044 Time maturity = rateDayCounter.yearFraction(settlementDate, 00045 exerciseDate); 00046 00047 std::cout << "option type = " << OptionTypeFormatter::toString(type) 00048 << std::endl; 00049 std::cout << "Time to maturity = " << maturity 00050 << std::endl; 00051 std::cout << "Underlying price = " << underlying 00052 << std::endl; 00053 std::cout << "Strike = " << strike 00054 << std::endl; 00055 std::cout << "Risk-free interest rate = " << riskFreeRate 00056 << std::endl; 00057 std::cout << "dividend yield = " << dividendYield 00058 << std::endl; 00059 std::cout << "Volatility = " << volatility 00060 << std::endl; 00061 std::cout << std::endl; 00062 00063 std::string method; 00064 00065 Real value, discrepancy, rightValue, relativeDiscrepancy; 00066 rightValue = (type == Option::Put ? 4.48667344 : 2.17372645); 00067 00068 std::cout << std::endl ; 00069 00070 // write column headings 00071 std::cout << "Method\t\t\t\t Value\t\tDiscrepancy" 00072 "\tRel. Discr." << std::endl; 00073 00074 Date midlifeDate(19, November, 1998); 00075 std::vector<Date> exDates(2); 00076 exDates[0]=midlifeDate; 00077 exDates[1]=exerciseDate; 00078 00079 boost::shared_ptr<Exercise> exercise( 00080 new EuropeanExercise(exerciseDate)); 00081 boost::shared_ptr<Exercise> amExercise( 00082 new AmericanExercise(settlementDate, 00083 exerciseDate)); 00084 boost::shared_ptr<Exercise> berExercise(new BermudanExercise(exDates)); 00085 00086 00087 RelinkableHandle<Quote> underlyingH( 00088 boost::shared_ptr<Quote>(new SimpleQuote(underlying))); 00089 00090 // bootstrap the yield/dividend/vol curves 00091 RelinkableHandle<TermStructure> flatTermStructure( 00092 boost::shared_ptr<TermStructure>( 00093 new FlatForward(todaysDate, settlementDate, 00094 riskFreeRate, rateDayCounter))); 00095 RelinkableHandle<TermStructure> flatDividendTS( 00096 boost::shared_ptr<TermStructure>( 00097 new FlatForward(todaysDate, settlementDate, 00098 dividendYield, rateDayCounter))); 00099 RelinkableHandle<BlackVolTermStructure> flatVolTS( 00100 boost::shared_ptr<BlackVolTermStructure>( 00101 new BlackConstantVol(settlementDate, volatility))); 00102 00103 std::vector<Date> dates(4); 00104 dates[0] = settlementDate.plusMonths(1); 00105 dates[1] = exerciseDate; 00106 dates[2] = exerciseDate.plusMonths(6); 00107 dates[3] = exerciseDate.plusMonths(12); 00108 std::vector<Real> strikes(4); 00109 strikes[0] = underlying*0.9; 00110 strikes[1] = underlying; 00111 strikes[2] = underlying*1.1; 00112 strikes[3] = underlying*1.2; 00113 00114 Matrix vols(4,4); 00115 vols[0][0] = volatility*1.1; vols[0][1] = volatility; 00116 vols[0][2] = volatility*0.9; vols[0][3] = volatility*0.8; 00117 vols[1][0] = volatility*1.1; vols[1][1] = volatility; 00118 vols[1][2] = volatility*0.9; vols[1][3] = volatility*0.8; 00119 vols[2][0] = volatility*1.1; vols[2][1] = volatility; 00120 vols[2][2] = volatility*0.9; vols[2][3] = volatility*0.8; 00121 vols[3][0] = volatility*1.1; vols[3][1] = volatility; 00122 vols[3][2] = volatility*0.9; vols[3][3] = volatility*0.8; 00123 RelinkableHandle<BlackVolTermStructure> blackSurface( 00124 boost::shared_ptr<BlackVolTermStructure>( 00125 new BlackVarianceSurface(settlementDate, dates, 00126 strikes, vols))); 00127 00128 boost::shared_ptr<StrikedTypePayoff> payoff(new 00129 PlainVanillaPayoff(type, strike)); 00130 00131 boost::shared_ptr<BlackScholesProcess> stochasticProcess(new 00132 BlackScholesProcess( 00133 underlyingH, 00134 flatDividendTS, 00135 flatTermStructure, 00136 flatVolTS)); 00137 00138 // European option 00139 VanillaOption euroOption(stochasticProcess, payoff, exercise, 00140 boost::shared_ptr<PricingEngine>(new AnalyticEuropeanEngine())); 00141 00142 // method: Black Scholes Engine 00143 method = "equivalent European option "; 00144 value = euroOption.NPV(); 00145 std::cout << method << " " 00146 << DecimalFormatter::toString(value, 6) << "\t" 00147 << "N/A\t\t" 00148 << "N/A\t\t" 00149 << std::endl; 00150 00151 // American option 00152 VanillaOption option(stochasticProcess, payoff, amExercise); 00153 00154 Size timeSteps = 801; 00155 00156 // Binomial Method (JR) 00157 method = "Binomial Jarrow-Rudd "; 00158 option.setPricingEngine(boost::shared_ptr<PricingEngine>( 00159 new BinomialVanillaEngine<JarrowRudd>(timeSteps))); 00160 value = option.NPV(); 00161 discrepancy = QL_FABS(value-rightValue); 00162 relativeDiscrepancy = discrepancy/rightValue; 00163 std::cout << method << " " 00164 << DecimalFormatter::toString(value, 6) << "\t" 00165 << DecimalFormatter::toString(discrepancy, 6) << "\t" 00166 << DecimalFormatter::toString(relativeDiscrepancy, 6) 00167 << std::endl; 00168 00169 // Binomial Method (CRR) 00170 method = "Binomial Cox-Ross-Rubinstein "; 00171 option.setPricingEngine(boost::shared_ptr<PricingEngine>( 00172 new BinomialVanillaEngine<CoxRossRubinstein>(timeSteps))); 00173 value = option.NPV(); 00174 discrepancy = QL_FABS(value-rightValue); 00175 relativeDiscrepancy = discrepancy/rightValue; 00176 std::cout << method << " " 00177 << DecimalFormatter::toString(value, 6) << "\t" 00178 << DecimalFormatter::toString(discrepancy, 6) << "\t" 00179 << DecimalFormatter::toString(relativeDiscrepancy, 6) 00180 << std::endl; 00181 00182 // Equal Probability Additive Binomial Tree (EQP) 00183 method = "Additive equiprobabilities "; 00184 option.setPricingEngine(boost::shared_ptr<PricingEngine>( 00185 new BinomialVanillaEngine<AdditiveEQPBinomialTree>(timeSteps))); 00186 value = option.NPV(); 00187 discrepancy = QL_FABS(value-rightValue); 00188 relativeDiscrepancy = discrepancy/rightValue; 00189 std::cout << method << " " 00190 << DecimalFormatter::toString(value, 6) << "\t" 00191 << DecimalFormatter::toString(discrepancy, 6) << "\t" 00192 << DecimalFormatter::toString(relativeDiscrepancy, 6) 00193 << std::endl; 00194 00195 // Equal Jumps Additive Binomial Tree (Trigeorgis) 00196 method = "Binomial Trigeorgis "; 00197 option.setPricingEngine(boost::shared_ptr<PricingEngine>( 00198 new BinomialVanillaEngine<Trigeorgis>(timeSteps))); 00199 value = option.NPV(); 00200 discrepancy = QL_FABS(value-rightValue); 00201 relativeDiscrepancy = discrepancy/rightValue; 00202 std::cout << method << " " 00203 << DecimalFormatter::toString(value, 6) << "\t" 00204 << DecimalFormatter::toString(discrepancy, 6) << "\t" 00205 << DecimalFormatter::toString(relativeDiscrepancy, 6) 00206 << std::endl; 00207 00208 // Tian Binomial Tree (third moment matching) 00209 method = "Binomial Tian "; 00210 option.setPricingEngine(boost::shared_ptr<PricingEngine>( 00211 new BinomialVanillaEngine<Tian>(timeSteps))); 00212 value = option.NPV(); 00213 discrepancy = QL_FABS(value-rightValue); 00214 relativeDiscrepancy = discrepancy/rightValue; 00215 std::cout << method << " " 00216 << DecimalFormatter::toString(value, 6) << "\t" 00217 << DecimalFormatter::toString(discrepancy, 6) << "\t" 00218 << DecimalFormatter::toString(relativeDiscrepancy, 6) 00219 << std::endl; 00220 00221 // Leisen-Reimer Binomial Tree 00222 method = "Binomial Leisen-Reimer "; 00223 option.setPricingEngine(boost::shared_ptr<PricingEngine>( 00224 new BinomialVanillaEngine<LeisenReimer>(timeSteps))); 00225 value = option.NPV(); 00226 discrepancy = QL_FABS(value-rightValue); 00227 relativeDiscrepancy = discrepancy/rightValue; 00228 std::cout << method << " " 00229 << DecimalFormatter::toString(value, 6) << "\t" 00230 << DecimalFormatter::toString(discrepancy, 6) << "\t" 00231 << DecimalFormatter::toString(relativeDiscrepancy, 6) 00232 << std::endl; 00233 00234 // Barone-Adesi and Whaley approximation 00235 method = "Barone-Adesi and Whaley approx. "; 00236 option.setPricingEngine(boost::shared_ptr<PricingEngine>( 00237 new BaroneAdesiWhaleyApproximationEngine)); 00238 value = option.NPV(); 00239 discrepancy = QL_FABS(value-rightValue); 00240 relativeDiscrepancy = discrepancy/rightValue; 00241 std::cout << method << " " 00242 << DecimalFormatter::toString(value, 6) << "\t" 00243 << DecimalFormatter::toString(discrepancy, 6) << "\t" 00244 << DecimalFormatter::toString(relativeDiscrepancy, 6) 00245 << std::endl; 00246 00247 // Bjerksund and Stensland approximation 00248 method = "Bjerksund and Stensland approx. "; 00249 option.setPricingEngine(boost::shared_ptr<PricingEngine>( 00250 new BjerksundStenslandApproximationEngine)); 00251 value = option.NPV(); 00252 discrepancy = QL_FABS(value-rightValue); 00253 relativeDiscrepancy = discrepancy/rightValue; 00254 std::cout << method << " " 00255 << DecimalFormatter::toString(value, 6) << "\t" 00256 << DecimalFormatter::toString(discrepancy, 6) << "\t" 00257 << DecimalFormatter::toString(relativeDiscrepancy, 6) 00258 << std::endl; 00259 00260 return 0; 00261 } catch (std::exception& e) { 00262 std::cout << e.what() << std::endl; 00263 return 1; 00264 } catch (...) { 00265 std::cout << "unknown error" << std::endl; 00266 return 1; 00267 } 00268 }

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