/**
         * 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);
        }
        private double decomposedValueOnDefault(
            CDS indexCDS,
            double indexCoupon,
            YieldTermStructure yieldCurve,
            IntrinsicIndexDataBundle intrinsicData,
            int singleName)
        {
            double weight       = intrinsicData.getWeight(singleName);
            double protection   = intrinsicData.getLGD(singleName);
            double singleNamePV = _pricer.pv(indexCDS, yieldCurve, intrinsicData.getCreditCurves()[singleName], indexCoupon);

            return(weight * (protection - singleNamePV));
        }
        /**
         * The normalised expected default settlement value paid on the  exercise settlement date.
         * The actual default settlement is this multiplied by the (initial) index notional.
         *
         * @param timeToExpiry Time to expiry
         * @param intrinsicData credit curves, weights and recovery rates of the intrinsic names
         * @return The normalised expected default settlement value
         */
        public double expectedDefaultSettlementValue(
            double timeToExpiry,
            IntrinsicIndexDataBundle intrinsicData)
        {
            int    indexSize = intrinsicData.getIndexSize();
            double d         = 0.0; //computed the expected default settlement amount (paid on the  expiry settlement date)

            for (int i = 0; i < indexSize; i++)
            {
                double qBar = intrinsicData.isDefaulted(i) ? 1.0 : 1.0 - Math.Exp(-intrinsicData.getCreditCurve(i).getRT_(
                                                                                      timeToExpiry));
                d += intrinsicData.getWeight(i) * intrinsicData.getLGD(i) * qBar;
            }
            return(d);
        }
        /**
         * The  intrinsic annuity of a CDS portfolio (index) for a unit (initial) notional.
         * The value of the premium leg is this multiplied by the <b> initial</b> notional of the index
         * and the index coupon (as a fraction).
         *
         * @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
         * @param priceType Clean or dirty
         * @param valuationTime Valuation time. The leg value is calculated for today (t=0),
         *  then rolled forward (using the risk free yield curve) to the valuation time.
         *  This is because cash payments occur on the cash-settlement-date, which is usually
         *  three working days after the trade date (today)
         * @return The  intrinsic annuity of a CDS portfolio (index)
         */
        public double indexAnnuity(
            CDS indexCDS,
            YieldTermStructure yieldCurve,
            IntrinsicIndexDataBundle intrinsicData,
            CdsPriceType priceType,
            double valuationTime)
        {
            int    n = intrinsicData.getIndexSize();
            double a = 0;

            for (int i = 0; i < n; i++)
            {
                if (!intrinsicData.isDefaulted(i))
                {
                    a += intrinsicData.getWeight(i) * _pricer.annuity(indexCDS, yieldCurve, intrinsicData.getCreditCurve(i), priceType, 0);
                }
            }
            a /= Math.Exp(-yieldCurve.getRT_(valuationTime));

            return(a);
        }
        /**
         * The normalised intrinsic value of the protection leg of a CDS portfolio (index).
         * The actual value of the leg is this multiplied by the <b>initial</b>  notional of the index.
         *
         * @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
         * @param valuationTime Valuation time. The leg value is calculated for today (t=0),
         *  then rolled forward (using the risk free yield curve) to the valuation time.
         *  This is because cash payments occur on the cash-settlement-date, which is usually
         *  three working days after the trade date (today)
         * @return The normalised intrinsic value of the protection leg.
         */
        public double indexProtLeg(
            CDS indexCDS,
            YieldTermStructure yieldCurve,
            IntrinsicIndexDataBundle intrinsicData,
            double valuationTime)
        {
            CDS    cds     = indexCDS.withRecoveryRate(0.0);
            int    n       = intrinsicData.getIndexSize();
            double protLeg = 0;

            for (int i = 0; i < n; i++)
            {
                if (!intrinsicData.isDefaulted(i))
                {
                    protLeg += intrinsicData.getWeight(i) * intrinsicData.getLGD(i) *
                               _pricer.protectionLeg(cds, yieldCurve, intrinsicData.getCreditCurve(i), 0);
                }
            }
            protLeg /= Math.Exp(-yieldCurve.getRT_(valuationTime));
            return(protLeg);
        }
        /**
         * Sensitivity of the intrinsic value of a CDS index to intrinsic CDS recovery rates.
         *
         * @param indexCDS The CDS index
         * @param indexCoupon The index coupon
         * @param yieldCurve The yield curve
         * @param intrinsicData Credit curves, weights and recovery rates of the intrinsic names
         * @return The sensitivity
         */
        public double[] recovery01(
            CDS indexCDS,
            double indexCoupon,
            YieldTermStructure yieldCurve,
            IntrinsicIndexDataBundle intrinsicData)
        {
            CDS zeroRR    = indexCDS.withRecoveryRate(0.0);
            int indexSize = intrinsicData.getIndexSize();

            double[] res = new double[indexSize];
            for (int i = 0; i < indexSize; ++i)
            {
                if (intrinsicData.isDefaulted(i))
                {
                    res[i] = 0.0;
                }
                else
                {
                    res[i] = -_pricer.protectionLeg(zeroRR, yieldCurve, intrinsicData.getCreditCurve(i)) *
                             intrinsicData.getWeight(i);
                }
            }
            return(res);
        }