class ImpliedTrinomialTreeLocalVolatilityCalculator implements LocalVolatilityCalculator {

  @Override
  public InterpolatedNodalSurface localVolatilityFromImpliedVolatility(
      Surface impliedVolatilitySurface,
      double spot,
      Function<Double, Double> interestRate,
      Function<Double, Double> dividendRate) {

    Function<DoublesPair, Double> surface = new Function<DoublesPair, Double>() {
      @Override
      public Double apply(DoublesPair tk) {
        return impliedVolatilitySurface.zValue(tk);
      }
    };
    ImmutableList<double[]> localVolData = calibrate(surface, spot, interestRate, dividendRate).getFirst();
    SurfaceMetadata metadata = DefaultSurfaceMetadata.builder()
        .xValueType(ValueType.YEAR_FRACTION)
        .yValueType(ValueType.STRIKE)
        .zValueType(ValueType.LOCAL_VOLATILITY)
        .surfaceName(SurfaceName.of("localVol_" + impliedVolatilitySurface.getName()))
        .build();
    return InterpolatedNodalSurface.ofUnsorted(
        metadata,
        DoubleArray.ofUnsafe(localVolData.get(0)),
        DoubleArray.ofUnsafe(localVolData.get(1)),
        DoubleArray.ofUnsafe(localVolData.get(2)),
        interpolator);
  }

  public  ImpliedTrinomialTreeLocalVolatilityCalculator();
  public  ImpliedTrinomialTreeLocalVolatilityCalculator(int nSteps, double maxTime);
  public  ImpliedTrinomialTreeLocalVolatilityCalculator(int nSteps, double maxTime, SurfaceInterpolator interpolator);

}