/**
   * recalculate interval if total number of partitions greater than maximum number of allowed
   * partitions
   *
   * @param low watermark value
   * @param high watermark value
   * @param partition interval
   * @param Maximum number of allowed partitions
   * @return calculated interval
   */
  private long getInterval(
      long lowWatermarkValue, long highWatermarkValue, long partitionInterval, int maxIntervals) {
    if (lowWatermarkValue > highWatermarkValue) {
      LOG.info(
          "lowWatermarkValue: "
              + lowWatermarkValue
              + " is greater than highWatermarkValue: "
              + highWatermarkValue);

      return 0;
    }
    long outputInterval = partitionInterval;
    boolean longOverflow = false;
    long totalIntervals = Long.MAX_VALUE;
    try {
      totalIntervals =
          DoubleMath.roundToLong(
              (double) highWatermarkValue / partitionInterval
                  - (double) lowWatermarkValue / partitionInterval,
              RoundingMode.CEILING);
    } catch (java.lang.ArithmeticException e) {
      longOverflow = true;
    }
    if (longOverflow || totalIntervals > maxIntervals) {
      outputInterval =
          DoubleMath.roundToLong(
              (double) highWatermarkValue / maxIntervals
                  - (double) lowWatermarkValue / maxIntervals,
              RoundingMode.CEILING);
    }
    return outputInterval;
  }
  private double getZOverChi(double rho, double z) {

    // Implementation comment: To avoid numerical instability (0/0) around ATM the first order
    // approximation is used.
    if (DoubleMath.fuzzyEquals(z, 0.0, SMALL_Z)) {
      return 1.0 - rho * z / 2.0;
    }

    double rhoStar = 1 - rho;
    if (DoubleMath.fuzzyEquals(rhoStar, 0.0, RHO_EPS)) {
      if (z < 1.0) {
        return -z / Math.log(1.0d - z);
      } else {
        throw new IllegalArgumentException("can't handle z>=1, rho=1");
      }
    }

    double rhoHat = 1 + rho;
    if (DoubleMath.fuzzyEquals(rhoHat, 0.0, RHO_EPS_NEGATIVE)) {
      if (z > -1) {
        return z / Math.log(1 + z);
      } else if (z < -1) {
        if (rhoHat == 0) {
          return 0.0;
        }
        double chi = Math.log(rhoHat) - Math.log(-(1 + z) / rhoStar);
        return z / chi;
      } else {
        return 0.0;
      }
    }

    double arg;
    if (z < LARGE_NEG_Z) {
      arg =
          (rho * rho - 1)
              / 2
              / z; // get rounding errors due to fine balanced cancellation for very large negative
                   // z
    } else if (z > LARGE_POS_Z) {
      arg = 2 * (z - rho);
    } else {
      arg = (Math.sqrt(1 - 2 * rho * z + z * z) + z - rho);
      // Mathematically this cannot be less than zero, but you know what computers are like.
      if (arg <= 0.0) {
        return 0.0;
      }
    }

    double chi = Math.log(arg) - Math.log(rhoStar);
    return z / chi;
  }
Exemple #3
0
 @ScalarOperator(SATURATED_FLOOR_CAST)
 @SqlType(StandardTypes.INTEGER)
 public static long saturatedFloorCastToInteger(@SqlType(StandardTypes.DOUBLE) double value) {
   if (value <= MIN_INT_AS_DOUBLE) {
     return Integer.MIN_VALUE;
   }
   if (MAX_INT_AS_DOUBLE - value <= 1) {
     return Integer.MAX_VALUE;
   }
   return DoubleMath.roundToInt(value, FLOOR);
 }
Exemple #4
0
 @ScalarOperator(SATURATED_FLOOR_CAST)
 @SqlType(StandardTypes.BIGINT)
 public static long saturatedFloorCastToBigint(@SqlType(StandardTypes.DOUBLE) double value) {
   if (value <= MIN_LONG_AS_DOUBLE) {
     return Long.MIN_VALUE;
   }
   if (MAX_LONG_AS_DOUBLE_PLUS_ONE - value <= 1) {
     return Long.MAX_VALUE;
   }
   return DoubleMath.roundToLong(value, FLOOR);
 }
  synchronized void startPublishingTimer() {
    if (state.get() == State.Closed) return;

    lifetimeCounter--;

    if (lifetimeCounter < 1) {
      logger.debug("[id={}] lifetime expired.", subscriptionId);

      setState(State.Closing);
    } else {
      long interval = DoubleMath.roundToLong(publishingInterval, RoundingMode.UP);

      subscriptionManager
          .getServer()
          .getScheduledExecutorService()
          .schedule(this::onPublishingTimer, interval, TimeUnit.MILLISECONDS);
    }
  }
Exemple #6
0
  private static Integer parseInteger(String value) {

    try {
      return Integer.valueOf(value);
    } catch (NumberFormatException nfeInteger) {

      try {
        Double result = parseDouble(value);

        if (DoubleMath.isMathematicalInteger(result)) {
          return result.intValue();
        }
      } catch (NumberFormatException nfeDouble) {
        // Ignored
      }

      throw nfeInteger;
    }
  }
Exemple #7
0
  private void writeResultForGnuplot(
      AbstractMeter meter, String ds, String operation, int size, Collection<Double> values)
      throws IOException {
    String dirName = outputDir + "/" + meter.getName() + "/";

    // Write data for *single* plot
    String fileName = ds + "_" + operation;
    String extension = plotExtension;
    Writer w = fileWriters.get(dirName + fileName + extension);
    if (w == null) {
      w = new Writer(dirName, fileName + extension);
      writeGnuplotHeaderSingle(w, dirName, fileName, operation, meter, ds);
      fileWriters.put(dirName + fileName + extension, w);
    }

    extension = rawExtension;
    w = fileWriters.get(dirName + fileName + extension);
    if (w == null) {
      w = new Writer(dirName, fileName + extension);
      fileWriters.put(dirName + fileName + extension, w);
    }

    double min = Collections.min(values);
    double max = Collections.max(values);
    double mean = DoubleMath.mean(values);

    w.writeln(" " + size + " " + mean + " " + min + " " + max);

    // Check for the aggregation file
    extension = plotExtension;
    String innerLastWrittenOp = lastWrittenOp.get(dirName + operation + extension);

    if (innerLastWrittenOp == null || !innerLastWrittenOp.equals(operation)) {
      w = fileWriters.get(dirName + aggregationFile);
      if (w == null) {
        w = new Writer(dirName, aggregationFile, true);
        fileWriters.put(dirName + aggregationFile, w);
      }
      w.writeln(operation + ";" + meter.getUnit() + ";" + fileName + rawExtension);
    }
    lastWrittenOp.put(dirName + operation + extension, operation);
  }
