예제 #1
0
    public double protectionLeg(IsdaCompliantCreditCurve creditCurve) {

      double ht0 = creditCurve.getRT(_proLegIntPoints[0]);
      double rt0 = _proYieldCurveRT[0];
      double b0 = _proDF[0] * Math.exp(-ht0);

      double pv = 0.0;

      for (int i = 1; i < _nProPoints; ++i) {
        double ht1 = creditCurve.getRT(_proLegIntPoints[i]);
        double rt1 = _proYieldCurveRT[i];
        double b1 = _proDF[i] * Math.exp(-ht1);
        double dht = ht1 - ht0;
        double drt = rt1 - rt0;
        double dhrt = dht + drt;

        // this is equivalent to the ISDA code without explicitly calculating the time step - it
        // also handles the limit
        double dPV;
        if (Math.abs(dhrt) < 1e-5) {
          dPV = dht * b0 * epsilon(-dhrt);
        } else {
          dPV = (b0 - b1) * dht / dhrt;
        }
        pv += dPV;
        ht0 = ht1;
        rt0 = rt1;
        b0 = b1;
      }
      pv *= _lgdDF; // multiply by LGD and adjust to valuation date

      return pv;
    }
예제 #2
0
    private double calculateSinglePeriodAccrualOnDefault(
        int paymentIndex, IsdaCompliantCreditCurve creditCurve) {

      double[] knots = _premLegIntPoints[paymentIndex];
      if (knots == null) {
        return 0.0;
      }
      double[] df = _premDF[paymentIndex];
      double[] deltaT = _premDt[paymentIndex];
      double[] rt = _rt[paymentIndex];
      double accRate = _accRate[paymentIndex];
      double accStart = _offsetAccStart[paymentIndex];

      double t = knots[0];
      double ht0 = creditCurve.getRT(t);
      double rt0 = rt[0];
      double b0 = df[0] * Math.exp(-ht0);

      double t0 = t - accStart + _omega;
      double pv = 0.0;
      int nItems = knots.length;
      for (int j = 1; j < nItems; ++j) {
        t = knots[j];
        double ht1 = creditCurve.getRT(t);
        double rt1 = rt[j];
        double b1 = df[j] * Math.exp(-ht1);
        double dt = deltaT[j - 1];

        double dht = ht1 - ht0;
        double drt = rt1 - rt0;
        double dhrt = dht + drt + 1e-50; // to keep consistent with ISDA c code

        double tPV;
        if (getAccOnDefaultFormula() == AccrualOnDefaultFormulae.MARKIT_FIX) {
          if (Math.abs(dhrt) < 1e-5) {
            tPV = dht * dt * b0 * epsilonP(-dhrt);
          } else {
            tPV = dht * dt / dhrt * ((b0 - b1) / dhrt - b1);
          }
        } else {
          double t1 = t - accStart + _omega;
          if (Math.abs(dhrt) < 1e-5) {
            tPV = dht * b0 * (t0 * epsilon(-dhrt) + dt * epsilonP(-dhrt));
          } else {
            tPV = dht / dhrt * (t0 * b0 - t1 * b1 + dt / dhrt * (b0 - b1));
          }
          t0 = t1;
        }
        pv += tPV;
        ht0 = ht1;
        rt0 = rt1;
        b0 = b1;
      }
      return accRate * pv;
    }
예제 #3
0
    public double rpv01(IsdaCompliantCreditCurve creditCurve, CdsPriceType cleanOrDirty) {

      double pv = 0.0;
      for (int i = 0; i < _nPayments; i++) {
        CdsCoupon c = _cds.getCoupon(i);
        double q = creditCurve.getDiscountFactor(c.getEffEnd());
        pv += c.getYearFrac() * _paymentDF[i] * q;
      }

      if (_cds.isPayAccOnDefault()) {
        double accPV = 0.0;
        for (int i = 0; i < _nPayments; i++) {
          accPV += calculateSinglePeriodAccrualOnDefault(i, creditCurve);
        }
        pv += accPV;
      }

      pv /= _valuationDF;

      if (cleanOrDirty == CdsPriceType.CLEAN) {
        pv -= _cds.getAccruedYearFraction();
      }
      return pv;
    }
