/** * 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)); }
/** * 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 * @return The normalised intrinsic annuity of a CDS portfolio (index) */ public double indexAnnuity( CDS indexCDS, YieldTermStructure yieldCurve, IntrinsicIndexDataBundle intrinsicData, CdsPriceType priceType) { return(indexAnnuity(indexCDS, yieldCurve, intrinsicData, priceType, indexCDS.getCashSettleTime())); }
public double ProtectionLegNPV_Exact(CDS cds, double notional, PiecewiseconstantHazardRate hazard, YieldTermStructure yt, DateTime tradedate, DateTime settlementDate, double recoveryrate, List <double> Jumps, List <double> creditCurveKnot) { DateTime Stepindate = tradedate.AddDays(1); OMLib.Conventions.DayCount.Actual360 dc = new OMLib.Conventions.DayCount.Actual360(); double t0 = 0; double T = cds.getProtectionEnd(); List <double> JumpNodes = new List <double>(); JumpNodes.Add(t0); for (int j = 0; j < Jumps.Count; j++) { if (Jumps[j] < T) { JumpNodes.Add(Jumps[j]); } } JumpNodes.Add(T); double ht0 = hazard.getRT_(JumpNodes[0]); double rt0 = yt.getRT_(JumpNodes[0]); double b0 = Math.Exp(-ht0 - rt0); // risky discount factor double pv = 0.0; double dPV = 0.0; for (int i = 1; i < JumpNodes.Count; ++i) { double ht1 = hazard.getRT_(JumpNodes[i]); double rt1 = yt.getRT_(JumpNodes[i]); double b1 = Math.Exp(-ht1 - rt1); double dht = ht1 - ht0; double drt = rt1 - rt0; double dhrt = dht + drt; // The formula has been modified from ISDA (but is equivalent) to avoid log(exp(x)) and explicitly // calculating the time step - it also handles the limit if (Math.Abs(dhrt) < 1e-5) { dPV = dht * b0 * (Math.Exp(-dhrt) - 1) / (-dhrt); } else { dPV = (b0 - b1) * dht / dhrt; } pv += dPV; ht0 = ht1; rt0 = rt1; b0 = b1; } return(pv * notional * (1 - recoveryrate) / yt.discount(settlementDate)); }
/** * 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). * This calculation assumes an homogeneous pool that can be described by a single index curve. * * @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. This must contain the index recovery rate. * @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 indexCurve Pseudo credit curve for the index. * @return the default adjusted forward index value */ public double defaultAdjustedForwardIndexValue( CDS fwdStartingCDS, double timeToExpiry, YieldTermStructure yieldCurve, double indexCoupon, PiecewiseconstantHazardRate indexCurve) { double defSet = expectedDefaultSettlementValue(timeToExpiry, indexCurve, fwdStartingCDS.getLGD()); return(defSet + _pricer.pv(fwdStartingCDS, yieldCurve, indexCurve, indexCoupon)); }
public static PiecewiseconstantHazardRate[] buildCreditCurves(DateTime tradeDate, double[,] parSpreads, double[] recoveryRates, int[] tenors, YieldTermStructure yieldCurve) { CdsAnalyticFactory factory = new CdsAnalyticFactory(0.0); CDS[] pillarCDS = factory.makeImmCds(tradeDate, CDX_HY_TENORS); int indexSize = parSpreads.GetLength(0); PiecewiseconstantHazardRate[] creditCurves = new PiecewiseconstantHazardRate[indexSize]; //this section of code is hugely wasteful. If we do this for real (i.e. not just in a test), must improve for (int i = 0; i < indexSize; i++) { int m = parSpreads.GetLength(1); double[] spreads = new double[m]; for (int j = 0; j < m; j++) { spreads[j] = parSpreads[i, j]; } int nPillars = spreads.Length; CDS[] tempCDS = new CDS[nPillars]; double[] tempSpreads = new double[nPillars]; int count = 0; for (int j = 0; j < nPillars; j++) { if (!double.IsNaN(parSpreads[i, j])) { tempCDS[count] = pillarCDS[j].withRecoveryRate(recoveryRates[i]); tempSpreads[count] = spreads[j]; count++; } } CDS[] calCDS = null; double[] calSpreads = null; if (count == nPillars) { calCDS = tempCDS; calSpreads = tempSpreads; } else { calCDS = new CDS[count]; calSpreads = new double[count]; Array.Copy(tempCDS, 0, calCDS, 0, count); Array.Copy(tempSpreads, 0, calSpreads, 0, count); } CreditCurveCalibrator calibrator = new CreditCurveCalibrator(calCDS, yieldCurve); creditCurves[i] = calibrator.calibrate(calSpreads); } return(creditCurves); }
/** * 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()); }
/** * 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 (default adjusted) intrinsic forward spread of an index <b>when no defaults have yet occurred</b>. * 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. * This calculation assumes an homogeneous pool that can be described by a single index curve. * * @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 * @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 indexCurve Pseudo credit curve for the index. * @return The normalised expected default settlement value */ public double defaultAdjustedForwardSpread( CDS fwdStartingCDS, double timeToExpiry, YieldTermStructure yieldCurve, PiecewiseconstantHazardRate indexCurve) { double defSettle = expectedDefaultSettlementValue(timeToExpiry, indexCurve, fwdStartingCDS.getLGD()); double protLeg = _pricer.protectionLeg(fwdStartingCDS, yieldCurve, indexCurve); double ann = _pricer.annuity(fwdStartingCDS, yieldCurve, indexCurve); return((protLeg + defSettle) / ann); }
/** * 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); }
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 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); }
//******************************************************************************************************************* //* 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)); }
/** * 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); }
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); }
/** * Make a set of CDS by specifying all dates. * * @param tradeDate the trade date * @param stepinDate (aka Protection Effective sate or assignment date). Date when party assumes ownership. * This is usually T+1. This is when protection (and risk) starts in terms of the model. * Note, this is sometimes just called the Effective Date, however this can cause * confusion with the legal effective date which is T-60 or T-90. * @param valueDate the valuation date. The date that values are PVed to. * Is is normally today + 3 business days. Aka cash-settle date. * @param accStartDate this is when the CDS nominally starts in terms of premium payments. i.e. the number * of days in the first period (and thus the amount of the first premium payment) is counted from this date. * @param maturities The maturities of the CDSs. For a standard CDS these are IMM dates * @return an array of CDS analytic descriptions */ public CDS[] makeCds( DateTime tradeDate, DateTime stepinDate, DateTime valueDate, DateTime accStartDate, DateTime[] maturities) { int n = maturities.Length; CDS[] cds = new CDS[n]; for (int i = 0; i < n; i++) { cds[i] = new CDS(Coupon, notional, maturities[i], getNextIMMDate(tradeDate), tradeDate, accStartDate, frequency, _recoveryRate, DEFAULT_STEPIN, DEFAULT_CASH_SETTLE); } return(cds); }
/** * 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). * This calculation assumes an homogeneous pool that can be described by a single index curve. * * @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. This must contain the index recovery rate. * @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 initialIndexSize The initial number of names in the index * @param yieldCurve The yield curve * @param indexCoupon The coupon of the index * @param indexCurve Pseudo credit curve for the index. * @param initialDefaultSettlement The (normalised) value of any defaults that have already * occurred (e.g. if two defaults have occurred from an index with * initially 100 entries, and the realised recovery rates are 0.2 and 0.35, the this value is (0.8 + 0.65)/100 ) * @param numDefaults The number of defaults that have already occurred * @return the default adjusted forward index value */ public double defaultAdjustedForwardIndexValue( CDS fwdStartingCDS, double timeToExpiry, int initialIndexSize, YieldTermStructure yieldCurve, double indexCoupon, PiecewiseconstantHazardRate indexCurve, double initialDefaultSettlement, int numDefaults) { double f = (initialIndexSize - numDefaults) / ((double)initialIndexSize); double defSet = expectedDefaultSettlementValue(initialIndexSize, timeToExpiry, indexCurve, fwdStartingCDS.getLGD(), initialDefaultSettlement, numDefaults); return(defSet + f * _pricer.pv(fwdStartingCDS, yieldCurve, indexCurve, indexCoupon)); }
/** * 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. This calculation assumes an homogeneous pool that * can be described by a single index curve. * * @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 * @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 initialIndexSize The initial number of names in the index * @param yieldCurve The yield curve * @param indexCurve Pseudo credit curve for the index. * @param initialDefaultSettlement The (normalised) value of any defaults that have * already occurred (e.g. if two defaults have occurred from an index with * initially 100 entries, and the realised recovery rates are 0.2 and 0.35, the this value is (0.8 + 0.65)/100 ) * @param numDefaults The number of defaults that have already occurred * @return The normalised expected default settlement value */ public double defaultAdjustedForwardSpread( CDS fwdStartingCDS, double timeToExpiry, int initialIndexSize, YieldTermStructure yieldCurve, PiecewiseconstantHazardRate indexCurve, double initialDefaultSettlement, int numDefaults) { double f = (initialIndexSize - numDefaults) / ((double)initialIndexSize); double defSettle = expectedDefaultSettlementValue(initialIndexSize, timeToExpiry, indexCurve, fwdStartingCDS.getLGD(), initialDefaultSettlement, numDefaults); double protLeg = f * _pricer.protectionLeg(fwdStartingCDS, yieldCurve, indexCurve); double ann = f * _pricer.annuity(fwdStartingCDS, yieldCurve, indexCurve); return((protLeg + defSettle) / ann); }
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); }
public double PremiumLegNPV_Exact(CDS cds, PiecewiseconstantHazardRate hazard, YieldTermStructure yt, DateTime tradedate, DateTime settlementDate, double notional, double coupon, List <double> Jumps, DateTime lastpayment) { double ita = (double)365 / 360; double totalNPV = 0.0; CdsCoupon[] cf = cds.getCoupons(); for (int i = 0; i < cf.Length; ++i) { totalNPV += cf[i].getYearFrac() * notional * Math.Exp(-hazard.getRT_(cf[i].getEffEnd())) * Math.Exp(-yt.getRT_(cf[i].getEffEnd())); } double accrualpaidondefault = calculateSinglePeriodAccrualOnDefault(cf, coupon, tradedate, yt, hazard, lastpayment); totalNPV += ita * coupon * accrualpaidondefault * notional / yt.discount(tradedate.AddDays(3)); OMLib.Conventions.DayCount.Actual360 dc = new OMLib.Conventions.DayCount.Actual360(); Calendar calendar = new UnitedStates(); return(totalNPV / Math.Exp(-yt.getRT_(cds.getCashSettleTime()))); }
/** * 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 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; } }