public virtual void comparisonDupireVolTest()
        {
            double tol = 1.0e-2;
            ImpliedTrinomialTreeLocalVolatilityCalculator calc = new ImpliedTrinomialTreeLocalVolatilityCalculator(28, 1.45d, INTERP_LINEAR);

            System.Func <double, double> interestRate = (double?x) =>
            {
                return(0.03d);
            };
            System.Func <double, double> dividendRate = (double?x) =>
            {
                return(0.01d);
            };
            InterpolatedNodalSurface resTri = calc.localVolatilityFromImpliedVolatility(VOL_SURFACE, SPOT, interestRate, dividendRate);
            DeformedSurface          resDup = (new DupireLocalVolatilityCalculator()).localVolatilityFromImpliedVolatility(VOL_SURFACE, SPOT, interestRate, dividendRate);

            double[][] sampleStrikes = new double[][]
            {
                new double[] { 0.7 * SPOT, SPOT, 1.1 * SPOT, 1.4 * SPOT },
                new double[] { 0.5 * SPOT, 0.9 * SPOT, SPOT, 1.3 * SPOT, 1.9 * SPOT }
            };
            double[] sampleTimes = new double[] { 0.8, 1.1 };
            for (int i = 0; i < sampleTimes.Length; ++i)
            {
                double time = sampleTimes[i];
                foreach (double strike in sampleStrikes[i])
                {
                    double volTri = resTri.zValue(time, strike);
                    double volDup = resDup.zValue(time, strike);
                    assertEquals(volTri, volDup, tol);
                }
            }
        }
        public virtual void comparisonDupirePriceTest()
        {
            double tol = 7.0e-2;
            ImpliedTrinomialTreeLocalVolatilityCalculator calc = new ImpliedTrinomialTreeLocalVolatilityCalculator(22, 1.1d, INTERP_LINEAR);

            System.Func <double, double> interestRate = (double?x) =>
            {
                return(0.003d);
            };
            System.Func <double, double> dividendRate = (double?x) =>
            {
                return(0.01d);
            };
            InterpolatedNodalSurface resTri = calc.localVolatilityFromPrice(PRICE_SURFACE, SPOT, interestRate, dividendRate);
            DeformedSurface          resDup = (new DupireLocalVolatilityCalculator()).localVolatilityFromPrice(PRICE_SURFACE, SPOT, interestRate, dividendRate);

            // limited range due to interpolation/extrapolation of price surface -> negative call/put price reached
            double[][] sampleStrikes = new double[][]
            {
                new double[] { 0.95 * SPOT, 1.05 * SPOT },
                new double[] { 0.9 * SPOT, SPOT, 1.1 * SPOT }
            };
            double[] sampleTimes = new double[] { 0.7, 1.05 };
            for (int i = 0; i < sampleTimes.Length; ++i)
            {
                double time = sampleTimes[i];
                foreach (double strike in sampleStrikes[i])
                {
                    double volTri = resTri.zValue(time, strike);
                    double volDup = resDup.zValue(time, strike);
                    assertEquals(volTri, volDup, tol);
                }
            }
        }
        public virtual void flatVolPriceTest()
        {
            double          tol               = 2.0e-2;
            double          constantVol       = 0.15;
            double          spot              = 100d;
            double          maxTime           = 1d;
            int             nSteps            = 9;
            ConstantSurface impliedVolSurface = ConstantSurface.of("impliedVol", constantVol);

            System.Func <double, double> zeroRate = (double?x) =>
            {
                return(0d);
            };
            System.Func <DoublesPair, ValueDerivatives> func = (DoublesPair x) =>
            {
                double price = BlackFormulaRepository.price(spot, x.Second, x.First, constantVol, true);
                return(ValueDerivatives.of(price, DoubleArray.EMPTY));
            };
            DeformedSurface priceSurface = DeformedSurface.of(DefaultSurfaceMetadata.of("price"), impliedVolSurface, func);
            ImpliedTrinomialTreeLocalVolatilityCalculator calc = new ImpliedTrinomialTreeLocalVolatilityCalculator(nSteps, maxTime, INTERP_TIMESQ_LINEAR);
            InterpolatedNodalSurface localVolSurface           = calc.localVolatilityFromPrice(priceSurface, spot, zeroRate, zeroRate);

            assertEquals(localVolSurface.ZValues.Where(d => !DoubleMath.fuzzyEquals(d, constantVol, tol)).Count(), 0);
        }