Exemple #8
0
  int determineHighestPossible(int currentMtn, int[] perceivedHighest, int heights[]) {
    // Any connection from peaks < currentMtn to peaks after
    int highestPossible = 1000000000;

    for (int mtn = 1; mtn < currentMtn; ++mtn) {
      int percievedMax = perceivedHighest[mtn - 1];

      if (percievedMax <= currentMtn) continue;

      Line line =
          new Line(
              new Point(mtn, heights[mtn - 1]), new Point(percievedMax, heights[percievedMax - 1]));

      double cur = line.getPointGivenX(currentMtn).y();

      int heightInt =
          DoubleMath.isMathematicalInteger(cur) ? (int) Math.floor(cur) - 1 : (int) Math.floor(cur);

      highestPossible = Math.min(heightInt, highestPossible);
    }

    return highestPossible;
  }
  @Override
  public List<WorkUnit> pack(Map<String, List<WorkUnit>> workUnitsByTopic, int numContainers) {
    setWorkUnitEstSizes(workUnitsByTopic);
    List<WorkUnit> workUnits = Lists.newArrayList();
    for (List<WorkUnit> workUnitsForTopic : workUnitsByTopic.values()) {

      // For each topic, merge all empty workunits into a single workunit, so that a single
      // empty task will be created instead of many.
      MultiWorkUnit zeroSizeWorkUnit = MultiWorkUnit.createEmpty();
      for (WorkUnit workUnit : workUnitsForTopic) {
        if (DoubleMath.fuzzyEquals(getWorkUnitEstSize(workUnit), 0.0, EPS)) {
          addWorkUnitToMultiWorkUnit(workUnit, zeroSizeWorkUnit);
        } else {
          workUnit.setWatermarkInterval(getWatermarkIntervalFromWorkUnit(workUnit));
          workUnits.add(workUnit);
        }
      }
      if (!zeroSizeWorkUnit.getWorkUnits().isEmpty()) {
        workUnits.add(squeezeMultiWorkUnit(zeroSizeWorkUnit));
      }
    }
    return worstFitDecreasingBinPacking(workUnits, numContainers);
  }
  public void test_cashFlowEquivalent() {
    Swap swap = Swap.builder().legs(IBOR_LEG, FIXED_LEG).build();
    ExpandedSwapLeg computed =
        CashFlowEquivalentCalculator.cashFlowEquivalentSwap(swap.expand(), PROVIDER);
    ExpandedSwapLeg computedIborLeg =
        CashFlowEquivalentCalculator.cashFlowEquivalentIborLeg(IBOR_LEG.expand(), PROVIDER);
    ExpandedSwapLeg computedFixedLeg =
        CashFlowEquivalentCalculator.cashFlowEquivalentFixedLeg(FIXED_LEG.expand(), PROVIDER);
    assertEquals(computedFixedLeg.getPaymentEvents(), computed.getPaymentEvents().subList(0, 2));
    assertEquals(computedIborLeg.getPaymentEvents(), computed.getPaymentEvents().subList(2, 6));

    // expected payments from fixed leg
    NotionalExchange fixedPayment1 =
        NotionalExchange.of(PAYMENT1, CurrencyAmount.of(GBP, NOTIONAL * RATE * PAY_YC1));
    NotionalExchange fixedPayment2 =
        NotionalExchange.of(PAYMENT2, CurrencyAmount.of(GBP, NOTIONAL * RATE * PAY_YC2));
    // expected payments from ibor leg
    LocalDate fixingSTART1 = GBP_LIBOR_3M.calculateEffectiveFromFixing(FIXING1);
    double fixedYearFraction1 =
        GBP_LIBOR_3M
            .getDayCount()
            .relativeYearFraction(
                fixingSTART1, GBP_LIBOR_3M.calculateMaturityFromEffective(fixingSTART1));
    double beta1 =
        (1d + fixedYearFraction1 * PROVIDER.iborIndexRates(GBP_LIBOR_3M).rate(FIXING1))
            * PROVIDER.discountFactor(GBP, PAYMENT1)
            / PROVIDER.discountFactor(GBP, fixingSTART1);
    NotionalExchange iborPayment11 =
        NotionalExchange.of(
            fixingSTART1, CurrencyAmount.of(GBP, -NOTIONAL * beta1 * PAY_YC1 / fixedYearFraction1));
    NotionalExchange iborPayment12 =
        NotionalExchange.of(
            PAYMENT1, CurrencyAmount.of(GBP, NOTIONAL * PAY_YC1 / fixedYearFraction1));
    LocalDate fixingSTART2 = GBP_LIBOR_3M.calculateEffectiveFromFixing(FIXING2);
    double fixedYearFraction2 =
        GBP_LIBOR_3M
            .getDayCount()
            .relativeYearFraction(
                fixingSTART2, GBP_LIBOR_3M.calculateMaturityFromEffective(fixingSTART2));
    double beta2 =
        (1d + fixedYearFraction2 * PROVIDER.iborIndexRates(GBP_LIBOR_3M).rate(FIXING2))
            * PROVIDER.discountFactor(GBP, PAYMENT2)
            / PROVIDER.discountFactor(GBP, fixingSTART2);
    NotionalExchange iborPayment21 =
        NotionalExchange.of(
            fixingSTART2, CurrencyAmount.of(GBP, -NOTIONAL * beta2 * PAY_YC2 / fixedYearFraction2));
    NotionalExchange iborPayment22 =
        NotionalExchange.of(
            PAYMENT2, CurrencyAmount.of(GBP, NOTIONAL * PAY_YC2 / fixedYearFraction2));

    ExpandedSwapLeg expected =
        ExpandedSwapLeg.builder()
            .type(OTHER)
            .payReceive(RECEIVE)
            .paymentEvents(
                fixedPayment1,
                fixedPayment2,
                iborPayment11,
                iborPayment12,
                iborPayment21,
                iborPayment22)
            .build();

    double eps = 1.0e-12;
    assertEquals(computed.getPaymentEvents().size(), expected.getPaymentEvents().size());
    for (int i = 0; i < 6; ++i) {
      NotionalExchange payCmp = (NotionalExchange) computed.getPaymentEvents().get(i);
      NotionalExchange payExp = (NotionalExchange) expected.getPaymentEvents().get(i);
      assertEquals(payCmp.getCurrency(), payExp.getCurrency());
      assertEquals(payCmp.getPaymentDate(), payExp.getPaymentDate());
      assertTrue(
          DoubleMath.fuzzyEquals(
              payCmp.getPaymentAmount().getAmount(),
              payExp.getPaymentAmount().getAmount(),
              NOTIONAL * eps));
    }
  }
