public YieldTermStructure fitSwap(int curveIndex, BasicFixedLeg swap, YieldTermStructure curve, double swapRate) { int nPayments = swap._nPayments; int nNodes = curve.nJumps_; double t1 = curveIndex == 0 ? 0.0 : curve.t[curveIndex - 1]; double t2 = curveIndex == nNodes - 1 ? double.PositiveInfinity : curve.t[curveIndex + 1]; double temp = 0; double temp2 = 0; int i1 = 0; int i2 = nPayments; double[] paymentAmounts = new double[nPayments]; for (int i = 0; i < nPayments; i++) { double t = swap.getPaymentTime(i); paymentAmounts[i] = swap.getPaymentAmounts(i, swapRate); if (t <= t1) { double df = Math.Exp(-curve.getRT_(t)); temp += paymentAmounts[i] * df; temp2 -= paymentAmounts[i] * curve.getSingleNodeDiscountFactorSensitivity(t, curveIndex); i1++; } else if (t >= t2) { double df = Math.Exp(-curve.getRT_(t)); temp += paymentAmounts[i] * df; temp2 += paymentAmounts[i] * curve.getSingleNodeDiscountFactorSensitivity(t, curveIndex); i2--; } } double cachedValues = temp; double cachedSense = temp2; int index1 = i1; int index2 = i2; BracketRoot BRACKETER = new BracketRoot(); NewtonRaphsonSingleRootFinder ROOTFINDER = new NewtonRaphsonSingleRootFinder(); Func <double, double> func = x => apply_(x, curve, curveIndex, cachedValues, index1, index2, swap, paymentAmounts); Func <double, double> grad = x => apply_sen(x, curve, curveIndex, cachedSense, index1, index2, swap, swapRate); double guess = curve.getZeroRateAtIndex(curveIndex); if (guess == 0.0 && func(guess) == 0.0) { return(curve); } double[] bracket = BRACKETER.getBracketedPoints(func, 0.8 * guess, 1.25 * guess, 0, double.PositiveInfinity); double r = ROOTFINDER.getRoot(func, grad, bracket[0], bracket[1]); return(curve.withRate(r, curveIndex)); }
public double apply_(double x, YieldTermStructure curve, int curveIndex, double cachedValues, int index1, int index2, BasicFixedLeg swap, double[] paymentAmounts) { YieldTermStructure tempCurve = curve.withRate(x, curveIndex); double sum = 1.0 - cachedValues; // Floating leg at par for (int i = index1; i < index2; i++) { double t = swap.getPaymentTime(i); sum -= paymentAmounts[i] * Math.Exp(-tempCurve.getRT_(t)); } return(sum); }
public double apply_sen(double x, YieldTermStructure curve, int curveIndex, double cachedSense, int index1, int index2, BasicFixedLeg swap, double swapRate) { YieldTermStructure tempCurve = curve.withRate(x, curveIndex); double sum = cachedSense; for (int i = index1; i < index2; i++) { double t = swap.getPaymentTime(i); // TODO have two looks ups for the same time - could have a specialist function in ISDACompliantCurve sum -= swap.getPaymentAmounts(i, swapRate) * tempCurve.getSingleNodeDiscountFactorSensitivity(t, curveIndex); } return(sum); }
/** * 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); }