double alpha = mp.getEntry(0);
final double beta = mp.getEntry(1);
final double rho = mp.getEntry(2);
final double nu = mp.getEntry(3);
final SABRFormulaData sabrFormulaData;
if (recoverATMVol) {
alpha = _atmCalculator.calculate(new SABRFormulaData(alpha, beta, rho, nu), atmOption, forward, atmVol);
sabrFormulaData = new SABRFormulaData(alpha, beta, rho, nu);
} else {
sabrFormulaData = new SABRFormulaData(alpha, beta, rho, nu);
}
final EuropeanVanillaOption option = new EuropeanVanillaOption(strike, maturity, true);
return _formula.getVolatilityFunction(option, forward).evaluate(sabrFormulaData);
}
};
final DoubleMatrix1D fp = transforms.transform(new DoubleMatrix1D(initialFitParameters));
LeastSquareResults lsRes = errors == null ? SOLVER.solve(new DoubleMatrix1D(strikes), new DoubleMatrix1D(blackVols), function, fp)
: SOLVER.solve(new DoubleMatrix1D(strikes), new DoubleMatrix1D(blackVols), new DoubleMatrix1D(errors), function, fp);
final double[] mp = transforms.inverseTransform(lsRes.getFitParameters()).toArray();
if (recoverATMVol) {
final double beta = mp[1];
final double nu = mp[2];
final double rho = mp[3];
final EuropeanVanillaOption option = new EuropeanVanillaOption(forward, maturity, true);
final SABRFormulaData sabrFormulaData = new SABRFormulaData(mp[0], beta, rho, nu);
final double value = _atmCalculator.calculate(sabrFormulaData, option, forward, atmVol);
mp[0] = value;
lsRes = new LeastSquareResults(lsRes.getChiSq(), new DoubleMatrix1D(mp), lsRes.getCovariance());
}
return new LeastSquareResultsWithTransform(lsRes, transforms);