/**
         * 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));
        }
        public Index_Pricing_725()
        {
            TRADE_DATE = new DateTime(2016, 7, 25);
            NOTIONAL   = 1.0e6;

            //Contract Detail
            Read_Contract();

            //Index Market Data
            PRICES     = CDSIndexProvider.CDX_NA_HY_20160725_PRICES;
            PILLAR_PUF = new PointsUpFront[PRICES.Length];

            //Build the Interest Rate Curve
            Build_yield_curve(TRADE_DATE);

            //Read constituent features, build credit curves
            Build_credit_curves(TRADE_DATE);

            //Build Index data bundle
            INTRINSIC_DATA = new IntrinsicIndexDataBundle(CREDIT_CURVES, RECOVERY_RATES);

            weights_ = new double[component_num];
            weights_ = Enumerable.Repeat((double)1.0 / component_num, component_num).ToArray();
            INTRINSIC_DATA._weights = weights_;
            //Create CDX class
            CdsAnalyticFactory FACTORY = new CdsAnalyticFactory(INDEX_RECOVERY);

            int[] CDX_Tenor = new int[] { 12, 24, 36, 60, 84, 120 };
            CDX = FACTORY.makeCdx(TRADE_DATE, CDX_Tenor);
        }
 /**
  * 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
  * @return The normalised intrinsic annuity of a CDS portfolio (index)
  */
 public double indexAnnuity(
     CDS indexCDS,
     YieldTermStructure yieldCurve,
     IntrinsicIndexDataBundle intrinsicData)
 {
     return(indexAnnuity(indexCDS, yieldCurve, intrinsicData, CdsPriceType.CLEAN, indexCDS.getCashSettleTime()));
 }
        /**
         * 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 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
  * @return The normalised intrinsic value of the protection leg.
  */
 public double indexProtLeg(
     CDS indexCDS,
     YieldTermStructure yieldCurve,
     IntrinsicIndexDataBundle intrinsicData)
 {
     return(indexProtLeg(indexCDS, yieldCurve, intrinsicData, indexCDS.getCashSettleTime()));
 }
