コード例 #1
0
 private void testVolatilityAdjoint(
     double forward,
     EuropeanVanillaOption optionData,
     SabrFormulaData sabrData,
     double eps,
     double tol) {
   double volatility =
       FUNCTION.getVolatility(
           forward, optionData.getStrike(), optionData.getTimeToExpiry(), sabrData);
   double[] volatilityAdjoint =
       toArray(
           FUNCTION.getVolatilityAdjoint(
               forward, optionData.getStrike(), optionData.getTimeToExpiry(), 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);
 }
コード例 #2
0
 private void volatilityAdjoint2ForInstrument(
     EuropeanVanillaOption option, double tolerance1, double tolerance2) {
   // vol
   double volatility =
       FUNCTION.getVolatility(F, option.getStrike(), option.getTimeToExpiry(), DATA);
   double[] volatilityAdjoint =
       toArray(
           FUNCTION.getVolatilityAdjoint(F, option.getStrike(), option.getTimeToExpiry(), DATA));
   double[] volD = new double[6];
   double[][] volD2 = new double[2][2];
   double vol =
       FUNCTION.getVolatilityAdjoint2(
           F, option.getStrike(), option.getTimeToExpiry(), 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.getVolatility(F + deltaF, option.getStrike(), option.getTimeToExpiry(), DATA);
   double volatilityFM =
       FUNCTION.getVolatility(F - deltaF, option.getStrike(), option.getTimeToExpiry(), 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.getVolatility(F, option.getStrike() + deltaK, option.getTimeToExpiry(), DATA);
   double volatilityKM =
       FUNCTION.getVolatility(F, option.getStrike() - deltaK, option.getTimeToExpiry(), DATA);
   double derivativeKK_FD = (volatilityKP + volatilityKM - 2 * volatility) / (deltaK * deltaK);
   assertEquals(derivativeKK_FD, volD2[1][1], tolerance2);
   // Derivative strike-forward
   double volatilityFPKP =
       FUNCTION.getVolatility(
           F + deltaF, option.getStrike() + deltaK, option.getTimeToExpiry(), 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);
 }
コード例 #3
0
  @SuppressWarnings("null")
  private double fdSensitivity(
      EuropeanVanillaOption optionData,
      double forward,
      SabrFormulaData sabrData,
      SabrParameter param,
      double delta) {

    Function<SabrFormulaData, Double> funcC = null;
    Function<SabrFormulaData, Double> funcB = null;
    Function<SabrFormulaData, Double> funcA = null;
    SabrFormulaData dataC = null;
    SabrFormulaData dataB = sabrData;
    SabrFormulaData dataA = null;
    Function<SabrFormulaData, Double> func = getVolatilityFunction(optionData, forward);

    FiniteDifferenceType fdType = null;

    switch (param) {
      case Strike:
        double strike = optionData.getStrike();
        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 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 Alpha:
        double a = sabrData.getAlpha();
        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 Beta:
        double b = sabrData.getBeta();
        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 Nu:
        double n = sabrData.getNu();
        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 Rho:
        double r = sabrData.getRho();
        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 FORWARD:
          return (-1.5 * funcA.apply(dataA) + 2.0 * funcB.apply(dataB) - 0.5 * funcC.apply(dataC))
              / delta;
        case BACKWARD:
          return (0.5 * funcA.apply(dataA) - 2.0 * funcB.apply(dataB) + 1.5 * funcC.apply(dataC))
              / delta;
        case CENTRAL:
          return (funcC.apply(dataC) - funcA.apply(dataA)) / 2.0 / delta;
        default:
          throw new MathException("enum not found");
      }
    }
    throw new MathException("enum not found");
  }