}
return BlackFormulaRepository.impliedVolatility(price, fwd, k, expiry, isCall);
}
};
final BlackVolatilitySurface<Strike> surfaceStrike = new BlackVolatilitySurfaceStrike(FunctionalDoublesSurface.from(surf));
final int nExp = EXPIRIES.length;
int temp = 0;
for (int i = 0; i < nExp; i++) {
temp += STRIKES[i].length;
}
final int totalStrikes = temp;
final ForwardCurve fwdCurve = new ForwardCurve(1.0);
final List<double[]> tk = new ArrayList<>(totalStrikes);
final List<Double> vols = new ArrayList<>(totalStrikes);
final List<Double> sigmas = new ArrayList<>(totalStrikes);
for (int i = 0; i < nExp; i++) {
final double t = EXPIRIES[i];
for (int j = 0; j < STRIKES[i].length; j++) {
final double[] a = new double[] {t, STRIKES[i][j] };
tk.add(a);
vols.add(surfaceStrike.getVolatility(t, STRIKES[i][j]));
sigmas.add(1.0);
}
}
final int[] nKnots = new int[] {8, 20 };
final int[] degree = new int[] {3, 3 };
final int[] diff = new int[] {2, 2 };
final double[] lambda = new double[] {0.1, 0.3 };
final PSplineFitter splineFitter = new PSplineFitter();
final GeneralizedLeastSquareResults<double[]> res = splineFitter.solve(tk, vols, sigmas, new double[] {0.0, 0.0 }, new double[] {2.0, 3.0 }, nKnots, degree, lambda, diff);
System.out.println(res.getChiSq());
final Function1D<double[], Double> func = res.getFunction();
final Function<Double, Double> temp2 = new Function<Double, Double>() {
@Override
public Double evaluate(final Double... tk) {
return func.evaluate(new double[] {tk[0], tk[1] });
}
};
//PDEUtilityTools.printSurface("start", surfaceStrike.getSurface(), 0.01, 2.0, 0.3, 3.0);
final FunctionalDoublesSurface s = FunctionalDoublesSurface.from(temp2);
PDEUtilityTools.printSurface("fitted", s, 0.01, 2.0, 0.3, 3.0);
final DupireLocalVolatilityCalculator dCal = new DupireLocalVolatilityCalculator();
final LocalVolatilitySurfaceStrike lv = dCal.getLocalVolatility(new BlackVolatilitySurfaceStrike(s), fwdCurve);
PDEUtilityTools.printSurface("lv", lv.getSurface(), 0.01, 2.0, 0.3, 3.0);
}