Exemple #6
0
        //Constructor
        public Index_Pricing()
        {
            //User Input of Trade Date
            TRADE_DATE = new DateTime(2014, 2, 13);
            NOTIONAL   = 1.0e6;

            //Contract Detail
            Read_Contract();

            //Index Market Data
            PRICES     = CDSIndexProvider.CDX_NA_HY_20140213_PRICES;
            PILLAR_PUF = new PointsUpFront[PRICES.Length];

            //Build the Interest Rate Curve
            Build_yield_curve(TRADE_DATE);

            //Read constituent features, build credit curves
            Build_credit_curves(TRADE_DATE);

            //Build Index data bundle
            INTRINSIC_DATA = new IntrinsicIndexDataBundle(CREDIT_CURVES, RECOVERY_RATES);

            //Create CDX class
            CdsAnalyticFactory FACTORY = new CdsAnalyticFactory(INDEX_RECOVERY);

            CDX = FACTORY.makeCdx(TRADE_DATE, CDSIndexProvider.INDEX_TENORS);
        }
 /**
  * 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 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,
     double valuationTime)
 {
     return(indexAnnuity(indexCDS, yieldCurve, intrinsicData, CdsPriceType.CLEAN, valuationTime));
 }
        /**
         * Intrinsic (normalised) price an index from the credit curves of the individual single names.
         * To get the actual index value, this multiplied by the <b>initial</b>  notional of the index.
         *
         * @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 recovery rates of the intrinsic names
         * @return The index value for a unit  notional.
         */
        public double indexPV(
            CDS indexCDS,
            double indexCoupon,
            YieldTermStructure yieldCurve,
            IntrinsicIndexDataBundle intrinsicData)
        {
            double prot    = indexProtLeg(indexCDS, yieldCurve, intrinsicData);
            double annuity = indexAnnuity(indexCDS, yieldCurve, intrinsicData);

            return(prot - indexCoupon * annuity);
        }
 /**
  * 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);
        }
        /**
         * Intrinsic (normalised) price an index from the credit curves of the individual single names.
         * To get the actual index value, this multiplied by the <b>initial</b>  notional of the index.
         *
         * @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 recovery rates of the intrinsic names
         * @param priceType Clean or dirty price
         * @param valuationTime 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 index value for a unit  notional.
         */
        public double indexPV(
            CDS indexCDS,
            double indexCoupon,
            YieldTermStructure yieldCurve,
            IntrinsicIndexDataBundle intrinsicData,
            CdsPriceType priceType,
            double valuationTime)
        {
            double prot    = indexProtLeg(indexCDS, yieldCurve, intrinsicData, valuationTime);
            double annuity = indexAnnuity(indexCDS, yieldCurve, intrinsicData, priceType, valuationTime);

            return(prot - indexCoupon * annuity);
        }
        //*******************************************************************************************************************
        //* Forward values adjusted for defaults
        //****************************************************************************************************************

        /**
         * For a future expiry date, the default adjusted forward index value is the expected (full)
         * value of the index plus the cash settlement of any defaults before
         * the expiry date, valued on the (forward) cash settlement date (usually 3 working days after
         * the expiry date - i.e. the expiry settlement date).
         *
         * @param fwdStartingCDS A forward starting CDS to represent cash flows in the index.
         *  The stepin date should be one day after the expiry and the cashSettlement
         *  date (usually) 3 working days after expiry.
         * @param timeToExpiry the time in years between the trade date and expiry.
         *  This should use the same DCC as the curves (ACT365F unless manually changed).
         * @param yieldCurve The yield curve
         * @param indexCoupon The coupon of the index
         * @param intrinsicData credit curves, weights and recovery rates of the intrinsic names
         *  initially 100 entries, and the realised recovery rates are 0.2 and 0.35, the this value is (0.8 + 0.65)/100 )
         * @return the default adjusted forward index value
         */
        public double defaultAdjustedForwardIndexValue(
            CDS fwdStartingCDS,
            double timeToExpiry,
            YieldTermStructure yieldCurve,
            double indexCoupon,
            IntrinsicIndexDataBundle intrinsicData)
        {
            //the expected value of the index (not including default settlement) at the expiry settlement date
            double indexPV1 = indexPV(fwdStartingCDS, indexCoupon, yieldCurve, intrinsicData);
            double d        = expectedDefaultSettlementValue(timeToExpiry, intrinsicData);

            return(indexPV1 + d);
        }
Exemple #13
0
        public IntrinsicIndexDataBundle adjustCurves(
            double indexPUF,
            CDS indexCDS,
            double indexCoupon,
            YieldTermStructure yieldCurve,
            IntrinsicIndexDataBundle intrinsicData)
        {
            Func <double, double> func = getHazardRateAdjFunction(indexPUF, indexCDS, indexCoupon, yieldCurve, intrinsicData);
            double x = ROOTFINDER.getRoot(func, 1.0);

            PiecewiseconstantHazardRate[] adjCC = adjustCurves(intrinsicData.getCreditCurves(), x);
            return(intrinsicData.withCreditCurves(adjCC));
        }
        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));
        }
