// Test getDelta, getGamma and getVega
        public virtual void greeksTest()
        {
            double tol = 1.0e-12;
            double eps = 1.0e-5;

            EuropeanVanillaOption[] options = new EuropeanVanillaOption[] { ITM_CALL, ITM_PUT, OTM_CALL, OTM_PUT, ATM_CALL, ATM_PUT };
            foreach (EuropeanVanillaOption option in options)
            {
                // consistency with getPriceFunction for first order derivatives
                ValueDerivatives price = FUNCTION.getPriceAdjoint(option, VOL_DATA);
                double           delta = FUNCTION.getDelta(option, VOL_DATA);
                double           vega  = FUNCTION.getVega(option, VOL_DATA);
                assertEquals(price.getDerivative(0), delta, tol);
                assertEquals(price.getDerivative(1), vega, tol);

                // testing second order derivative against finite difference approximation
                NormalFunctionData dataUp  = NormalFunctionData.of(F + eps, DF, SIGMA);
                NormalFunctionData dataDw  = NormalFunctionData.of(F - eps, DF, SIGMA);
                double             deltaUp = FUNCTION.getDelta(option, dataUp);
                double             deltaDw = FUNCTION.getDelta(option, dataDw);
                double             @ref    = 0.5 * (deltaUp - deltaDw) / eps;
                double             gamma   = FUNCTION.getGamma(option, VOL_DATA);
                assertEquals(gamma, @ref, eps);

                EuropeanVanillaOption optionUp = EuropeanVanillaOption.of(option.Strike, T + eps, option.PutCall);
                EuropeanVanillaOption optionDw = EuropeanVanillaOption.of(option.Strike, T - eps, option.PutCall);
                double priceTimeUp             = FUNCTION.getPriceFunction(optionUp).apply(VOL_DATA);
                double priceTimeDw             = FUNCTION.getPriceFunction(optionDw).apply(VOL_DATA);
                @ref = -0.5 * (priceTimeUp - priceTimeDw) / eps;
                double theta = FUNCTION.getTheta(option, VOL_DATA);
                assertEquals(theta, @ref, eps);
            }
        }
예제 #2
0
        public virtual void intrinsic_price()
        {
            NormalFunctionData    data    = NormalFunctionData.of(1.0, 1.0, 0.01);
            EuropeanVanillaOption option1 = EuropeanVanillaOption.of(0.5, 1.0, PutCall.CALL);

            assertThrowsIllegalArg(() => impliedVolatility(data, option1, 1e-6));
            EuropeanVanillaOption option2 = EuropeanVanillaOption.of(1.5, 1.0, PutCall.PUT);

            assertThrowsIllegalArg(() => impliedVolatility(data, option2, 1e-6));
        }
예제 #3
0
 //-----------------------------------------------------------------------
 public override bool Equals(object obj)
 {
     if (obj == this)
     {
         return(true);
     }
     if (obj != null && obj.GetType() == this.GetType())
     {
         NormalFunctionData other = (NormalFunctionData)obj;
         return(JodaBeanUtils.equal(forward, other.forward) && JodaBeanUtils.equal(numeraire, other.numeraire) && JodaBeanUtils.equal(normalVolatility, other.normalVolatility));
     }
     return(false);
 }
