/**
   * Compute theta price of cash-or-nothing option
   *
   * @param spot The spot
   * @param strike The strike
   * @param timeToExpiry The time to expiry
   * @param lognormalVol The log-normal volatility
   * @param interestRate The interest rate
   * @param costOfCarry The cost-of-carry
   * @param isCall True for calls, false for puts
   * @return The option price
   */
  public static double theta(
      final double spot,
      final double strike,
      final double timeToExpiry,
      final double lognormalVol,
      final double interestRate,
      final double costOfCarry,
      final boolean isCall) {
    ArgumentChecker.isTrue(spot > 0.0, "negative/NaN spot; have {}", spot);
    ArgumentChecker.isTrue(strike > 0.0, "negative/NaN strike; have {}", strike);
    ArgumentChecker.isTrue(timeToExpiry > 0.0, "negative/NaN timeToExpiry; have {}", timeToExpiry);
    ArgumentChecker.isTrue(lognormalVol > 0.0, "negative/NaN lognormalVol; have {}", lognormalVol);
    ArgumentChecker.isFalse(Double.isNaN(interestRate), "interestRate is NaN");
    ArgumentChecker.isFalse(Double.isNaN(costOfCarry), "costOfCarry is NaN");

    final double d =
        (Math.log(spot / strike) + (costOfCarry - 0.5 * lognormalVol * lognormalVol) * timeToExpiry)
            / lognormalVol
            / Math.sqrt(timeToExpiry);
    final double sign = isCall ? 1. : -1.;
    final double div =
        0.5
            * (-Math.log(spot / strike) / Math.pow(timeToExpiry, 1.5)
                + (costOfCarry - 0.5 * lognormalVol * lognormalVol) / Math.pow(timeToExpiry, 0.5))
            / lognormalVol;
    return interestRate * Math.exp(-interestRate * timeToExpiry) * NORMAL.getCDF(sign * d)
        - sign * Math.exp(-interestRate * timeToExpiry) * NORMAL.getPDF(d) * div;
  }