Exemple #15
0
        private Func <double, double> getHazardRateAdjFunction(
            double indexPUF,
            CDS indexCDS,
            double indexCoupon,
            YieldTermStructure yieldCurve,
            IntrinsicIndexDataBundle intrinsicData)
        {
            PiecewiseconstantHazardRate[] creditCurves = intrinsicData.getCreditCurves();
            double clean = intrinsicData.getIndexFactor() * indexPUF;
            Func <double, double> function = x => _pricer.indexPV(indexCDS, indexCoupon,
                                                                  yieldCurve, intrinsicData.withCreditCurves(adjustCurves(creditCurves, x))) - clean;

            return(function);
        }
        /**
         * The (default adjusted) intrinsic forward spread of an index.
         * This is defined as the ratio of expected value of the protection leg and default settlement to
         * the expected value of the annuity at expiry.
         *
         * @param fwdStartingCDS  forward starting CDS to represent cash flows in the index.
         *  The stepin date should be one day after the expiry and the cashSettlement
         *  date (usually) 3 working days after expiry the time in years between the trade date and expiry.
         *  This should use the same DCC as the curves (ACT365F unless manually changed).
         * @param timeToExpiry the time in years between the trade date and expiry.
         *  This should use the same DCC as the curves (ACT365F unless manually changed).
         * @param yieldCurve The yield curve
         * @param intrinsicData credit curves, weights and recovery rates of the intrinsic names
         *  initially 100 entries, and the realised recovery rates are 0.2 and 0.35, the this value is (0.8 + 0.65)/100 )
         * @return The (default adjusted) forward spread (as a fraction)
         */
        public double defaultAdjustedForwardSpread(
            CDS fwdStartingCDS,
            double timeToExpiry,
            YieldTermStructure yieldCurve,
            IntrinsicIndexDataBundle intrinsicData)
        {
            // Note: these values are all calculated for payment on the (forward) cash settlement date
            // there is no point discounting to today
            double protLeg   = indexProtLeg(fwdStartingCDS, yieldCurve, intrinsicData);
            double defSettle = expectedDefaultSettlementValue(timeToExpiry, intrinsicData);
            double ann       = indexAnnuity(fwdStartingCDS, yieldCurve, intrinsicData);

            return((protLeg + defSettle) / ann);
        }
        /**
         * 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);
        }
Exemple #18
0
        public void testMethod()
        {
            for (int i = 0; i < PRICES.Length; i++)
            {
                PILLAR_PUF[i] = new PointsUpFront(INDEX_COUPON, 1 - PRICES[i]);
            }

            int pos        = 1; // target CDX is 5Y
            CDS targentCDX = CDX[pos];
            int n          = PILLAR_PUF.Length;

            double[] indexPUF = new double[n];
            for (int i = 0; i < n; i++)
            {
                indexPUF[i] = PILLAR_PUF[i].getPointsUpFront();
            }
            int    accrualDays    = targentCDX.getAccuredDays();
            double accruedPremium = targentCDX.getAccruedPremium(INDEX_COUPON) * INTRINSIC_DATA.getIndexFactor() * NOTIONAL; // indexFactor = (initialIndexSize - numDefaults) / initialIndexSize

            /*
             * Using credit curves for constituent single name CDSs.
             * The curves are adjusted by using only the target CDX.
             */
            IntrinsicIndexDataBundle adjCurves = PSA.adjustCurves(indexPUF[pos], CDX[pos], INDEX_COUPON, YIELD_CURVE,
                                                                  INTRINSIC_DATA);
            double cleanPV      = INDEX_CAL.indexPV(targentCDX, INDEX_COUPON, YIELD_CURVE, adjCurves) * NOTIONAL; // should be consistent with 1 - PRICES[pos]
            double dirtyPV      = INDEX_CAL.indexPV(targentCDX, INDEX_COUPON, YIELD_CURVE, adjCurves, CdsPriceType.DIRTY) * NOTIONAL;
            double expectedLoss = INDEX_CAL.expectedDefaultSettlementValue(targentCDX.getProtectionEnd(), adjCurves) * NOTIONAL;
            double cleanRPV01   = INDEX_CAL.indexAnnuity(targentCDX, YIELD_CURVE, adjCurves);
            double dirtyRPV01   = INDEX_CAL.indexAnnuity(targentCDX, YIELD_CURVE, adjCurves, CdsPriceType.DIRTY);
            double durationWeightedAverageSpread = INDEX_CAL.intrinsicIndexSpread(targentCDX, YIELD_CURVE, adjCurves) *
                                                   TEN_THOUSAND;
            double parallelIR01 = INDEX_CAL.parallelIR01(targentCDX, INDEX_COUPON, YIELD_CURVE, adjCurves) * NOTIONAL;

            double[] jumpToDefault = INDEX_CAL.jumpToDefault(targentCDX, INDEX_COUPON, YIELD_CURVE, adjCurves);
            for (int i = 0; i < jumpToDefault.Length; ++i)
            {
                jumpToDefault[i] *= NOTIONAL;
            }
            double[] recovery01 = INDEX_CAL.recovery01(targentCDX, INDEX_COUPON, YIELD_CURVE, adjCurves);
            for (int i = 0; i < recovery01.Length; ++i)
            {
                recovery01[i] *= NOTIONAL;
            }
        }
        /**
         * The change in the intrinsic value of a CDS index when zero rate at node points of the yield curve is bumped by 1bps.
         * If the index is priced as a single name CDS, use {@link InterestRateSensitivityCalculator}.
         *
         * @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 bucketed IR01
         */
        public double[] bucketedIR01(
            CDS indexCDS,
            double indexCoupon,
            YieldTermStructure yieldCurve,
            IntrinsicIndexDataBundle intrinsicData)
        {
            double basePV = indexPV(indexCDS, indexCoupon, yieldCurve, intrinsicData, CdsPriceType.DIRTY);
            int    n      = yieldCurve.t.Count;

            double[] res = new double[n];
            for (int i = 0; i < n; ++i)
            {
                YieldTermStructure bumpedYieldCurve = yieldCurve.withRate(yieldCurve.getZeroRateAtIndex(i) + ONE_BPS, i);
                double             bumpedPV         = indexPV(indexCDS, indexCoupon, bumpedYieldCurve, intrinsicData, CdsPriceType.DIRTY);
                res[i] = bumpedPV - basePV;
            }
            return(res);
        }
        /**
         * The change in the intrinsic value of a CDS index when the yield curve is bumped by 1bps.
         * If the index is priced as a single name CDS, use {@link InterestRateSensitivityCalculator}.
         *
         * @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 parallel IR01
         */
        public double parallelIR01(
            CDS indexCDS,
            double indexCoupon,
            YieldTermStructure yieldCurve,
            IntrinsicIndexDataBundle intrinsicData)
        {
            double pv     = indexPV(indexCDS, indexCoupon, yieldCurve, intrinsicData, CdsPriceType.DIRTY);
            int    nKnots = yieldCurve.t.Count;

            double[] rates = yieldCurve.getKnotZeroRates().ToArray();
            for (int i = 0; i < nKnots; ++i)
            {
                rates[i] += ONE_BPS;
            }
            YieldTermStructure yieldCurveUp = yieldCurve.withRates(rates.ToList());
            double             pvUp         = indexPV(indexCDS, indexCoupon, yieldCurveUp, intrinsicData, CdsPriceType.DIRTY);

            return(pvUp - pv);
        }
        /**
         * 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);
        }
        /**
         * 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);
        }
        /**
         * Values on per-name default
         * @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 jump to default
         */
        public double[] jumpToDefault(
            CDS indexCDS,
            double indexCoupon,
            YieldTermStructure yieldCurve,
            IntrinsicIndexDataBundle intrinsicData)
        {
            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] = decomposedValueOnDefault(indexCDS, indexCoupon, yieldCurve, intrinsicData, i);
                }
            }
            return(res);
        }
        /**
         * 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);
        }
Exemple #25
0
        public void testMethod1()
        {
            for (int i = 0; i < PRICES.Length; i++)
            {
                PILLAR_PUF[i] = new PointsUpFront(INDEX_COUPON, 1 - PRICES[i]);
            }
            int pos        = 1; // target CDX is 5Y
            CDS targentCDX = CDX[pos];
            int n          = PILLAR_PUF.Length;

            double[] indexPUF = new double[n];
            for (int i = 0; i < n; i++)
            {
                indexPUF[i] = PILLAR_PUF[i].getPointsUpFront();
            }

            IntrinsicIndexDataBundle dataDefaulted = INTRINSIC_DATA;
            int    accrualDays    = targentCDX.getAccuredDays();
            double accruedPremium = targentCDX.getAccruedPremium(INDEX_COUPON) * NOTIONAL * dataDefaulted.getIndexFactor();

            /*
             * Using credit curves for constituent single name CDSs.
             * The curves are adjusted by using only the target CDX.
             */

            double cleanPV      = INDEX_CAL.indexPV(targentCDX, INDEX_COUPON, YIELD_CURVE, dataDefaulted) * NOTIONAL;
            double dirtyPV      = INDEX_CAL.indexPV(targentCDX, INDEX_COUPON, YIELD_CURVE, dataDefaulted, CdsPriceType.DIRTY) * NOTIONAL; // should be consistent with 1 - PRICES[pos]
            double expectedLoss = INDEX_CAL.expectedDefaultSettlementValue(targentCDX.getProtectionEnd(), dataDefaulted) * NOTIONAL;
            double cleanRPV01   = INDEX_CAL.indexAnnuity(targentCDX, YIELD_CURVE, dataDefaulted);
            double dirtyRPV01   = INDEX_CAL.indexAnnuity(targentCDX, YIELD_CURVE, dataDefaulted, CdsPriceType.DIRTY);
            double durationWeightedAverageSpread = INDEX_CAL.intrinsicIndexSpread(targentCDX, YIELD_CURVE, dataDefaulted) *
                                                   TEN_THOUSAND;
            double parallelIR01 = INDEX_CAL.parallelIR01(targentCDX, INDEX_COUPON, YIELD_CURVE, dataDefaulted) * NOTIONAL;

            double[] jumpToDefault = INDEX_CAL.jumpToDefault(targentCDX, INDEX_COUPON, YIELD_CURVE, dataDefaulted);
            for (int i = 0; i < jumpToDefault.Length; ++i)
            {
                jumpToDefault[i] *= NOTIONAL;
            }
            double[] recovery01 = INDEX_CAL.recovery01(targentCDX, INDEX_COUPON, YIELD_CURVE, dataDefaulted);
            for (int i = 0; i < recovery01.Length; ++i)
            {
                recovery01[i] *= NOTIONAL;
            }


            IntrinsicIndexDataBundle adjCurvesAll = PSA.adjustCurves(indexPUF, CDX, INDEX_COUPON, YIELD_CURVE,
                                                                     dataDefaulted);
            double cleanPVAll = INDEX_CAL.indexPV(targentCDX, INDEX_COUPON, YIELD_CURVE, adjCurvesAll) * NOTIONAL;
            double dirtyPVAll = INDEX_CAL.indexPV(targentCDX, INDEX_COUPON, YIELD_CURVE, adjCurvesAll, CdsPriceType.DIRTY) *
                                NOTIONAL; // should be consistent with 1 - PRICES[pos]
            double expectedLossAll = INDEX_CAL.expectedDefaultSettlementValue(targentCDX.getProtectionEnd(), adjCurvesAll) *
                                     NOTIONAL;
            double cleanRPV01All = INDEX_CAL.indexAnnuity(targentCDX, YIELD_CURVE, adjCurvesAll);
            double dirtyRPV01All = INDEX_CAL.indexAnnuity(targentCDX, YIELD_CURVE, adjCurvesAll, CdsPriceType.DIRTY);
            double durationWeightedAverageSpreadAll = INDEX_CAL.intrinsicIndexSpread(targentCDX, YIELD_CURVE, adjCurvesAll) *
                                                      TEN_THOUSAND;
            double parallelIR01All = INDEX_CAL.parallelIR01(targentCDX, INDEX_COUPON, YIELD_CURVE, adjCurvesAll) * NOTIONAL;

            double[] jumpToDefaultAll = INDEX_CAL.jumpToDefault(targentCDX, INDEX_COUPON, YIELD_CURVE, adjCurvesAll);
            for (int i = 0; i < jumpToDefaultAll.Length; ++i)
            {
                jumpToDefaultAll[i] *= NOTIONAL;
            }
            double[] recovery01All = INDEX_CAL.recovery01(targentCDX, INDEX_COUPON, YIELD_CURVE, adjCurvesAll);
            for (int i = 0; i < recovery01All.Length; ++i)
            {
                recovery01All[i] *= NOTIONAL;
            }
            PiecewiseconstantHazardRate indexCurve = (new Commons.FastCreditCurveBuilder()).calibrateCreditCurve(targentCDX,
                                                                                                                 INDEX_COUPON, YIELD_CURVE, indexPUF[pos]); // single node index curve, indexFactors cancel out
            double cleanPriceIndexCurve = PRICER_OG_FIX.pv(targentCDX, YIELD_CURVE, indexCurve, INDEX_COUPON) *
                                          dataDefaulted.getIndexFactor() * NOTIONAL;
            double dirtyPriceIndexCurve = PRICER_OG_FIX.pv(targentCDX, YIELD_CURVE, indexCurve, INDEX_COUPON,
                                                           CdsPriceType.DIRTY) * dataDefaulted.getIndexFactor() * NOTIONAL;
            double cleanRPV01IndexCurve = PRICER_OG_FIX.annuity(targentCDX, YIELD_CURVE, indexCurve) *
                                          dataDefaulted.getIndexFactor();
            double dirtyRPV01IndexCurve = PRICER_OG_FIX.annuity(targentCDX, YIELD_CURVE, indexCurve, CdsPriceType.DIRTY) *
                                          dataDefaulted.getIndexFactor();
            double spreadIndexCurve = PRICER_OG_FIX.parSpread(targentCDX, YIELD_CURVE, indexCurve) * TEN_THOUSAND;
        }
