For a given set of option parameters, this example computes the value of three different equity options types (with european, bermudan and american exercise features) using different valuation algorithms. The calculation methods are Black-Scholes (for european options only), Barone-Adesi/Whaley (american-only), Bjerksund/Stensland (american), Integral (european), finite differences, binomial trees, crude Monte Carlo (european-only) and Sobol-sequence Monte Carlo (european-only).
#if !defined(BOOST_ALL_NO_LIB) && defined(BOOST_MSVC)
#endif
#include <iostream>
#include <iomanip>
int main(int, char* []) {
try {
std::cout << std::endl;
Date todaysDate(15, May, 1998);
Date settlementDate(17, May, 1998);
Settings::instance().evaluationDate() = todaysDate;
Rate riskFreeRate = 0.06;
Date maturity(17, May, 1999);
std::cout << "Option type = " << type << std::endl;
std::cout << "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;
std::string method;
std::cout << std::endl ;
Size widths[] = { 35, 14, 14, 14 };
std::cout << std::setw(widths[0]) << std::left << "Method"
<< std::setw(widths[1]) << std::left << "European"
<< std::setw(widths[2]) << std::left << "Bermudan"
<< std::setw(widths[3]) << std::left << "American"
<< std::endl;
std::vector<Date> exerciseDates;
exerciseDates.push_back(settlementDate + 3*i*Months);
auto europeanExercise = ext::make_shared<EuropeanExercise>(maturity);
auto bermudanExercise = ext::make_shared<BermudanExercise>(exerciseDates);
auto americanExercise = ext::make_shared<AmericanExercise>(settlementDate, maturity);
auto underlyingH = makeQuoteHandle(underlying);
ext::make_shared<FlatForward>(settlementDate, riskFreeRate, dayCounter));
ext::make_shared<FlatForward>(settlementDate, dividendYield, dayCounter));
ext::make_shared<BlackConstantVol>(settlementDate, calendar, volatility,
dayCounter));
auto payoff = ext::make_shared<PlainVanillaPayoff>(type, strike);
auto bsmProcess = ext::make_shared<BlackScholesMertonProcess>(
underlyingH, flatDividendTS, flatTermStructure, flatVolTS);
method = "Black-Scholes";
europeanOption.
setPricingEngine(ext::make_shared<AnalyticEuropeanEngine>(bsmProcess));
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanOption.
NPV()
<< std::setw(widths[2]) << std::left << "N/A"
<< std::setw(widths[3]) << std::left << "N/A"
<< std::endl;
method = "Black Vasicek Model";
auto vasicekProcess = ext::make_shared<Vasicek>(r0, a,
b, sigma_r, riskPremium);
europeanOption.
setPricingEngine(ext::make_shared<AnalyticBlackVasicekEngine>(bsmProcess, vasicekProcess, correlation));
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanOption.
NPV()
<< std::setw(widths[2]) << std::left << "N/A"
<< std::setw(widths[3]) << std::left << "N/A"
<< std::endl;
method = "Heston semi-analytic";
auto hestonProcess = ext::make_shared<HestonProcess>(flatTermStructure, flatDividendTS,
underlyingH, volatility*volatility,
1.0, volatility*volatility, 0.001, 0.0);
auto hestonModel = ext::make_shared<HestonModel>(hestonProcess);
europeanOption.
setPricingEngine(ext::make_shared<AnalyticHestonEngine>(hestonModel));
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanOption.
NPV()
<< std::setw(widths[2]) << std::left << "N/A"
<< std::setw(widths[3]) << std::left << "N/A"
<< std::endl;
method = "Bates semi-analytic";
auto batesProcess = ext::make_shared<BatesProcess>(flatTermStructure, flatDividendTS,
underlyingH, volatility*volatility,
1.0, volatility*volatility, 0.001, 0.0,
1e-14, 1e-14, 1e-14);
auto batesModel = ext::make_shared<BatesModel>(batesProcess);
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanOption.
NPV()
<< std::setw(widths[2]) << std::left << "N/A"
<< std::setw(widths[3]) << std::left << "N/A"
<< std::endl;
method = "Barone-Adesi/Whaley";
americanOption.
setPricingEngine(ext::make_shared<BaroneAdesiWhaleyApproximationEngine>(bsmProcess));
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << "N/A"
<< std::setw(widths[2]) << std::left << "N/A"
<< std::setw(widths[3]) << std::left << americanOption.
NPV()
<< std::endl;
method = "Bjerksund/Stensland";
americanOption.
setPricingEngine(ext::make_shared<BjerksundStenslandApproximationEngine>(bsmProcess));
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << "N/A"
<< std::setw(widths[2]) << std::left << "N/A"
<< std::setw(widths[3]) << std::left << americanOption.
NPV()
<< std::endl;
method = "QD+ fixed-point (fast)";
(bsmProcess, QdFpAmericanEngine::fastScheme()));
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << "N/A"
<< std::setw(widths[2]) << std::left << "N/A"
<< std::setw(widths[3]) << std::left << americanOption.
NPV()
<< std::endl;
method = "QD+ fixed-point (accurate)";
(bsmProcess, QdFpAmericanEngine::accurateScheme()));
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << "N/A"
<< std::setw(widths[2]) << std::left << "N/A"
<< std::setw(widths[3]) << std::left << americanOption.
NPV()
<< std::endl;
method = "QD+ fixed-point (high precision)";
(bsmProcess, QdFpAmericanEngine::highPrecisionScheme()));
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << "N/A"
<< std::setw(widths[2]) << std::left << "N/A"
<< std::setw(widths[3]) << std::left << americanOption.
NPV()
<< std::endl;
method = "Integral";
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanOption.
NPV()
<< std::setw(widths[2]) << std::left << "N/A"
<< std::setw(widths[3]) << std::left << "N/A"
<< std::endl;
method = "Finite differences";
auto fdengine =
ext::make_shared<FdBlackScholesVanillaEngine>(bsmProcess,
timeSteps,
timeSteps-1);
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanOption.
NPV()
<< std::setw(widths[2]) << std::left << bermudanOption.
NPV()
<< std::setw(widths[3]) << std::left << americanOption.
NPV()
<< std::endl;
method = "Binomial Jarrow-Rudd";
auto jrEngine = ext::make_shared<BinomialVanillaEngine<JarrowRudd>>(bsmProcess, timeSteps);
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanOption.
NPV()
<< std::setw(widths[2]) << std::left << bermudanOption.
NPV()
<< std::setw(widths[3]) << std::left << americanOption.
NPV()
<< std::endl;
method = "Binomial Cox-Ross-Rubinstein";
auto crrEngine = ext::make_shared<BinomialVanillaEngine<CoxRossRubinstein>>(bsmProcess, timeSteps);
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanOption.
NPV()
<< std::setw(widths[2]) << std::left << bermudanOption.
NPV()
<< std::setw(widths[3]) << std::left << americanOption.
NPV()
<< std::endl;
method = "Additive equiprobabilities";
auto aeqpEngine = ext::make_shared<BinomialVanillaEngine<AdditiveEQPBinomialTree>>(bsmProcess, timeSteps);
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanOption.
NPV()
<< std::setw(widths[2]) << std::left << bermudanOption.
NPV()
<< std::setw(widths[3]) << std::left << americanOption.
NPV()
<< std::endl;
method = "Binomial Trigeorgis";
auto trigeorgisEngine = ext::make_shared<BinomialVanillaEngine<Trigeorgis>>(bsmProcess, timeSteps);
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanOption.
NPV()
<< std::setw(widths[2]) << std::left << bermudanOption.
NPV()
<< std::setw(widths[3]) << std::left << americanOption.
NPV()
<< std::endl;
method = "Binomial Tian";
auto tianEngine = ext::make_shared<BinomialVanillaEngine<Tian>>(bsmProcess, timeSteps);
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanOption.
NPV()
<< std::setw(widths[2]) << std::left << bermudanOption.
NPV()
<< std::setw(widths[3]) << std::left << americanOption.
NPV()
<< std::endl;
method = "Binomial Leisen-Reimer";
auto lrEngine = ext::make_shared<BinomialVanillaEngine<LeisenReimer>>(bsmProcess, timeSteps);
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanOption.
NPV()
<< std::setw(widths[2]) << std::left << bermudanOption.
NPV()
<< std::setw(widths[3]) << std::left << americanOption.
NPV()
<< std::endl;
method = "Binomial Joshi";
auto joshiEngine = ext::make_shared<BinomialVanillaEngine<Joshi4>>(bsmProcess, timeSteps);
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanOption.
NPV()
<< std::setw(widths[2]) << std::left << bermudanOption.
NPV()
<< std::setw(widths[3]) << std::left << americanOption.
NPV()
<< std::endl;
timeSteps = 1;
method = "MC (crude)";
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanOption.
NPV()
<< std::setw(widths[2]) << std::left << "N/A"
<< std::setw(widths[3]) << std::left << "N/A"
<< std::endl;
method = "QMC (Sobol)";
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanOption.
NPV()
<< std::setw(widths[2]) << std::left << "N/A"
<< std::setw(widths[3]) << std::left << "N/A"
<< std::endl;
method = "MC (Longstaff Schwartz)";
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << "N/A"
<< std::setw(widths[2]) << std::left << "N/A"
<< std::setw(widths[3]) << std::left << americanOption.
NPV()
<< std::endl;
return 0;
} catch (std::exception& e) {
std::cerr << e.what() << std::endl;
return 1;
} catch (...) {
std::cerr << "unknown error" << std::endl;
return 1;
}
}
Analytic European engine.
analytic Heston-model engine
Barone-Adesi and Whaley approximation engine.
analytic Bates model engine
Bjerksund and Stensland approximation engine.
Actual/365 (Fixed) day count convention.
Shared handle to an observable.
Real NPV() const
returns the net present value of the instrument.
void setPricingEngine(const ext::shared_ptr< PricingEngine > &)
set the pricing engine to be used.
Monte Carlo American engine factory.
MakeMCAmericanEngine & withCalibrationSamples(Size calibrationSamples)
MakeMCAmericanEngine & withAbsoluteTolerance(Real tolerance)
MakeMCAmericanEngine & withSeed(BigNatural seed)
MakeMCAmericanEngine & withAntitheticVariate(bool b=true)
MakeMCAmericanEngine & withSteps(Size steps)
Monte Carlo European engine factory.
MakeMCEuropeanEngine & withSeed(BigNatural seed)
MakeMCEuropeanEngine & withSteps(Size steps)
MakeMCEuropeanEngine & withAbsoluteTolerance(Real tolerance)
MakeMCEuropeanEngine & withSamples(Size samples)
Vanilla option (no discrete dividends, no barriers) on a single asset.
ext::function< Real(Real)> b
Finite-differences Black Scholes vanilla option engine.
Real Volatility
volatility
QL_INTEGER Integer
integer number
Real Spread
spreads on interest rates
std::size_t Size
size of a container
ext::shared_ptr< QuantLib::Payoff > payoff
American Monte Carlo engine.
Monte Carlo European option engine.
Global definitions and compiler switches.
Vanilla option on a single asset.