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;
    }
  /**
   * The bucked CS01 (or credit DV01) by shifting each implied par-spread in turn. This takes an
   * extraneous yield curve and a credit curve and a set of bucket CDSs (CDSs with maturities equal
   * to the bucket points). Par-spreads at the bucket maturities are implied from the credit curve.
   * These spreads form pseudo market spreads to bootstraps a new credit (hazard) curve - the target
   * CDS is then priced with this credit curve. This is then repeated with each spreads bumped in
   * turn. The result is the vector of differences (bumped minus base price) divided by the bump
   * amount.
   *
   * @param cds analytic description of a CDS traded at a certain time
   * @param cdsCoupon The <b>fraction</b> spread of the CDS
   * @param bucketCDSs these are the reference instruments that correspond to maturity buckets
   * @param yieldCurve The yield (or discount) curve
   * @param creditCurve the credit curve
   * @param fracBumpAmount The fraction bump amount, so a 1pb bump is 1e-4
   * @return The credit DV01
   */
  public double[] bucketedCS01FromCreditCurve(
      CdsAnalytic cds,
      double cdsCoupon,
      CdsAnalytic[] bucketCDSs,
      IsdaCompliantYieldCurve yieldCurve,
      IsdaCompliantCreditCurve creditCurve,
      double fracBumpAmount) {

    ArgChecker.notNull(cds, "cds");
    ArgChecker.noNulls(bucketCDSs, "bucketCDSs");
    ArgChecker.notNull(creditCurve, "creditCurve");
    ArgChecker.notNull(yieldCurve, "yieldCurve");
    ArgChecker.isTrue(Math.abs(fracBumpAmount) > 1e-10, "bump amount too small");
    int n = bucketCDSs.length;

    double[] impSpreads = new double[n];
    double[] t = new double[n];
    for (int i = 0; i < n; i++) {
      impSpreads[i] = _pricer.parSpread(bucketCDSs[i], yieldCurve, creditCurve);
      t[i] = bucketCDSs[i].getProtectionEnd();
      if (i > 0) {
        ArgChecker.isTrue(t[i] > t[i - 1], "buckets must be assending");
      }
    }
    int index = Arrays.binarySearch(t, cds.getProtectionEnd());
    if (index < 0) {
      index = -1 - index;
    }
    index = Math.min(index, n - 1);

    IsdaCompliantCreditCurve baseCurve =
        _curveBuilder.calibrateCreditCurve(bucketCDSs, impSpreads, yieldCurve);
    double basePrice = _pricer.pv(cds, yieldCurve, baseCurve, cdsCoupon);
    double[] res = new double[n];
    for (int i = 0; i <= index; i++) { // don't bother calculating where there is no sensitivity
      double[] bumpedSpreads = makeBumpedSpreads(impSpreads, fracBumpAmount, ShiftType.ABSOLUTE, i);
      IsdaCompliantCreditCurve bumpedCurve =
          _curveBuilder.calibrateCreditCurve(bucketCDSs, bumpedSpreads, yieldCurve);
      double price = _pricer.pv(cds, yieldCurve, bumpedCurve, cdsCoupon);
      res[i] = (price - basePrice) / fracBumpAmount;
    }
    return res;
  }
    public Pricer(
        CdsAnalytic cds,
        IsdaCompliantYieldCurve yieldCurve,
        double[] creditCurveKnots,
        double fractionalSpread,
        double pointsUpfront) {

      _cds = cds;
      _fracSpread = fractionalSpread;
      _pointsUpfront = pointsUpfront;

      // protection leg
      _proLegIntPoints =
          getIntegrationsPoints(
              cds.getEffectiveProtectionStart(),
              cds.getProtectionEnd(),
              yieldCurve.getKnotTimes(),
              creditCurveKnots);
      _nProPoints = _proLegIntPoints.length;
      double lgd = cds.getLGD();
      _valuationDF = yieldCurve.getDiscountFactor(cds.getCashSettleTime());
      _lgdDF = lgd / _valuationDF;
      _proYieldCurveRT = new double[_nProPoints];
      _proDF = new double[_nProPoints];
      for (int i = 0; i < _nProPoints; i++) {
        _proYieldCurveRT[i] = yieldCurve.getRT(_proLegIntPoints[i]);
        _proDF[i] = Math.exp(-_proYieldCurveRT[i]);
      }

      // premium leg
      _nPayments = cds.getNumPayments();
      _paymentDF = new double[_nPayments];
      for (int i = 0; i < _nPayments; i++) {
        _paymentDF[i] = yieldCurve.getDiscountFactor(cds.getCoupon(i).getPaymentTime());
      }

      if (cds.isPayAccOnDefault()) {
        double tmp =
            cds.getNumPayments() == 1 ? cds.getEffectiveProtectionStart() : cds.getAccStart();
        double[] integrationSchedule =
            getIntegrationsPoints(
                tmp, cds.getProtectionEnd(), yieldCurve.getKnotTimes(), creditCurveKnots);

        _accRate = new double[_nPayments];
        _offsetAccStart = new double[_nPayments];
        _premLegIntPoints = new double[_nPayments][];
        _premDF = new double[_nPayments][];
        _rt = new double[_nPayments][];
        _premDt = new double[_nPayments][];
        for (int i = 0; i < _nPayments; i++) {
          CdsCoupon c = cds.getCoupon(i);
          _offsetAccStart[i] = c.getEffStart();
          double offsetAccEnd = c.getEffEnd();
          _accRate[i] = c.getYFRatio();
          double start = Math.max(_offsetAccStart[i], cds.getEffectiveProtectionStart());
          if (start >= offsetAccEnd) {
            continue;
          }
          _premLegIntPoints[i] = truncateSetInclusive(start, offsetAccEnd, integrationSchedule);
          int n = _premLegIntPoints[i].length;
          _rt[i] = new double[n];
          _premDF[i] = new double[n];
          for (int k = 0; k < n; k++) {
            _rt[i][k] = yieldCurve.getRT(_premLegIntPoints[i][k]);
            _premDF[i][k] = Math.exp(-_rt[i][k]);
          }
          _premDt[i] = new double[n - 1];

          for (int k = 1; k < n; k++) {
            double dt = _premLegIntPoints[i][k] - _premLegIntPoints[i][k - 1];
            _premDt[i][k - 1] = dt;
          }
        }
      } else {
        _accRate = null;
        _offsetAccStart = null;
        _premDF = null;
        _premDt = null;
        _rt = null;
        _premLegIntPoints = null;
      }
    }