private System.Func <SabrFormulaData, double> getVolatilityFunction(EuropeanVanillaOption option, double forward)
 {
     return((SabrFormulaData data) =>
     {
         ArgChecker.notNull(data, "data");
         return FUNCTION.volatility(forward, option.Strike, option.TimeToExpiry, data);
     });
 }
        private void testVolatilityAdjoint(double forward, EuropeanVanillaOption optionData, SabrFormulaData sabrData, double eps, double tol)
        {
            double volatility = FUNCTION.volatility(forward, optionData.Strike, optionData.TimeToExpiry, sabrData);

            double[] volatilityAdjoint = toArray(FUNCTION.volatilityAdjoint(forward, optionData.Strike, optionData.TimeToExpiry, sabrData));
            assertEquals(volatility, volatilityAdjoint[0], tol);
            assertEqualsRelTol("Forward Sensitivity" + sabrData.ToString(), fdSensitivity(optionData, forward, sabrData, SabrParameter.Forward, eps), volatilityAdjoint[1], tol);
            assertEqualsRelTol("Strike Sensitivity" + sabrData.ToString(), fdSensitivity(optionData, forward, sabrData, SabrParameter.Strike, eps), volatilityAdjoint[2], tol);
            assertEqualsRelTol("Alpha Sensitivity" + sabrData.ToString(), fdSensitivity(optionData, forward, sabrData, SabrParameter.Alpha, eps), volatilityAdjoint[3], tol);
            assertEqualsRelTol("Beta Sensitivity" + sabrData.ToString(), fdSensitivity(optionData, forward, sabrData, SabrParameter.Beta, eps), volatilityAdjoint[4], tol);
            assertEqualsRelTol("Rho Sensitivity" + sabrData.ToString(), fdSensitivity(optionData, forward, sabrData, SabrParameter.Rho, eps), volatilityAdjoint[5], tol);
            assertEqualsRelTol("Nu Sensitivity" + sabrData.ToString(), fdSensitivity(optionData, forward, sabrData, SabrParameter.Nu, eps), volatilityAdjoint[6], tol);
        }
        //-------------------------------------------------------------------------
        public virtual void present_value_theta_formula()
        {
            double                forward         = PRICER_SWAP.parRate(RSWAP_REC, MULTI_USD);
            double                pvbp            = PRICER_SWAP.LegPricer.pvbp(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), MULTI_USD);
            double                volatility      = NORMAL_VOLS_USD_STD.volatility(SWAPTION_LONG_REC.Expiry, SWAP_TENOR_YEAR, STRIKE, forward);
            NormalFunctionData    normalData      = NormalFunctionData.of(forward, Math.Abs(pvbp), volatility);
            double                expiry          = NORMAL_VOLS_USD_STD.relativeTime(SWAPTION_LONG_REC.Expiry);
            EuropeanVanillaOption option          = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.PUT);
            double                pvThetaExpected = NORMAL.getTheta(option, normalData);
            CurrencyAmount        pvThetaComputed = PRICER_SWAPTION_NORMAL.presentValueTheta(SWAPTION_LONG_REC, MULTI_USD, NORMAL_VOLS_USD_STD);

            assertEquals(pvThetaComputed.Currency, USD);
            assertEquals(pvThetaComputed.Amount, pvThetaExpected, TOLERANCE_PV);
        }
        //-------------------------------------------------------------------------
        public virtual void test_presentValueTheta()
        {
            CurrencyAmount        pvThetaRecComputed = PRICER_SWAPTION.presentValueTheta(SWAPTION_REC_LONG, RATE_PROVIDER, VOLS);
            CurrencyAmount        pvThetaPayComputed = PRICER_SWAPTION.presentValueTheta(SWAPTION_PAY_SHORT, RATE_PROVIDER, VOLS);
            double                forward            = PRICER_SWAP.parRate(RSWAP_REC, RATE_PROVIDER);
            double                annuityCash        = PRICER_SWAP.LegPricer.annuityCash(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), forward);
            double                volatility         = VOLS.volatility(SWAPTION_REC_LONG.Expiry, SWAP_TENOR_YEAR, STRIKE, forward);
            double                discount           = RATE_PROVIDER.discountFactor(USD, SETTLE_DATE);
            NormalFunctionData    normalData         = NormalFunctionData.of(forward, annuityCash * discount, volatility);
            double                expiry             = VOLS.relativeTime(SWAPTION_REC_LONG.Expiry);
            EuropeanVanillaOption optionRec          = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.PUT);
            EuropeanVanillaOption optionPay          = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.CALL);
            double                pvThetaRecExpected = NORMAL.getTheta(optionRec, normalData);
            double                pvThetaPayExpected = -NORMAL.getTheta(optionPay, normalData);

            assertEquals(pvThetaRecComputed.Currency, USD);
            assertEquals(pvThetaRecComputed.Amount, pvThetaRecExpected, NOTIONAL * TOL);
            assertEquals(pvThetaPayComputed.Currency, USD);
            assertEquals(pvThetaPayComputed.Amount, pvThetaPayExpected, NOTIONAL * TOL);
        }
        private void volatilityAdjoint2ForInstrument(EuropeanVanillaOption option, double tolerance1, double tolerance2)
        {
            // vol
            double volatility = FUNCTION.volatility(F, option.Strike, option.TimeToExpiry, DATA);

            double[] volatilityAdjoint = toArray(FUNCTION.volatilityAdjoint(F, option.Strike, option.TimeToExpiry, DATA));
            double[] volD = new double[6];
//JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java:
//ORIGINAL LINE: double[][] volD2 = new double[2][2];
            double[][] volD2 = RectangularArrays.ReturnRectangularDoubleArray(2, 2);
            double     vol   = FUNCTION.volatilityAdjoint2(F, option.Strike, option.TimeToExpiry, DATA, volD, volD2);

            assertEquals(volatility, vol, tolerance1);
            // Derivative
            for (int loopder = 0; loopder < 6; loopder++)
            {
                assertEquals(volatilityAdjoint[loopder + 1], volD[loopder], tolerance1);
            }
            // Derivative forward-forward
            double deltaF          = 0.000001;
            double volatilityFP    = FUNCTION.volatility(F + deltaF, option.Strike, option.TimeToExpiry, DATA);
            double volatilityFM    = FUNCTION.volatility(F - deltaF, option.Strike, option.TimeToExpiry, DATA);
            double derivativeFF_FD = (volatilityFP + volatilityFM - 2 * volatility) / (deltaF * deltaF);

            assertEquals(derivativeFF_FD, volD2[0][0], tolerance2);
            // Derivative strike-strike
            double deltaK          = 0.000001;
            double volatilityKP    = FUNCTION.volatility(F, option.Strike + deltaK, option.TimeToExpiry, DATA);
            double volatilityKM    = FUNCTION.volatility(F, option.Strike - deltaK, option.TimeToExpiry, DATA);
            double derivativeKK_FD = (volatilityKP + volatilityKM - 2 * volatility) / (deltaK * deltaK);

            assertEquals(derivativeKK_FD, volD2[1][1], tolerance2);
            // Derivative strike-forward
            double volatilityFPKP  = FUNCTION.volatility(F + deltaF, option.Strike + deltaK, option.TimeToExpiry, DATA);
            double derivativeFK_FD = (volatilityFPKP + volatility - volatilityFP - volatilityKP) / (deltaF * deltaK);

            assertEquals(derivativeFK_FD, volD2[0][1], tolerance2);
            assertEquals(volD2[0][1], volD2[1][0], 1E-6);
        }
 private EuropeanVanillaOption withStrike(EuropeanVanillaOption option, double strike)
 {
     return(EuropeanVanillaOption.of(strike, option.TimeToExpiry, option.PutCall));
 }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @SuppressWarnings("null") private double fdSensitivity(com.opengamma.strata.pricer.impl.option.EuropeanVanillaOption optionData, double forward, SabrFormulaData sabrData, SabrParameter param, double delta)
        private double fdSensitivity(EuropeanVanillaOption optionData, double forward, SabrFormulaData sabrData, SabrParameter param, double delta)
        {
            System.Func <SabrFormulaData, double> funcC = null;
            System.Func <SabrFormulaData, double> funcB = null;
            System.Func <SabrFormulaData, double> funcA = null;
            SabrFormulaData dataC = null;
            SabrFormulaData dataB = sabrData;
            SabrFormulaData dataA = null;

            System.Func <SabrFormulaData, double> func = getVolatilityFunction(optionData, forward);

            FiniteDifferenceType fdType = null;

            switch (param)
            {
            case com.opengamma.strata.pricer.impl.volatility.smile.SabrHaganVolatilityFunctionProviderTest.SabrParameter.Strike:
                double strike = optionData.Strike;
                if (strike >= delta)
                {
                    fdType = FiniteDifferenceType.CENTRAL;
                    funcA  = getVolatilityFunction(withStrike(optionData, strike - delta), forward);
                    funcC  = getVolatilityFunction(withStrike(optionData, strike + delta), forward);
                }
                else
                {
                    fdType = FiniteDifferenceType.FORWARD;
                    funcA  = func;
                    funcB  = getVolatilityFunction(withStrike(optionData, strike + delta), forward);
                    funcC  = getVolatilityFunction(withStrike(optionData, strike + 2 * delta), forward);
                }
                dataC = sabrData;
                dataB = sabrData;
                dataA = sabrData;
                break;

            case com.opengamma.strata.pricer.impl.volatility.smile.SabrHaganVolatilityFunctionProviderTest.SabrParameter.Forward:
                if (forward > delta)
                {
                    fdType = FiniteDifferenceType.CENTRAL;
                    funcA  = getVolatilityFunction(optionData, forward - delta);
                    funcC  = getVolatilityFunction(optionData, forward + delta);
                }
                else
                {
                    fdType = FiniteDifferenceType.FORWARD;
                    funcA  = func;
                    funcB  = getVolatilityFunction(optionData, forward + delta);
                    funcC  = getVolatilityFunction(optionData, forward + 2 * delta);
                }
                dataC = sabrData;
                dataB = sabrData;
                dataA = sabrData;
                break;

            case com.opengamma.strata.pricer.impl.volatility.smile.SabrHaganVolatilityFunctionProviderTest.SabrParameter.Alpha:
                double a = sabrData.Alpha;
                if (a >= delta)
                {
                    fdType = FiniteDifferenceType.CENTRAL;
                    dataA  = sabrData.withAlpha(a - delta);
                    dataC  = sabrData.withAlpha(a + delta);
                }
                else
                {
                    fdType = FiniteDifferenceType.FORWARD;
                    dataA  = sabrData;
                    dataB  = sabrData.withAlpha(a + delta);
                    dataC  = sabrData.withAlpha(a + 2 * delta);
                }
                funcC = func;
                funcB = func;
                funcA = func;
                break;

            case com.opengamma.strata.pricer.impl.volatility.smile.SabrHaganVolatilityFunctionProviderTest.SabrParameter.Beta:
                double b = sabrData.Beta;
                if (b >= delta)
                {
                    fdType = FiniteDifferenceType.CENTRAL;
                    dataA  = sabrData.withBeta(b - delta);
                    dataC  = sabrData.withBeta(b + delta);
                }
                else
                {
                    fdType = FiniteDifferenceType.FORWARD;
                    dataA  = sabrData;
                    dataB  = sabrData.withBeta(b + delta);
                    dataC  = sabrData.withBeta(b + 2 * delta);
                }
                funcC = func;
                funcB = func;
                funcA = func;
                break;

            case com.opengamma.strata.pricer.impl.volatility.smile.SabrHaganVolatilityFunctionProviderTest.SabrParameter.Nu:
                double n = sabrData.Nu;
                if (n >= delta)
                {
                    fdType = FiniteDifferenceType.CENTRAL;
                    dataA  = sabrData.withNu(n - delta);
                    dataC  = sabrData.withNu(n + delta);
                }
                else
                {
                    fdType = FiniteDifferenceType.FORWARD;
                    dataA  = sabrData;
                    dataB  = sabrData.withNu(n + delta);
                    dataC  = sabrData.withNu(n + 2 * delta);
                }
                funcC = func;
                funcB = func;
                funcA = func;
                break;

            case com.opengamma.strata.pricer.impl.volatility.smile.SabrHaganVolatilityFunctionProviderTest.SabrParameter.Rho:
                double r = sabrData.Rho;
                if ((r + 1) < delta)
                {
                    fdType = FiniteDifferenceType.FORWARD;
                    dataA  = sabrData;
                    dataB  = sabrData.withRho(r + delta);
                    dataC  = sabrData.withRho(r + 2 * delta);
                }
                else if ((1 - r) < delta)
                {
                    fdType = FiniteDifferenceType.BACKWARD;
                    dataA  = sabrData.withRho(r - 2 * delta);
                    dataB  = sabrData.withRho(r - delta);
                    dataC  = sabrData;
                }
                else
                {
                    fdType = FiniteDifferenceType.CENTRAL;
                    dataC  = sabrData.withRho(r + delta);
                    dataA  = sabrData.withRho(r - delta);
                }
                funcC = func;
                funcB = func;
                funcA = func;
                break;

            default:
                throw new MathException("enum not found");
            }

            if (fdType != null)
            {
                switch (fdType)
                {
                case FiniteDifferenceType.FORWARD:
                    return((-1.5 * funcA(dataA) + 2.0 * funcB(dataB) - 0.5 * funcC(dataC)) / delta);

                case FiniteDifferenceType.BACKWARD:
                    return((0.5 * funcA(dataA) - 2.0 * funcB(dataB) + 1.5 * funcC(dataC)) / delta);

                case FiniteDifferenceType.CENTRAL:
                    return((funcC(dataC) - funcA(dataA)) / 2.0 / delta);

                default:
                    throw new MathException("enum not found");
                }
            }
            throw new MathException("enum not found");
        }