예제 #4
0
 static NormalFormulaRepositoryImpliedVolatilityTest()
 {
     PRICES = new double[N];
     SIGMA  = new double[N];
     DATA   = new NormalFunctionData[N];
     for (int i = 0; i < N; i++)
     {
         STRIKES[i]     = FORWARD + (-N / 2 + i) * 10;
         STRIKES_ATM[i] = FORWARD + (-0.5d * N + i) / 100.0d;
         SIGMA[i]       = FORWARD * (0.05 + 4.0 * i / 100.0);
         SIGMA_BLACK[i] = 0.20 + i / 100.0d;
         DATA[i]        = NormalFunctionData.of(FORWARD, DF, SIGMA[i]);
         OPTIONS[i]     = EuropeanVanillaOption.of(STRIKES[i], T, PutCall.CALL);
         PRICES[i]      = FUNCTION.getPriceFunction(OPTIONS[i]).apply(DATA[i]);
     }
 }
        // Testing the branch for sigmaRootT < 1e-16
        public virtual void smallParameterGreeksTest()
        {
            double             eps       = 1.0e-5;
            NormalFunctionData dataVolUp = NormalFunctionData.of(F, DF, eps);
            NormalFunctionData dataFwUp  = NormalFunctionData.of(F + eps, DF, 0.0);
            NormalFunctionData dataFwDw  = NormalFunctionData.of(F - eps, DF, 0.0);

            EuropeanVanillaOption[] options = new EuropeanVanillaOption[] { ITM_CALL, ITM_PUT, OTM_CALL, OTM_PUT, ATM_CALL, ATM_PUT };
            foreach (EuropeanVanillaOption option in options)
            {
                double delta    = FUNCTION.getDelta(option, ZERO_VOL_DATA);
                double priceUp  = FUNCTION.getPriceFunction(option).apply(dataFwUp);
                double priceDw  = FUNCTION.getPriceFunction(option).apply(dataFwDw);
                double refDelta = 0.5 * (priceUp - priceDw) / eps;
                assertEquals(delta, refDelta, eps);

                double vega       = FUNCTION.getVega(option, ZERO_VOL_DATA);
                double priceVolUp = FUNCTION.getPriceFunction(option).apply(dataVolUp);
                double price      = FUNCTION.getPriceFunction(option).apply(ZERO_VOL_DATA);
                double refVega    = (priceVolUp - price) / eps;
                assertEquals(vega, refVega, eps);

                double gamma    = FUNCTION.getGamma(option, ZERO_VOL_DATA);
                double deltaUp  = FUNCTION.getDelta(option, dataFwUp);
                double deltaDw  = FUNCTION.getDelta(option, dataFwDw);
                double refGamma = 0.5 * (deltaUp - deltaDw) / eps;
                if (Math.Abs(refGamma) > 0.1 / eps)
                {   // infinity handled
                    assertTrue(double.IsInfinity(gamma));
                }
                else
                {
                    assertEquals(gamma, refGamma, eps);
                }

                EuropeanVanillaOption optionUp = EuropeanVanillaOption.of(option.Strike, T + eps, option.PutCall);
                EuropeanVanillaOption optionDw = EuropeanVanillaOption.of(option.Strike, T - eps, option.PutCall);
                double priceTimeUp             = FUNCTION.getPriceFunction(optionUp).apply(ZERO_VOL_DATA);
                double priceTimeDw             = FUNCTION.getPriceFunction(optionDw).apply(ZERO_VOL_DATA);
                double refTheta = -0.5 * (priceTimeUp - priceTimeDw) / eps;
                double theta    = FUNCTION.getTheta(option, ZERO_VOL_DATA);
                assertEquals(theta, refTheta, eps);
            }
        }
        public virtual void testPriceAdjoint()
        {
            // Price
            double           price        = FUNCTION.getPriceFunction(ITM_CALL).apply(VOL_DATA);
            ValueDerivatives priceAdjoint = FUNCTION.getPriceAdjoint(ITM_CALL, VOL_DATA);

            assertEquals(priceAdjoint.Value, price, 1E-10);
            // Price with 0 volatility
            double           price0        = FUNCTION.getPriceFunction(ITM_CALL).apply(ZERO_VOL_DATA);
            ValueDerivatives price0Adjoint = FUNCTION.getPriceAdjoint(ITM_CALL, ZERO_VOL_DATA);

            assertEquals(price0Adjoint.Value, price0, 1E-10);
            // Derivative forward.
            double             deltaF         = 0.01;
            NormalFunctionData dataFP         = NormalFunctionData.of(F + deltaF, DF, SIGMA);
            NormalFunctionData dataFM         = NormalFunctionData.of(F - deltaF, DF, SIGMA);
            double             priceFP        = FUNCTION.getPriceFunction(ITM_CALL).apply(dataFP);
            double             priceFM        = FUNCTION.getPriceFunction(ITM_CALL).apply(dataFM);
            double             derivativeF_FD = (priceFP - priceFM) / (2 * deltaF);

            assertEquals(priceAdjoint.getDerivative(0), derivativeF_FD, 1E-7);
            // Derivative strike.
            double deltaK = 0.01;
            EuropeanVanillaOption optionKP = EuropeanVanillaOption.of(F - DELTA + deltaK, T, CALL);
            EuropeanVanillaOption optionKM = EuropeanVanillaOption.of(F - DELTA - deltaK, T, CALL);
            double priceKP        = FUNCTION.getPriceFunction(optionKP).apply(VOL_DATA);
            double priceKM        = FUNCTION.getPriceFunction(optionKM).apply(VOL_DATA);
            double derivativeK_FD = (priceKP - priceKM) / (2 * deltaK);

            assertEquals(priceAdjoint.getDerivative(2), derivativeK_FD, 1E-7);
            // Derivative volatility.
            double             deltaV         = 0.0001;
            NormalFunctionData dataVP         = NormalFunctionData.of(F, DF, SIGMA + deltaV);
            NormalFunctionData dataVM         = NormalFunctionData.of(F, DF, SIGMA - deltaV);
            double             priceVP        = FUNCTION.getPriceFunction(ITM_CALL).apply(dataVP);
            double             priceVM        = FUNCTION.getPriceFunction(ITM_CALL).apply(dataVM);
            double             derivativeV_FD = (priceVP - priceVM) / (2 * deltaV);

            assertEquals(priceAdjoint.getDerivative(1), derivativeV_FD, 1E-6);
        }
 /// <summary>
 /// Computes vega of an option in the normally distributed assets hypothesis (Bachelier model).
 /// </summary>
 /// <param name="option">  the option description </param>
 /// <param name="data">  the model data </param>
 /// <returns> vega </returns>
 public double getVega(EuropeanVanillaOption option, NormalFunctionData data)
 {
     ArgChecker.notNull(option, "option");
     ArgChecker.notNull(data, "data");
     return(data.Numeraire * NormalFormulaRepository.vega(data.Forward, option.Strike, option.TimeToExpiry, data.NormalVolatility, option.PutCall));
 }
 /// <summary>
 /// Computes the price of an option in the normally distributed assets hypothesis (Bachelier model).
 /// The first order price derivatives are also provided.
 /// </summary>
 /// <param name="option">  the option description </param>
 /// <param name="data">  the model data </param>
 /// <returns> a <seealso cref="ValueDerivatives"/> with the price in the value and the derivatives with
 ///  respect to [0] the forward, [1] the volatility and [2] the strike </returns>
 public ValueDerivatives getPriceAdjoint(EuropeanVanillaOption option, NormalFunctionData data)
 {
     ArgChecker.notNull(option, "option");
     ArgChecker.notNull(data, "data");
     return(NormalFormulaRepository.priceAdjoint(data.Forward, option.Strike, option.TimeToExpiry, data.NormalVolatility, data.Numeraire, option.PutCall));
 }
예제 #9
0
 private double impliedVolatility(NormalFunctionData data, EuropeanVanillaOption option, double price)
 {
     return(NormalFormulaRepository.impliedVolatility(price, data.Forward, option.Strike, option.TimeToExpiry, data.NormalVolatility, data.Numeraire, option.PutCall));
 }