public virtual void test_parameterSensitivity_withSpread_full()
        {
            int    periodPerYear = 2;
            double spread        = 0.0011; // 11 bp
            ZeroRatePeriodicDiscountFactors test = ZeroRatePeriodicDiscountFactors.of(GBP, DATE_VAL, CURVE);
            double sensiValue         = 25d;
            ZeroRateSensitivity point = test.zeroRatePointSensitivityWithSpread(DATE_AFTER, spread, PERIODIC, periodPerYear);

            point = point.multipliedBy(sensiValue);
            CurrencyParameterSensitivities sensiObject = test.parameterSensitivity(point);

            assertEquals(sensiObject.Sensitivities.size(), 1);
            DoubleArray sensi0 = sensiObject.Sensitivities.get(0).Sensitivity;
            double      shift  = 1.0E-6;

            for (int i = 0; i < X.size(); i++)
            {
                DoubleArray            yP     = Y.with(i, Y.get(i) + shift);
                InterpolatedNodalCurve curveP = InterpolatedNodalCurve.of(META_ZERO_PERIODIC, X, yP, INTERPOLATOR);
                double                 dfP    = ZeroRatePeriodicDiscountFactors.of(GBP, DATE_VAL, curveP).discountFactorWithSpread(DATE_AFTER, spread, PERIODIC, periodPerYear);
                DoubleArray            yM     = Y.with(i, Y.get(i) - shift);
                InterpolatedNodalCurve curveM = InterpolatedNodalCurve.of(META_ZERO_PERIODIC, X, yM, INTERPOLATOR);
                double                 dfM    = ZeroRatePeriodicDiscountFactors.of(GBP, DATE_VAL, curveM).discountFactorWithSpread(DATE_AFTER, spread, PERIODIC, periodPerYear);
                assertEquals(sensi0.get(i), sensiValue * (dfP - dfM) / (2 * shift), TOLERANCE_DELTA_FD, "With spread - " + i);
            }
        }
        public virtual void test_zeroRatePointSensitivityWithSpread_sensitivityCurrency_smallYearFraction()
        {
            ZeroRatePeriodicDiscountFactors test     = ZeroRatePeriodicDiscountFactors.of(GBP, DATE_VAL, CURVE);
            ZeroRateSensitivity             expected = ZeroRateSensitivity.of(GBP, 0d, USD, 0.0d);
            ZeroRateSensitivity             computed = test.zeroRatePointSensitivityWithSpread(DATE_VAL, USD, SPREAD, CONTINUOUS, 0);

            assertTrue(computed.compareKey(expected) == 0);
            assertEquals(computed.Sensitivity, expected.Sensitivity, TOLERANCE_DELTA_FD);
        }
        public virtual void test_zeroRatePointSensitivityWithSpread_sensitivityCurrency_continous()
        {
            ZeroRatePeriodicDiscountFactors test = ZeroRatePeriodicDiscountFactors.of(GBP, DATE_VAL, CURVE);
            double relativeYearFraction          = ACT_365F.relativeYearFraction(DATE_VAL, DATE_AFTER);
            double df = test.discountFactorWithSpread(DATE_AFTER, SPREAD, CONTINUOUS, 0);
            ZeroRateSensitivity expected = ZeroRateSensitivity.of(GBP, relativeYearFraction, USD, -df * relativeYearFraction);
            ZeroRateSensitivity computed = test.zeroRatePointSensitivityWithSpread(DATE_AFTER, USD, SPREAD, CONTINUOUS, 0);

            assertTrue(computed.compareKey(expected) == 0);
            assertEquals(computed.Sensitivity, expected.Sensitivity, TOLERANCE_DELTA);
        }
        public virtual void test_zeroRatePointSensitivityWithSpread_sensitivityCurrency_periodic()
        {
            int periodPerYear = 4;
            ZeroRatePeriodicDiscountFactors test = ZeroRatePeriodicDiscountFactors.of(GBP, DATE_VAL, CURVE);
            double relativeYearFraction          = ACT_365F.relativeYearFraction(DATE_VAL, DATE_AFTER);
            double df     = test.discountFactor(DATE_AFTER);
            double z      = -1.0 / relativeYearFraction * Math.Log(df);
            double shift  = 1.0E-6;
            double zP     = z + shift;
            double zM     = z - shift;
            double dfSP   = Math.Pow(Math.Pow(Math.Exp(-zP * relativeYearFraction), -1.0 / (relativeYearFraction * periodPerYear)) + SPREAD / periodPerYear, -relativeYearFraction * periodPerYear);
            double dfSM   = Math.Pow(Math.Pow(Math.Exp(-zM * relativeYearFraction), -1.0 / (relativeYearFraction * periodPerYear)) + SPREAD / periodPerYear, -relativeYearFraction * periodPerYear);
            double ddfSdz = (dfSP - dfSM) / (2 * shift);
            ZeroRateSensitivity expected = ZeroRateSensitivity.of(GBP, relativeYearFraction, USD, ddfSdz);
            ZeroRateSensitivity computed = test.zeroRatePointSensitivityWithSpread(DATE_AFTER, USD, SPREAD, PERIODIC, periodPerYear);

            assertTrue(computed.compareKey(expected) == 0);
            assertEquals(computed.Sensitivity, expected.Sensitivity, TOLERANCE_DELTA_FD);
        }