private static VolatilitySurfaceData<Double, Double> getSurfaceFromPriceQuote(final VolatilitySurfaceSpecification specification,
final VolatilitySurfaceData<Number, Double> optionPrices, final NodalDoublesCurve futurePrices, final ZonedDateTime now, final String surfaceQuoteType,
final Calendar calendar) {
double callAboveStrike = 0;
SurfaceInstrumentProvider<?, ?> instrumentProvider = specification.getSurfaceInstrumentProvider();
ExchangeTradedInstrumentExpiryCalculator expiryRule;
if (instrumentProvider instanceof CallPutSurfaceInstrumentProvider) {
expiryRule = ((CallPutSurfaceInstrumentProvider<?, ?>) instrumentProvider).getExpiryRuleCalculator();
} else {
expiryRule = IRFutureAndFutureOptionExpiryCalculator.getInstance();
}
if (specification.getSurfaceInstrumentProvider() instanceof CallPutSurfaceInstrumentProvider) {
callAboveStrike = ((CallPutSurfaceInstrumentProvider<?, ?>) specification.getSurfaceInstrumentProvider()).useCallAboveStrike();
}
final Map<Pair<Double, Double>, Double> volatilityValues = new HashMap<Pair<Double, Double>, Double>();
final DoubleArrayList txList = new DoubleArrayList();
final DoubleArrayList kList = new DoubleArrayList();
final LocalDate today = now.toLocalDate();
for (final Number x : optionPrices.getXs()) { // Loop over option expiries
final LocalDate expiry = expiryRule.getExpiryDate(x.intValue(), today, calendar);
final Double optionTtm = TimeCalculator.getTimeBetween(today, expiry);
// Get the corresponding future, which may not share the same expiries as the option itself
final Double[] futureExpiries = futurePrices.getXData();
final int nFutures = futureExpiries.length;
if (nFutures == 0) {