Exemple #11
0
 /**
  * Erzeugt einen neuen Pixel an der Stelle (x,y). Die doubles werden entsprechend auf die
  * Integerpositionen des Pixels gerundet.
  *
  * @param x die x-Koordinate des Pixels
  * @param y die y-Koordinate des Pixels
  */
 public Pixel(double x, double y) {
   this.x = DoubleMath.roundToInt(x, RoundingMode.HALF_DOWN);
   this.y = DoubleMath.roundToInt(y, RoundingMode.HALF_DOWN);
 }
 /**
  * Computes the first and second order derivatives of the Black implied volatility in the SABR
  * model.
  *
  * <p>The first derivative values will be stored in the input array {@code volatilityD} The array
  * contains, [0] Derivative w.r.t the forward, [1] the derivative w.r.t the strike, [2] the
  * derivative w.r.t. to alpha, [3] the derivative w.r.t. to beta, [4] the derivative w.r.t. to
  * rho, and [5] the derivative w.r.t. to nu. Thus the length of the array should be 6.
  *
  * <p>The second derivative values will be stored in the input array {@code volatilityD2}. Only
  * the second order derivative with respect to the forward and strike are implemented. The array
  * contains [0][0] forward-forward; [0][1] forward-strike; [1][1] strike-strike. Thus the size
  * should be 2 x 2.
  *
  * <p>Around ATM, a first order expansion is used to due to some 0/0-type indetermination. The
  * second order derivative produced is poor around ATM.
  *
  * @param forward the forward value of the underlying
  * @param strike the strike value of the option
  * @param timeToExpiry the time to expiry of the option
  * @param data the SABR data.
  * @param volatilityD the array used to return the first order derivative
  * @param volatilityD2 the array of array used to return the second order derivative
  * @return the Black implied volatility
  */
 @Override
 public double volatilityAdjoint2(
     double forward,
     double strike,
     double timeToExpiry,
     SabrFormulaData data,
     double[] volatilityD,
     double[][] volatilityD2) {
   double k = Math.max(strike, 0.000001);
   double alpha = data.getAlpha();
   double beta = data.getBeta();
   double rho = data.getRho();
   double nu = data.getNu();
   // Forward
   double h0 = (1 - beta) / 2;
   double h1 = forward * k;
   double h1h0 = Math.pow(h1, h0);
   double h12 = h1h0 * h1h0;
   double h2 = Math.log(forward / k);
   double h22 = h2 * h2;
   double h23 = h22 * h2;
   double h24 = h23 * h2;
   double f1 = h1h0 * (1 + h0 * h0 / 6.0 * (h22 + h0 * h0 / 20.0 * h24));
   double f2 = nu / alpha * h1h0 * h2;
   double f3 =
       h0 * h0 / 6.0 * alpha * alpha / h12
           + rho * beta * nu * alpha / 4.0 / h1h0
           + (2 - 3 * rho * rho) / 24.0 * nu * nu;
   double sqrtf2 = Math.sqrt(1 - 2 * rho * f2 + f2 * f2);
   double f2x = 0.0;
   double x = 0.0, xp = 0, xpp = 0;
   if (DoubleMath.fuzzyEquals(f2, 0.0, SMALL_Z)) {
     f2x = 1.0 - 0.5 * f2 * rho; // small f2 expansion to f2^2 terms
   } else {
     if (DoubleMath.fuzzyEquals(rho, 1.0, RHO_EPS)) {
       x =
           f2 < 1.0
               ? -Math.log(1.0 - f2) - 0.5 * Math.pow(f2 / (f2 - 1.0), 2) * (1.0 - rho)
               : Math.log(2.0 * f2 - 2.0) - Math.log(1.0 - rho);
     } else {
       x = Math.log((sqrtf2 + f2 - rho) / (1 - rho));
     }
     xp = 1. / sqrtf2;
     xpp = (rho - f2) / Math.pow(sqrtf2, 3.0);
     f2x = f2 / x;
   }
   double sigma = Math.max(MIN_VOL, alpha / f1 * f2x * (1 + f3 * timeToExpiry));
   // First level
   double h0Dbeta = -0.5;
   double sigmaDf1 = -sigma / f1;
   double sigmaDf2 = 0;
   if (DoubleMath.fuzzyEquals(f2, 0.0, SMALL_Z)) {
     sigmaDf2 = alpha / f1 * (1 + f3 * timeToExpiry) * -0.5 * rho;
   } else {
     sigmaDf2 = alpha / f1 * (1 + f3 * timeToExpiry) * (1.0 / x - f2 * xp / (x * x));
   }
   double sigmaDf3 = alpha / f1 * f2x * timeToExpiry;
   double sigmaDf4 = f2x / f1 * (1 + f3 * timeToExpiry);
   double sigmaDx = -alpha / f1 * f2 / (x * x) * (1 + f3 * timeToExpiry);
   double[][] sigmaD2ff = new double[3][3];
   sigmaD2ff[0][0] = -sigmaDf1 / f1 + sigma / (f1 * f1); // OK
   sigmaD2ff[0][1] = -sigmaDf2 / f1;
   sigmaD2ff[0][2] = -sigmaDf3 / f1;
   if (DoubleMath.fuzzyEquals(f2, 0.0, SMALL_Z)) {
     sigmaD2ff[1][2] = alpha / f1 * -0.5 * rho * timeToExpiry;
   } else {
     sigmaD2ff[1][1] =
         alpha
             / f1
             * (1 + f3 * timeToExpiry)
             * (-2 * xp / (x * x) - f2 * xpp / (x * x) + 2 * f2 * xp * xp / (x * x * x));
     sigmaD2ff[1][2] = alpha / f1 * timeToExpiry * (1.0 / x - f2 * xp / (x * x));
   }
   sigmaD2ff[2][2] = 0.0;
   //      double sigma = alpha / f1 * f2x * (1 + f3 * theta);
   // Second level
   double[] f1Dh = new double[3];
   double[] f2Dh = new double[3];
   double[] f3Dh = new double[3];
   f1Dh[0] = h1h0 * (h0 * (h22 / 3.0 + h0 * h0 / 40.0 * h24)) + Math.log(h1) * f1;
   f1Dh[1] = h0 * f1 / h1;
   f1Dh[2] = h1h0 * (h0 * h0 / 6.0 * (2.0 * h2 + h0 * h0 / 5.0 * h23));
   f2Dh[0] = Math.log(h1) * f2;
   f2Dh[1] = h0 * f2 / h1;
   f2Dh[2] = nu / alpha * h1h0;
   f3Dh[0] =
       h0 / 3.0 * alpha * alpha / h12
           - 2 * h0 * h0 / 6.0 * alpha * alpha / h12 * Math.log(h1)
           - rho * beta * nu * alpha / 4.0 / h1h0 * Math.log(h1);
   f3Dh[1] =
       -2 * h0 * h0 / 6.0 * alpha * alpha / h12 * h0 / h1
           - rho * beta * nu * alpha / 4.0 / h1h0 * h0 / h1;
   f3Dh[2] = 0.0;
   double[] f1Dp = new double[4]; // Derivative to sabr parameters
   double[] f2Dp = new double[4];
   double[] f3Dp = new double[4];
   double[] f4Dp = new double[4];
   f1Dp[0] = 0.0;
   f1Dp[1] = f1Dh[0] * h0Dbeta;
   f1Dp[2] = 0.0;
   f1Dp[3] = 0.0;
   f2Dp[0] = -f2 / alpha;
   f2Dp[1] = f2Dh[0] * h0Dbeta;
   f2Dp[2] = 0.0;
   f2Dp[3] = h1h0 * h2 / alpha;
   f3Dp[0] = h0 * h0 / 3.0 * alpha / h12 + rho * beta * nu / 4.0 / h1h0;
   f3Dp[1] = rho * nu * alpha / 4.0 / h1h0 + f3Dh[0] * h0Dbeta;
   f3Dp[2] = beta * nu * alpha / 4.0 / h1h0 - rho / 4.0 * nu * nu;
   f3Dp[3] = rho * beta * alpha / 4.0 / h1h0 + (2 - 3 * rho * rho) / 12.0 * nu;
   f4Dp[0] = 1.0;
   f4Dp[1] = 0.0;
   f4Dp[2] = 0.0;
   f4Dp[3] = 0.0;
   double sigmaDh1 = sigmaDf1 * f1Dh[1] + sigmaDf2 * f2Dh[1] + sigmaDf3 * f3Dh[1];
   double sigmaDh2 = sigmaDf1 * f1Dh[2] + sigmaDf2 * f2Dh[2] + sigmaDf3 * f3Dh[2];
   double[][] f1D2hh = new double[2][2]; // No h0
   double[][] f2D2hh = new double[2][2];
   double[][] f3D2hh = new double[2][2];
   f1D2hh[0][0] = h0 * (h0 - 1) * f1 / (h1 * h1);
   f1D2hh[0][1] = h0 * h1h0 / h1 * h0 * h0 / 6.0 * (2.0 * h2 + 4.0 * h0 * h0 / 20.0 * h23);
   f1D2hh[1][1] = h1h0 * (h0 * h0 / 6.0 * (2.0 + 12.0 * h0 * h0 / 20.0 * h2));
   f2D2hh[0][0] = h0 * (h0 - 1) * f2 / (h1 * h1);
   f2D2hh[0][1] = nu / alpha * h0 * h1h0 / h1;
   f2D2hh[1][1] = 0.0;
   f3D2hh[0][0] =
       2 * h0 * (2 * h0 + 1) * h0 * h0 / 6.0 * alpha * alpha / (h12 * h1 * h1)
           + h0 * (h0 + 1) * rho * beta * nu * alpha / 4.0 / (h1h0 * h1 * h1);
   f3D2hh[0][1] = 0.0;
   f3D2hh[1][1] = 0.0;
   double[][] sigmaD2hh = new double[2][2]; // No h0
   for (int loopx = 0; loopx < 2; loopx++) {
     for (int loopy = loopx; loopy < 2; loopy++) {
       sigmaD2hh[loopx][loopy] =
           (sigmaD2ff[0][0] * f1Dh[loopy + 1]
                       + sigmaD2ff[0][1] * f2Dh[loopy + 1]
                       + sigmaD2ff[0][2] * f3Dh[loopy + 1])
                   * f1Dh[loopx + 1]
               + sigmaDf1 * f1D2hh[loopx][loopy]
               + (sigmaD2ff[0][1] * f1Dh[loopy + 1]
                       + sigmaD2ff[1][1] * f2Dh[loopy + 1]
                       + sigmaD2ff[1][2] * f3Dh[loopy + 1])
                   * f2Dh[loopx + 1]
               + sigmaDf2 * f2D2hh[loopx][loopy]
               + (sigmaD2ff[0][2] * f1Dh[loopy + 1]
                       + sigmaD2ff[1][2] * f2Dh[loopy + 1]
                       + sigmaD2ff[2][2] * f3Dh[loopy + 1])
                   * f3Dh[loopx + 1]
               + sigmaDf3 * f3D2hh[loopx][loopy];
     }
   }
   // Third level
   double h1Df = k;
   double h1Dk = forward;
   double h1D2ff = 0.0;
   double h1D2kf = 1.0;
   double h1D2kk = 0.0;
   double h2Df = 1.0 / forward;
   double h2Dk = -1.0 / k;
   double h2D2ff = -1 / (forward * forward);
   double h2D2fk = 0.0;
   double h2D2kk = 1.0 / (k * k);
   volatilityD[0] = sigmaDh1 * h1Df + sigmaDh2 * h2Df;
   volatilityD[1] = sigmaDh1 * h1Dk + sigmaDh2 * h2Dk;
   volatilityD[2] =
       sigmaDf1 * f1Dp[0] + sigmaDf2 * f2Dp[0] + sigmaDf3 * f3Dp[0] + sigmaDf4 * f4Dp[0];
   volatilityD[3] =
       sigmaDf1 * f1Dp[1] + sigmaDf2 * f2Dp[1] + sigmaDf3 * f3Dp[1] + sigmaDf4 * f4Dp[1];
   if (DoubleMath.fuzzyEquals(f2, 0.0, SMALL_Z)) {
     volatilityD[4] = -0.5 * f2 + sigmaDf3 * f3Dp[2];
   } else {
     double xDr;
     if (DoubleMath.fuzzyEquals(rho, 1.0, RHO_EPS)) {
       xDr =
           f2 > 1.0
               ? 1.0 / (1.0 - rho) + (0.5 - f2) / (f2 - 1.0) / (f2 - 1.0)
               : 0.5 * Math.pow(f2 / (1.0 - f2), 2.0)
                   + 0.25 * (f2 - 4.0) * Math.pow(f2 / (f2 - 1.0), 3) / (f2 - 1.0) * (1.0 - rho);
       if (Doubles.isFinite(xDr)) {
         volatilityD[4] =
             sigmaDf1 * f1Dp[2] + sigmaDx * xDr + sigmaDf3 * f3Dp[2] + sigmaDf4 * f4Dp[2];
       } else {
         volatilityD[4] = Double.NEGATIVE_INFINITY;
       }
     } else {
       xDr = (-f2 / sqrtf2 - 1 + (sqrtf2 + f2 - rho) / (1 - rho)) / (sqrtf2 + f2 - rho);
       volatilityD[4] =
           sigmaDf1 * f1Dp[2] + sigmaDx * xDr + sigmaDf3 * f3Dp[2] + sigmaDf4 * f4Dp[2];
     }
   }
   volatilityD[5] =
       sigmaDf1 * f1Dp[3] + sigmaDf2 * f2Dp[3] + sigmaDf3 * f3Dp[3] + sigmaDf4 * f4Dp[3];
   volatilityD2[0][0] =
       (sigmaD2hh[0][0] * h1Df + sigmaD2hh[0][1] * h2Df) * h1Df
           + sigmaDh1 * h1D2ff
           + (sigmaD2hh[0][1] * h1Df + sigmaD2hh[1][1] * h2Df) * h2Df
           + sigmaDh2 * h2D2ff;
   volatilityD2[0][1] =
       (sigmaD2hh[0][0] * h1Dk + sigmaD2hh[0][1] * h2Dk) * h1Df
           + sigmaDh1 * h1D2kf
           + (sigmaD2hh[0][1] * h1Dk + sigmaD2hh[1][1] * h2Dk) * h2Df
           + sigmaDh2 * h2D2fk;
   volatilityD2[1][0] = volatilityD2[0][1];
   volatilityD2[1][1] =
       (sigmaD2hh[0][0] * h1Dk + sigmaD2hh[0][1] * h2Dk) * h1Dk
           + sigmaDh1 * h1D2kk
           + (sigmaD2hh[0][1] * h1Dk + sigmaD2hh[1][1] * h2Dk) * h2Dk
           + sigmaDh2 * h2D2kk;
   return sigma;
 }
