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