Пример #2
0
 @Test
 public void test() {
   ProbabilityDistribution<Double> dist = new StudentTDistribution(1, ENGINE);
   assertCDFWithNull(dist);
   assertPDFWithNull(dist);
   assertInverseCDF(X, dist);
   for (int i = 0; i < 10; i++) {
     dist = new StudentTDistribution(DOF[i], ENGINE);
     assertEquals(P[i], dist.getCDF(X[i]), EPS);
   }
 }
 @Test
 /** Test the present value. */
 public void presentValueExplicit() {
   final MultipleCurrencyAmount pv = METHOD_HW.presentValue(SWAPTION_LONG_PAYER, HW_MULTICURVES);
   final double timeToExpiry = SWAPTION_LONG_PAYER.getTimeToExpiry();
   final AnnuityPaymentFixed cfe =
       CFEC.visitSwap(SWAPTION_LONG_PAYER.getUnderlyingSwap(), MULTICURVES);
   final int numberOfPayments = cfe.getNumberOfPayments();
   final double alpha[] = new double[numberOfPayments];
   final double disccf[] = new double[numberOfPayments];
   for (int loopcf = 0; loopcf < numberOfPayments; loopcf++) {
     alpha[loopcf] =
         MODEL.alpha(
             HW_PARAMETERS,
             0.0,
             timeToExpiry,
             timeToExpiry,
             cfe.getNthPayment(loopcf).getPaymentTime());
     disccf[loopcf] =
         MULTICURVES.getDiscountFactor(EUR, cfe.getNthPayment(loopcf).getPaymentTime())
             * cfe.getNthPayment(loopcf).getAmount();
   }
   final double kappa = MODEL.kappa(disccf, alpha);
   double pvExpected = 0.0;
   for (int loopcf = 0; loopcf < numberOfPayments; loopcf++) {
     pvExpected += disccf[loopcf] * NORMAL.getCDF(-kappa - alpha[loopcf]);
   }
   assertEquals(
       "Swaption physical - Hull-White - present value", pvExpected, pv.getAmount(EUR), 1E-2);
   final MultipleCurrencyAmount pv2 =
       METHOD_HW.presentValue(SWAPTION_LONG_PAYER, cfe, HW_MULTICURVES);
   assertEquals("Swaption physical - Hull-White - present value", pv, pv2);
 }
  /**
   * Compute gamma of cash-or-nothing option
   *
   * @param spot The spot
   * @param strike The strike
   * @param timeToExpiry The time to expiry
   * @param lognormalVol The log-normal volatility
   * @param interestRate The interest rate
   * @param costOfCarry The cost-of-carry
   * @param isCall True for calls, false for puts
   * @return The option price
   */
  public static double gamma(
      final double spot,
      final double strike,
      final double timeToExpiry,
      final double lognormalVol,
      final double interestRate,
      final double costOfCarry,
      final boolean isCall) {
    ArgumentChecker.isTrue(spot > 0.0, "negative/NaN spot; have {}", spot);
    ArgumentChecker.isTrue(strike > 0.0, "negative/NaN strike; have {}", strike);
    ArgumentChecker.isTrue(timeToExpiry > 0.0, "negative/NaN timeToExpiry; have {}", timeToExpiry);
    ArgumentChecker.isTrue(lognormalVol > 0.0, "negative/NaN lognormalVol; have {}", lognormalVol);
    ArgumentChecker.isFalse(Double.isNaN(interestRate), "interestRate is NaN");
    ArgumentChecker.isFalse(Double.isNaN(costOfCarry), "costOfCarry is NaN");

    final double sigmaRootT = lognormalVol * Math.sqrt(timeToExpiry);
    final double d =
        (Math.log(spot / strike) + (costOfCarry - 0.5 * lognormalVol * lognormalVol) * timeToExpiry)
            / sigmaRootT;
    final double sign = isCall ? 1. : -1.;
    return -sign
        * (Math.exp(-interestRate * timeToExpiry)
            * NORMAL.getPDF(d)
            * (1. + d / sigmaRootT)
            / spot
            / spot
            / sigmaRootT);
  }
 /**
  * Computes the price curve sensitivity in the Hull-White one factor model.
  *
  * @param security The option security.
  * @param hwMulticurves The multi-curves provider with Hull-White one factor parameters.
  * @return The curve sensitivity.
  */
 @Override
 public MulticurveSensitivity priceCurveSensitivity(
     final InterestRateFutureOptionMarginSecurity security,
     final HullWhiteOneFactorProviderInterface hwMulticurves) {
   ArgumentChecker.notNull(security, "Option security");
   ArgumentChecker.notNull(hwMulticurves, "Hull-White and multi-curves data");
   ArgumentChecker.isTrue(
       security.getCurrency().equals(hwMulticurves.getHullWhiteCurrency()),
       "Model currency incompatible with security currency");
   final MulticurveProviderInterface multicurves = hwMulticurves.getMulticurveProvider();
   final HullWhiteOneFactorPiecewiseConstantParameters parameters =
       hwMulticurves.getHullWhiteParameters();
   final double k = security.getStrike();
   final double ktilde = 1.0 - k;
   final double theta = security.getExpirationTime();
   final double delta = security.getUnderlyingFuture().getFixingPeriodAccrualFactor();
   final double t0 = security.getUnderlyingFuture().getTradingLastTime();
   final double t1 = security.getUnderlyingFuture().getFixingPeriodStartTime();
   final double t2 = security.getUnderlyingFuture().getFixingPeriodEndTime();
   // forward sweep
   final double alpha = MODEL.alpha(parameters, 0.0, theta, t1, t2);
   final double gamma = MODEL.futuresConvexityFactor(parameters, t0, t1, t2);
   final double forward =
       multicurves.getSimplyCompoundForwardRate(
           security.getUnderlyingFuture().getIborIndex(), t1, t2, delta);
   final double kappa =
       -Math.log((1 + delta * ktilde) / (1 + delta * forward) / gamma) / alpha - 0.5 * alpha;
   // Bakcward sweep
   final double priceBar = 1.0;
   double forwardBar;
   if (security.isCall()) {
     final double normalAlphaKappa = NORMAL.getCDF(-kappa - alpha);
     forwardBar = -gamma * normalAlphaKappa * priceBar;
   } else {
     final double normalAlphaKappa = NORMAL.getCDF(kappa + alpha);
     forwardBar = gamma * normalAlphaKappa * priceBar;
   }
   final Map<String, List<ForwardSensitivity>> mapFwd = new HashMap<>();
   final List<ForwardSensitivity> listForward = new ArrayList<>();
   listForward.add(new SimplyCompoundedForwardSensitivity(t1, t2, delta, forwardBar));
   mapFwd.put(
       hwMulticurves
           .getMulticurveProvider()
           .getName(security.getUnderlyingFuture().getIborIndex()),
       listForward);
   return MulticurveSensitivity.ofForward(mapFwd);
 }
