/** * 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())); }
//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); }
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)); }
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); }
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); }
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; }
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)); }
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; } }