Posted by
UNG on
Jan 16, 2006; 1:32pm
URL: http://quantlib.414.s1.nabble.com/Strange-Basic-Option-Valuation-Problem-Part-II-tp4357.html
Consider the following European option:
Option::Type type(Option::Call);
Real underlying = 30.07;
Real strike = 35.0;
Spread dividendYield = 0.0;
Rate riskFreeRate = 0.0433;
Date todaysDate(16, January, 2006);
Date settlementDate(16, January, 2006);
Date exerciseDate(18, February, 2006);
DayCounter dayCounter = Actual360();
double optPx = 0.55;
Compare results from:
** Option calculator
http://www.888options.com/resources/options_calc.jsp(Bloomberg results are the same within 4th decimal)
I.V. 0.549 Delta 0.2105 Gamma 0.0576 Vega 0.0261
Rho 0.0052
** Quantlib:
impliedVol: 0.549073
delta: 0.0567826
gamma: 0.0417672
theta: -0.00485107
vega: 0.0103857
rho: 0.150655
Attached is QuantLib default example with hardcoded
parameters.
---8<-----------------------------------------------------------------------------------------------------
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil;
c-basic-offset: 4 -*- */
/*!
Copyright (C) 2003 Ferdinando Ametrano
Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
This file is part of QuantLib, a
free-software/open-source library for financial
quantitative analysts and developers -
http://quantlib.org/ QuantLib is free software: you can redistribute it
and/or modify it under the terms of the QuantLib
license. You should have received a copy of the
license along with this program; if not, please email
<
[hidden email]>. The license is also
available online at
<
http://quantlib.org/reference/license.html>.
This program is distributed in the hope that it will
be useful, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the license for more details.
*/
#include <ql/quantlib.hpp>
#include <iostream>
using namespace QuantLib;
#if defined(QL_ENABLE_SESSIONS)
namespace QuantLib {
Integer sessionId() { return 0; }
}
#endif
// This will be included in the library after a bit of
redesign class WeightedPayoff {
public:
WeightedPayoff(Option::Type type,
Time maturity,
Real strike,
Real s0,
Volatility sigma,
Rate r,
Rate q)
: type_(type), maturity_(maturity),
strike_(strike),
s0_(s0),
sigma_(sigma),r_(r), q_(q){}
Real operator()(Real x) const {
Real nuT =
(r_-q_-0.5*sigma_*sigma_)*maturity_;
return std::exp(-r_*maturity_)
*PlainVanillaPayoff(type_,
strike_)(s0_*std::exp(x))
*std::exp(-(x - nuT)*(x
-nuT)/(2*sigma_*sigma_*maturity_))
/std::sqrt(2.0*M_PI*sigma_*sigma_*maturity_);
}
private:
Option::Type type_;
Time maturity_;
Real strike_;
Real s0_;
Volatility sigma_;
Rate r_,q_;
};
int main(int, char* [])
{
try {
QL_IO_INIT
std::cout << "Using " << QL_VERSION <<
std::endl << std::endl;
// our option
Option::Type type(Option::Call);
Real underlying = 30.07; //50.78; //51.69;
Real strike = 35.0; // 52.5;
Spread dividendYield = 0.0; // 0.0070964;
//0.0;
Rate riskFreeRate = 0.0433; //0.01;
Date todaysDate(16, January, 2006);
Date settlementDate(16, January, 2006);
Settings::instance().evaluationDate() =
todaysDate;
Date exerciseDate(18, February, 2006);
DayCounter dayCounter = Actual360();
Time maturity =
dayCounter.yearFraction(settlementDate,
exerciseDate);
Volatility volatility = 0.3;
std::cout << "option type = " << 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 = " <<
io::rate(riskFreeRate)
<< std::endl;
std::cout << "Dividend yield = " <<
io::rate(dividendYield)
<< std::endl;
std::cout << "Volatility = " <<
io::volatility(volatility)
<< std::endl;
std::cout << 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));
//
//
Handle<Quote> underlyingH(
boost::shared_ptr<Quote>(new
SimpleQuote(underlying)));
// bootstrap the yield/dividend/vol curves
Handle<YieldTermStructure> flatTermStructure(
boost::shared_ptr<YieldTermStructure>(
new FlatForward(settlementDate,
riskFreeRate, dayCounter)));
Handle<YieldTermStructure> flatDividendTS(
boost::shared_ptr<YieldTermStructure>(
new FlatForward(settlementDate,
dividendYield, dayCounter)));
Handle<BlackVolTermStructure> flatVolTS(
boost::shared_ptr<BlackVolTermStructure>(
new BlackConstantVol(settlementDate,
volatility, dayCounter))); //
// std::vector<Date> dates(4);
// dates[0] = settlementDate + 1*Months;
// dates[1] = exerciseDate;
// dates[2] = exerciseDate + 6*Months;
// dates[3] = exerciseDate + 12*Months;
// 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;
//
// Handle<BlackVolTermStructure> blackSurface(
//
boost::shared_ptr<BlackVolTermStructure>(
// new
BlackVarianceSurface(settlementDate, dates,
// strikes,
vols, dayCounter)));
boost::shared_ptr<StrikedTypePayoff>
payoff(new
PlainVanillaPayoff(type, strike));
boost::shared_ptr<BlackScholesProcess>
stochasticProcess(new
BlackScholesProcess(underlyingH,
flatDividendTS,
flatTermStructure,
// blackSurface
flatVolTS));
EuropeanOption option(stochasticProcess,
payoff, exercise);
std::string method;
Real value, discrepancy, rightValue,
relativeDiscrepancy;
std::cout << std::endl << std::endl;
// write column headings
std::cout <<
"Method\t\tValue\t\tEstimatedError\tDiscrepancy"
"\tRel. Discr." << std::endl;
// method: Black-Scholes Engine
method = "Black-Scholes";
option.setPricingEngine(boost::shared_ptr<PricingEngine>(
new AnalyticEuropeanEngine()));
double optPx = 0.55; //1.6; //1.75;
double impliedVol = option.impliedVolatility(
optPx );
double delta = option.delta();
double gamma = option.gamma();
double theta = option.theta()/365.0;
double vega = option.vega()/100.0;
double rho = option.rho();
double divRho = option.dividendRho();
std::cout << "impliedVol: " << "\t" <<
impliedVol << std::endl
<< "delta: " << "\t" << delta << std::endl
<< "gamma: " << "\t" << gamma << std::endl
<< "theta: " << "\t" << theta << std::endl
<< "vega: " << "\t" << vega << std::endl
<< "rho: " << "\t" << rho << std::endl
<< "divRho: " << "\t" << divRho <<
std::endl;
rightValue = value = option.NPV();
discrepancy = std::fabs(value-rightValue);
relativeDiscrepancy = discrepancy/rightValue;
std::cout << method << "\t"
<< value << "\t" << "N/A\t\t"
<< discrepancy << "\t\t" <<
relativeDiscrepancy << std::endl;
// method: Integral
method = "Integral";
option.setPricingEngine(boost::shared_ptr<PricingEngine>(
new IntegralEngine()));
value = option.NPV();
discrepancy = std::fabs(value-rightValue);
relativeDiscrepancy = discrepancy/rightValue;
std::cout << method << "\t"
<< value << "\t" << "N/A\t\t"
<< discrepancy << "\t" <<
relativeDiscrepancy << std::endl;
/*
// method: Integral
method = "Binary Cash";
option.setPricingEngine(boost::shared_ptr<PricingEngine>(
new IntegralCashOrNothingEngine(1.0)));
value = option.NPV();
discrepancy = std::fabs(value-rightValue);
relativeDiscrepancy = discrepancy/rightValue;
std::cout << method << "\t"
<< value << "\t" << "N/A\t\t"
<< discrepancy << "\t" <<
relativeDiscrepancy << std::endl;
// method: Integral
method = "Binary Asset";
option.setPricingEngine(boost::shared_ptr<PricingEngine>(
new IntegralAssetOrNothingEngine()));
value = option.NPV();
discrepancy = std::fabs(value-rightValue);
relativeDiscrepancy = discrepancy/rightValue;
std::cout << method << "\t"
<< value << "\t" << "N/A\t\t"
<< discrepancy << "\t" <<
relativeDiscrepancy << std::endl;
*/
Size timeSteps = 801;
// Binomial Method (JR)
method = "Binomial (JR)";
option.setPricingEngine(boost::shared_ptr<PricingEngine>(
new
BinomialVanillaEngine<JarrowRudd>(timeSteps)));
value = option.NPV();
discrepancy = std::fabs(value-rightValue);
relativeDiscrepancy = discrepancy/rightValue;
std::cout << method << "\t"
<< value << "\t" << "N/A\t\t"
<< discrepancy << "\t" <<
relativeDiscrepancy << std::endl;
// Binomial Method (CRR)
method = "Binomial (CRR)";
option.setPricingEngine(boost::shared_ptr<PricingEngine>(
new
BinomialVanillaEngine<CoxRossRubinstein>(timeSteps)));
value = option.NPV();
discrepancy = std::fabs(value-rightValue);
relativeDiscrepancy = discrepancy/rightValue;
std::cout << method << "\t"
<< value << "\t" << "N/A\t\t"
<< discrepancy << "\t" <<
relativeDiscrepancy << std::endl;
// Equal Probability Additive Binomial Tree
(EQP)
method = "Additive (EQP)";
option.setPricingEngine(boost::shared_ptr<PricingEngine>(
new
BinomialVanillaEngine<AdditiveEQPBinomialTree>(timeSteps)));
value = option.NPV();
discrepancy = std::fabs(value-rightValue);
relativeDiscrepancy = discrepancy/rightValue;
std::cout << method << "\t"
<< value << "\t" << "N/A\t\t"
<< discrepancy << "\t" <<
relativeDiscrepancy << std::endl;
// Equal Jumps Additive Binomial Tree
(Trigeorgis)
method = "Bin. Trigeorgis";
option.setPricingEngine(boost::shared_ptr<PricingEngine>(
new
BinomialVanillaEngine<Trigeorgis>(timeSteps)));
value = option.NPV();
discrepancy = std::fabs(value-rightValue);
relativeDiscrepancy = discrepancy/rightValue;
std::cout << method << "\t"
<< value << "\t" << "N/A\t\t"
<< discrepancy << "\t" <<
relativeDiscrepancy << 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 = std::fabs(value-rightValue);
relativeDiscrepancy = discrepancy/rightValue;
std::cout << method << "\t"
<< value << "\t" << "N/A\t\t"
<< discrepancy << "\t" <<
relativeDiscrepancy << std::endl;
// Leisen-Reimer Binomial Tree
method = "Binomial LR";
option.setPricingEngine(boost::shared_ptr<PricingEngine>(
new
BinomialVanillaEngine<LeisenReimer>(timeSteps)));
value = option.NPV();
discrepancy = std::fabs(value-rightValue);
relativeDiscrepancy = discrepancy/rightValue;
std::cout << method << "\t"
<< value << "\t" << "N/A\t\t"
<< discrepancy << "\t" <<
relativeDiscrepancy << std::endl;
// Finite Differences
method = "Finite Diff.";
timeSteps = 100;
Size gridPoints = 100;
option.setPricingEngine(boost::shared_ptr<PricingEngine>(
new FDEuropeanEngine(timeSteps,
gridPoints)));
value = option.NPV();
discrepancy = std::fabs(value-rightValue);
relativeDiscrepancy = discrepancy/rightValue;
std::cout << method << "\t"
<< value << "\t" << "N/A\t\t"
<< discrepancy << "\t" <<
relativeDiscrepancy << std::endl;
// Monte Carlo Method
timeSteps = 1;
method = "MC (crude)";
Size mcSeed = 42;
boost::shared_ptr<PricingEngine> mcengine1;
mcengine1 =
MakeMCEuropeanEngine<PseudoRandom>().withSteps(timeSteps)
.withTolerance(0.02)
.withSeed(mcSeed);
option.setPricingEngine(mcengine1);
value = option.NPV();
Real errorEstimate = option.errorEstimate();
discrepancy = std::fabs(value-rightValue);
relativeDiscrepancy = discrepancy/rightValue;
std::cout << method << "\t"
<< value << "\t" << errorEstimate <<
"\t"
<< discrepancy << "\t" <<
relativeDiscrepancy << std::endl;
method = "MC (Sobol)";
timeSteps = 1;
Size nSamples = 32768; // 2^15
boost::shared_ptr<PricingEngine> mcengine2;
mcengine2 =
MakeMCEuropeanEngine<LowDiscrepancy>().withSteps(timeSteps)
.withSamples(nSamples);
option.setPricingEngine(mcengine2);
value = option.NPV();
discrepancy = std::fabs(value-rightValue);
relativeDiscrepancy = discrepancy/rightValue;
std::cout << method << "\t"
<< value << "\t" << "N/A\t\t"
<< discrepancy << "\t" <<
relativeDiscrepancy << 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;
}
}
---8<-----------------------------------------------------------------------------------------------------