public PiecewiseconstantHazardRate makeFromRT(List <double> t, double[] ht) { List <DateTime> jumpdate = jumpDates_; PiecewiseconstantHazardRate curve = new PiecewiseconstantHazardRate(latestReference_, null, jumpDates_, t, ht.ToList()); return(curve); }
public double ProtectionLegNPV_Exact(List <CashFlow> cf, double notional, PiecewiseconstantHazardRate hazard, YieldTermStructure yt, DateTime tradedate, DateTime settlementDate, double recoveryrate, List <DateTime> Jumps, List <DateTime> creditCurveKnot) { DateTime Stepindate = tradedate.AddDays(1); OMLib.Conventions.DayCount.Actual360 dc = new OMLib.Conventions.DayCount.Actual360(); if (cf.Count() == 0) { return(0.0); } DateTime t0 = tradedate; DateTime T = cf.Last().CashFlowDate; List <DateTime> JumpNodes = new List <DateTime>(); JumpNodes.Add(t0); for (int j = 0; j < Jumps.Count; j++) { if ((DateTime.Compare(Jumps[j], T) < 0)) { 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)); }
/** * The normalised expected default settlement value paid on the exercise settlement * date <b>when no defaults have yet occurred</b>. * The actual default settlement is this multiplied by the (initial) * index notional. This calculation assumes an homogeneous pool that can be described by a single index curve. * * @param timeToExpiry Time to expiry * @param indexCurve Pseudo credit curve for the index. * @param lgd The index Loss Given Default (LGD) * @return The normalised expected default settlement value */ public double expectedDefaultSettlementValue( double timeToExpiry, PiecewiseconstantHazardRate indexCurve, double lgd) { double q = Math.Exp(-indexCurve.getRT_(timeToExpiry)); double d = lgd * (1 - q); return(d); }
/** * 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)); }
private PiecewiseconstantHazardRate[] adjustCurves(PiecewiseconstantHazardRate[] creditCurve, double amount) { int nCurves = creditCurve.Length; PiecewiseconstantHazardRate[] adjCurves = new PiecewiseconstantHazardRate[nCurves]; for (int jj = 0; jj < nCurves; jj++) { adjCurves[jj] = adjustCreditCurve(creditCurve[jj], amount); } return(adjCurves); }
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 (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); }
public PiecewiseconstantHazardRate makeFromR(List <double> t, double[] h) { List <DateTime> jumpdate = jumpDates_; List <double> rt_ = new List <double>(); for (int i = 0; i < t.Count; i++) { rt_.Add(h[i] * t[i]); // We make no check that rt is ascending (i.e. we allow negative forward rates) } PiecewiseconstantHazardRate curve = new PiecewiseconstantHazardRate(latestReference_, null, jumpDates_, t, rt_); return(curve); }
/** * The normalised expected default settlement value paid on the exercise settlement date. * The actual default settlement is this multiplied by the (initial) * index notional. This calculation assumes an homogeneous pool that can be described by a single index curve. * @param initialIndexSize Initial index size * @param timeToExpiry Time to expiry * @param indexCurve Pseudo credit curve for the index. * @param lgd The index Loss Given Default (LGD) * @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 expectedDefaultSettlementValue( int initialIndexSize, double timeToExpiry, PiecewiseconstantHazardRate indexCurve, double lgd, double initialDefaultSettlement, int numDefaults) { double defFrac = numDefaults / ((double)initialIndexSize); // this upper range is if all current defaults have zero recovery double q = Math.Exp(-indexCurve.getRT_(timeToExpiry)); double d = (1 - defFrac) * lgd * (1 - q) + initialDefaultSettlement; return(d); }
public void Pricing(YieldTermStructure yt, PiecewiseconstantHazardRate hazard) { //Calculate PV for both legs CashFlowCalculation engine = new CashFlowCalculation(); this.FixLeg = engine.Calculation(this.PremiumRate, this.Notional, this.Payment_Schedule, this.tradedate, yt, hazard, this.Cashsettlement, formerpaymentdate); NPV_PricingEngine engine2 = new NPV_PricingEngine(); double pv_premium = engine2.PremiumLegNPV_Exact(this.FixLeg, this.piecewiseHazardRate, this.yieldcurve, this.tradedate, this.tradedate.AddDays(3), this.Notional, this.PremiumRate, yt.jumpDates_, formerpaymentdate); double pv_protection = engine2.ProtectionLegNPV_Exact(this, this.Notional, this.piecewiseHazardRate, this.yieldcurve, this.tradedate, this.tradedate.AddDays(3), this.Recovery, yt.t, hazard.t); this.pv = pv_protection - pv_premium; this.marketvalue = this.pv + accruedamt; }
public PiecewiseconstantHazardRate adjustCreditCurve( PiecewiseconstantHazardRate creditCurve, double amount, int firstKnot, int lastKnot) { double[] rt = creditCurve.rt.ToArray(); double[] rtAdj = rt; for (int i = firstKnot; i < lastKnot; i++) { rtAdj[i] = rt[i] * amount; } PiecewiseconstantHazardRate hazard = new PiecewiseconstantHazardRate(creditCurve.latestReference_, null, null, null, null); return(hazard.makeFromRT(creditCurve.t, rtAdj)); }
/** * 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 PiecewiseconstantHazardRate adjustCreditCurve(PiecewiseconstantHazardRate creditCurve, double amount) { if (creditCurve == null) { return(creditCurve); } int nKnots = creditCurve.t.Count; double[] rt = creditCurve.rt.ToArray(); double[] rtAdj = new double[nKnots]; for (int i = 0; i < nKnots; i++) { rtAdj[i] = rt[i] * amount; } PiecewiseconstantHazardRate hazard = new PiecewiseconstantHazardRate(creditCurve.latestReference_, null, null, null, null); return(hazard.makeFromRT(creditCurve.t, rtAdj)); }
public void curve_output(YieldTermStructure yt, PiecewiseconstantHazardRate ct) { double it = ct.SurvivalProb(new DateTime(2021, 06, 20)); List <double> yield = new List <double>(); for (int j = 1; j < 120; j++) { DateTime t = this.evalDate.AddMonths(j); double t_ = (double)j / 12; yield.Add(-Math.Log(yt.discount(t)) / t_); } this.yield_series = yield; List <double> survival = new List <double>(); for (int j = 1; j < 120; j++) { DateTime t = this.tradedate.AddMonths(j); survival.Add(ct.SurvivalProb(t)); } this.survival_prob = survival; }
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 PiecewiseconstantHazardRate[] adjustCurves( PiecewiseconstantHazardRate[] creditCurve, double amount, int[] firstKnots, int[] lastknots) { int nCurves = creditCurve.Length; PiecewiseconstantHazardRate[] adjCurves = new PiecewiseconstantHazardRate[nCurves]; for (int jj = 0; jj < nCurves; jj++) { if (creditCurve[jj] == null) { adjCurves[jj] = null; } else { adjCurves[jj] = adjustCreditCurve(creditCurve[jj], amount, firstKnots[jj], lastknots[jj]); } } return(adjCurves); }
public double PremiumLegNPV_Exact(List <CashFlow> cf, PiecewiseconstantHazardRate hazard, YieldTermStructure yt, DateTime tradedate, DateTime settlementDate, double notional, double coupon, List <DateTime> Jumps, DateTime lastpayment) { 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(cf, coupon, tradedate, yt, hazard, Jumps, 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 / yt.discount(settlementDate)); }
public double PremiumLegNPV_Approx(List <CashFlow> cf, PiecewiseconstantHazardRate HazardTermStructure, YieldTermStructure yt, DateTime tradedate, DateTime settlementDate) { if (cf.Count() == 0) { return(0.0); } double totalNPV = 0.0; for (int i = 0; i < cf.Count; ++i) { if (i == 0) { totalNPV += cf[i].Amount * cf[i].DiscountFactor * 1 / 2 * (1 + cf[i].Survivalprobability); } else { totalNPV += cf[i].Amount * 1 / 2 * (cf[i].Survivalprobability + cf[i - 1].Survivalprobability) * cf[i].DiscountFactor; } } return(totalNPV); }
public IntrinsicIndexDataBundle adjustCurves( double[] indexPUF, CDS[] indexCDS, double indexCoupon, YieldTermStructure yieldCurve, IntrinsicIndexDataBundle intrinsicData) { int nIndexTerms = indexCDS.Length; if (nIndexTerms == 1) { return(adjustCurves(indexPUF[0], indexCDS[0], indexCoupon, yieldCurve, intrinsicData)); } double[] indexKnots = new double[nIndexTerms]; for (int i = 0; i < nIndexTerms; i++) { indexKnots[i] = indexCDS[i].getProtectionEnd(); } PiecewiseconstantHazardRate[] creditCurves = intrinsicData.getCreditCurves(); int nCurves = creditCurves.Length; //we cannot assume that all the credit curves have knots at the same times or that the terms of the indices fall on these knots. PiecewiseconstantHazardRate[] modCreditCurves = new PiecewiseconstantHazardRate[nCurves]; int[,] indexMap = new int[nCurves, nIndexTerms]; for (int i = 0; i < nCurves; i++) { if (creditCurves[i] == null) { modCreditCurves[i] = null; //null credit curves correspond to defaulted names, so are ignored } else { double[] ccKnots = creditCurves[i].t.ToArray(); double[] comKnots = DoublesScheduleGenerator.combineSets(ccKnots, indexKnots); int nKnots = comKnots.Length; if (nKnots == ccKnots.Length) { modCreditCurves[i] = creditCurves[i]; } else { double[] rt = new double[nKnots]; for (int j = 0; j < nKnots; j++) { rt[j] = creditCurves[i].getRT_(comKnots[j]); } PiecewiseconstantHazardRate hazard = new PiecewiseconstantHazardRate(creditCurves[i].latestReference_, null, null, null, null); modCreditCurves[i] = hazard.makeFromRT(comKnots.ToList(), rt); } for (int j = 0; j < nIndexTerms; j++) { int index = Array.BinarySearch(modCreditCurves[i].t.ToArray(), indexKnots[j]); indexMap[i, j] = index; } } } int[] startKnots = new int[nCurves]; int[] endKnots = new int[nCurves]; double alpha = 1.0; for (int i = 0; i < nIndexTerms; i++) { if (i == (nIndexTerms - 1)) { for (int jj = 0; jj < nCurves; jj++) { if (modCreditCurves[jj] != null) { endKnots[jj] = modCreditCurves[jj].t.Count; } } } else { for (int jj = 0; jj < nCurves; jj++) { if (modCreditCurves[jj] != null) { endKnots[jj] = indexMap[jj, i] + 1; } } } IntrinsicIndexDataBundle modIntrinsicData = intrinsicData.withCreditCurves(modCreditCurves); Func <double, double> func = getHazardRateAdjFunction(indexPUF[i], indexCDS[i], indexCoupon, yieldCurve, modIntrinsicData, startKnots, endKnots); alpha = ROOTFINDER.getRoot(func, alpha); modCreditCurves = adjustCurves(modCreditCurves, alpha, startKnots, endKnots); startKnots = endKnots; } return(intrinsicData.withCreditCurves(modCreditCurves)); }
public PiecewiseconstantHazardRate impliedHazardRate(double targetNPV, double Notional, DateTime tradedate, List <double> spreads, List <DateTime> tenor, YieldTermStructure yt, OMLib.Conventions.DayCount.DayCounter dayCounter, string frequency, DateTime firstpaymentdate, DateTime lastpaymentdate, List <DateTime> Jumps, double recoveryRate = 0.4, double accuracy = 1e-8) { OMLib.Calendars.Calendar cal = new OMLib.Calendars.Calendar(); PiecewiseconstantHazardRate probability = new PiecewiseconstantHazardRate(tradedate, null, tenor, null, null); double error = 2; double pv_premium = 0; double pv_protection = 0; NPV_PricingEngine engine = new NPV_PricingEngine(); //Join the knots List <DateTime> result = new List <DateTime>(); int index = 0, indexj = 0, lastIndex = 0; while (index < Jumps.Count || indexj < tenor.Count) { if (lastIndex > 0) { if (index >= Jumps.Count) { if (!DateTime.Equals(result.Last(), tenor[indexj])) { result.Add(tenor[indexj]); lastIndex++; } indexj++; continue; } if (indexj >= tenor.Count) { if (!DateTime.Equals(result.Last(), Jumps[index])) { result.Add(Jumps[index]); lastIndex++; } index++; continue; } } DateTime smallestVal = tenor.Last(); // Choose the smaller of a or b if (DateTime.Compare(Jumps[index], tenor[indexj]) < 0) { smallestVal = Jumps[index++]; } else { smallestVal = tenor[indexj++]; } // Don't insert duplicates if (lastIndex > 0) { if (!DateTime.Equals(result.Last(), smallestVal)) { result.Add(smallestVal); lastIndex++; } } else { result.Add(smallestVal); lastIndex++; } } for (int i = 0; i < spreads.Count(); i++) { //Accrued Interest double guess = spreads[i] / (1 - recoveryRate); //spreads[i] / (1 - recoveryRate); probability.addhazardrate(tenor[i], guess); double target = targetNPV - (double)85 / 360 * spreads[i] * Notional; error = 2; double step = guess * 0.01; int j = 0; double error_0 = 1000; while (Math.Abs(error) > accuracy) { CashFlowCalculation cf_calculation = new CashFlowCalculation(); //Schedule should be built here List <DateTime> schedule = new List <DateTime>(); schedule = PremiumDates(tenor[i], firstpaymentdate, frequency); List <CashFlow> FixLeg = cf_calculation.Calculation(spreads[i], Notional, schedule, tradedate, yt, probability, 3, lastpaymentdate); //pv_premium = engine.PremiumLegNPV_Approx(FixLeg, probability, yt, tradedate.AddDays(1), tradedate.AddDays(3)/*,Notional,spreads[i]*/); pv_premium = engine.PremiumLegNPV_Exact(FixLeg, probability, yt, tradedate, tradedate.AddDays(3), Notional, spreads[i], Jumps, lastpaymentdate); pv_protection = engine.ProtectionLegNPV_Exact(FixLeg, Notional, probability, yt, tradedate, tradedate.AddDays(3), recoveryRate, result, tenor); //pv_protection = engine.ProtectionLeg_Approx(FixLeg, Notional, probability, yt, tradedate, tradedate.AddDays(3), recoveryRate); int k1 = dayCounter.DayCount(tradedate, FixLeg[1].CashFlowDate); error = pv_protection - pv_premium - target; if (j > 1) { double temp = guess; guess = guess + step * error / (error_0 - error); step = guess - temp; } else { guess = guess + step; } error_0 = error; j = j + 1; probability.update(guess); } } // probability.update2(); return(probability); }
public List <CashFlow> Calculation(double fixrate, double initialNotional, List <DateTime> fixedSchedule, DateTime tradedate, YieldTermStructure yt, PiecewiseconstantHazardRate piecewiseFlatHazardRate, int settlement, DateTime lastpaymentdate) { List <CashFlow> result = new List <CashFlow>(); OMLib.Conventions.DayCount.Actual360 daycountconvention = new OMLib.Conventions.DayCount.Actual360(); for (int i = 0; i < fixedSchedule.Count; i++) { CashFlow cf = new CashFlow(); Calendar calendar = new UnitedStates(); //fixedSchedule[i] = calendar.adjust(fixedSchedule[i], BusinessDayConvention.Following); cf.CashFlowDate = fixedSchedule[i]; if (i == 0) { //The protection buyer pays the next coupon in full on the coupon date, //(even if this is the next day); in return the buyer receives (from the protection seller) the accrued //interest[Geoff Chaplin. Credit Derivatives.], which is paid on the cash settlement date. if (lastpaymentdate != null) { lastpaymentdate = calendar.adjust(lastpaymentdate, BusinessDayConvention.Following); cf.Amount = (double)initialNotional * fixrate * (daycountconvention.DayCount(lastpaymentdate, fixedSchedule[i])) / 360; } else { cf.Amount = (double)initialNotional * fixrate * (daycountconvention.DayCount(tradedate, fixedSchedule[i])) / 360; } } else { //Each coupon is equal to (annual coupon/360) (# of days in accrual period). //The accrual period always stretches from (previous coupon payment date) through (this coupon //payment date–1), inclusive; except a contract's last accrual period, which ends with (and //includes) the unadjusted maturity date. if (i == fixedSchedule.Count - 1) { cf.Amount = (double)initialNotional * fixrate * (daycountconvention.DayCount(fixedSchedule[i - 1], fixedSchedule[i].AddDays(1))) / 360; } else { cf.Amount = (double)initialNotional * fixrate * (daycountconvention.DayCount(fixedSchedule[i - 1], fixedSchedule[i])) / 360; } } //Assume all cash flows are discounted to the cash settlement date cf.DiscountFactor = yt.discount(fixedSchedule[i]); if (i == fixedSchedule.Count - 1) { cf.Survivalprobability = piecewiseFlatHazardRate.SurvivalProb(fixedSchedule[i].AddDays(1)); } else { cf.Survivalprobability = piecewiseFlatHazardRate.SurvivalProb(fixedSchedule[i]); } result.Add(cf); } return(result); }
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 double ProtectionLeg_Approx(List<CashFlow> cf, double notional, PiecewiseconstantHazardRate HazardTermStructure, // YieldTermStructure yt, DateTime tradedate, DateTime settlementDate, double recoveryrate) //{ // if (cf.Count() == 0) // { // return 0.0; // } // double totalNPV = 0.0; // for (int i = 0; i < cf.Count; ++i) // { // if (i == 0) // { // totalNPV += (1 - recoveryrate)*notional * cf[i].DiscountFactor * (1- cf[i].Survivalprobability); // } // else // { // totalNPV += notional * cf[i].DiscountFactor * (cf[i - 1].Survivalprobability // - cf[i].Survivalprobability) * (1 - recoveryrate); // } // } // return totalNPV/yt.discount(settlementDate); //} public double calculateSinglePeriodAccrualOnDefault(List <CashFlow> cf, double coupon, DateTime tradedate, YieldTermStructure yieldCurve, PiecewiseconstantHazardRate creditCurve, List <DateTime> Jumps, DateTime lastpayment) { double Acc = 0; DateTime effectiveStart = tradedate.AddDays(1); for (int i = 0; i < cf.Count; ++i) { //Accured on default DateTime t_0 = (i > 0) ? cf[i - 1].CashFlowDate.AddDays(-1) : tradedate; DateTime T = cf[i].CashFlowDate; if (i == cf.Count - 1) { T = cf[i].CashFlowDate; } else { T = cf[i].CashFlowDate.AddDays(-1); } List <DateTime> knots = new List <DateTime>(); knots.Add(t_0); for (int j = 0; j < Jumps.Count; j++) { if ((DateTime.Compare(Jumps[j], T) < 0) && (DateTime.Compare(t_0, Jumps[j]) < 0)) { knots.Add(Jumps[j]); } } knots.Add(T); DateTime 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 = (double)dc.DayCount(lastpayment.AddDays(1), knots[0]) / 365; } else { t0 = (double)dc.DayCount(cf[i].CashFlowDate.AddDays(1), knots[0]) / 365; } 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 = (double)dc.DayCount(knots[j - 1], knots[j]) / 365; double dht = ht1 - ht0; double drt = rt1 - rt0; double dhrt = dht + drt + 1e-50; double tPV; double t1; if (i == 0) { t1 = (double)dc.DayCount(lastpayment.AddDays(1), knots[j]) / 365; } else { t1 = (double)dc.DayCount(cf[i].CashFlowDate.AddDays(1), knots[j]) / 365; } 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); }
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); }
public void hazardratecurve(YieldTermStructure yt, OMLib.Conventions.DayCount.Actual365 dayCounter, List <double> QuotedSpot, List <double> QuotedSpread, double FixRate, double Spread_traded, double Upfront, DateTime maturity, DateTime firstpaymentdate, DateTime evalDate, DateTime formerpaymentdate, string frequency, double recovery) { List <DateTime> dates = new List <DateTime>(); List <DateTime> discountDates = new List <DateTime>(); int accrued = dayCounter.DayCount(formerpaymentdate, tradedate); if (QuotedSpread == null) { if (Spread_traded > 0) { // Infer the constant hazard rate from the quoted spread /*When the Spread is input: Consider a CDS with exactly the same specification as * the Standard CDS except that its Coupon Rate is equal to the Spread. Assume that * the Upfront of this CDS is zero. Solve for the Constant Hazard Rate that gives this * CDS a MTM equal to minus its Accrued Premium (based on a Coupon Rate equal * to Spread) discounted riskless to T */ impliedhazardrate ih = new impliedhazardrate(); List <double> spread = new List <double> { Spread_traded }; List <DateTime> mat = new List <DateTime> { maturity }; PiecewiseconstantHazardRate flatrate = ih.impliedHazardRate(-this.Notional * Spread_traded * accrued / 360, this.Notional, this.tradedate, spread, mat, yt, dayCounter, frequency, firstpaymentdate, this.formerpaymentdate, this.Jump_Nodes, recovery); this.piecewiseHazardRate = flatrate; } else if (Upfront > 0) { // Infer the constant hazard rate from the quoted upfront /*When the Upfront is input: Solve for the Constant Hazard Rate that gives the * Standard CDS a MTM equal to Notional * Upfront – AccruedPremium discounted riskless to T*/ impliedhazardrate ih = new impliedhazardrate(); List <double> spread = new List <double> { Spread_traded }; List <DateTime> mat = new List <DateTime> { maturity }; PiecewiseconstantHazardRate flatrate = ih.impliedHazardRate(this.Notional * Upfront - this.accruedamt, this.Notional, this.tradedate, spread, mat, yt, dayCounter, frequency, firstpaymentdate, this.formerpaymentdate, this.Jump_Nodes, recovery); this.piecewiseHazardRate = flatrate; } } else // Construct the credit curve with the predefined term structure { dates.Add(firstpaymentdate.AddMonths(6)); dates.Add(firstpaymentdate.AddYears(1)); dates.Add(firstpaymentdate.AddYears(3)); dates.Add(firstpaymentdate.AddYears(5)); dates.Add(firstpaymentdate.AddYears(7)); dates.Add(firstpaymentdate.AddYears(10)); for (int i = 0; i < QuotedSpread.Count(); i++) { QuotedSpread[i] = QuotedSpread[i] / 10000; } impliedhazardrate implied = new impliedhazardrate(); PiecewiseconstantHazardRate hazardcurve = implied.impliedHazardRate(0, this.Notional, this.tradedate, QuotedSpread, dates, yt, dayCounter, frequency, this.firstpaymentdate, this.formerpaymentdate, this.Jump_Nodes, recovery); this.piecewiseHazardRate = hazardcurve; List <double> survival = new List <double>(); for (int i = 0; i < dates.Count; i++) { survival.Add(piecewiseHazardRate.SurvivalProb(dates[i].AddDays(1))); } } }