Exemple #13
0
 @Override
 public double factorialDouble(int n) {
   return DoubleMath.factorial(n);
 }
  @Override
  public double volatility(
      double forward,
      double strike,
      double timeToExpiry,
      double alpha,
      double beta,
      double rho,
      double nu) {

    ArgChecker.isTrue(forward > 0.0, "forward must be greater than zero");
    ArgChecker.isTrue(strike >= 0.0, "strike must be greater than zero");
    ArgChecker.isTrue(timeToExpiry >= 0.0, "timeToExpiry must be greater than zero");

    if (alpha == 0.0) {
      return 0.0;
    }
    double cutoff = forward * CUTOFF_MONEYNESS;
    double k;
    if (strike < cutoff) {
      Logger s_logger = LoggerFactory.getLogger(SabrHaganVolatilityFunctionProvider.class);
      s_logger.info(
          "Given strike of {} is less than cutoff at {}, therefore the strike is taken as {}",
          new Object[] {strike, cutoff, cutoff});
      k = cutoff;
    } else {
      k = strike;
    }
    double vol, z, zOverChi;
    double beta1 = 1 - beta;
    if (DoubleMath.fuzzyEquals(forward, k, ATM_EPS)) {
      double f1 = Math.pow(forward, beta1);
      vol =
          alpha
              * (1
                  + timeToExpiry
                      * (beta1 * beta1 * alpha * alpha / 24 / f1 / f1
                          + rho * alpha * beta * nu / 4 / f1
                          + nu * nu * (2 - 3 * rho * rho) / 24))
              / f1;
    } else {
      if (DoubleMath.fuzzyEquals(beta, 0, BETA_EPS)) {
        double ln = Math.log(forward / k);
        z = nu * Math.sqrt(forward * k) * ln / alpha;
        zOverChi = getZOverChi(rho, z);
        vol =
            alpha
                * ln
                * zOverChi
                * (1
                    + timeToExpiry
                        * (alpha * alpha / forward / k + nu * nu * (2 - 3 * rho * rho))
                        / 24)
                / (forward - k);
      } else if (DoubleMath.fuzzyEquals(beta, 1, BETA_EPS)) {
        double ln = Math.log(forward / k);
        z = nu * ln / alpha;
        zOverChi = getZOverChi(rho, z);
        vol =
            alpha
                * zOverChi
                * (1 + timeToExpiry * (rho * alpha * nu / 4 + nu * nu * (2 - 3 * rho * rho) / 24));
      } else {
        double ln = Math.log(forward / k);
        double f1 = Math.pow(forward * k, beta1);
        double f1Sqrt = Math.sqrt(f1);
        double lnBetaSq = Math.pow(beta1 * ln, 2);
        z = nu * f1Sqrt * ln / alpha;
        zOverChi = getZOverChi(rho, z);
        double first = alpha / (f1Sqrt * (1 + lnBetaSq / 24 + lnBetaSq * lnBetaSq / 1920));
        double second = zOverChi;
        double third =
            1
                + timeToExpiry
                    * (beta1 * beta1 * alpha * alpha / 24 / f1
                        + rho * nu * beta * alpha / 4 / f1Sqrt
                        + nu * nu * (2 - 3 * rho * rho) / 24);
        vol = first * second * third;
      }
    }
    // There is nothing to prevent the nu * nu * (2 - 3 * rho * rho) / 24 to be large negative, and
    // hence the volatility negative
    return Math.max(MIN_VOL, vol);
  }
