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);
                }
            }
        }
        private void testSurfaceSensitivity(CurrencyParameterSensitivity computed, NormalIborCapletFloorletExpiryStrikeVolatilities vols, System.Func <IborCapletFloorletVolatilities, CurrencyAmount> valueFn)
        {
            double pvBase = valueFn(vols).Amount;
            InterpolatedNodalSurface surfaceBase = (InterpolatedNodalSurface)vols.Surface;
            int nParams = surfaceBase.ParameterCount;

            for (int i = 0; i < nParams; ++i)
            {
                DoubleArray zBumped = surfaceBase.ZValues.with(i, surfaceBase.ZValues.get(i) + EPS_FD);
                InterpolatedNodalSurface surfaceBumped = surfaceBase.withZValues(zBumped);
                NormalIborCapletFloorletExpiryStrikeVolatilities volsBumped = NormalIborCapletFloorletExpiryStrikeVolatilities.of(vols.Index, vols.ValuationDateTime, surfaceBumped);
                double fd = (valueFn(volsBumped).Amount - pvBase) / EPS_FD;
                assertEquals(computed.Sensitivity.get(i), fd, NOTIONAL * EPS_FD);
            }
        }
        public virtual void flatVolTest()
        {
            double          tol               = 2.0e-2;
            double          constantVol       = 0.15;
            ConstantSurface impliedVolSurface = ConstantSurface.of("impliedVol", constantVol);

            System.Func <double, double> zeroRate = (double?x) =>
            {
                return(0.05d);
            };
            System.Func <double, double> zeroRate1 = (double?x) =>
            {
                return(0.02d);
            };
            ImpliedTrinomialTreeLocalVolatilityCalculator calc = new ImpliedTrinomialTreeLocalVolatilityCalculator(45, 1d, INTERP_TIMESQ_LINEAR);
            InterpolatedNodalSurface localVolSurface           = calc.localVolatilityFromImpliedVolatility(impliedVolSurface, 100d, zeroRate, zeroRate1);

            assertEquals(localVolSurface.ZValues.Where(d => !DoubleMath.fuzzyEquals(d, constantVol, tol)).Count(), 0);
        }
        //-------------------------------------------------------------------------
        public virtual void test_parameterSensitivity()
        {
            double    expiry      = ACT_365F.relativeYearFraction(VAL_DATE, LocalDate.of(2015, 8, 14));
            LocalDate fixing      = LocalDate.of(2016, 9, 14);
            double    strikePrice = 1.0025;
            double    futurePrice = 0.9975;
            double    sensitivity = 123456;
            IborFutureOptionSensitivity    point = IborFutureOptionSensitivity.of(VOL_SIMPLE_MONEY_RATE.Name, expiry, fixing, strikePrice, futurePrice, EUR, sensitivity);
            CurrencyParameterSensitivities ps    = VOL_SIMPLE_MONEY_RATE.parameterSensitivity(point);
            double shift = 1.0E-6;
            double v0    = VOL_SIMPLE_MONEY_RATE.volatility(expiry, fixing, strikePrice, futurePrice);

            for (int i = 0; i < NORMAL_VOL_RATES.size(); i++)
            {
                DoubleArray v = NORMAL_VOL_RATES.with(i, NORMAL_VOL_RATES.get(i) + shift);
                InterpolatedNodalSurface param = InterpolatedNodalSurface.of(Surfaces.normalVolatilityByExpirySimpleMoneyness("Rate", ACT_365F, MoneynessType.RATES), TIMES, MONEYNESS_RATES, v, INTERPOLATOR_2D);
                NormalIborFutureOptionExpirySimpleMoneynessVolatilities vol = NormalIborFutureOptionExpirySimpleMoneynessVolatilities.of(EUR_EURIBOR_3M, VAL_DATE_TIME, param);
                double vP = vol.volatility(expiry, fixing, strikePrice, futurePrice);
                double s  = ps.getSensitivity(PARAMETERS_RATE.Name, EUR).Sensitivity.get(i);
                assertEquals(s, (vP - v0) / shift * sensitivity, TOLERANCE_DELTA);
            }
        }
        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);
        }