Пример #6
0
 @Test
 public void testNormal() {
   final ProbabilityDistribution<Double> highDOF = new StudentTDistribution(1000000, ENGINE);
   final ProbabilityDistribution<Double> normal = new NormalDistribution(0, 1, ENGINE);
   final double eps = 1e-4;
   double x;
   for (int i = 0; i < 100; i++) {
     x = RANDOM.nextDouble();
     assertEquals(highDOF.getCDF(x), normal.getCDF(x), eps);
     assertEquals(highDOF.getPDF(x), normal.getPDF(x), eps);
     assertEquals(highDOF.getInverseCDF(x), normal.getInverseCDF(x), eps);
   }
 }
 /**
  * Computes the price in the Hull-White one factor model.
  *
  * @param security The option security.
  * @param hwMulticurves The multi-curves provider with Hull-White one factor parameters.
  * @return The price.
  */
 @Override
 public double price(
     final InterestRateFutureOptionMarginSecurity security,
     final HullWhiteOneFactorProviderInterface hwMulticurves) {
   ArgumentChecker.notNull(security, "Option security");
   ArgumentChecker.notNull(hwMulticurves, "Hull-White and multi-curves data");
   ArgumentChecker.isTrue(
       security.getCurrency().equals(hwMulticurves.getHullWhiteCurrency()),
       "Model currency incompatible with security currency");
   final MulticurveProviderInterface multicurves = hwMulticurves.getMulticurveProvider();
   final HullWhiteOneFactorPiecewiseConstantParameters parameters =
       hwMulticurves.getHullWhiteParameters();
   final double k = security.getStrike();
   final double ktilde = 1.0 - k;
   final double theta = security.getExpirationTime();
   final double delta = security.getUnderlyingFuture().getFixingPeriodAccrualFactor();
   final double t0 = security.getUnderlyingFuture().getTradingLastTime();
   final double t1 = security.getUnderlyingFuture().getFixingPeriodStartTime();
   final double t2 = security.getUnderlyingFuture().getFixingPeriodEndTime();
   final double alpha = MODEL.alpha(parameters, 0.0, theta, t1, t2);
   final double gamma = MODEL.futuresConvexityFactor(parameters, t0, t1, t2);
   final double forward =
       multicurves.getSimplyCompoundForwardRate(
           security.getUnderlyingFuture().getIborIndex(), t1, t2, delta);
   final double kappa =
       -Math.log((1 + delta * ktilde) / (1 + delta * forward) / gamma) / alpha - 0.5 * alpha;
   if (security.isCall()) {
     final double normalKappa = NORMAL.getCDF(-kappa);
     final double normalAlphaKappa = NORMAL.getCDF(-kappa - alpha);
     return (1 - k + 1.0 / delta) * normalKappa
         - (1.0 / delta + forward) * gamma * normalAlphaKappa;
   }
   final double normalKappa = NORMAL.getCDF(kappa);
   final double normalAlphaKappa = NORMAL.getCDF(kappa + alpha);
   return (1.0 / delta + forward) * gamma * normalAlphaKappa - (1 - k + 1.0 / delta) * normalKappa;
 }
  /**
   * Compute driftless (forward) theta price of cash-or-nothing option
   *
   * @param forward The forward
   * @param strike The strike
   * @param timeToExpiry The time to expiry
   * @param lognormalVol The log-normal volatility
   * @param isCall True for calls, false for puts
   * @return The option price
   */
  public static double driftlessTheta(
      final double forward,
      final double strike,
      final double timeToExpiry,
      final double lognormalVol,
      final boolean isCall) {
    ArgumentChecker.isTrue(forward > 0.0, "negative/NaN forward; have {}", forward);
    ArgumentChecker.isTrue(strike > 0.0, "negative/NaN strike; have {}", strike);
    ArgumentChecker.isTrue(timeToExpiry > 0.0, "negative/NaN timeToExpiry; have {}", timeToExpiry);
    ArgumentChecker.isTrue(lognormalVol > 0.0, "negative/NaN lognormalVol; have {}", lognormalVol);

    final double sigmaRootT = lognormalVol * Math.sqrt(timeToExpiry);
    final double d = Math.log(forward / strike) / sigmaRootT - 0.5 * sigmaRootT;
    final double sign = isCall ? 1. : -1.;
    final double div =
        0.5
            * (-Math.log(forward / strike) / Math.pow(timeToExpiry, 1.5) / lognormalVol
                - 0.5 * lognormalVol / Math.pow(timeToExpiry, 0.5));
    return -sign * NORMAL.getPDF(d) * div;
  }