Exemple #15
0
  @Override
  public ExperimentResults compute(Builder builder, Set<SimArgs> inputs) {
    final IdMap<MASConfiguration> configMap = new IdMap<>("c", MASConfiguration.class);
    final IdMap<ScenarioProvider> scenarioMap = new IdMap<>("s", ScenarioProvider.class);
    final IdMap<ObjectiveFunction> objFuncMap = new IdMap<>("o", ObjectiveFunction.class);

    final List<ResultListener> listeners = newArrayList(builder.resultListeners);

    @SuppressWarnings({"rawtypes", "unchecked"})
    final IdMap<PostProcessor<?>> ppMap = new IdMap("p", PostProcessor.class);
    final Map<String, Scenario> scenariosMap = newLinkedHashMap();

    // create tasks
    final List<SimulationTask> tasks = newArrayList();
    constructTasks(inputs, tasks, configMap, scenarioMap, objFuncMap, ppMap, scenariosMap);

    // this sorts tasks using this chain: scenario, configuration, objective
    // function, postprocessor, seed
    Collections.sort(tasks);

    // determine size of batches
    final int numBatches = Math.min(tasks.size(), builder.numBatches);
    final int batchSize =
        DoubleMath.roundToInt(tasks.size() / (double) numBatches, RoundingMode.CEILING);

    final Map<Task<?>, JPPFJob> taskJobMap = newLinkedHashMap();
    final ResultsCollector res =
        new ResultsCollector(tasks.size(), scenariosMap, taskJobMap, listeners);
    final List<JPPFJob> jobs = newArrayList();

    for (int i = 0; i < numBatches; i++) {
      final JPPFJob job = new JPPFJob(new MemoryMapDataProvider(), res);
      job.setName(Joiner.on("").join(JOB_NAME, " ", i + 1, "/", numBatches));
      jobs.add(job);
      for (final SimulationTask t : tasks.subList(i * batchSize, (i + 1) * batchSize)) {
        try {
          final MASConfiguration config = configMap.getValue(t.getConfigurationId());
          final ScenarioProvider scenario = scenarioMap.getValue(t.getScenarioId());
          final ObjectiveFunction objFunc = objFuncMap.getValue(t.getObjectiveFunctionId());
          job.getDataProvider()
              .setParameter(t.getPostProcessorId(), ppMap.getValue(t.getPostProcessorId()));
          job.getDataProvider().setParameter(t.getConfigurationId(), config);
          job.getDataProvider().setParameter(t.getScenarioId(), scenario);
          job.getDataProvider().setParameter(t.getObjectiveFunctionId(), objFunc);

          job.add(t);
        } catch (final JPPFException e) {
          throw new IllegalStateException(e);
        }
        taskJobMap.put(t, job);
      }
    }

    for (final ResultListener l : listeners) {
      l.startComputing(tasks.size());
    }

    checkState(!getJPPFClient().isClosed());
    try {
      for (final JPPFJob job : jobs) {
        getJPPFClient().submitJob(job);
      }
    } catch (final Exception e) {
      throw new IllegalStateException(e);
    }
    res.awaitResults();
    for (final ResultListener l : listeners) {
      l.doneComputing();
    }
    return ExperimentResults.create(builder, res.buildResults());
  }