Exemple #26
0
        public IntrinsicIndexDataBundle adjustCurves(
            double[] indexPUF,
            CDS[] indexCDS,
            double indexCoupon,
            YieldTermStructure yieldCurve,
            IntrinsicIndexDataBundle intrinsicData)
        {
            int nIndexTerms = indexCDS.Length;

            if (nIndexTerms == 1)
            {
                return(adjustCurves(indexPUF[0], indexCDS[0], indexCoupon, yieldCurve, intrinsicData));
            }
            double[] indexKnots = new double[nIndexTerms];
            for (int i = 0; i < nIndexTerms; i++)
            {
                indexKnots[i] = indexCDS[i].getProtectionEnd();
            }

            PiecewiseconstantHazardRate[] creditCurves = intrinsicData.getCreditCurves();
            int nCurves = creditCurves.Length;

            //we cannot assume that all the credit curves have knots at the same times or that the terms of the indices fall on these knots.
            PiecewiseconstantHazardRate[] modCreditCurves = new PiecewiseconstantHazardRate[nCurves];
            int[,] indexMap = new int[nCurves, nIndexTerms];
            for (int i = 0; i < nCurves; i++)
            {
                if (creditCurves[i] == null)
                {
                    modCreditCurves[i] = null; //null credit curves correspond to defaulted names, so are ignored
                }
                else
                {
                    double[] ccKnots  = creditCurves[i].t.ToArray();
                    double[] comKnots = DoublesScheduleGenerator.combineSets(ccKnots, indexKnots);
                    int      nKnots   = comKnots.Length;
                    if (nKnots == ccKnots.Length)
                    {
                        modCreditCurves[i] = creditCurves[i];
                    }
                    else
                    {
                        double[] rt = new double[nKnots];
                        for (int j = 0; j < nKnots; j++)
                        {
                            rt[j] = creditCurves[i].getRT_(comKnots[j]);
                        }
                        PiecewiseconstantHazardRate hazard = new PiecewiseconstantHazardRate(creditCurves[i].latestReference_, null, null, null, null);
                        modCreditCurves[i] = hazard.makeFromRT(comKnots.ToList(), rt);
                    }

                    for (int j = 0; j < nIndexTerms; j++)
                    {
                        int index = Array.BinarySearch(modCreditCurves[i].t.ToArray(), indexKnots[j]);

                        indexMap[i, j] = index;
                    }
                }
            }

            int[]  startKnots = new int[nCurves];
            int[]  endKnots   = new int[nCurves];
            double alpha      = 1.0;

            for (int i = 0; i < nIndexTerms; i++)
            {
                if (i == (nIndexTerms - 1))
                {
                    for (int jj = 0; jj < nCurves; jj++)
                    {
                        if (modCreditCurves[jj] != null)
                        {
                            endKnots[jj] = modCreditCurves[jj].t.Count;
                        }
                    }
                }
                else
                {
                    for (int jj = 0; jj < nCurves; jj++)
                    {
                        if (modCreditCurves[jj] != null)
                        {
                            endKnots[jj] = indexMap[jj, i] + 1;
                        }
                    }
                }

                IntrinsicIndexDataBundle modIntrinsicData = intrinsicData.withCreditCurves(modCreditCurves);
                Func <double, double>    func             = getHazardRateAdjFunction(indexPUF[i], indexCDS[i], indexCoupon, yieldCurve,
                                                                                     modIntrinsicData, startKnots, endKnots);
                alpha           = ROOTFINDER.getRoot(func, alpha);
                modCreditCurves = adjustCurves(modCreditCurves, alpha, startKnots, endKnots);
                startKnots      = endKnots;
            }

            return(intrinsicData.withCreditCurves(modCreditCurves));
        }
