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 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)); }
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()))); }
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); }
/** * 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); }
/** * 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); }
public double calculateSinglePeriodAccrualOnDefault(CdsCoupon[] cf, double coupon, DateTime tradedate, YieldTermStructure yieldCurve, PiecewiseconstantHazardRate creditCurve, DateTime lastpayment) { double Acc = 0; DateTime effectiveStart = tradedate.AddDays(1); for (int i = 0; i < cf.Length; ++i) { //Accured on default double t_0 = (i > 0) ? cf[i].getEffStart() : 0; double T = cf[i].getEffEnd(); T = cf[i].getPaymentTime(); List <double> knots = new List <double>(); knots.Add(t_0); for (int j = 0; j < yieldCurve.t.Count; j++) { if ((yieldCurve.t[j] < T) && (t_0 < yieldCurve.t[j])) { knots.Add(yieldCurve.t[j]); } } knots.Add(T); 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 OMLib.Conventions.DayCount.Actual365 dc = new OMLib.Conventions.DayCount.Actual365(); double t0; if (i == 0) { t0 = knots[0] - cf[0].getEffStart(); } else { t0 = knots[0] - cf[i].getEffStart(); } double pv = 0.0; int nItems = knots.Count; 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 + 1e-50; double tPV; double t1; if (i == 0) { t1 = knots[j] - cf[0].getEffStart(); } else { t1 = knots[j] - cf[i].getEffStart(); } if (Math.Abs(dhrt) < 1e-5) { tPV = dht * b0 * (t0 * (Math.Exp(-dhrt) - 1) / (-dhrt) + dt * ((-dhrt - 1) * (Math.Exp(-dhrt) - 1) - dhrt) / (dhrt * dhrt)); } else { tPV = dht * dt / dhrt * ((b0 - b1) / dhrt - b1); } t0 = t1; pv += tPV; ht0 = ht1; rt0 = rt1; b0 = b1; } Acc += pv; } return(Acc); }