00001
00002
00021 #include <ql/quantlib.hpp>
00022 #include <iostream>
00023
00024 using namespace QuantLib;
00025
00026 #if defined(QL_ENABLE_SESSIONS)
00027 namespace QuantLib {
00028
00029 Integer sessionId() { return 0; }
00030
00031 }
00032 #endif
00033
00034
00035
00036 class WeightedPayoff {
00037 public:
00038 WeightedPayoff(Option::Type type,
00039 Time maturity,
00040 Real strike,
00041 Real s0,
00042 Volatility sigma,
00043 Rate r,
00044 Rate q)
00045 : type_(type), maturity_(maturity),
00046 strike_(strike),
00047 s0_(s0),
00048 sigma_(sigma),r_(r), q_(q){}
00049
00050 Real operator()(Real x) const {
00051 Real nuT = (r_-q_-0.5*sigma_*sigma_)*maturity_;
00052 return std::exp(-r_*maturity_)
00053 *PlainVanillaPayoff(type_, strike_)(s0_*std::exp(x))
00054 *std::exp(-(x - nuT)*(x -nuT)/(2*sigma_*sigma_*maturity_))
00055 /std::sqrt(2.0*M_PI*sigma_*sigma_*maturity_);
00056 }
00057 private:
00058 Option::Type type_;
00059 Time maturity_;
00060 Real strike_;
00061 Real s0_;
00062 Volatility sigma_;
00063 Rate r_,q_;
00064 };
00065
00066
00067 int main(int, char* [])
00068 {
00069 try {
00070 QL_IO_INIT
00071
00072 std::cout << "Using " << QL_VERSION << std::endl << std::endl;
00073
00074
00075 Option::Type type(Option::Call);
00076 Real underlying = 7;
00077 Real strike = 8;
00078 Spread dividendYield = 0.05;
00079 Rate riskFreeRate = 0.05;
00080
00081 Date todaysDate(15, May, 1998);
00082 Date settlementDate(17, May, 1998);
00083 Settings::instance().evaluationDate() = todaysDate;
00084
00085 Date exerciseDate(17, May, 1999);
00086 DayCounter dayCounter = Actual365Fixed();
00087 Time maturity = dayCounter.yearFraction(settlementDate,
00088 exerciseDate);
00089
00090 Volatility volatility = 0.10;
00091 std::cout << "option type = " << type << std::endl;
00092 std::cout << "Time to maturity = " << maturity
00093 << std::endl;
00094 std::cout << "Underlying price = " << underlying
00095 << std::endl;
00096 std::cout << "Strike = " << strike
00097 << std::endl;
00098 std::cout << "Risk-free interest rate = " << io::rate(riskFreeRate)
00099 << std::endl;
00100 std::cout << "Dividend yield = " << io::rate(dividendYield)
00101 << std::endl;
00102 std::cout << "Volatility = " << io::volatility(volatility)
00103 << std::endl;
00104 std::cout << std::endl;
00105
00106 Date midlifeDate(19, November, 1998);
00107 std::vector<Date> exDates(2);
00108 exDates[0]=midlifeDate;
00109 exDates[1]=exerciseDate;
00110
00111 boost::shared_ptr<Exercise> exercise(
00112 new EuropeanExercise(exerciseDate));
00113 boost::shared_ptr<Exercise> amExercise(
00114 new AmericanExercise(settlementDate,
00115 exerciseDate));
00116 boost::shared_ptr<Exercise> berExercise(new BermudanExercise(exDates));
00117
00118
00119 Handle<Quote> underlyingH(
00120 boost::shared_ptr<Quote>(new SimpleQuote(underlying)));
00121
00122
00123 Handle<YieldTermStructure> flatTermStructure(
00124 boost::shared_ptr<YieldTermStructure>(
00125 new FlatForward(settlementDate, riskFreeRate, dayCounter)));
00126 Handle<YieldTermStructure> flatDividendTS(
00127 boost::shared_ptr<YieldTermStructure>(
00128 new FlatForward(settlementDate, dividendYield, dayCounter)));
00129 Handle<BlackVolTermStructure> flatVolTS(
00130 boost::shared_ptr<BlackVolTermStructure>(
00131 new BlackConstantVol(settlementDate, volatility, dayCounter)));
00132
00133 std::vector<Date> dates(4);
00134 dates[0] = settlementDate + 1*Months;
00135 dates[1] = exerciseDate;
00136 dates[2] = exerciseDate + 6*Months;
00137 dates[3] = exerciseDate + 12*Months;
00138 std::vector<Real> strikes(4);
00139 strikes[0] = underlying*0.9;
00140 strikes[1] = underlying;
00141 strikes[2] = underlying*1.1;
00142 strikes[3] = underlying*1.2;
00143
00144 Matrix vols(4,4);
00145 vols[0][0] = volatility*1.1;
00146 vols[0][1] = volatility;
00147 vols[0][2] = volatility*0.9;
00148 vols[0][3] = volatility*0.8;
00149 vols[1][0] = volatility*1.1;
00150 vols[1][1] = volatility;
00151 vols[1][2] = volatility*0.9;
00152 vols[1][3] = volatility*0.8;
00153 vols[2][0] = volatility*1.1;
00154 vols[2][1] = volatility;
00155 vols[2][2] = volatility*0.9;
00156 vols[2][3] = volatility*0.8;
00157 vols[3][0] = volatility*1.1;
00158 vols[3][1] = volatility;
00159 vols[3][2] = volatility*0.9;
00160 vols[3][3] = volatility*0.8;
00161
00162 Handle<BlackVolTermStructure> blackSurface(
00163 boost::shared_ptr<BlackVolTermStructure>(
00164 new BlackVarianceSurface(settlementDate, dates,
00165 strikes, vols, dayCounter)));
00166
00167
00168 boost::shared_ptr<StrikedTypePayoff> payoff(new
00169 PlainVanillaPayoff(type, strike));
00170
00171 boost::shared_ptr<BlackScholesProcess> stochasticProcess(new
00172 BlackScholesProcess(underlyingH, flatDividendTS,
00173 flatTermStructure,
00174
00175 flatVolTS));
00176
00177 EuropeanOption option(stochasticProcess, payoff, exercise);
00178
00179
00180 std::string method;
00181 Real value, discrepancy, rightValue, relativeDiscrepancy;
00182
00183 std::cout << std::endl << std::endl;
00184
00185
00186 std::cout << "Method\t\tValue\t\tEstimatedError\tDiscrepancy"
00187 "\tRel. Discr." << std::endl;
00188
00189
00190 method = "Black-Scholes";
00191 option.setPricingEngine(boost::shared_ptr<PricingEngine>(
00192 new AnalyticEuropeanEngine()));
00193 rightValue = value = option.NPV();
00194 discrepancy = std::fabs(value-rightValue);
00195 relativeDiscrepancy = discrepancy/rightValue;
00196 std::cout << method << "\t"
00197 << value << "\t" << "N/A\t\t"
00198 << discrepancy << "\t\t" << relativeDiscrepancy << std::endl;
00199
00200
00201
00202 method = "Integral";
00203 option.setPricingEngine(boost::shared_ptr<PricingEngine>(
00204 new IntegralEngine()));
00205 value = option.NPV();
00206 discrepancy = std::fabs(value-rightValue);
00207 relativeDiscrepancy = discrepancy/rightValue;
00208 std::cout << method << "\t"
00209 << value << "\t" << "N/A\t\t"
00210 << discrepancy << "\t" << relativeDiscrepancy << std::endl;
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 Size timeSteps = 801;
00237
00238
00239 method = "Binomial (JR)";
00240 option.setPricingEngine(boost::shared_ptr<PricingEngine>(
00241 new BinomialVanillaEngine<JarrowRudd>(timeSteps)));
00242 value = option.NPV();
00243 discrepancy = std::fabs(value-rightValue);
00244 relativeDiscrepancy = discrepancy/rightValue;
00245 std::cout << method << "\t"
00246 << value << "\t" << "N/A\t\t"
00247 << discrepancy << "\t" << relativeDiscrepancy << std::endl;
00248
00249
00250
00251 method = "Binomial (CRR)";
00252 option.setPricingEngine(boost::shared_ptr<PricingEngine>(
00253 new BinomialVanillaEngine<CoxRossRubinstein>(timeSteps)));
00254 value = option.NPV();
00255 discrepancy = std::fabs(value-rightValue);
00256 relativeDiscrepancy = discrepancy/rightValue;
00257 std::cout << method << "\t"
00258 << value << "\t" << "N/A\t\t"
00259 << discrepancy << "\t" << relativeDiscrepancy << std::endl;
00260
00261
00262 method = "Additive (EQP)";
00263 option.setPricingEngine(boost::shared_ptr<PricingEngine>(
00264 new BinomialVanillaEngine<AdditiveEQPBinomialTree>(timeSteps)));
00265 value = option.NPV();
00266 discrepancy = std::fabs(value-rightValue);
00267 relativeDiscrepancy = discrepancy/rightValue;
00268 std::cout << method << "\t"
00269 << value << "\t" << "N/A\t\t"
00270 << discrepancy << "\t" << relativeDiscrepancy << std::endl;
00271
00272
00273 method = "Bin. Trigeorgis";
00274 option.setPricingEngine(boost::shared_ptr<PricingEngine>(
00275 new BinomialVanillaEngine<Trigeorgis>(timeSteps)));
00276 value = option.NPV();
00277 discrepancy = std::fabs(value-rightValue);
00278 relativeDiscrepancy = discrepancy/rightValue;
00279 std::cout << method << "\t"
00280 << value << "\t" << "N/A\t\t"
00281 << discrepancy << "\t" << relativeDiscrepancy << std::endl;
00282
00283
00284 method = "Binomial Tian";
00285 option.setPricingEngine(boost::shared_ptr<PricingEngine>(
00286 new BinomialVanillaEngine<Tian>(timeSteps)));
00287 value = option.NPV();
00288 discrepancy = std::fabs(value-rightValue);
00289 relativeDiscrepancy = discrepancy/rightValue;
00290 std::cout << method << "\t"
00291 << value << "\t" << "N/A\t\t"
00292 << discrepancy << "\t" << relativeDiscrepancy << std::endl;
00293
00294
00295 method = "Binomial LR";
00296 option.setPricingEngine(boost::shared_ptr<PricingEngine>(
00297 new BinomialVanillaEngine<LeisenReimer>(timeSteps)));
00298 value = option.NPV();
00299 discrepancy = std::fabs(value-rightValue);
00300 relativeDiscrepancy = discrepancy/rightValue;
00301 std::cout << method << "\t"
00302 << value << "\t" << "N/A\t\t"
00303 << discrepancy << "\t" << relativeDiscrepancy << std::endl;
00304
00305
00306
00307 method = "Finite Diff.";
00308 timeSteps = 100;
00309 Size gridPoints = 100;
00310 option.setPricingEngine(boost::shared_ptr<PricingEngine>(
00311 new FDEuropeanEngine(timeSteps, gridPoints)));
00312 value = option.NPV();
00313 discrepancy = std::fabs(value-rightValue);
00314 relativeDiscrepancy = discrepancy/rightValue;
00315 std::cout << method << "\t"
00316 << value << "\t" << "N/A\t\t"
00317 << discrepancy << "\t" << relativeDiscrepancy << std::endl;
00318
00319
00320 timeSteps = 1;
00321
00322 method = "MC (crude)";
00323 Size mcSeed = 42;
00324
00325 boost::shared_ptr<PricingEngine> mcengine1;
00326 mcengine1 =
00327 MakeMCEuropeanEngine<PseudoRandom>().withSteps(timeSteps)
00328 .withTolerance(0.02)
00329 .withSeed(mcSeed);
00330 option.setPricingEngine(mcengine1);
00331
00332 value = option.NPV();
00333 Real errorEstimate = option.errorEstimate();
00334 discrepancy = std::fabs(value-rightValue);
00335 relativeDiscrepancy = discrepancy/rightValue;
00336 std::cout << method << "\t"
00337 << value << "\t" << errorEstimate << "\t"
00338 << discrepancy << "\t" << relativeDiscrepancy << std::endl;
00339
00340 method = "MC (Sobol)";
00341 timeSteps = 1;
00342 Size nSamples = 32768;
00343
00344 boost::shared_ptr<PricingEngine> mcengine2;
00345 mcengine2 =
00346 MakeMCEuropeanEngine<LowDiscrepancy>().withSteps(timeSteps)
00347 .withSamples(nSamples);
00348 option.setPricingEngine(mcengine2);
00349
00350 value = option.NPV();
00351 discrepancy = std::fabs(value-rightValue);
00352 relativeDiscrepancy = discrepancy/rightValue;
00353 std::cout << method << "\t"
00354 << value << "\t" << "N/A\t\t"
00355 << discrepancy << "\t" << relativeDiscrepancy << std::endl;
00356
00357 return 0;
00358 } catch (std::exception& e) {
00359 std::cout << e.what() << std::endl;
00360 return 1;
00361 } catch (...) {
00362 std::cout << "unknown error" << std::endl;
00363 return 1;
00364 }
00365 }