/**
     * General method when you wish to compute the expected variance from a log-moneyness
     * parametrised surface to within a certain tolerance
     *
     * @param surface log-moneyness parametrised volatility surface
     * @return expected variance
     */
    @SuppressWarnings("synthetic-access")
    @Override
    public Double visitLogMoneyness(final BlackVolatilitySurfaceLogMoneyness surface) {
      final double atmVol = surface.getVolatilityForLogMoneyness(_t, 0.0);
      if (_t < 1e-4) {
        return atmVol * atmVol;
      }
      final double rootT = Math.sqrt(_t);
      final double invNorTol = NORMAL.getInverseCDF(_tol);

      final Function1D<Double, Double> integrand = getLogMoneynessIntegrand(surface);

      double putPart;
      if (_addResidual) {
        putPart = _integrator.integrate(integrand, Math.log(_lowStrikeCutoff / _f), 0.0);
        putPart += _residual;
      } else {
        final double l = invNorTol * atmVol * rootT; // initial estimate of lower limit
        putPart = _integrator.integrate(integrand, l, 0.0);
        double rem = integrand.evaluate(l);
        double error = rem / putPart;
        int step = 1;
        while (error > _tol) {
          putPart += _integrator.integrate(integrand, (step + 1) * l, step * l);
          step++;
          rem = integrand.evaluate((step + 1) * l);
          error = rem / putPart;
        }
        putPart +=
            rem; // add on the (very small) remainder estimate otherwise we'll always underestimate
                 // variance
      }

      final double u =
          _f * Math.exp(-invNorTol * atmVol * rootT); // initial estimate of upper limit
      double callPart = _integrator.integrate(integrand, 0.0, u);
      double rem = integrand.evaluate(u);
      double error = rem / callPart;
      int step = 1;
      while (error > _tol) {
        callPart += _integrator.integrate(integrand, step * u, (1 + step) * u);
        step++;
        rem = integrand.evaluate((1 + step) * u);
        error = rem / putPart;
      }
      // callPart += rem;
      // don't add on the remainder estimate as it is very conservative, and likely too large

      return 2 * (putPart + callPart) / _t;
    }
  @Test
  public void test() {
    for (int i = 0; i < 10; i++) {
      final double x = A + (B - A) * RANDOM.nextDouble();
      final double y = 5 * NORMAL.nextRandom();
      assertRoundTrip(RANGE_LIMITS, x);
      assertReverseRoundTrip(RANGE_LIMITS, y);

      assertGradient(RANGE_LIMITS, x);
      assertInverseGradient(RANGE_LIMITS, y);

      assertGradientRoundTrip(RANGE_LIMITS, x);
    }
  }
Beispiel #3
0
    /**
     * @param token The token to analyse.
     * @return The text size corresponding to the given latex token or null.
     * @since 3.0
     */
    public static TextSize getTextSizeFromToken(final String token) {
      TextSize textSize;

      if (TINY.equals(token)) textSize = TINY;
      else if (FOOTNOTE.equals(token)) textSize = FOOTNOTE;
      else if (HUGE1.equals(token)) textSize = HUGE1;
      else if (HUGE2.equals(token)) textSize = HUGE2;
      else if (LARGE1.equals(token)) textSize = LARGE1;
      else if (LARGE2.equals(token)) textSize = LARGE2;
      else if (LARGE3.equals(token)) textSize = LARGE3;
      else if (NORMAL.equals(token)) textSize = NORMAL;
      else if (SCRIPT.equals(token)) textSize = SCRIPT;
      else if (SMALL.equals(token)) textSize = SMALL;
      else textSize = null;

      return textSize;
    }
    @SuppressWarnings("synthetic-access")
    @Override
    public Double visitStrike(final BlackVolatilitySurfaceStrike surface) {

      final double atmVol = surface.getVolatility(_t, _f);
      if (_t < 1e-4) {
        return atmVol * atmVol;
      }
      final double rootT = Math.sqrt(_t);
      final double invNorTol = NORMAL.getInverseCDF(_tol);

      final Function1D<Double, Double> integrand = getStrikeIntegrand(surface);
      final Function1D<Double, Double> remainder =
          new Function1D<Double, Double>() {
            @Override
            public Double evaluate(final Double strike) {
              if (strike == 0) {
                return 0.0;
              }
              final boolean isCall = strike >= _f;
              final double vol = surface.getVolatility(_t, strike);
              final double otmPrice = BlackFormulaRepository.price(_f, strike, _t, vol, isCall);
              final double res = (isCall ? otmPrice / strike : otmPrice / 2 / strike);
              return res;
            }
          };

      double putPart;
      if (_addResidual) {
        putPart = _integrator.integrate(integrand, _lowStrikeCutoff, _f);
        putPart += _residual;
      } else {
        double l = _f * Math.exp(invNorTol * atmVol * rootT); // initial estimate of lower limit
        putPart = _integrator.integrate(integrand, l, _f);
        double rem = remainder.evaluate(l);
        double error = rem / putPart;
        while (error > _tol) {
          l /= 2.0;
          putPart += _integrator.integrate(integrand, l, 2 * l);
          rem = remainder.evaluate(l);
          error = rem / putPart;
        }
        putPart +=
            rem; // add on the (very small) remainder estimate otherwise we'll always underestimate
                 // variance
      }

      double u = _f * Math.exp(-invNorTol * atmVol * rootT); // initial estimate of upper limit
      double callPart = _integrator.integrate(integrand, _f, u);
      double rem = remainder.evaluate(u);
      double error = rem / callPart;
      while (error > _tol) {
        callPart += _integrator.integrate(integrand, u, 2 * u);
        u *= 2.0;
        rem = remainder.evaluate(u);
        error = rem / putPart;
      }
      // callPart += rem/2.0;
      // don't add on the remainder estimate as it is very conservative, and likely too large

      return 2 * (putPart + callPart) / _t;
    }