private double fdCentral( CdsAnalytic pricingCDS, double cdsSpread, CdsAnalytic[] curvePoints, double[] spreads, double[] deltaSpreads, IsdaCompliantYieldCurve yieldCurve, CdsPriceType priceType) { int n = curvePoints.length; double[] spreadUp = new double[n]; double[] spreadDown = new double[n]; for (int i = 0; i < n; i++) { spreadUp[i] = spreads[i] + deltaSpreads[i]; spreadDown[i] = spreads[i] - deltaSpreads[i]; } IsdaCompliantCreditCurve curveUp = _curveBuilder.calibrateCreditCurve(curvePoints, spreadUp, yieldCurve); IsdaCompliantCreditCurve curveDown = _curveBuilder.calibrateCreditCurve(curvePoints, spreadDown, yieldCurve); double up = _pricer.pv(pricingCDS, yieldCurve, curveUp, cdsSpread, priceType); double down = _pricer.pv(pricingCDS, yieldCurve, curveDown, cdsSpread, priceType); return up - down; }
/** * The bucked CS01 (or credit DV01) by shifting each market par-spread in turn. This takes an * extraneous yield curve, a set of reference CDSs (marketCDSs) and their par-spreads (expressed * as <b>fractions not basis points</b>) and bootstraps a credit (hazard) curve - the target CDS * is then priced with this credit curve. This is then repeated with each market spreads bumped in * turn. The result is the vector of differences (bumped minus base price) divided by the bump * amount.<br> * For small bumps (<1e-4) this approximates $$\frac{\partial V}{\partial S_i}$$ where $$S_i$$ is * the spread of the $$1^{th}$$ market CDS<br> * * @param cds analytic description of a CDS traded at a certain time * @param cdsCoupon The <b>fraction</b> spread of the CDS * @param yieldCurve The yield (or discount) curve * @param marketCDSs The market CDSs - these are the reference instruments used to build the * credit curve * @param marketParSpreads The <b>fractional</b> par-spreads of the market CDSs * @param fracBumpAmount The fraction bump amount, so a 1pb bump is 1e-4 * @param shiftType ABSOLUTE or RELATIVE * @return The credit CS01 */ public double[] bucketedCS01FromParSpreads( CdsAnalytic cds, double cdsCoupon, IsdaCompliantYieldCurve yieldCurve, CdsAnalytic[] marketCDSs, double[] marketParSpreads, double fracBumpAmount, ShiftType shiftType) { ArgChecker.notNull(cds, "cds"); ArgChecker.noNulls(marketCDSs, "curvePoints"); ArgChecker.notEmpty(marketParSpreads, "spreads"); ArgChecker.notNull(yieldCurve, "yieldCurve"); ArgChecker.notNull(shiftType, "shiftType"); ArgChecker.isTrue(Math.abs(fracBumpAmount) > 1e-10, "bump amount too small"); int n = marketCDSs.length; ArgChecker.isTrue(n == marketParSpreads.length, "speads length does not match curvePoints"); CdsPriceType priceType = CdsPriceType.DIRTY; IsdaCompliantCreditCurve baseCurve = _curveBuilder.calibrateCreditCurve(marketCDSs, marketParSpreads, yieldCurve); double basePrice = _pricer.pv(cds, yieldCurve, baseCurve, cdsCoupon, priceType); double[] res = new double[n]; for (int i = 0; i < n; i++) { double[] temp = makeBumpedSpreads(marketParSpreads, fracBumpAmount, shiftType, i); IsdaCompliantCreditCurve bumpedCurve = _curveBuilder.calibrateCreditCurve(marketCDSs, temp, yieldCurve); double price = _pricer.pv(cds, yieldCurve, bumpedCurve, cdsCoupon, priceType); res[i] = (price - basePrice) / fracBumpAmount; } return res; }
/** * The bucked CS01 (or credit DV01) by a shift of each the market spread in turn. This takes an * extraneous yield curve, a set of reference CDSs (marketCDSs) and their market quotes and * bootstraps a credit (hazard) curve - the target CDS is then priced with this credit curve. This * is then repeated with each market spreads bumped in turn by some amount. The result is the * array of differences (bumped minus base price) is divided by the bump amount.<br> * This can take quotes as ParSpread, PointsUpFront or QuotedSpread (or some mix). For * par-spreads, these are bumped and a new credit curve built; for quoted-spreads, there are * bumped and a new curve build be first converting to PUF; and finally for PUF, these are * converted to quoted spreads, bumped and converted back to build the credit curve. * * @param cds analytic description of a CDS traded at a certain time - it is this CDS that we are * calculation CDV01 for * @param cdsCoupon the coupon of the traded CDS (expressed as <b>fractions not basis points</b>) * @param yieldCurve The yield (or discount) curve * @param marketCDSs The market CDSs - these are the reference instruments used to build the * credit curve * @param quotes The quotes for the market CDSs - these can be ParSpread, PointsUpFront or * QuotedSpread (or any mixture of these) * @param fracBumpAmount The fraction bump amount, so a 1pb bump is 1e-4 * @return The bucketed credit DV01 */ public double[] bucketedCS01FromPillarQuotes( CdsAnalytic cds, double cdsCoupon, IsdaCompliantYieldCurve yieldCurve, CdsAnalytic[] marketCDSs, CdsQuoteConvention[] quotes, double fracBumpAmount) { ArgChecker.notNull(cds, "cds"); ArgChecker.noNulls(marketCDSs, "curvePoints"); ArgChecker.noNulls(quotes, "quotes"); ArgChecker.notNull(yieldCurve, "yieldCurve"); ArgChecker.isTrue(Math.abs(fracBumpAmount) > 1e-10, "bump amount too small"); int n = marketCDSs.length; ArgChecker.isTrue(n == quotes.length, "speads length does not match curvePoints"); IsdaCompliantCreditCurve baseCurve = _curveBuilder.calibrateCreditCurve(marketCDSs, quotes, yieldCurve); double basePrice = _pricer.pv(cds, yieldCurve, baseCurve, cdsCoupon); double[] res = new double[n]; for (int i = 0; i < n; i++) { CdsQuoteConvention[] bumpedQuotes = bumpQuoteAtIndex(marketCDSs, quotes, yieldCurve, fracBumpAmount, i); IsdaCompliantCreditCurve bumpedCurve = _curveBuilder.calibrateCreditCurve(marketCDSs, bumpedQuotes, yieldCurve); double price = _pricer.pv(cds, yieldCurve, bumpedCurve, cdsCoupon); res[i] = (price - basePrice) / fracBumpAmount; } return res; }
/** * The bucked CS01 (or credit DV01) on a set of CDSS by bumping each quoted (or flat) spread in * turn. This takes an extraneous yield curve, a set of reference CDSs (marketCDSs) and their * quoted (or flat) spreads (expressed as <b>fractions not basis points</b>) and bootstraps a * credit (hazard) curve - the target CDS is then priced with this credit curve. This is then * repeated with each market spreads bumped in turn. The result is the vector of differences * (bumped minus base price) divided by the bump amount.<br> * For small bumps (<1e-4) this approximates $$\frac{\partial V}{\partial S_i}$$ for a flat curve * where $$S_i$$ * * @param cds a set of analytic description of CDSs traded at a certain times * @param dealSpread The <b>fraction</b> spread of the CDS * @param yieldCurve The yield (or discount) curve * @param marketCDSs The market CDSs - these are the reference instruments used to build the * credit curve * @param quotedSpreads The <b>fractional</b> spreads of the market CDSs * @param fracBumpAmount The fraction bump amount, so a 1pb bump is 1e-4 * @param shiftType ABSOLUTE or RELATIVE * @return The bucked CS01 for a set of CDSs */ public double[][] bucketedCS01FromQuotedSpreads( CdsAnalytic[] cds, double dealSpread, IsdaCompliantYieldCurve yieldCurve, CdsAnalytic[] marketCDSs, double[] quotedSpreads, double fracBumpAmount, ShiftType shiftType) { ArgChecker.noNulls(cds, "cds"); ArgChecker.noNulls(marketCDSs, "curvePoints"); ArgChecker.notEmpty(quotedSpreads, "spreads"); ArgChecker.notNull(yieldCurve, "yieldCurve"); ArgChecker.notNull(shiftType, "shiftType"); ArgChecker.isTrue(Math.abs(fracBumpAmount) > 1e-10, "bump amount too small"); int nMarketCDSs = marketCDSs.length; ArgChecker.isTrue( nMarketCDSs == quotedSpreads.length, "speads length does not match curvePoints"); CdsPriceType priceType = CdsPriceType.DIRTY; double[] premiums = new double[nMarketCDSs]; Arrays.fill(premiums, dealSpread); // assume the premiums of all CDS are equal int nTradeCDSs = cds.length; double[] puf = _pufConverter.quotedSpreadsToPUF(marketCDSs, premiums, yieldCurve, quotedSpreads); // TODO not needed IsdaCompliantCreditCurve baseCurve = _curveBuilder.calibrateCreditCurve(marketCDSs, premiums, yieldCurve, puf); double[] basePrices = new double[nTradeCDSs]; for (int j = 0; j < nTradeCDSs; j++) { basePrices[j] = _pricer.pv(cds[j], yieldCurve, baseCurve, dealSpread, priceType); } double[] bumpedPUF = new double[nMarketCDSs]; double[][] res = new double[nTradeCDSs][nMarketCDSs]; for (int i = 0; i < nMarketCDSs; i++) { // Outer loop is over bumps System.arraycopy(puf, 0, bumpedPUF, 0, nMarketCDSs); double bumpedSpread = bumpedSpread(quotedSpreads[i], fracBumpAmount, shiftType); bumpedPUF[i] = _pufConverter.quotedSpreadToPUF(marketCDSs[i], premiums[i], yieldCurve, bumpedSpread); // TODO a lot of unnecessary recalibration here IsdaCompliantCreditCurve bumpedCurve = _curveBuilder.calibrateCreditCurve(marketCDSs, premiums, yieldCurve, bumpedPUF); for (int j = 0; j < nTradeCDSs; j++) { double price = _pricer.pv(cds[j], yieldCurve, bumpedCurve, dealSpread, priceType); res[j][i] = (price - basePrices[j]) / fracBumpAmount; } } return res; }
private double fdCreditDV01( CdsAnalytic pricingCDS, double cdsSpread, CdsAnalytic[] curvePoints, double[] spreadsUp, double[] spreadsDown, IsdaCompliantYieldCurve yieldCurve, CdsPriceType priceType) { IsdaCompliantCreditCurve curveUp = _curveBuilder.calibrateCreditCurve(curvePoints, spreadsUp, yieldCurve); IsdaCompliantCreditCurve curveDown = _curveBuilder.calibrateCreditCurve(curvePoints, spreadsDown, yieldCurve); double up = _pricer.pv(pricingCDS, yieldCurve, curveUp, cdsSpread, priceType); double down = _pricer.pv(pricingCDS, yieldCurve, curveDown, cdsSpread, priceType); return up - down; }
/** * The bucked CS01 (or credit DV01) by shifting each implied par-spread in turn. This takes an * extraneous yield curve and a credit curve and a set of bucket CDSs (CDSs with maturities equal * to the bucket points). Par-spreads at the bucket maturities are implied from the credit curve. * These spreads form pseudo market spreads to bootstraps a new credit (hazard) curve - the target * CDS is then priced with this credit curve. This is then repeated with each spreads bumped in * turn. The result is the vector of differences (bumped minus base price) divided by the bump * amount. * * @param cds analytic description of a CDS traded at a certain time * @param cdsCoupon The <b>fraction</b> spread of the CDS * @param bucketCDSs these are the reference instruments that correspond to maturity buckets * @param yieldCurve The yield (or discount) curve * @param creditCurve the credit curve * @param fracBumpAmount The fraction bump amount, so a 1pb bump is 1e-4 * @return The credit DV01 */ public double[] bucketedCS01FromCreditCurve( CdsAnalytic cds, double cdsCoupon, CdsAnalytic[] bucketCDSs, IsdaCompliantYieldCurve yieldCurve, IsdaCompliantCreditCurve creditCurve, double fracBumpAmount) { ArgChecker.notNull(cds, "cds"); ArgChecker.noNulls(bucketCDSs, "bucketCDSs"); ArgChecker.notNull(creditCurve, "creditCurve"); ArgChecker.notNull(yieldCurve, "yieldCurve"); ArgChecker.isTrue(Math.abs(fracBumpAmount) > 1e-10, "bump amount too small"); int n = bucketCDSs.length; double[] impSpreads = new double[n]; double[] t = new double[n]; for (int i = 0; i < n; i++) { impSpreads[i] = _pricer.parSpread(bucketCDSs[i], yieldCurve, creditCurve); t[i] = bucketCDSs[i].getProtectionEnd(); if (i > 0) { ArgChecker.isTrue(t[i] > t[i - 1], "buckets must be assending"); } } int index = Arrays.binarySearch(t, cds.getProtectionEnd()); if (index < 0) { index = -1 - index; } index = Math.min(index, n - 1); IsdaCompliantCreditCurve baseCurve = _curveBuilder.calibrateCreditCurve(bucketCDSs, impSpreads, yieldCurve); double basePrice = _pricer.pv(cds, yieldCurve, baseCurve, cdsCoupon); double[] res = new double[n]; for (int i = 0; i <= index; i++) { // don't bother calculating where there is no sensitivity double[] bumpedSpreads = makeBumpedSpreads(impSpreads, fracBumpAmount, ShiftType.ABSOLUTE, i); IsdaCompliantCreditCurve bumpedCurve = _curveBuilder.calibrateCreditCurve(bucketCDSs, bumpedSpreads, yieldCurve); double price = _pricer.pv(cds, yieldCurve, bumpedCurve, cdsCoupon); res[i] = (price - basePrice) / fracBumpAmount; } return res; }
/** * The CS01 (or credit DV01) by a shift of the quoted (or flat) spread of the CDS <b>when the CDS * is quoted as points up-front (PUF)</b>.<br> * This simply converts the PUF quote to a quoted (or flat) spread then calls * parallelCS01FromQuotedSpread * * @param cds analytic description of a CDS traded at a certain time - it is this CDS that we are * calculation CDV01 for * @param coupon the of the traded CDS (expressed as <b>fractions not basis points</b>) * @param yieldCurve The yield (or discount) curve * @param puf points up-front (as a fraction) * @param fracBumpAmount The fraction bump amount <b>of the quoted (or flat) spread</b>, so a 1pb * bump is 1e-4 * @return The credit DV01 */ public double parallelCS01FromPUF( CdsAnalytic cds, double coupon, IsdaCompliantYieldCurve yieldCurve, double puf, double fracBumpAmount) { double bumpedQSpread = _pufConverter.pufToQuotedSpread(cds, coupon, yieldCurve, puf) + fracBumpAmount; IsdaCompliantCreditCurve bumpedCurve = _curveBuilder.calibrateCreditCurve(cds, bumpedQSpread, yieldCurve); double bumpedPrice = _pricer.pv(cds, yieldCurve, bumpedCurve, coupon); return (bumpedPrice - puf) / fracBumpAmount; }
public double parallelCS01FromCreditCurve( CdsAnalytic cds, double cdsCoupon, CdsAnalytic[] pillarCDSs, IsdaCompliantYieldCurve yieldCurve, IsdaCompliantCreditCurve creditCurve, double fracBumpAmount) { ArgChecker.notNull(cds, "cds"); ArgChecker.noNulls(pillarCDSs, "pillarCDSs"); ArgChecker.notNull(creditCurve, "creditCurve"); ArgChecker.notNull(yieldCurve, "yieldCurve"); ArgChecker.isTrue(Math.abs(fracBumpAmount) > 1e-10, "bump amount too small"); int n = pillarCDSs.length; double[] impSpreads = new double[n]; double[] t = new double[n]; for (int i = 0; i < n; i++) { impSpreads[i] = _pricer.parSpread(pillarCDSs[i], yieldCurve, creditCurve); t[i] = pillarCDSs[i].getProtectionEnd(); if (i > 0) { ArgChecker.isTrue(t[i] > t[i - 1], "pillars must be assending"); } } IsdaCompliantCreditCurve baseCurve = _curveBuilder.calibrateCreditCurve(pillarCDSs, impSpreads, yieldCurve); double basePrice = _pricer.pv(cds, yieldCurve, baseCurve, cdsCoupon); double[] bumpedSpreads = makeBumpedSpreads(impSpreads, fracBumpAmount, ShiftType.ABSOLUTE); IsdaCompliantCreditCurve bumpedCurve = _curveBuilder.calibrateCreditCurve(pillarCDSs, bumpedSpreads, yieldCurve); double price = _pricer.pv(cds, yieldCurve, bumpedCurve, cdsCoupon); double res = (price - basePrice) / fracBumpAmount; return res; }