/* @Real */final double qRates[] = { 0.04, 0.05, 0.06 };
/* @Real */final double rRates[] = { 0.01, 0.05, 0.15 };
/* @Integer */final int lengths[] = { 1, 2 };
/* @Volatility */final double vols[] = { 0.11, 0.50, 1.20 };
final DayCounter dc = new Actual360();
final SimpleQuote spot = new SimpleQuote(0.0);
final SimpleQuote qRate = new SimpleQuote(0.0);
final YieldTermStructure qTS = Utilities.flatRate(qRate, dc);
final SimpleQuote rRate = new SimpleQuote(0.0);
final YieldTermStructure rTS = Utilities.flatRate(rRate, dc);
final SimpleQuote vol = new SimpleQuote(0.0);
final BlackVolTermStructure volTS = Utilities.flatVol(vol, dc);
final BlackScholesMertonProcess process = new BlackScholesMertonProcess(
new Handle<Quote>(spot),
new Handle<YieldTermStructure>(qTS),
new Handle<YieldTermStructure>(rTS),
new Handle<BlackVolTermStructure>(volTS));
final Date today = new Settings().evaluationDate();
for (final Type type : types) {
for (final double strike : strikes) {
for (final int length : lengths) {
final Date exerciseDate = new Date(today.dayOfMonth(), today.month(), today.year() + length);
final EuropeanExercise maturity = new EuropeanExercise(exerciseDate);
final PlainVanillaPayoff payoff = new PlainVanillaPayoff(type, strike);
final double runningAverage = 120;
final int pastFixings = 1;
final List<Date> fixingDates = new ArrayList<Date>();
final Date d = today.clone();
final Period THREEMONTH = new Period(3, TimeUnit.Months);
d.addAssign(new Period(3, TimeUnit.Months));
for (d.addAssign(THREEMONTH); d.le(maturity.lastDate()); d.addAssign(THREEMONTH)) {
fixingDates.add(d.clone());
}
final PricingEngine engine = new AnalyticDiscreteGeometricAveragePriceAsianEngine(process);
final DiscreteAveragingAsianOption option = new DiscreteAveragingAsianOption(
AverageType.Geometric, runningAverage, pastFixings, fixingDates, payoff, maturity);
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);
final double value = option.NPV();
final Map<String, Double> calculated = new HashMap<String, Double>();
calculated.put("delta", option.delta());
calculated.put("gamma", option.gamma());
calculated.put("theta", option.theta());
calculated.put("rho", option.rho());
calculated.put("divRho", option.dividendRho());
calculated.put("vega", option.vega());
final Map<String, Double> expected = new HashMap<String, Double>();
if (value > spot.value() * 1.0e-5) {
// perturb spot and get delta and gamma
final double du = u * 1.0e-4;
spot.setValue(u + du);
double value_p = option.NPV();
final double delta_p = option.delta();
spot.setValue(u - du);
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 rates and get rho and dividend rho
final 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));
final double dq = q * 1.0e-4;
qRate.setValue(q + dq);
value_p = option.NPV();
qRate.setValue(q - dq);
value_m = option.NPV();
qRate.setValue(q);
expected.put("divRho", (value_p - value_m) / (2 * dq));
// perturb volatility and get vega
final 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 Date yesterday = today.sub(1);
final Date tomorrow = today.add(1);
final double dT = dc.yearFraction(yesterday, tomorrow);
new Settings().setEvaluationDate(yesterday);
value_m = option.NPV();
new Settings().setEvaluationDate(tomorrow);
value_p = option.NPV();
expected.put("theta", (value_p - value_m) / dT);