예제 #4
0
  /** {@inheritDoc} */
  @Override
  public IsdaCompliantCreditCurve calibrateCreditCurve(
      CdsAnalytic[] cds,
      double[] premiums,
      IsdaCompliantYieldCurve yieldCurve,
      double[] pointsUpfront) {

    ArgChecker.noNulls(cds, "null CDSs");
    ArgChecker.notEmpty(premiums, "empty fractionalSpreads");
    ArgChecker.notEmpty(pointsUpfront, "empty pointsUpfront");
    ArgChecker.notNull(yieldCurve, "null yieldCurve");
    int n = cds.length;
    ArgChecker.isTrue(n == premiums.length, "Number of CDSs does not match number of spreads");
    ArgChecker.isTrue(
        n == pointsUpfront.length, "Number of CDSs does not match number of pointsUpfront");
    double proStart = cds[0].getEffectiveProtectionStart();
    for (int i = 1; i < n; i++) {
      ArgChecker.isTrue(
          proStart == cds[i].getEffectiveProtectionStart(),
          "all CDSs must has same protection start");
      ArgChecker.isTrue(
          cds[i].getProtectionEnd() > cds[i - 1].getProtectionEnd(),
          "protection end must be ascending");
    }

    // use continuous premiums as initial guess
    double[] guess = new double[n];
    double[] t = new double[n];
    for (int i = 0; i < n; i++) {
      t[i] = cds[i].getProtectionEnd();
      guess[i] = (premiums[i] + pointsUpfront[i] / t[i]) / cds[i].getLGD();
    }

    IsdaCompliantCreditCurve creditCurve = new IsdaCompliantCreditCurve(t, guess);
    for (int i = 0; i < n; i++) {
      Pricer pricer = new Pricer(cds[i], yieldCurve, t, premiums[i], pointsUpfront[i]);
      Function1D<Double, Double> func = pricer.getPointFunction(i, creditCurve);

      switch (getArbHanding()) {
        case Ignore:
          {
            try {
              double[] bracket =
                  BRACKER.getBracketedPoints(
                      func,
                      0.8 * guess[i],
                      1.25 * guess[i],
                      Double.NEGATIVE_INFINITY,
                      Double.POSITIVE_INFINITY);
              double zeroRate =
                  bracket[0] > bracket[1]
                      ? ROOTFINDER.getRoot(func, bracket[1], bracket[0])
                      : ROOTFINDER.getRoot(func, bracket[0], bracket[1]); // Negative guess handled
              creditCurve = creditCurve.withRate(zeroRate, i);
            } catch (
                MathException e) { // handling bracketing failure due to small survival probability
              if (Math.abs(func.evaluate(creditCurve.getZeroRateAtIndex(i - 1))) < 1.e-12) {
                creditCurve = creditCurve.withRate(creditCurve.getZeroRateAtIndex(i - 1), i);
              } else {
                throw new MathException(e);
              }
            }
            break;
          }
        case Fail:
          {
            double minValue =
                i == 0 ? 0.0 : creditCurve.getRTAtIndex(i - 1) / creditCurve.getTimeAtIndex(i);
            if (i > 0 && func.evaluate(minValue) > 0.0) { // can never fail on the first spread
              StringBuilder msg = new StringBuilder();
              if (pointsUpfront[i] == 0.0) {
                msg.append("The par spread of " + premiums[i] + " at index " + i);
              } else {
                msg.append(
                    "The premium of "
                        + premiums[i]
                        + "and points up-front of "
                        + pointsUpfront[i]
                        + " at index "
                        + i);
              }
              msg.append(
                  " is an arbitrage; cannot fit a curve with positive forward hazard rate. ");
              throw new IllegalArgumentException(msg.toString());
            }
            guess[i] = Math.max(minValue, guess[i]);
            double[] bracket =
                BRACKER.getBracketedPoints(
                    func, guess[i], 1.2 * guess[i], minValue, Double.POSITIVE_INFINITY);
            double zeroRate = ROOTFINDER.getRoot(func, bracket[0], bracket[1]);
            creditCurve = creditCurve.withRate(zeroRate, i);
            break;
          }
        case ZeroHazardRate:
          {
            double minValue =
                i == 0 ? 0.0 : creditCurve.getRTAtIndex(i - 1) / creditCurve.getTimeAtIndex(i);
            if (i > 0 && func.evaluate(minValue) > 0.0) { // can never fail on the first spread
              creditCurve = creditCurve.withRate(minValue, i);
            } else {
              guess[i] = Math.max(minValue, guess[i]);
              double[] bracket =
                  BRACKER.getBracketedPoints(
                      func, guess[i], 1.2 * guess[i], minValue, Double.POSITIVE_INFINITY);
              double zeroRate = ROOTFINDER.getRoot(func, bracket[0], bracket[1]);
              creditCurve = creditCurve.withRate(zeroRate, i);
            }
            break;
          }
        default:
          throw new IllegalArgumentException("unknow case " + getArbHanding());
      }
    }
    return creditCurve;
  }