I have been looking at QuantLib I am trying to figure out why I need to write so much boilerplate code even when pricing the "simplest" of European Options using the analytical Black-Scholes formula (note: I am new to option pricing and I might be missing what the following code provides beyond the textbook option pricing examples. In other words if this code takes into account "real-world" option issues it would be great to point this out):
#include <ql/quantlib.hpp>
using namespace QuantLib;
int main(int, char* []) {
// date set up
Calendar calendar = TARGET();
Date todaysDate(27, Jan, 2011);
Date settlementDate(27, Jan, 2011);
Settings::instance().evaluationDate() = todaysDate;
// option parameters
Option::Type type(Option::Call);
Real stock = 47;
Real strike = 40;
Spread dividendYield = 0.00;
Rate riskFreeRate = 0.05;
Volatility volatility = 0.20;
Date maturity(27, May, 2011);
DayCounter dayCounter = Actual365Fixed();
boost::shared_ptr<Exercise>
europeanExercise(new EuropeanExercise(maturity));
Handle<Quote>
underlyingH(boost::shared_ptr<Quote>(new SimpleQuote(stock)));
// 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,
calendar,
volatility,
dayCounter)));
boost::shared_ptr<StrikedTypePayoff> payoff(
new PlainVanillaPayoff(
type,
strike));
boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(
new BlackScholesMertonProcess(
underlyingH,
flatDividendTS,
flatTermStructure,
flatVolTS));
// our option is European-style
VanillaOption europeanOption(
payoff,
europeanExercise);
// computing the option price with the analytic Black-Scholes formulae
europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
new AnalyticEuropeanEngine(
bsmProcess)));
// outputting
std::cout << "Option type = " << type << std::endl;
std::cout << "Maturity = " << maturity << std::endl;
std::cout << "Stock price = " << stock << 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::endl;
std::cout<<"European Option value = " << europeanOption.NPV() << std::endl;
return 0;
}