Exemple #27
0
        public void Pricing()
        {
            for (int i = 0; i < PRICES.Length; i++)
            {
                PILLAR_PUF[i] = new PointsUpFront(INDEX_COUPON, 1 - PRICES[i]);
            }
            int pos        = 1; // target CDX is 5Y
            CDS targentCDX = CDX[pos];
            int n          = PILLAR_PUF.Length;

            double[] indexPUF = new double[n];
            for (int i = 0; i < n; i++)
            {
                indexPUF[i] = PILLAR_PUF[i].getPointsUpFront();
            }

            defaultedNames = new int[] { 2, 15, 37, 51 };

            IntrinsicIndexDataBundle dataDefaulted = INTRINSIC_DATA.withDefault(defaultedNames);
            int    accrualDays    = targentCDX.getAccuredDays();
            double accruedPremium = targentCDX.getAccruedPremium(INDEX_COUPON) * NOTIONAL * dataDefaulted.getIndexFactor();

            /*
             * Using credit curves for constituent single name CDSs.
             * The curves are adjusted by using only the target CDX.
             */
            IntrinsicIndexDataBundle adjCurves = PSA.adjustCurves(indexPUF[pos], CDX[pos], INDEX_COUPON, YIELD_CURVE,
                                                                  dataDefaulted);

            cleanPV      = INDEX_CAL.indexPV(targentCDX, INDEX_COUPON, YIELD_CURVE, adjCurves) * NOTIONAL;
            dirtyPV      = INDEX_CAL.indexPV(targentCDX, INDEX_COUPON, YIELD_CURVE, adjCurves, CdsPriceType.DIRTY) * NOTIONAL; // should be consistent with 1 - PRICES[pos]
            expectedLoss = INDEX_CAL.expectedDefaultSettlementValue(targentCDX.getProtectionEnd(), adjCurves) * NOTIONAL;
            cleanRPV01   = INDEX_CAL.indexAnnuity(targentCDX, YIELD_CURVE, adjCurves);
            dirtyRPV01   = INDEX_CAL.indexAnnuity(targentCDX, YIELD_CURVE, adjCurves, CdsPriceType.DIRTY);
            durationWeightedAverageSpread = INDEX_CAL.intrinsicIndexSpread(targentCDX, YIELD_CURVE, adjCurves) *
                                            TEN_THOUSAND;
            parallelIR01 = INDEX_CAL.parallelIR01(targentCDX, INDEX_COUPON, YIELD_CURVE, adjCurves) * NOTIONAL;
            double[] jumpToDefault = INDEX_CAL.jumpToDefault(targentCDX, INDEX_COUPON, YIELD_CURVE, adjCurves);
            for (int i = 0; i < jumpToDefault.Length; ++i)
            {
                jumpToDefault[i] *= NOTIONAL;
            }
            recovery01 = INDEX_CAL.recovery01(targentCDX, INDEX_COUPON, YIELD_CURVE, adjCurves);

            //Build Cash flow
            QLNet.UnitedStates cal     = new QLNet.UnitedStates();
            CdsCoupon[]        coupons = targentCDX.getCoupons();
            int npayments = coupons.Count();

            cashflow = new List <CouponPayment>();
            for (int i = 0; i < npayments; i++)
            {
                CouponPayment cf = new CouponPayment();
                cf.Amount = (-coupons[i].getEffStart() + coupons[i].getEffEnd()) * NOTIONAL * INDEX_COUPON;
                cf.Amount = Math.Round(cf.Amount, 2);
                double days = coupons[i].getEffEnd() * 365;
                cf.CashFlowDate = i == 0? CdsAnalyticFactory.getNextIMMDate(TRADE_DATE):
                                  CdsAnalyticFactory.getNextIMMDate(cashflow[i - 1].CashFlowDate);
                cf.CashFlowDate = cal.adjust(cf.CashFlowDate);
                cashflow.Add(cf);
            }

            for (int i = 0; i < recovery01.Length; ++i)
            {
                recovery01[i] *= NOTIONAL;
            }
        }