Exemple #16
0
  public double findMinPerim(int leftIndex, int rightIndex, List<PointInt> listPointsSortedY) {
    int numberOfPoints = rightIndex - leftIndex + 1;
    Preconditions.checkArgument(listPointsSortedY.size() == numberOfPoints);

    if (numberOfPoints < 3) {
      return Double.MAX_VALUE;
    }

    int leftHalfEndIndex = leftIndex + numberOfPoints / 2 - 1;
    int rightHalfStartIndex = leftHalfEndIndex + 1;

    Preconditions.checkState(rightHalfStartIndex <= rightIndex);

    double min = Double.MAX_VALUE;

    /*
     * In order to avoid having to do another sort by y, (taking n log n), we just split using the sortedY list
     */
    List<PointInt> leftList = new ArrayList<>(leftHalfEndIndex - leftIndex + 1);
    List<PointInt> rightList = new ArrayList<>(rightIndex - rightHalfStartIndex + 1);

    // We must compare x and y because though we are partitioning by a vertical line, we must also
    // be able to partition if all points have the same x
    // Because the partition is strictly less and due to rounding error from longs,
    // we use this as the division point
    PointInt midPoint = list.get(rightHalfStartIndex);

    for (PointInt pl : listPointsSortedY) {
      // Verify the points are still between left and right index
      Preconditions.checkState(list.get(leftIndex).getX() <= pl.getX());
      Preconditions.checkState(list.get(rightIndex).getX() >= pl.getX());

      if (compX.compare(pl, midPoint) < 0) {
        leftList.add(pl);
      } else {
        rightList.add(pl);
      }
    }

    Preconditions.checkState(leftList.size() == numberOfPoints / 2);
    Preconditions.checkState(leftList.size() > 0);
    Preconditions.checkState(rightList.size() > 0);

    Preconditions.checkState(leftHalfEndIndex != rightIndex);
    Preconditions.checkState(rightHalfStartIndex != leftIndex);

    Preconditions.checkState(numberOfPoints == leftList.size() + rightList.size());

    // Divide
    double minLeft = findMinPerim(leftIndex, leftHalfEndIndex, leftList);
    double minRight = findMinPerim(rightHalfStartIndex, rightIndex, rightList);
    min = Math.min(minLeft, minRight);

    /*
     * For the combine, we make a box.
     * Left bound is min / 2 from vertical line, right bound is min / 2.
     *
     * Reason being that any triangle covering the vertical line and with a
     * point greater than min / 2 would have a perimeter > min.
     */

    int boxMargin =
        DoubleMath.roundToInt(
            (min > Double.MAX_VALUE / 2 ? Integer.MAX_VALUE : min) / 2d, RoundingMode.UP);
    Preconditions.checkState(min > Integer.MAX_VALUE || boxMargin < min);
    Preconditions.checkState(min > Integer.MAX_VALUE || boxMargin * 2 >= min);

    List<PointInt> boxPoints = new ArrayList<>();
    int startBox = 0;
    for (int i = 0; i < listPointsSortedY.size(); ++i) {
      PointInt point = listPointsSortedY.get(i);

      if (Math.abs(point.getX() - midPoint.getX()) > boxMargin) {
        continue;
      }

      // Calculate start of the box to consider.  Should be at most
      // boxMargin away from currenty point.  End of box is the last point added
      while (startBox < boxPoints.size()
          && point.getY() - boxPoints.get(startBox).getY() > boxMargin) {
        startBox++;
      }

      /**
       * To explain this, the box goes from -minP / 2 to + minP / 2 from the dividing vertical line.
       * Its height is also minP / 2.
       *
       * <p>Because we have the minimum with respect to the left and right sides, all triangles to
       * the left and right have max perimiter <= minP.
       *
       * <p>The only way to cram 16 points is to have 2 points on each corner and in the middle
       *
       * <p>PP-------PP--------PP
       *
       * <p>PP PP
       *
       * <p>PP-------PP--------PP
       *
       * <p>The perim of any triangle is >= minP. Any other point would be a triangle of perim <
       * minP.
       */
      Preconditions.checkState(boxPoints.size() - startBox <= 16);

      // Consider all points in box (can be proved <= 16...Similar to most 6 for closest 2 points
      // algorithm
      for (int bi = startBox; bi < boxPoints.size(); ++bi) {
        for (int j = bi + 1; j < boxPoints.size(); ++j) {
          double perim =
              point.distance(boxPoints.get(bi))
                  + point.distance(boxPoints.get(j))
                  + boxPoints.get(bi).distance(boxPoints.get(j));

          min = Math.min(min, perim);
        }
      }

      boxPoints.add(point);
    }

    return min;
  }
  /**
   * Computes the implied volatility in the SABR model and its derivatives.
   *
   * <p>The derivatives are stored in an array with:
   *
   * <ul>
   *   <li>[0] derivative with respect to the forward
   *   <li>[1] derivative with respect to the strike
   *   <li>[2] derivative with respect to the alpha
   *   <li>[3] derivative with respect to the beta
   *   <li>[4] derivative with respect to the rho
   *   <li>[5] derivative with respect to the nu
   * </ul>
   *
   * @param forward the forward value of the underlying
   * @param strike the strike value of the option
   * @param timeToExpiry the time to expiry of the option
   * @param alpha the SABR alpha value
   * @param beta the SABR beta value
   * @param rho the SABR rho value
   * @param nu the SABR nu value
   * @return the volatility and associated derivatives
   */
  @Override
  public ValueDerivatives volatilityAdjoint(
      double forward,
      double strike,
      double timeToExpiry,
      double alpha,
      double beta,
      double rho,
      double nu) {

    ArgChecker.isTrue(forward > 0.0, "forward must be greater than zero");
    ArgChecker.isTrue(strike >= 0.0, "strike must be greater than zero");
    ArgChecker.isTrue(timeToExpiry >= 0.0, "timeToExpiry must be greater than zero");
    double cutoff = forward * CUTOFF_MONEYNESS;
    double k = strike;
    if (k < cutoff) {
      Logger s_logger = LoggerFactory.getLogger(SabrHaganVolatilityFunctionProvider.class);
      s_logger.info(
          "Given strike of {} is less than cutoff at {}, therefore the strike is taken as {}",
          new Object[] {k, cutoff, cutoff});
      k = cutoff;
    }
    double betaStar = 1 - beta;
    double rhoStar = 1.0 - rho;

    if (alpha == 0.0) {
      double alphaBar;
      if (DoubleMath.fuzzyEquals(forward, k, ATM_EPS)) { // TODO should this is relative
        alphaBar =
            (1 + (2 - 3 * rho * rho) * nu * nu / 24 * timeToExpiry) / Math.pow(forward, betaStar);
      } else {
        // for non-atm options the alpha sensitivity at alpha = 0 is infinite. Returning this will
        // most likely break calibrations,
        // so we return an arbitrary large number
        alphaBar = 1e7;
      }
      return ValueDerivatives.of(0d, DoubleArray.of(0, 0, alphaBar, 0, 0, 0));
    }

    // Implementation note: Forward sweep.
    double sfK = Math.pow(forward * k, betaStar / 2);
    double lnrfK = Math.log(forward / k);
    double z = nu / alpha * sfK * lnrfK;
    double rzxz;
    double xz = 0;
    if (DoubleMath.fuzzyEquals(z, 0.0, SMALL_Z)) {
      rzxz = 1.0 - 0.5 * z * rho; // small z expansion to z^2 terms
    } else {
      if (DoubleMath.fuzzyEquals(rhoStar, 0.0, RHO_EPS)) {
        if (z < 1.0) {
          xz = -Math.log(1.0d - z);
          rzxz = z / xz;
        } else {
          throw new IllegalArgumentException("can't handle z>=1, rho=1");
        }
      } else {
        double arg;
        if (z < LARGE_NEG_Z) {
          arg =
              (rho * rho - 1)
                  / 2
                  / z; // get rounding errors due to fine balanced cancellation for very large
                       // negative z
        } else if (z > LARGE_POS_Z) {
          arg = 2 * (z - rho);
        } else {
          arg = (Math.sqrt(1 - 2 * rho * z + z * z) + z - rho);
        }
        if (arg
            <= 0.0) { // Mathematically this cannot be less than zero, but you know what computers
                      // are like.
          rzxz = 0.0;
        } else {
          xz = Math.log(arg / (1 - rho));
          rzxz = z / xz;
        }
      }
    }
    double sf1 =
        sfK
            * (1
                + betaStar * betaStar / 24 * (lnrfK * lnrfK)
                + Math.pow(betaStar, 4) / 1920 * Math.pow(lnrfK, 4));
    double sf2 =
        (1
            + (Math.pow(betaStar * alpha / sfK, 2) / 24
                    + (rho * beta * nu * alpha) / (4 * sfK)
                    + (2 - 3 * rho * rho) * nu * nu / 24)
                * timeToExpiry);
    double volatility = Math.max(MIN_VOL, alpha / sf1 * rzxz * sf2);

    // Implementation note: Backward sweep.
    double vBar = 1;
    double sf2Bar = alpha / sf1 * rzxz * vBar;
    double sf1Bar = -alpha / (sf1 * sf1) * rzxz * sf2 * vBar;
    double rzxzBar = alpha / sf1 * sf2 * vBar;
    double zBar;
    double xzBar = 0.0;
    if (DoubleMath.fuzzyEquals(z, 0.0, SMALL_Z)) {
      zBar = -rho / 2 * rzxzBar;
    } else {
      if (DoubleMath.fuzzyEquals(rhoStar, 0.0, RHO_EPS)) {
        if (z < 1.0) {
          xzBar = -z / (xz * xz) * rzxzBar;
          zBar = 1.0d / xz * rzxzBar + 1.0d / (1.0d - z) * xzBar;
        } else {
          throw new IllegalArgumentException("can't handle z>=1, rho=1");
        }
      } else {
        if (z < LARGE_NEG_Z) {
          zBar = 1 / xz * rzxzBar + xzBar / (xz * xz) * rzxzBar;
        } else if (z > LARGE_POS_Z) {
          zBar = 1 / xz * rzxzBar - xzBar / (xz * xz) * rzxzBar;
        } else {
          xzBar = -z / (xz * xz) * rzxzBar;
          zBar =
              1 / xz * rzxzBar
                  + 1
                      / ((Math.sqrt(1 - 2 * rho * z + z * z) + z - rho))
                      * (0.5 * Math.pow(1 - 2 * rho * z + z * z, -0.5) * (-2 * rho + 2 * z) + 1)
                      * xzBar;
        }
      }
    }

    double lnrfKBar =
        sfK
                * (betaStar * betaStar / 12 * lnrfK
                    + Math.pow(betaStar, 4) / 1920 * 4 * Math.pow(lnrfK, 3))
                * sf1Bar
            + nu / alpha * sfK * zBar;
    double sfKBar =
        nu / alpha * lnrfK * zBar
            + sf1 / sfK * sf1Bar
            - (Math.pow(betaStar * alpha, 2) / Math.pow(sfK, 3) / 12
                    + (rho * beta * nu * alpha) / 4 / (sfK * sfK))
                * timeToExpiry
                * sf2Bar;
    double strikeBar = -1 / k * lnrfKBar + betaStar * sfK / (2 * k) * sfKBar;
    double forwardBar = 1 / forward * lnrfKBar + betaStar * sfK / (2 * forward) * sfKBar;
    double nuBar =
        1 / alpha * sfK * lnrfK * zBar
            + ((rho * beta * alpha) / (4 * sfK) + (2 - 3 * rho * rho) * nu / 12)
                * timeToExpiry
                * sf2Bar;

    double rhoBar;
    if (Math.abs(forward - k) < ATM_EPS) {
      rhoBar = -z / 2 * rzxzBar;
    } else {
      if (DoubleMath.fuzzyEquals(rhoStar, 0.0, RHO_EPS)) {
        if (z >= 1) {
          if (rhoStar == 0.0) {
            rhoBar =
                Double
                    .NEGATIVE_INFINITY; // the derivative at rho = 1 is infinite  - this sets it to
                                        // some arbitrary large number
          } else {
            rhoBar = xzBar * (1.0 / rhoStar + (0.5 - z) / (z - 1.0) / (z - 1.0));
          }
        } else {
          rhoBar =
              (0.5 * Math.pow(z / (1 - z), 2)
                      + 0.25 * (z - 4.0) * Math.pow(z / (1.0 - z), 3) / (1.0 - z) * rhoStar)
                  * xzBar;
        }
      } else {
        rhoBar =
            (1
                        / (Math.sqrt(1 - 2 * rho * z + z * z) + z - rho)
                        * (-Math.pow(1 - 2 * rho * z + z * z, -0.5) * z - 1)
                    + 1 / rhoStar)
                * xzBar;
      }
    }
    rhoBar += ((beta * nu * alpha) / (4 * sfK) - rho * nu * nu / 4) * timeToExpiry * sf2Bar;

    double alphaBar =
        -nu / (alpha * alpha) * sfK * lnrfK * zBar
            + ((betaStar * alpha / sfK) * (betaStar / sfK) / 12 + (rho * beta * nu) / (4 * sfK))
                * timeToExpiry
                * sf2Bar
            + 1 / sf1 * rzxz * sf2 * vBar;
    double betaBar =
        -0.5 * Math.log(forward * k) * sfK * sfKBar
            - sfK
                * (betaStar / 12 * (lnrfK * lnrfK)
                    + Math.pow(betaStar, 3) / 480 * Math.pow(lnrfK, 4))
                * sf1Bar
            + (-betaStar * alpha * alpha / sfK / sfK / 12 + rho * nu * alpha / 4 / sfK)
                * timeToExpiry
                * sf2Bar;

    return ValueDerivatives.of(
        volatility, DoubleArray.of(forwardBar, strikeBar, alphaBar, betaBar, rhoBar, nuBar));
  }