public IsdaPremiumLegSchedule(DateTime[] unadjustedDates, QLNet.BusinessDayConvention businessdayAdjustmentConvention, QLNet.Calendar calendar, bool protectionStart) { _nPayments = unadjustedDates.Length - 1; _nominalPaymentDates = new DateTime[_nPayments]; _paymentDates = new DateTime[_nPayments]; _accStartDates = new DateTime[_nPayments]; _accEndDates = new DateTime[_nPayments]; DateTime dPrev = unadjustedDates[0]; DateTime dPrevAdj = dPrev; // first date is never adjusted for (int i = 0; i < _nPayments; i++) { DateTime dNext = unadjustedDates[i + 1]; DateTime dNextAdj = businessDayAdjustDate(dNext, calendar, businessdayAdjustmentConvention); _accStartDates[i] = dPrevAdj; _accEndDates[i] = dNextAdj; _nominalPaymentDates[i] = dNext; _paymentDates[i] = dNextAdj; dPrev = dNext; dPrevAdj = dNextAdj; } // the last accrual date is not adjusted for business-day _accEndDates[_nPayments - 1] = getAccEndDate(unadjustedDates[_nPayments], protectionStart); }
private DateTime businessDayAdjustDate(DateTime date, QLNet.Calendar calendar, QLNet.BusinessDayConvention convention) { QLNet.UnitedStates cal = new QLNet.UnitedStates(); return(cal.adjust(date, convention)); }
/// <summary> /// Mimics JpmcdsCdsFeeLegMake </summary> /// <param name="startDate"> The protection start date </param> /// <param name="endDate"> The protection end date </param> /// <param name="step"> The period or frequency at which payments are made (e.g. every three months) </param> /// <param name="stubType"> The stub convention </param> /// <param name="businessdayAdjustmentConvention"> options are 'following' or 'proceeding' </param> /// <param name="calandar"> A holiday calendar </param> /// <param name="protectionStart"> If true, protection starts are the beginning rather than end of day (protection still ends at end of day). </param> public IsdaPremiumLegSchedule(DateTime startDate, DateTime endDate, int step, StubConvention stubType, QLNet.BusinessDayConvention businessdayAdjustmentConvention, QLNet.Calendar calandar, bool protectionStart) : this(getUnadjustedDates(startDate, endDate, step, stubType), businessdayAdjustmentConvention, calandar, protectionStart) { }
/** * 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; } }