/**
         * Imply a single (pseudo) credit curve for an index that will give the same index values
         * at a set of terms (supplied via pillarCDS) as the intrinsic value.
         *
         * @param pillarCDS Point to build the curve
         * @param indexCoupon The index coupon
         * @param yieldCurve The current yield curves
         * @param intrinsicData credit curves, weights and recovery rates of the intrinsic names
         * @return A (pseudo) credit curve for an index
         */
        public PiecewiseconstantHazardRate impliedIndexCurve(
            CDS[] pillarCDS,
            double indexCoupon,
            YieldTermStructure yieldCurve,
            IntrinsicIndexDataBundle intrinsicData)
        {
            if (intrinsicData.getNumOfDefaults() == intrinsicData.getIndexSize())
            {
            }
            int n = pillarCDS.Length;

            double[] puf         = new double[n];
            double   indexFactor = intrinsicData.getIndexFactor();

            for (int i = 0; i < n; i++)
            {
                // PUF are always given for full index
                puf[i] = indexPV(pillarCDS[i], indexCoupon, yieldCurve, intrinsicData) / indexFactor;
            }
            CreditCurveCalibrator calibrator = new CreditCurveCalibrator(pillarCDS, yieldCurve);

            double[] coupons = new double[n];
            Array.ConvertAll <double, double>(coupons, b => b = indexCoupon);
            return(calibrator.calibrate(coupons, puf));
        }
        /**
         * The average spread of a CDS portfolio (index), defined as the weighted average of the
         * (implied) par spreads of the constituent names.
         *
         * @see #intrinsicIndexSpread
         * @param indexCDS representation of the index cashflows (seen from today).
         * @param yieldCurve The current yield curves
         * @param intrinsicData credit curves, weights and recovery rates of the intrinsic names
         * @return The average spread
         */
        public double averageSpread(
            CDS indexCDS,
            YieldTermStructure yieldCurve,
            IntrinsicIndexDataBundle intrinsicData)
        {
            if (intrinsicData.getNumOfDefaults() == intrinsicData.getIndexSize())
            {
            }

            CDS    cds = indexCDS.withRecoveryRate(0.0);
            int    n   = intrinsicData.getIndexSize();
            double sum = 0;

            for (int i = 0; i < n; i++)
            {
                if (!intrinsicData.isDefaulted(i))
                {
                    double protLeg = intrinsicData.getLGD(i) * _pricer.protectionLeg(cds, yieldCurve, intrinsicData.getCreditCurve(i));
                    double annuity = _pricer.annuity(cds, yieldCurve, intrinsicData.getCreditCurve(i));
                    double s       = protLeg / annuity;
                    sum += intrinsicData.getWeight(i) * s;
                }
            }
            sum /= intrinsicData.getIndexFactor();
            return(sum);
        }
 /**
  * The Points-Up-Front (PUF) of an index. This is the (clean) price of a unit notional index.
  * The actual clean price is this multiplied by the (current) index notional
  * (i.e. the initial notional times the index factor).
  *
  * @param indexCDS analytic description of a CDS traded at a certain time
  * @param indexCoupon The coupon of the index (as a fraction)
  * @param yieldCurve The yield curve
  * @param intrinsicData credit curves, weights and recover
  * @return PUF of an index
  */
 public double indexPUF(
     CDS indexCDS,
     double indexCoupon,
     YieldTermStructure yieldCurve,
     IntrinsicIndexDataBundle intrinsicData)
 {
     if (intrinsicData.getNumOfDefaults() == intrinsicData.getIndexSize())
     {
     }
     return(indexPV(indexCDS, indexCoupon, yieldCurve, intrinsicData) / intrinsicData.getIndexFactor());
 }
        /**
         * The intrinsic index spread. this is defined as the ratio of the intrinsic protection leg to the intrinsic annuity.
         *
         * @see #averageSpread
         * @param indexCDS analytic description of a CDS traded at a certain time
         * @param yieldCurve The yield curve
         * @param intrinsicData credit curves, weights and recovery rates of the intrinsic names
         * @return intrinsic index spread (as a fraction)
         */
        public double intrinsicIndexSpread(
            CDS indexCDS,
            YieldTermStructure yieldCurve,
            IntrinsicIndexDataBundle intrinsicData)
        {
            if (intrinsicData.getNumOfDefaults() == intrinsicData.getIndexSize())
            {
            }
            double prot    = indexProtLeg(indexCDS, yieldCurve, intrinsicData);
            double annuity = indexAnnuity(indexCDS, yieldCurve, intrinsicData);

            return(prot / annuity);
        }