public double discount(DateTime enddate) { OMLib.Conventions.DayCount.Actual365 dc = new OMLib.Conventions.DayCount.Actual365(); double t1 = (double)dc.DayCount(latestReference_, enddate) / 365; return(Math.Exp(-getRT_(t1))); }
public double getRT(DateTime t1) { OMLib.Conventions.DayCount.Actual365 dc = new OMLib.Conventions.DayCount.Actual365(); double t_ = (double)dc.DayCount(latestReference_, t1) / 365; return(getRT_(t_)); }
public double SurvivalProb(DateTime enddate) { OMLib.Conventions.DayCount.Actual365 dc = new OMLib.Conventions.DayCount.Actual365(); double t1 = (double)dc.DayCount(latestReference_.AddDays(1), enddate) / 365; return(Math.Exp(-getRT_(t1))); }
public void Curve_Building(List <double> QuotedSpot, List <double> QuotedSpread, double Spread_traded, double Upfront) { OMLib.Conventions.DayCount.Actual365 dayCounter = new OMLib.Conventions.DayCount.Actual365(); //Build interest rate curve, discount curve InterestRateCurve IRC = new InterestRateCurve(); YieldTermStructure yt = new YieldTermStructure(this.tradedate); yt = IRC.calculation(tradedate, QuotedSpot); //return a discounting curve this.Jump_Nodes = IRC.Nodes; this.yieldcurve = yt; // Build Payment Schedule List <ZeroRates> zero_rates = new List <ZeroRates>(yt.jumps_.Count); for (int i = 0; i < yt.t.Count; i++) { ZeroRates temp = new ZeroRates(); temp.YearFraction = yt.t[i]; temp.Rate = yt.getKnotZeroRates()[i]; zero_rates.Add(temp); } this.zero_rates = zero_rates; // Implied hazard rates from quoted spreads. hazardratecurve(yt, dayCounter, QuotedSpot, QuotedSpread, this.PremiumRate, Spread_traded, Upfront, this.Maturity, this.firstpaymentdate, this.evalDate, this.formerpaymentdate, this.Frequency, this.Recovery); double k = piecewiseHazardRate.SurvivalProb(new DateTime(2021, 06, 20)); // Build Yield Curve / Credit Curve to be output curve_output(yt, this.piecewiseHazardRate); }
public void addhazardrate(DateTime jumpdate, double hazardrate) { jumps_.Add(hazardrate); jumpDates_.Add(jumpdate); nJumps_ += 1; OMLib.Conventions.DayCount.Actual365 dc = new OMLib.Conventions.DayCount.Actual365(); double x = (double)dc.DayCount(latestReference_, jumpDates_[nJumps_ - 1]) / 365; t.Add(x); rt.Add(jumps_[nJumps_ - 1] * t[nJumps_ - 1]); }
public YieldTermStructure withDiscountFactor(double discountFactor, int index) { int n = this.t.Count; List <double> t_ = this.t; List <double> rt_ = this.rt; rt_[index] = -Math.Log(discountFactor); OMLib.Conventions.DayCount.Actual365 dc = new OMLib.Conventions.DayCount.Actual365(); YieldTermStructure temp = new YieldTermStructure(latestReference_, jumps_, jumpDates_, t_, rt_); return(temp); }
public CDS(double Coupon, double notional, DateTime maturity, DateTime firstpaymentday, DateTime tradedate, DateTime formerpaymentday, string frequency, double recovery, int settlement, int Cashsettlement) { // Product Setup OMLib.Conventions.DayCount.Actual360 AccuralDCC = new OMLib.Conventions.DayCount.Actual360(); OMLib.Conventions.DayCount.Actual365 curveDCC = new OMLib.Conventions.DayCount.Actual365(); Calendar calendar = new UnitedStates(); formerpaymentday = calendar.adjust(formerpaymentday, BusinessDayConvention.Following); int accrued = AccuralDCC.DayCount(formerpaymentday, calendar.adjust(tradedate, BusinessDayConvention.Following)) + 1; this.accruedday = accrued; this.marketvalue = new double(); this.accruedamt = notional * Coupon * accrued / 360; this.Notional = notional; this._payAccOnDefault = true; OMLib.Conventions.BusinessDayConvention convention = new OMLib.Conventions.BusinessDayConvention(Enums.BusinessDayConvention.ModifiedFollowing, tradedate); this.tradedate = calendar.adjust(tradedate, BusinessDayConvention.ModifiedFollowing); /*convention.AdjustedDate;*/ this.Recovery = recovery; convention = new OMLib.Conventions.BusinessDayConvention(Enums.BusinessDayConvention.ModifiedFollowing, firstpaymentday); this.firstpaymentdate = CdsAnalyticFactory.getNextIMMDate(tradedate); /*convention.AdjustedDate;*/ convention = new OMLib.Conventions.BusinessDayConvention(Enums.BusinessDayConvention.ModifiedFollowing, formerpaymentday); this.formerpaymentdate = CdsAnalyticFactory.getPrevIMMDate(tradedate);//calendar.adjust(formerpaymentday,BusinessDayConvention.ModifiedFollowing); /*convention.AdjustedDate;*/ this.Maturity = maturity; this.PremiumRate = Coupon; this.Frequency = frequency; this.Cashsettlement = Cashsettlement; DateTime valueDate = calendar.adjust(tradedate.AddDays(Cashsettlement)); convention = new OMLib.Conventions.BusinessDayConvention(Enums.BusinessDayConvention.ModifiedFollowing, tradedate.AddDays(3)); this.evalDate = calendar.adjust(tradedate.AddDays(settlement), BusinessDayConvention.ModifiedFollowing); /*convention.AdjustedDate;*/ this.Payment_Schedule = PremiumDates(this.Maturity, CdsAnalyticFactory.getNextIMMDate(tradedate), this.Frequency); QLNet.Calendar.OrthodoxImpl cal = new Calendar.OrthodoxImpl(); IsdaPremiumLegSchedule paymentSchedule = new IsdaPremiumLegSchedule(formerpaymentdate, maturity, payment_interval, StubConvention.SHORT_INITIAL, QLNet.BusinessDayConvention.ModifiedFollowing, cal, true); _coupons = CdsCoupon.makeCoupons(tradedate, paymentSchedule, true, ACT_360, ACT_365); OMLib.Conventions.DayCount.Actual365 CurveDCC = new OMLib.Conventions.DayCount.Actual365(); DateTime effectiveStartDate = tradedate; _accStart = DateTime.Compare(formerpaymentdate, tradedate) < 0 ?-CurveDCC.YearFraction(formerpaymentdate, tradedate) : CurveDCC.YearFraction(tradedate, formerpaymentdate); _cashSettlementTime = CurveDCC.YearFraction(tradedate, valueDate); _effectiveProtectionStart = DateTime.Compare(effectiveStartDate, tradedate) < 0 ? -CurveDCC.YearFraction(effectiveStartDate, tradedate) : CurveDCC.YearFraction(tradedate, effectiveStartDate); _protectionEnd = CurveDCC.YearFraction(tradedate, maturity); DateTime accStart = paymentSchedule.getAccStartDate(0); }
public YieldTermStructure(DateTime referenceDate, List <double> rates = null, List <DateTime> jumpDates = null, List <double> t_ = null, List <double> RT = null) { List <DateTime> jumpDates_ = new List <DateTime>(); t = new List <double>(); rt = new List <double>(); jumps_ = new List <double>(); jumpDates_ = new List <DateTime>(); OMLib.Conventions.DayCount.Actual365 dc = new OMLib.Conventions.DayCount.Actual365(); latestReference_ = referenceDate; if (rates != null) { this.jumps_ = rates; } nJumps_ = jumps_.Count; if (t_ != null) { t = t_; } if (nJumps_ > 0) { this.jumpDates_ = jumpDates; } if (nJumps_ > 0 && (t == null) || (RT == null)) { if (t == null) { for (int i = 0; i < nJumps_; i++) { t.Add(dc.YearFraction(latestReference_, jumpDates[i])); rt.Add(jumps_[i] * t[i]); } } else //t not null, rt null { for (int i = 0; i < nJumps_; i++) { rt.Add(jumps_[i] * t[i]); } } } if (RT != null && t_ != null) { rt = RT; t = t_; } }
public BasicFixedLeg( DateTime spotDate, DateTime mat, int swapInterval ) { OMLib.Conventions.DayCount.Thirty360 swapDCC = new OMLib.Conventions.DayCount.Thirty360(); OMLib.Conventions.DayCount.Actual360 moneyMarketDCC = new OMLib.Conventions.DayCount.Actual360(); OMLib.Conventions.DayCount.Actual365 curveDCC = new OMLib.Conventions.DayCount.Actual365(); QLNet.UnitedStates cal = new QLNet.UnitedStates(); List <DateTime> list = new List <DateTime>(); DateTime tDate = mat; int step = 1; while (DateTime.Compare(tDate, spotDate) > 0) { list.Add(tDate); tDate = mat.AddMonths(-swapInterval * (step++)); } // remove spotDate from list, if it ends up there list.Remove(spotDate); _nPayments = list.Count(); _swapPaymentTimes = new double[_nPayments]; _yearFraction = new double[_nPayments]; DateTime prev = spotDate; int j = _nPayments - 1; for (int i = 0; i < _nPayments; i++, j--) { DateTime current = list[j]; DateTime adjCurr = cal.adjust(current, QLNet.BusinessDayConvention.Following); _yearFraction[i] = swapDCC.YearFraction(prev, adjCurr); _swapPaymentTimes[i] = curveDCC.YearFraction(spotDate, adjCurr); // Payment times always good business days prev = adjCurr; } }
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 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 YieldTermStructure calculation(DateTime tradedate, List <double> QuotedSpot) { DateTime SpotDate = tradedate.AddDays(2); /********************* * * ** CURVE BUILDING ** * * *********************/ DateTime d1m = SpotDate.AddMonths(1); DateTime d2m = SpotDate.AddMonths(2); DateTime d3m = SpotDate.AddMonths(3); DateTime d6m = SpotDate.AddMonths(6); DateTime d9m = SpotDate.AddMonths(9); DateTime d1y = SpotDate.AddYears(1); DateTime d2y = SpotDate.AddYears(2); DateTime d3y = SpotDate.AddYears(3); DateTime d4y = SpotDate.AddYears(4); DateTime d5y = SpotDate.AddYears(5); DateTime d6y = SpotDate.AddYears(6); DateTime d7y = SpotDate.AddYears(7); DateTime d8y = SpotDate.AddYears(8); DateTime d9y = SpotDate.AddYears(9); DateTime d10y = SpotDate.AddYears(10); DateTime d11y = SpotDate.AddYears(11); DateTime d12y = SpotDate.AddYears(12); DateTime d15y = SpotDate.AddYears(15); DateTime d20y = SpotDate.AddYears(20); DateTime d25y = SpotDate.AddYears(25); DateTime d30y = SpotDate.AddYears(30); List <DateTime> dates = new List <DateTime>(); dates.Add(d1m); dates.Add(d2m); dates.Add(d3m); dates.Add(d6m); dates.Add(d9m); dates.Add(d1y); dates.Add(d2y); dates.Add(d3y); dates.Add(d4y); dates.Add(d5y); dates.Add(d6y); dates.Add(d7y); dates.Add(d8y); dates.Add(d9y); dates.Add(d10y); dates.Add(d11y); dates.Add(d12y); dates.Add(d15y); dates.Add(d20y); dates.Add(d25y); dates.Add(d30y); // Any DayCounter would be fine. // ActualActual::ISDA ensures that 30 years is 30.0 OMLib.Conventions.DayCount.Actual365 dc = new OMLib.Conventions.DayCount.Actual365(); QLNet.UnitedStates calendar = new QLNet.UnitedStates(); String[] YIELD_CURVE_POINTS = new String[] { "1M", "2M", "3M", "6M", "9M", "1Y", "2Y", "3Y", "4Y", "5Y", "6Y", "7Y", "8Y", "9Y", "10Y", "11Y", "12Y", "15Y", "20Y", "25Y", "30Y" }; String[] YIELD_CURVE_INSTRUMENTS = new String[] { "M", "M", "M", "M", "M", "M", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S" }; DateTime today = tradedate; List <DateTime> matDates = dates; List <DateTime> adjMatDates = new List <DateTime>(); OMLib.Conventions.DayCount.Thirty360 swapDCC = new OMLib.Conventions.DayCount.Thirty360(); OMLib.Conventions.DayCount.Actual360 moneyMarketDCC = new OMLib.Conventions.DayCount.Actual360(); OMLib.Conventions.DayCount.Actual365 curveDCC = new OMLib.Conventions.DayCount.Actual365(); for (int i = 0; i < matDates.Count; i++) { adjMatDates.Add(calendar.adjust(matDates[i], QLNet.BusinessDayConvention.Following)); } adjMatDates[2] = adjMatDates[2].AddDays(-1); int nMM = 0; int n = YIELD_CURVE_INSTRUMENTS.Count(); double[] _t = new double[n]; for (int i = 0; i < n; i++) { _t[i] = curveDCC.YearFraction(SpotDate, adjMatDates[i]); if (YIELD_CURVE_INSTRUMENTS[i] == "M") { nMM++; } } int nSwap = n - nMM; double[] _mmYF = new double[nMM]; BasicFixedLeg[] _swaps = new BasicFixedLeg[nSwap]; int mmCount = 0; int swapCount = 0; int swapInterval = 12; for (int i = 0; i < n; i++) { if (YIELD_CURVE_INSTRUMENTS[i] == "M") { // TODO in ISDA code money market instruments of less than 21 days have special treatment _mmYF[mmCount++] = moneyMarketDCC.YearFraction(SpotDate, adjMatDates[i]); } else { _swaps[swapCount++] = new BasicFixedLeg(SpotDate, matDates[i], swapInterval); } } double _offset = DateTime.Compare(tradedate, SpotDate) > 0 ? curveDCC.YearFraction(SpotDate, tradedate) : -curveDCC.YearFraction( tradedate, SpotDate); YieldTermStructure curve = new YieldTermStructure(tradedate, QuotedSpot, dates, _t.ToList(), null); int mmCount_ = 0; int swapCount_ = 0; double[] rt_ = new double[n]; for (int i = 0; i < n; i++) { if (YIELD_CURVE_INSTRUMENTS[i] == "M") { // TODO in ISDA code money market instruments of less than 21 days have special treatment double z = 1.0 / (1 + QuotedSpot[i] * _mmYF[mmCount_++]); YieldTermStructure tempcurve = curve.withDiscountFactor(z, i); curve = tempcurve; } else { curve = curve.fitSwap(i, _swaps[swapCount_++], curve, QuotedSpot[i]); } } YieldTermStructure baseCurve = curve; List <double> ZeroRates = curve.getKnotZeroRates(); if (_offset == 0.0) { return(baseCurve); } this.Nodes = dates; return(baseCurve.withOffset(_offset)); }
public YieldTermStructure calculation2(DateTime tradedate, List <double> QuotedSpot) { /********************* *** MARKET DATA *** *********************/ QLNet.UnitedStates cal = new QLNet.UnitedStates(); DateTime SpotDate = tradedate.AddDays(4); //DateTime SpotDate = cal.advance(tradedate,2,QLNet.TimeUnit.Days,QLNet.BusinessDayConvention.ModifiedFollowing); // must be a business day /********************* * * ** CURVE BUILDING ** * * *********************/ DateTime d1m = SpotDate.AddMonths(1); DateTime d2m = SpotDate.AddMonths(2); DateTime d3m = SpotDate.AddMonths(3); DateTime d6m = SpotDate.AddMonths(6); DateTime d1y = SpotDate.AddYears(1); DateTime d2y = SpotDate.AddYears(2); DateTime d3y = SpotDate.AddYears(3); DateTime d4y = SpotDate.AddYears(4); DateTime d5y = SpotDate.AddYears(5); DateTime d6y = SpotDate.AddYears(6); DateTime d7y = SpotDate.AddYears(7); DateTime d8y = SpotDate.AddYears(8); DateTime d9y = SpotDate.AddYears(9); DateTime d10y = SpotDate.AddYears(10); DateTime d12y = SpotDate.AddYears(12); DateTime d15y = SpotDate.AddYears(15); DateTime d20y = SpotDate.AddYears(20); DateTime d25y = SpotDate.AddYears(25); DateTime d30y = SpotDate.AddYears(30); List <DateTime> dates = new List <DateTime>(); dates.Add(d1m); dates.Add(d2m); dates.Add(d3m); dates.Add(d6m); dates.Add(d1y); dates.Add(d2y); dates.Add(d3y); dates.Add(d4y); dates.Add(d5y); dates.Add(d6y); dates.Add(d7y); dates.Add(d8y); dates.Add(d9y); dates.Add(d10y); dates.Add(d12y); dates.Add(d15y); dates.Add(d20y); dates.Add(d25y); dates.Add(d30y); // Any DayCounter would be fine. // ActualActual::ISDA ensures that 30 years is 30.0 OMLib.Conventions.DayCount.Actual365 dc = new OMLib.Conventions.DayCount.Actual365(); QLNet.UnitedStates calendar = new QLNet.UnitedStates(); String[] YIELD_CURVE_POINTS = new String[] { "1M", "2M", "3M", "6M", "1Y", "2Y", "3Y", "4Y", "5Y", "6Y", "7Y", "8Y", "9Y", "10Y", "12Y", "15Y", "20Y", "25Y", "30Y" }; String[] YIELD_CURVE_INSTRUMENTS = new String[] { "M", "M", "M", "M", "M", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S" }; List <double> YIELD_CURVE_RATES = QuotedSpot; DateTime spotDate = SpotDate; List <DateTime> matDates = dates; List <DateTime> adjMatDates = new List <DateTime>(); OMLib.Conventions.DayCount.Thirty360 swapDCC = new OMLib.Conventions.DayCount.Thirty360(); OMLib.Conventions.DayCount.Actual360 moneyMarketDCC = new OMLib.Conventions.DayCount.Actual360(); OMLib.Conventions.DayCount.Actual365 curveDCC = new OMLib.Conventions.DayCount.Actual365(); for (int i = 0; i < matDates.Count; i++) { adjMatDates.Add(calendar.adjust(matDates[i], QLNet.BusinessDayConvention.ModifiedFollowing)); } int nMM = 0; int n = YIELD_CURVE_INSTRUMENTS.Count(); double[] _t = new double[n]; for (int i = 0; i < n; i++) { _t[i] = curveDCC.YearFraction(spotDate, adjMatDates[i]); if (YIELD_CURVE_INSTRUMENTS[i] == "M") { nMM++; } } int nSwap = n - nMM; double[] _mmYF = new double[nMM]; BasicFixedLeg[] _swaps = new BasicFixedLeg[nSwap]; int mmCount = 0; int swapCount = 0; int swapInterval = 6; for (int i = 0; i < n; i++) { if (YIELD_CURVE_INSTRUMENTS[i] == "M") { // TODO in ISDA code money market instruments of less than 21 days have special treatment _mmYF[mmCount++] = moneyMarketDCC.YearFraction(spotDate, adjMatDates[i]); } else { _swaps[swapCount++] = new BasicFixedLeg(spotDate, matDates[i], swapInterval); } } double _offset = DateTime.Compare(tradedate, spotDate) > 0 ? curveDCC.YearFraction(spotDate, tradedate) : -curveDCC.YearFraction( tradedate, spotDate); YieldTermStructure curve = new YieldTermStructure(tradedate, YIELD_CURVE_RATES, dates, _t.ToList(), null); int mmCount_ = 0; int swapCount_ = 0; double[] rt_ = new double[n]; for (int i = 0; i < n; i++) { if (YIELD_CURVE_INSTRUMENTS[i] == "M") { // TODO in ISDA code money market instruments of less than 21 days have special treatment double z = 1.0 / (1 + YIELD_CURVE_RATES[i] * _mmYF[mmCount_++]); YieldTermStructure tempcurve = curve.withDiscountFactor(z, i); curve = tempcurve; } else { curve = curve.fitSwap(i, _swaps[swapCount_++], curve, YIELD_CURVE_RATES[i]); } } YieldTermStructure baseCurve = curve; List <double> ZeroRates = curve.getKnotZeroRates(); if (_offset == 0.0) { return(baseCurve); } this.Nodes = dates; curve = baseCurve.withOffset(_offset); //List<double> rt = new List<double>() { 1.399914257002842E-4, 3.452229985902273E-4, 6.151397497988689E-4, 0.0017010975470283791, 0.005696357532861686, 0.008854793051714499, 0.0235368691596982, 0.04799336562986048, 0.07980430061988725, 0.11682686636178839, 0.1569272410971123, 0.1988340941576404, 0.24178776149530337, 0.2862865792161734, 0.37671732698783206, 0.512340347238558, 0.7299269275257245, 0.9365962573841474, 1.1363739062462221}; //curve.rt = rt; return(curve); }
/** * Set up a strip of increasing maturity CDSs that have some coupons in common. The trade date, step-in date and valuation date and * accrual start date are all common, as is the payment frequency. The maturities are expressed as integer multiples of the * payment interval from a reference date (the next IMM date after the trade date for standard CDSs) - this guarantees that premiums * will be the same across several CDSs. * @param tradeDate The trade date * @param stepinDate (aka Protection Effective sate or assignment date). Date when party assumes ownership. This is usually T+1. This is when protection * (and risk) starts in terms of the model. Note, this is sometimes just called the Effective Date, however this can cause * confusion with the legal effective date which is T-60 or T-90. * @param cashSettlementDate The cash settlement date. The date that values are PVed to. Is is normally today + 3 business days. * @param accStartDate Accrual Start Date. This is when the CDS nominally starts in terms of premium payments. i.e. the number * of days in the first period (and thus the amount of the first premium payment) is counted from this date. * @param maturityReferanceDate A reference date that maturities are measured from. For standard CDSSs, this is the next IMM date after * the trade date, so the actually maturities will be some fixed periods after this. * @param maturityIndexes The maturities are fixed integer multiples of the payment interval, so for 6M, 1Y and 2Y tenors with a 3M * payment interval, would require 2, 4, and 8 as the indices * @param payAccOnDefault Is the accrued premium paid in the event of a default * @param paymentInterval The nominal step between premium payments (e.g. 3 months, 6 months). * @param stubType the stub convention * @param protectStart If protectStart = true, then protections starts at the beginning of the day, otherwise it is at the end. * @param recoveryRate The recovery rate * @param businessdayAdjustmentConvention How are adjustments for non-business days made * @param calendar HolidayCalendar defining what is a non-business day * @param accrualDayCount Day count used for accrual * @param curveDayCount Day count used on curve (NOTE ISDA uses ACT/365 and it is not recommended to change this) */ public MultiCdsAnalytic( DateTime tradeDate, DateTime stepinDate, DateTime cashSettlementDate, DateTime accStartDate, DateTime maturityReferanceDate, int[] maturityIndexes, Boolean payAccOnDefault, int paymentInterval, StubConvention stubType, Boolean protectStart, double recoveryRate, QLNet.BusinessDayConvention businessdayAdjustmentConvention, QLNet.Calendar calendar, Enums.DayCount accrualDayCount, Enums.DayCount curveDayCount) { OMLib.Conventions.DayCount.Thirty360 swapDCC = new OMLib.Conventions.DayCount.Thirty360(); OMLib.Conventions.DayCount.Actual360 moneyMarketDCC = new OMLib.Conventions.DayCount.Actual360(); OMLib.Conventions.DayCount.Actual365 curveDCC = new OMLib.Conventions.DayCount.Actual365(); _nMaturities = maturityIndexes.Length; _payAccOnDefault = payAccOnDefault; _accStart = DateTime.Compare(accStartDate, tradeDate) < 0 ? -curveDCC.YearFraction(accStartDate, tradeDate) : curveDCC.YearFraction(tradeDate, accStartDate); DateTime temp = DateTime.Compare(stepinDate, accStartDate) > 0 ? stepinDate : accStartDate; DateTime effectiveStartDate = protectStart ? temp.AddDays(-1) : temp; _cashSettlementTime = curveDCC.YearFraction(tradeDate, cashSettlementDate); _effectiveProtectionStart = curveDCC.YearFraction(tradeDate, effectiveStartDate); _lgd = 1 - recoveryRate; DateTime[] maturities = new DateTime[_nMaturities]; _protectionEnd = new double[_nMaturities]; int period = paymentInterval; for (int i = 0; i < _nMaturities; i++) { int tStep = period * maturityIndexes[i]; maturities[i] = maturityReferanceDate.AddMonths(tStep); _protectionEnd[i] = curveDCC.YearFraction(tradeDate, maturities[i]); } IsdaPremiumLegSchedule fullPaymentSchedule = new IsdaPremiumLegSchedule(accStartDate, maturities[_nMaturities - 1], period, stubType, businessdayAdjustmentConvention, calendar, protectStart); //remove already expired coupons IsdaPremiumLegSchedule paymentSchedule = fullPaymentSchedule.truncateSchedule(stepinDate); int couponOffset = fullPaymentSchedule.getNumPayments() - paymentSchedule.getNumPayments(); _totalPayments = paymentSchedule.getNumPayments(); _standardCoupons = new CdsCoupon[_totalPayments - 1]; for (int i = 0; i < (_totalPayments - 1); i++) { //The last coupon is actually a terminal coupon, so not included here _standardCoupons[i] = new CdsCoupon( tradeDate, paymentSchedule.getAccPaymentDateTriplet(i), protectStart, accrualDayCount, curveDayCount); } //find the terminal coupons _terminalCoupons = new CdsCoupon[_nMaturities]; _matIndexToPayments = new int[_nMaturities]; _accruedDays = new int[_nMaturities]; _accrued = new double[_nMaturities]; long secondJulianDate = stepinDate.Ticks; for (int i = 0; i < _nMaturities; i++) { int index = fullPaymentSchedule.getNominalPaymentDateIndex(maturities[i]); //maturity is unadjusted, but if protectionStart=true (i.e. standard CDS) there is effectively an extra day of accrued interest DateTime accEnd = protectStart ? maturities[i].AddDays(1) : maturities[i]; _terminalCoupons[i] = new CdsCoupon( tradeDate, fullPaymentSchedule.getAccStartDate(index), accEnd, fullPaymentSchedule.getPaymentDate(index), protectStart); _matIndexToPayments[i] = index - couponOffset; //This will only matter for the edge case when the trade date is 1 day before maturity DateTime tDate2 = _matIndexToPayments[i] < 0 ? fullPaymentSchedule.getAccStartDate(couponOffset - 1) : paymentSchedule.getAccStartDate(0); long firstJulianDate = tDate2.Ticks; _accruedDays[i] = secondJulianDate > firstJulianDate ? (int)(secondJulianDate - firstJulianDate) : 0; _accrued[i] = DateTime.Compare(tDate2, stepinDate) < 0 ? swapDCC.YearFraction(tDate2, stepinDate) : 0.0; } }
public double calculateSinglePeriodAccrualOnDefault(CDS cds, YieldTermStructure yieldCurve, PiecewiseconstantHazardRate creditCurve) { double Acc = 0; List <double> Jumps = yieldCurve.t; DateTime tradedate = cds.tradedate; DateTime settlementDate = tradedate.AddDays(cds.Cashsettlement); double recoveryrate = cds.Recovery; DateTime Stepindate = tradedate.AddDays(1); double notional = cds.Notional; double coupon = cds.PremiumRate; DateTime lastpayment = cds.formerpaymentdate; DateTime effectiveStart = tradedate.AddDays(1); CdsCoupon[] cc = cds.getCoupons(); for (int i = 0; i < cds.getNumPayments(); ++i) { //Accured on default double t_0 = (i > 0) ? cc[i].getEffStart():0; double T = cc[i].getEffEnd(); List <double> knots = new List <double>(); knots.Add(t_0); for (int j = 0; j < Jumps.Count; j++) { if ((Jumps[j] < T) && (t_0 < Jumps[j])) { knots.Add(Jumps[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] - cc[0].getEffStart(); } else { t0 = knots[0] - cc[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] - cc[0].getEffStart(); } else { t1 = knots[j] - cc[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 / dhrt * (t0 * b0 - t1 * b1 + dt / dhrt * (b0 - 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))); } } }