_timeSteps, _spaceSteps, _timeGridBunching, _spaceGridBunching, 1.0);
final double[] timeNodes = pdeRes.getGrid().getTimeNodes();
final double[] spaceNodes = pdeRes.getGrid().getSpaceNodes();
final int n = pdeRes.getNumberSpaceNodes();
final DoubleArrayList strikes = new DoubleArrayList();
final DoubleArrayList impliedVolatilities = new DoubleArrayList();
final DoubleArrayList prices = new DoubleArrayList();
final DoubleArrayList blackPrices = new DoubleArrayList();
final DoubleArrayList absoluteDomesticPrice = new DoubleArrayList();
//final DoubleArrayList absoluteForeignPrice = new DoubleArrayList();
final DoubleArrayList bsDelta = new DoubleArrayList();
final DoubleArrayList bsDualDelta = new DoubleArrayList();
final DoubleArrayList bsGamma = new DoubleArrayList();
final DoubleArrayList bsDualGamma = new DoubleArrayList();
final DoubleArrayList bsVega = new DoubleArrayList();
final DoubleArrayList bsVanna = new DoubleArrayList();
final DoubleArrayList bsVomma = new DoubleArrayList();
final DoubleArrayList modelDelta = new DoubleArrayList();
final DoubleArrayList modelDualDelta = new DoubleArrayList();
final DoubleArrayList modelGamma = new DoubleArrayList();
final DoubleArrayList modelDualGamma = new DoubleArrayList();
final DoubleArrayList modelVega = new DoubleArrayList();
final DoubleArrayList modelVanna = new DoubleArrayList();
final DoubleArrayList modelVomma = new DoubleArrayList();
for (int i = 0; i < n - 1; i++) {
final double moneyness = pdeRes.getSpaceValue(i);
final double k = moneyness * forward;
final double mPrice = pdeRes.getFunctionValue(i);
double impVol = 0;
try {
impVol = getBSImpliedVol(mPrice, moneyness, expiry, isCall);
} catch (final Exception e) {
continue;
}
final int timeIndex = SurfaceArrayUtils.getLowerBoundIndex(timeNodes, expiry);
final int spaceIndex = SurfaceArrayUtils.getLowerBoundIndex(spaceNodes, moneyness);
final double value1 = forward * pdeRes.getFunctionValue(spaceIndex, timeIndex);
final double value2 = forward * pdeRes.getFunctionValue(spaceIndex + 1, timeIndex);
final double m1 = pdeRes.getSpaceValue(spaceIndex);
final double m2 = pdeRes.getSpaceValue(spaceIndex + 1);
//review R White 9/3/2012 This is pointless as moneyness == m1 (it is just the value at space index i) - what we should be doing
//is finding the price (and all other greeks) for a given moneyness (corresponding to an option) that is not on the grid
//So price and blackPrice should be the same (within the round trip to implied volatility)
final double price = ((m2 - moneyness) * value1 + (moneyness - m1) * value2) / (m2 - m1);
final double blackPrice = BlackFormulaRepository.price(forward, k, expiry, impVol, isCall);
strikes.add(k);
impliedVolatilities.add(impVol);
prices.add(price);
blackPrices.add(blackPrice);
bsDelta.add(getBSDelta(forward, k, expiry, impVol, isCall));
bsDualDelta.add(getBSDualDelta(forward, k, expiry, impVol, isCall));
bsGamma.add(getBSGamma(forward, k, expiry, impVol));
bsDualGamma.add(getBSDualGamma(forward, k, expiry, impVol));
bsVega.add(getBSVega(forward, k, expiry, impVol));
bsVanna.add(getBSVanna(forward, k, expiry, impVol));
bsVomma.add(getBSVomma(forward, k, expiry, impVol));
absoluteDomesticPrice.add(Math.PI); //DEBUG - just trying to get a number through the system
final double modelDD = getModelDualDelta(pdeRes, i);
modelDualDelta.add(modelDD);
final double fixedSurfaceDelta = getFixedSurfaceDelta(mPrice, moneyness, modelDD);
final double surfaceDelta = getSurfaceDelta(pdeResForwardUp, pdeResForwardDown, forward, forwardShift, i);
final double modelD = getModelDelta(fixedSurfaceDelta, forward, surfaceDelta);
modelDelta.add(modelD);
final double modelDG = getModelDualGamma(pdeRes, i, forward);
modelDualGamma.add(modelDG);
final double fixedSurfaceGamma = getFixedSurfaceGamma(moneyness, modelDG);
final double dSurfaceDMoneyness = getDSurfaceDMoneyness(pdeResForwardUp, pdeResForwardDown, forward, forwardShift, i);
final double surfaceGamma = getSurfaceGamma(pdeResForwardUp, pdeResForwardDown, pdeRes, forward, forwardShift, i);
modelGamma.add(getModelGamma(fixedSurfaceGamma, surfaceDelta, moneyness, dSurfaceDMoneyness, surfaceGamma));
modelVega.add(getModelVega(pdeResVolUp, pdeResVolDown, volShift, i));
final double xVanna = getXVanna(volShift, pdeResVolUp, pdeResVolDown, i, moneyness);
final double surfaceVanna = getSurfaceVanna(pdeResForwardUpVolUp, pdeResForwardUpVolDown, pdeResForwardDownVolUp, pdeResForwardDownVolDown, volShift, forwardShift, i);
modelVanna.add(getModelVanna(xVanna, surfaceVanna));
modelVomma.add(getModelVomma(pdeRes, pdeResVolUp, pdeResVolDown, volShift, i));
}
final PDEResultCollection result = new PDEResultCollection(strikes.toDoubleArray());
result.put(PDEResultCollection.GRID_PRICE, prices.toDoubleArray());
result.put(PDEResultCollection.GRID_BLACK_PRICE, blackPrices.toDoubleArray());
result.put(PDEResultCollection.GRID_IMPLIED_VOL, impliedVolatilities.toDoubleArray());
result.put(PDEResultCollection.GRID_BLACK_DELTA, bsDelta.toDoubleArray());
result.put(PDEResultCollection.GRID_BLACK_DUAL_DELTA, bsDualDelta.toDoubleArray());
result.put(PDEResultCollection.GRID_BLACK_GAMMA, bsGamma.toDoubleArray());
result.put(PDEResultCollection.GRID_BLACK_DUAL_GAMMA, bsDualGamma.toDoubleArray());
result.put(PDEResultCollection.GRID_BLACK_VEGA, bsVega.toDoubleArray());
result.put(PDEResultCollection.GRID_BLACK_VANNA, bsVanna.toDoubleArray());
result.put(PDEResultCollection.GRID_BLACK_VOMMA, bsVomma.toDoubleArray());
result.put(PDEResultCollection.GRID_DELTA, modelDelta.toDoubleArray());
result.put(PDEResultCollection.GRID_DUAL_DELTA, modelDualDelta.toDoubleArray());
result.put(PDEResultCollection.GRID_GAMMA, modelGamma.toDoubleArray());
result.put(PDEResultCollection.GRID_DUAL_GAMMA, modelDualGamma.toDoubleArray());
result.put(PDEResultCollection.GRID_VEGA, modelVega.toDoubleArray());
result.put(PDEResultCollection.GRID_VANNA, modelVanna.toDoubleArray());
result.put(PDEResultCollection.GRID_VOMMA, modelVomma.toDoubleArray());
result.put(PDEResultCollection.GRID_DOMESTIC_PV_QUOTE, absoluteDomesticPrice.toDoubleArray());
return result;
}