/* @Rate */ final double qRates[] = { 0.00, 0.10, 0.30 };
/* @Rate */ final double rRates[] = { 0.01, 0.05, 0.15 };
/* @Integer */ final int lengths[] = { 1, 2 };
/* @Volatility */ final double vols[] = { 0.05, 0.20, 0.40 };
final DayCounter dc = new Actual360();
final Date today = Date.todaysDate();
new Settings().setEvaluationDate(today);
final SimpleQuote spot = new SimpleQuote(0.0);
final SimpleQuote qRate = new SimpleQuote(0.0);
final Handle<YieldTermStructure> qTS = new Handle<YieldTermStructure>(Utilities.flatRate(qRate, dc));
final SimpleQuote rRate = new SimpleQuote(0.0);
final Handle<YieldTermStructure> rTS = new Handle<YieldTermStructure>(Utilities.flatRate(rRate, dc));
final SimpleQuote vol = new SimpleQuote(0.0);
final Handle<BlackVolTermStructure> volTS = new Handle<BlackVolTermStructure>(Utilities.flatVol(vol, dc));
for (final Type type : types)
for (final double strike : strikes)
for (final int length : lengths) {
final Date exDate = today.add(new Period(length, TimeUnit.Years));
final Exercise exercise = new EuropeanExercise(exDate);
final List<Date> dividendDates = new ArrayList<Date>();
final List</* @Real */ Double> dividends = new ArrayList<Double>();
for (final Date d = today.add(new Period(3, TimeUnit.Months));
d.lt(exercise.lastDate());
d.addAssign(new Period(6, TimeUnit.Months))) {
dividendDates.add(d.clone());
dividends.add(5.0);
}
final StrikedTypePayoff payoff = new PlainVanillaPayoff(type, strike);
final BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(new Handle<Quote>(spot), qTS, rTS, volTS);
final PricingEngine engine = new AnalyticDividendEuropeanEngine(stochProcess);
final DividendVanillaOption option = new DividendVanillaOption(payoff, exercise, dividendDates, dividends);
option.setPricingEngine(engine);
for (final double u : underlyings)
for (final double q : qRates)
for (final double r : rRates)
for (final double v : vols) {
spot.setValue(u);
qRate.setValue(q);
rRate.setValue(r);
vol.setValue(v);
/* @Real */ final double value = option.NPV();
calculated.put("delta", option.delta());
calculated.put("gamma", option.gamma());
calculated.put("theta", option.theta());
calculated.put("rho", option.rho());
calculated.put("vega", option.vega());
if (value > spot.value()*1.0e-5) {
// perturb spot and get delta and gamma
/* @Real */ final double du = u*1.0e-4;
spot.setValue(u+du);
/* @Real */ double value_p = option.NPV();
final double delta_p = option.delta();
spot.setValue(u-du);
/* @Real */ double value_m = option.NPV();
final double delta_m = option.delta();
spot.setValue(u);
expected.put("delta", (value_p - value_m)/(2*du) );
expected.put("gamma", (delta_p - delta_m)/(2*du) );
// perturb risk-free /* @Rate */ double and get rho
final /* @Spread */ double dr = r*1.0e-4;
rRate.setValue(r+dr);
value_p = option.NPV();
rRate.setValue(r-dr);
value_m = option.NPV();
rRate.setValue(r);
expected.put("rho", (value_p - value_m)/(2*dr) );
// perturb /* @Volatility */ double and get vega
final /* @Spread */ double dv = v*1.0e-4;
vol.setValue(v+dv);
value_p = option.NPV();
vol.setValue(v-dv);
value_m = option.NPV();
vol.setValue(v);
expected.put("vega", (value_p - value_m)/(2*dv) );
// perturb date and get theta
final /*@Time*/ double dT = dc.yearFraction(today.sub(1), today.add(1));
new Settings().setEvaluationDate(today.sub(1));
value_m = option.NPV();
new Settings().setEvaluationDate(today.add(1));
value_p = option.NPV();
new Settings().setEvaluationDate(today);