}
final Object objectCubeData = inputs.getValue(getCubeDataRequirement(target, cubeName));
if (objectCubeData == null) {
throw new OpenGammaRuntimeException("Could not get volatility cube data");
}
final VolatilityCubeData volatilityCubeData = (VolatilityCubeData) objectCubeData;
final SortedMap<Tenor, SortedMap<Tenor, Pair<double[], double[]>>> smiles = volatilityCubeData.getSmiles();
final SortedMap<Tenor, SortedMap<Tenor, ExternalId[]>> smileIds = volatilityCubeData.getSmileIds();
final SortedMap<Tenor, SortedMap<Tenor, Double[]>> smileRelativeStrikes = volatilityCubeData.getSmileRelativeStrikes();
final DoubleArrayList swapMaturitiesList = new DoubleArrayList();
final DoubleArrayList swaptionExpiriesList = new DoubleArrayList();
final DoubleArrayList alphaList = new DoubleArrayList();
final DoubleArrayList betaList = new DoubleArrayList();
final DoubleArrayList nuList = new DoubleArrayList();
final DoubleArrayList rhoList = new DoubleArrayList();
final DoubleArrayList chiSqList = new DoubleArrayList();
final Map<DoublesPair, DoubleMatrix2D> inverseJacobians = new HashMap<>();
final Map<Pair<Tenor, Tenor>, ExternalId[]> fittedSmileIds = new HashMap<>();
final Map<Pair<Tenor, Tenor>, Double[]> fittedRelativeStrikes = new HashMap<>();
for (final Map.Entry<Tenor, SortedMap<Tenor, Pair<double[], double[]>>> swapMaturityEntry : smiles.entrySet()) {
final double maturity = getTime(swapMaturityEntry.getKey());
for (final Map.Entry<Tenor, Pair<double[], double[]>> swaptionExpiryEntry : swapMaturityEntry.getValue().entrySet()) {
final double swaptionExpiry = getTime(swaptionExpiryEntry.getKey());
final double[] strikes = swaptionExpiryEntry.getValue().getFirst();
final double[] blackVols = swaptionExpiryEntry.getValue().getSecond();
final int n = strikes.length;
if (n != blackVols.length) {
throw new OpenGammaRuntimeException("Strike and Black volatility arrays were not the same length; should never happen");
}
ExternalId[] externalIds = new ExternalId[0];
if (smileIds != null) {
externalIds = smileIds.get(swapMaturityEntry.getKey()).get(swaptionExpiryEntry.getKey());
if (n != externalIds.length) {
throw new OpenGammaRuntimeException("Strike and id arrays were not the same length; should never happen");
}
}
Double[] relativeStrikes = new Double[0];
if (smileRelativeStrikes != null) {
relativeStrikes = smileRelativeStrikes.get(swapMaturityEntry.getKey()).get(swaptionExpiryEntry.getKey());
if (n != relativeStrikes.length) {
throw new OpenGammaRuntimeException("Strike and relative strike arrays were not the same length; should never happen");
}
}
final double[] errors = new double[n];
final Pair<Tenor, Tenor> tenorPair = Pair.of(swapMaturityEntry.getKey(), swaptionExpiryEntry.getKey());
if (volatilityCubeData.getATMStrikes() != null && volatilityCubeData.getATMStrikes().containsKey(tenorPair)) {
final double forward = volatilityCubeData.getATMStrikes().get(tenorPair);
for (int k = 0; k < n; k++) {
errors[k] = ERROR;
}
if (strikes.length > 4 && forward > 0) { //don't fit those smiles with insufficient data
final LeastSquareResultsWithTransform fittedResult = new SABRModelFitter(forward, strikes, swaptionExpiry, blackVols, errors, SABR_FUNCTION).solve(SABR_INITIAL_VALUES, FIXED);