public double[] bucketedCS01FromCreditCurve( CDS cds, double cdsCoupon, CDS[] bucketCDSs, YieldTermStructure yieldCurve, PiecewiseconstantHazardRate creditCurve) { int n = bucketCDSs.Length; Vector <double> vLambda = Vector <double> .Build.Random(n); for (int i = 0; i < n; i++) { vLambda[i] = _pricer.pvCreditSensitivity(cds, yieldCurve, creditCurve, cdsCoupon, i); } Matrix <double> jacT = Matrix <double> .Build.Random(n, n); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { jacT[i, j] = _pricer.parSpreadCreditSensitivity(bucketCDSs[j], yieldCurve, creditCurve, i); } } LU <double> LUResult = jacT.LU(); Vector <double> vS = LUResult.Solve(vLambda); return(vS.ToArray()); }
/** * Put any CDS market quote into the form needed for the curve builder, * namely coupon and points up-front (which can be zero). * * @param calibrationCDS * @param marketQuote * @param yieldCurve * @return The market quotes in the form required by the curve builder */ private double[] getStandardQuoteForm( CDS calibrationCDS, CdsQuoteConvention marketQuote, YieldTermStructure yieldCurve) { AnalyticalCdsPricer pricer = new AnalyticalCdsPricer(); double[] res = new double[2]; if (marketQuote is CdsParSpread) { res[0] = marketQuote.getCoupon(); } else if (marketQuote is CdsQuotedSpread) { CdsQuotedSpread temp = (CdsQuotedSpread)marketQuote; double coupon = temp.getCoupon(); double qSpread = temp.getQuotedSpread(); PiecewiseconstantHazardRate cc = calibrateCreditCurve( new CDS[] { calibrationCDS }, new double[] { qSpread }, yieldCurve, new double[1]); res[0] = coupon; res[1] = pricer.pv(calibrationCDS, yieldCurve, cc, coupon, CdsPriceType.CLEAN); } else if (marketQuote is PointsUpFront) { PointsUpFront temp = (PointsUpFront)marketQuote; res[0] = temp.getCoupon(); res[1] = temp.getPointsUpFront(); } return(res); }
public PiecewiseconstantHazardRate calibrate(double[] premiums, double[] puf) { _protLegElmtPV = new double[_nCDS][]; _premLegElmtPV = new double[_nCoupons][]; // use continuous premiums as initial guess double[] guess = new double[_nCDS]; for (int i = 0; i < _nCDS; i++) { guess[i] = (premiums[i] + puf[i] / _t[i]) / _lgd[i]; } PiecewiseconstantHazardRate hazard = new PiecewiseconstantHazardRate(baseline, null, null, null, null); _creditCurve = hazard.makeFromR(_t.ToList(), guess); for (int i = 0; i < _nCDS; i++) { Func <double, double> func = getPointFunction(i, premiums[i], puf[i]); Func <double, double> grad = getPointDerivative(i, premiums[i]); double zeroRate = ROOTFINDER.getRoot(func, grad, guess[i]); updateAll(zeroRate, i); } return(_creditCurve); }
public double rpv01(PiecewiseconstantHazardRate creditCurve, CdsPriceType cleanOrDirty) { double pv = 0.0; for (int i = 0; i < _nPayments; i++) { CdsCoupon c = _cds.getCoupon(i); double q = Math.Exp(-creditCurve.getRT_(c.getEffEnd())); pv += c.getYearFrac() * _paymentDF[i] * q; } if (_cds.isPayAccOnDefault()) { double accPV = 0.0; for (int i = 0; i < _nPayments; i++) { accPV += calculateSinglePeriodAccrualOnDefault(i, creditCurve); } pv += accPV; } pv /= _valuationDF; if (cleanOrDirty == CdsPriceType.CLEAN) { pv -= _cds.getAccruedYearFraction(); } return(pv); }
/** * The value of the annuity (or RPV01 - the premium leg per unit of coupon) at a specified valuation time. * The actual value of the leg is this multiplied by the notional and the fractional coupon (i.e. coupon * in basis points divided by 10,000). * <p> * If this is a spot starting CDS (effective protection start = 0) then cash flows from premium payments * and accrual-on-default are risky discounted to t=0 ('today'), then rolled forward (risk-free) to the * valuation time; if the annuity is requested clean, the accrued premium (paid at the cash-settle time) is * rolled (again risk-free) to the valuation time; the absolute value of this amount is subtracted from the * other cash flows to give the clean annuity. * <p> * If this is a forward starting CDS (effective protection start > 0), then the premium payments are again * risky discounted to t=0; if the annuity is requested clean, the accrued premium is risk-free discounted * to the effective protection start, then risky discounted to t=0 - this gives the t=0 value of the annuity * including the chance that a default occurs before protection starts. * <p> * If valuationTime > 0, the value of the annuity is rolled forward (risk-free) to that time. * To compute the Expected value of the annuity conditional on no default before the valuationTime, * one must divide this number by the survival probability to the valuationTime (for unit coupon). * * @param cds the analytic description of a CDS traded at a certain time * @param yieldCurve the yield (or discount) curve * @param creditCurve the credit (or survival) curve * @param cleanOrDirty the clean or dirty price * @param valuationTime the valuation time * @return 10,000 times the RPV01 (on a notional of 1) */ public double Annuity(CDS cds, PiecewiseconstantHazardRate hazard, YieldTermStructure yt, CdsPriceType cleanOrDirt) { List <CashFlow> cf = cds.FixLeg; DateTime tradedate = cds.tradedate; DateTime settlementDate = tradedate.AddDays(cds.Cashsettlement); double recoveryrate = cds.Recovery; DateTime Stepindate = tradedate.AddDays(1); OMLib.Conventions.DayCount.Actual360 dc = new OMLib.Conventions.DayCount.Actual360(); double notional = cds.Notional; double coupon = cds.PremiumRate; DateTime lastpayment = cds.formerpaymentdate; if (cf.Count() == 0) { return(0.0); } double ita = (double)365 / 360; double totalNPV = 0.0; for (int i = 0; i < cf.Count; ++i) { totalNPV += cf[i].Amount * cf[i].DiscountFactor * cf[i].Survivalprobability; } double accrualpaidondefault = calculateSinglePeriodAccrualOnDefault(cds, yt, hazard); totalNPV += ita * coupon * accrualpaidondefault * notional / yt.discount(tradedate.AddDays(3)); Calendar calendar = new UnitedStates(); return(totalNPV / yt.discount(settlementDate)); }
public virtual double[] pvAndSense(PiecewiseconstantHazardRate creditCurve) { double pv = _riskLessValue * Math.Exp(-creditCurve.getRT_(_effEnd)); double pvSense = -pv *creditCurve.getSingleNodeRTSensitivity(_effEnd, _creditCurveKnot); return(new double[] { pv, pvSense }); }
public double apply_(double x, int index, PiecewiseconstantHazardRate creditCurve) { PiecewiseconstantHazardRate cc = creditCurve.withRate(x, index); double rpv01_ = rpv01(cc, CdsPriceType.CLEAN); double pro = protectionLeg(cc); return(pro - _fracSpread * rpv01_ - _pointsUpfront); }
/** * This is the present value of the premium leg per unit coupon, seen at the cash-settlement date. * It is equal to 10,000 times the RPV01 (Risky PV01). The actual PV of the leg is this multiplied by the * notional and the fractional spread (i.e. coupon in basis points divided by 10,000). * * @param cds the analytic description of a CDS traded at a certain time * @param yieldCurve the yield (or discount) curve * @param creditCurve the credit (or survival) curve * @param cleanOrDirty the clean or dirty price * @return 10,000 times the RPV01 (on a notional of 1) * @see #annuity * @see #dirtyAnnuity */ public double annuity( CDS cds, YieldTermStructure yieldCurve, PiecewiseconstantHazardRate creditCurve, CdsPriceType cleanOrDirty) { return(annuity(cds, yieldCurve, creditCurve, cleanOrDirty, cds.getCashSettleTime())); }
/** * Present value (clean price) for the payer of premiums (i.e. the buyer of protection). * * @param cds the analytic description of a CDS traded at a certain time * @param yieldCurve the yield (or discount) curve * @param creditCurve the credit (or survival) curve * @param fractionalSpread the <b>fraction</b> spread * @return the PV */ public double pv( CDS cds, YieldTermStructure yieldCurve, PiecewiseconstantHazardRate creditCurve, double fractionalSpread) { return(pv(cds, yieldCurve, creditCurve, fractionalSpread, CdsPriceType.CLEAN)); }
/** * The sensitivity of a CDS to the recovery rate. Note this is per unit amount, so the change * in PV due to a one percent (say from 40% to 41%) rise is RR will be 0.01 * the returned value. * * @param cds the analytic description of a CDS traded at a certain time * @param yieldCurve the yield (or discount) curve * @param creditCurve the credit (or survival) curve * @return the recovery rate sensitivity (on a unit notional) */ public double recoveryRateSensitivity( CDS cds, YieldTermStructure yieldCurve, PiecewiseconstantHazardRate creditCurve) { CDS zeroRR = cds.withRecoveryRate(0); return(-_pricer.protectionLeg(zeroRR, yieldCurve, creditCurve)); }
private double calculateSinglePeriodAccrualOnDefault( CdsCoupon coupon, double effectiveStart, double[] integrationPoints, YieldTermStructure yieldCurve, PiecewiseconstantHazardRate creditCurve) { double start = Math.Max(coupon.getEffStart(), effectiveStart); if (start >= coupon.getEffEnd()) { return(0.0); //this coupon has already expired } double[] knots = DoublesScheduleGenerator.truncateSetInclusive(start, coupon.getEffEnd(), integrationPoints); double t = knots[0]; double ht0 = creditCurve.getRT_(t); double rt0 = yieldCurve.getRT_(t); double b0 = Math.Exp(-rt0 - ht0); // this is the risky discount factor double t0 = t - coupon.getEffStart() + _omega; double pv = 0.0; int nItems = knots.Length; for (int j = 1; j < nItems; ++j) { t = knots[j]; double ht1 = creditCurve.getRT_(t); double rt1 = yieldCurve.getRT_(t); double b1 = Math.Exp(-rt1 - ht1); double dt = knots[j] - knots[j - 1]; double dht = ht1 - ht0; double drt = rt1 - rt0; double dhrt = dht + drt; double tPV; double t1 = t - coupon.getEffStart() + _omega; if (Math.Abs(dhrt) < 1e-5) { tPV = dht * b0 * (t0 * Maths.Epsilon.epsilon(-dhrt) + dt * Maths.Epsilon.epsilonP(-dhrt)); } else { tPV = dht / dhrt * (t0 * b0 - t1 * b1 + dt / dhrt * (b0 - b1)); } t0 = t1; pv += tPV; ht0 = ht1; rt0 = rt1; b0 = b1; } return(coupon.getYFRatio() * pv); }
/** * Immediately prior to default, the CDS has some value V (to the protection buyer). * After default, the contract cancelled, so there is an immediate loss of -V (or a gain if V was negative). * The protection buyer pays the accrued interest A and receives 1-RR, so the full * Value on Default (VoD) is -V + (1-RR) (where the A has been absorbed as we use the clean price for V). * * @param cds the analytic description of a CDS traded at a certain time * @param yieldCurve the yield (or discount) curve * @param creditCurve the credit (or survival) curve * @param coupon the coupon of the CDS * @return the value on default or jump to default */ public double valueOnDefault( CDS cds, YieldTermStructure yieldCurve, PiecewiseconstantHazardRate creditCurve, double coupon) { double pv = _pricer.pv(cds, yieldCurve, creditCurve, coupon); return(-pv + cds.getLGD()); }
/** * The par spread par spread for a given yield and credit (hazard rate/survival) curve). * * @param cds analytic description of a CDS traded at a certain time * @param yieldCurve the yield (or discount) curve * @param creditCurve the credit (or survival) curve * @return the par spread */ public double parSpread(CDS cds, YieldTermStructure yieldCurve, PiecewiseconstantHazardRate creditCurve) { if (cds.getProtectionEnd() <= 0.0) { //short cut already Expired CDSs } double rpv01 = annuity(cds, yieldCurve, creditCurve, CdsPriceType.CLEAN, 0.0); double proLeg = protectionLeg(cds, yieldCurve, creditCurve, 0.0); return(proLeg / rpv01); }
//*************************************************************************************************************** // bucketed CS01 of a CDS from single market quote of that CDS //*************************************************************************************************************** public double[] bucketedCS01FromSpread( CDS cds, double coupon, YieldTermStructure yieldCurve, double marketSpread, CDS[] buckets) { PiecewiseconstantHazardRate cc = _curveBuilder.calibrateCreditCurve(cds, marketSpread, yieldCurve); return(bucketedCS01FromCreditCurve(cds, coupon, buckets, yieldCurve, cc)); }
public double[][] bucketedCS01( CDS[] cds, double[] cdsCoupons, CDS[] pillarCDSs, CdsQuoteConvention[] marketQuotes, YieldTermStructure yieldCurve) { PiecewiseconstantHazardRate creditCurve = _curveBuilder.calibrateCreditCurve(pillarCDSs, marketQuotes, yieldCurve); return(bucketedCS01FromCreditCurve(cds, cdsCoupons, pillarCDSs, yieldCurve, creditCurve)); }
public double[] bucketedCS01FromParSpreads( CDS cds, double cdsCoupon, YieldTermStructure yieldCurve, CDS[] pillarCDSs, double[] spreads) { PiecewiseconstantHazardRate creditCurve = _curveBuilder.calibrateCreditCurve(pillarCDSs, spreads, yieldCurve); return(bucketedCS01FromCreditCurve(cds, cdsCoupon, pillarCDSs, yieldCurve, creditCurve)); }
/** * Hedge a CDS with other CDSs on the same underlying (single-name or index) at different maturities. * <p> * The hedge is such that the total portfolio (the CDS <b>minus</b> the hedging CDSs, with notionals of the * CDS notional times the computed hedge ratios) is insensitive to infinitesimal changes to the the credit curve. * <p> * If the number of hedge-CDSs equals the number of credit-curve knots, the system is square * and is solved exactly (see below).<br> * If the number of hedge-CDSs is less than the number of credit-curve knots, the system is * solved in a least-square sense (i.e. is hedge is not exact).<br> * If the number of hedge-CDSs is greater than the number of credit-curve knots, the system * cannot be solved. <br> * The system may not solve if the maturities if the hedging CDSs and very different from the * knot times (i.e. the sensitivity matrix is singular). * * @param cds the CDS to be hedged * @param coupon the coupon of the CDS to be hedged * @param hedgeCDSs the CDSs to hedge with - these are also used to build the credit curve * @param hedgeCDSCoupons the coupons of the CDSs to hedge with/build credit curve * @param creditCurve The credit curve * @param yieldCurve the yield curve * @return the hedge ratios, * since we use a unit notional, the ratios should be multiplied by -notional to give the hedge notional amounts */ public double[] getHedgeRatios( CDS cds, double coupon, CDS[] hedgeCDSs, double[] hedgeCDSCoupons, PiecewiseconstantHazardRate creditCurve, YieldTermStructure yieldCurve) { double[] cdsSense = getCurveSensitivities(cds, coupon, creditCurve, yieldCurve); double[,] hedgeSense = getCurveSensitivities(hedgeCDSs, hedgeCDSCoupons, creditCurve, yieldCurve); return(getHedgeRatios(cdsSense, hedgeSense)); }
//------------------------------------------------------------------------- /** * Hedge a CDS with other CDSs on the same underlying (single-name or index) at different maturities. * <p> * The hedge is such that the total portfolio (the CDS <b>minus</b> the hedging CDSs, with notionals of the * CDS notional times the computed hedge ratios) is insensitive to infinitesimal changes to the the credit curve. * <p> * Here the credit curve is built using the hedging CDSs as pillars. * * @param cds the CDS to be hedged * @param coupon the coupon of the CDS to be hedged * @param hedgeCDSs the CDSs to hedge with - these are also used to build the credit curve * @param hedgeCDSCoupons the coupons of the CDSs to hedge with/build credit curve * @param hegdeCDSPUF the PUF of the CDSs to build credit curve * @param yieldCurve the yield curve * @return the hedge ratios, * since we use a unit notional, the ratios should be multiplied by -notional to give the hedge notional amounts */ public double[] getHedgeRatios( CDS cds, double coupon, CDS[] hedgeCDSs, double[] hedgeCDSCoupons, double[] hegdeCDSPUF, YieldTermStructure yieldCurve) { PiecewiseconstantHazardRate cc = _builder.calibrateCreditCurve(hedgeCDSs, hedgeCDSCoupons, yieldCurve, hegdeCDSPUF); return(getHedgeRatios(cds, coupon, hedgeCDSs, hedgeCDSCoupons, cc, yieldCurve)); }
/** * The analytic CS01 (or credit DV01). * * @param cds the analytic description of a CDS traded at a certain time * @param coupon the of the traded CDS (expressed as <b>fractions not basis points</b>) * @param yieldCurve the yield (or discount) curve * @param puf the points up-front (as a fraction) * @return the credit DV01 */ public double parallelCS01FromPUF(CDS cds, double coupon, YieldTermStructure yieldCurve, double puf) { PiecewiseconstantHazardRate cc = _curveBuilder.calibrateCreditCurve(cds, coupon, yieldCurve, puf); double a = _pricer.protectionLeg(cds, yieldCurve, cc); double b = _pricer.annuity(cds, yieldCurve, cc, CdsPriceType.CLEAN); double aPrime = _pricer.protectionLegCreditSensitivity(cds, yieldCurve, cc, 0); double bPrime = _pricer.pvPremiumLegCreditSensitivity(cds, yieldCurve, cc, 0); double s = a / b; double dPVdh = aPrime - coupon * bPrime; double dSdh = (aPrime - s * bPrime) / b; return(dPVdh / dSdh); }
public double parSpreadCreditSensitivity( CDS cds, YieldTermStructure yieldCurve, PiecewiseconstantHazardRate creditCurve, int creditCurveNode) { double a = protectionLeg(cds, yieldCurve, creditCurve); double b = annuity(cds, yieldCurve, creditCurve, CdsPriceType.CLEAN); double spread = a / b; double dadh = protectionLegCreditSensitivity(cds, yieldCurve, creditCurve, creditCurveNode); double dbdh = pvPremiumLegCreditSensitivity(cds, yieldCurve, creditCurve, creditCurveNode); return(spread * (dadh / a - dbdh / b)); }
//------------------------------------------------------------------------- /** * The sensitivity of the PV of a CDS to the zero hazard rates at the knots of the credit curve. * * @param cds the CDS * @param coupon the coupon * @param creditCurve the credit Curve * @param yieldCurve the yield curve * @return vector of sensitivities */ public double[] getCurveSensitivities( CDS cds, double coupon, PiecewiseconstantHazardRate creditCurve, YieldTermStructure yieldCurve) { int n = creditCurve.getNumberOfKnots(); double[] CurveSen = new double[n]; for (int i = 0; i < n; i++) { CurveSen[i] = _pricer.pvCreditSensitivity(cds, yieldCurve, creditCurve, coupon, i); } return(CurveSen); }
private double calculateSinglePeriodAccrualOnDefault(int paymentIndex, PiecewiseconstantHazardRate creditCurve) { double[] knots = _premLegIntPoints[paymentIndex]; if (knots == null) { return(0.0); } double[] df = _premDF[paymentIndex]; double[] deltaT = _premDt[paymentIndex]; double[] rt = _rt[paymentIndex]; double accRate = _accRate[paymentIndex]; double accStart = _offsetAccStart[paymentIndex]; double t = knots[0]; double ht0 = creditCurve.getRT_(t); double rt0 = rt[0]; double b0 = df[0] * Math.Exp(-ht0); double t0 = t - accStart + _omega; double pv = 0.0; int nItems = knots.Length; for (int j = 1; j < nItems; ++j) { t = knots[j]; double ht1 = creditCurve.getRT_(t); double rt1 = rt[j]; double b1 = df[j] * Math.Exp(-ht1); double dt = deltaT[j - 1]; double dht = ht1 - ht0; double drt = rt1 - rt0; double dhrt = dht + drt + 1e-50; // to keep consistent with ISDA c code double tPV; if (Math.Abs(dhrt) < 1e-5) { tPV = dht * dt * b0 * Epsilon.epsilonP(-dhrt); } else { tPV = dht * dt / dhrt * ((b0 - b1) / dhrt - b1); } } return(accRate * pv); }
public double pvPremiumLegCreditSensitivity( CDS cds, YieldTermStructure yieldCurve, PiecewiseconstantHazardRate creditCurve, int creditCurveNode) { if (cds.getProtectionEnd() <= 0.0) { //short cut already expired CDSs return(0.0); } int n = cds.getNumPayments(); double pvSense = 0.0; for (int i = 0; i < n; i++) { CdsCoupon c = cds.getCoupon(i); double paymentTime = c.getPaymentTime(); double creditObsTime = c.getEffEnd(); double dqdh = creditCurve.getSingleNodeDiscountFactorSensitivity(creditObsTime, creditCurveNode); if (dqdh == 0) { continue; } double p = Math.Exp(-yieldCurve.getRT_(paymentTime)); pvSense += c.getYearFrac() * p * dqdh; } if (cds.isPayAccOnDefault()) { double start = cds.getNumPayments() == 1 ? cds.getEffectiveProtectionStart() : cds.getAccStart(); double[] integrationSchedule = DoublesScheduleGenerator.getIntegrationsPoints(start, cds.getProtectionEnd(), yieldCurve, creditCurve); double accPVSense = 0.0; for (int i = 0; i < n; i++) { accPVSense += calculateSinglePeriodAccrualOnDefaultCreditSensitivity( cds.getCoupon(i), cds.getEffectiveProtectionStart(), integrationSchedule, yieldCurve, creditCurve, creditCurveNode); } pvSense += accPVSense; } double df = Math.Exp(-yieldCurve.getRT_(cds.getCashSettleTime())); pvSense /= df; return(pvSense); }
public override double[] pvAndSense(PiecewiseconstantHazardRate creditCurve) { double[] pv = base.pvAndSense(creditCurve); double[] aod = new double[2]; if (_formula == AccrualOnDefaultFormulae.MARKIT_FIX) { aod = accOnDefaultMarkitFix(creditCurve); } else { aod = accOnDefault(creditCurve); } QLNet.Rounding round = new QLNet.Rounding(18); return(new double[] { round.Round(pv[0] + aod[0]), pv[1] + aod[1] }); }
/** * Sensitivity of the present value (for the payer of premiums, i.e. the buyer of protection) to * the zero hazard rate of a given node (knot) of the credit curve. This is per unit of notional. * * @param cds the analytic description of a CDS traded at a certain time * @param yieldCurve the yield (or discount) curve * @param creditCurve the credit (or survival) curve * @param fractionalSpread the <b>fraction</b> spread * @param creditCurveNode the credit curve node * @return PV sensitivity to one node (knot) on the credit (hazard rate/survival) curve */ public double pvCreditSensitivity( CDS cds, YieldTermStructure yieldCurve, PiecewiseconstantHazardRate creditCurve, double fractionalSpread, int creditCurveNode) { if (cds.getProtectionEnd() <= 0.0) { //short cut already expired CDSs return(0.0); } double rpv01Sense = pvPremiumLegCreditSensitivity(cds, yieldCurve, creditCurve, creditCurveNode); double proLegSense = protectionLegCreditSensitivity(cds, yieldCurve, creditCurve, creditCurveNode); return(proLegSense - fractionalSpread * rpv01Sense); }
public double parallelCS01FromCreditCurve( CDS cds, double cdsCoupon, CDS[] bucketCDSs, YieldTermStructure yieldCurve, PiecewiseconstantHazardRate creditCurve) { double[] temp = bucketedCS01FromCreditCurve(cds, cdsCoupon, bucketCDSs, yieldCurve, creditCurve); double sum = 0; foreach (double cs in temp) { sum += cs; } return(sum); }
/** * CDS value for the payer of premiums (i.e. the buyer of protection) at the cash-settle date. * * @param cds the analytic description of a CDS traded at a certain time * @param yieldCurve the yield (or discount) curve * @param creditCurve the credit (or survival) curve * @param fractionalSpread the <b>fraction</b> spread * @param cleanOrDirty the clean or dirty price * @return the value of a unit notional payer CDS on the cash-settle date */ public double pv( CDS cds, YieldTermStructure yieldCurve, PiecewiseconstantHazardRate creditCurve, double fractionalSpread, CdsPriceType cleanOrDirty) { if (cds.getProtectionEnd() <= 0.0) { //short cut already Expired CDSs return(0.0); } // TODO check for any repeat calculations double rpv01 = annuity(cds, yieldCurve, creditCurve, cleanOrDirty); double proLeg = protectionLeg(cds, yieldCurve, creditCurve); return(proLeg - fractionalSpread * rpv01); }
/** * CDS value for the payer of premiums (i.e. the buyer of protection) at the specified valuation time. * * @param cds analytic description of a CDS traded at a certain time * @param yieldCurve the yield (or discount) curve * @param creditCurve the credit (or survival) curve * @param fractionalSpread the <b>fraction</b> spread * @param cleanOrDirty the clean or dirty price * @param valuationTime the valuation time, if time is zero, leg is valued today, * value often quoted for cash-settlement date * @return the value of a unit notional payer CDS at the specified valuation time */ public double pv( CDS cds, YieldTermStructure yieldCurve, PiecewiseconstantHazardRate creditCurve, double fractionalSpread, CdsPriceType cleanOrDirty, double valuationTime) { if (cds.getProtectionEnd() <= 0.0) { //short cut already Expired CDSs return(0.0); } double rpv01 = annuity(cds, yieldCurve, creditCurve, cleanOrDirty, 0.0); double proLeg = protectionLeg(cds, yieldCurve, creditCurve, 0.0); double df = Math.Exp(-yieldCurve.getRT_(valuationTime)); return((proLeg - fractionalSpread * rpv01) / df); }
/** * The sensitivity of a set of CDSs to the zero hazard rates at the knots of the credit curve. * The element (i,j) is the sensitivity of the PV of the jth CDS to the ith knot. * * @param cds the set of CDSs * @param coupons the coupons of the CDSs * @param creditCurve the credit Curve * @param yieldCurve the yield curve * @return matrix of sensitivities */ public double[,] getCurveSensitivities( CDS[] cds, double[] coupons, PiecewiseconstantHazardRate creditCurve, YieldTermStructure yieldCurve) { int nCDS = cds.Length; int nKnots = creditCurve.getNumberOfKnots(); double[,] sense = new double[nKnots, nCDS]; for (int i = 0; i < nCDS; i++) { for (int j = 0; j < nKnots; j++) { sense[j, i] = _pricer.pvCreditSensitivity(cds[i], yieldCurve, creditCurve, coupons[i], j); } } return(sense); }
public override PiecewiseconstantHazardRate calibrateCreditCurve( CDS[] cds, double[] premiums, YieldTermStructure yieldCurve, double[] pointsUpfront) { int n = cds.Length; double proStart = cds[0].getEffectiveProtectionStart(); // use continuous premiums as initial guess double[] guess = new double[n]; double[] t = new double[n]; for (int i = 0; i < n; i++) { t[i] = cds[i].getProtectionEnd(); guess[i] = (premiums[i] + pointsUpfront[i] / t[i]) / cds[i].getLGD(); } PiecewiseconstantHazardRate hazard = new PiecewiseconstantHazardRate(yieldCurve.latestReference_, null, null, null, null); PiecewiseconstantHazardRate creditCurve = hazard.makeFromRT(t.ToList(), guess); for (int i = 0; i < n; i++) { Pricer pricer = new Pricer(cds[i], yieldCurve, t, premiums[i], pointsUpfront[i]); Func <double, double> func = pricer.getPointFunction(i, creditCurve); double minValue = i == 0 ? 0.0 : creditCurve.getRTAtIndex(i - 1) / creditCurve.getTimeAtIndex(i); if (i > 0 && func(minValue) > 0.0) { //can never fail on the first spread creditCurve = creditCurve.withRate(minValue, i); } else { guess[i] = Math.Max(minValue, guess[i]); double[] bracket = BRACKER.getBracketedPoints(func, guess[i], 1.2 * guess[i], minValue, double.PositiveInfinity); double zeroRate = ROOTFINDER.getRoot(func, bracket[0], bracket[1]); creditCurve = creditCurve.withRate(zeroRate, i); } break; } return(creditCurve); }