/// <summary> /// CDS quoted as running-spread only /// </summary> /// <param name="side">Whether the protection is bought or sold.</param> /// <param name="notional">Notional value</param> /// <param name="spread">Running spread in fractional units.</param> /// <param name="schedule">Coupon schedule.</param> /// <param name="convention">Business-day convention for payment-date adjustment.</param> /// <param name="dayCounter">Day-count convention for accrual.</param> /// <param name="settlesAccrual">Whether or not the accrued coupon is due in the event of a default.</param> /// <param name="paysAtDefaultTime">If set to true, any payments triggered by a default event are /// due at default time. If set to false, they are due at the end of the accrual period.</param> /// <param name="protectionStart">The first date where a default event will trigger the contract.</param> /// <param name="claim"></param> /// <param name="lastPeriodDayCounter">Day-count convention for accrual in last period</param> /// <param name="rebatesAccrual">The protection seller pays the accrued scheduled current coupon at the start /// of the contract. The rebate date is not provided but computed to be two days after protection start.</param> public CreditDefaultSwap(Protection.Side side, double notional, double spread, Schedule schedule, BusinessDayConvention convention, DayCounter dayCounter, bool settlesAccrual = true, bool paysAtDefaultTime = true, Date protectionStart = null, Claim claim = null, DayCounter lastPeriodDayCounter = null, bool rebatesAccrual = true) { side_ = side; notional_ = notional; upfront_ = null; runningSpread_ = spread; settlesAccrual_ = settlesAccrual; paysAtDefaultTime_ = paysAtDefaultTime; claim_ = claim; protectionStart_ = protectionStart ?? schedule[0]; Utils.QL_REQUIRE(protectionStart_ <= schedule[0] || schedule.rule() == DateGeneration.Rule.CDS || schedule.rule() == DateGeneration.Rule.CDS2015 , () => "protection can not start after accrual"); leg_ = new FixedRateLeg(schedule) .withLastPeriodDayCounter(lastPeriodDayCounter) .withCouponRates(spread, dayCounter) .withNotionals(notional) .withPaymentAdjustment(convention); Date effectiveUpfrontDate = schedule.calendar().advance(protectionStart_, 2, TimeUnit.Days, convention); // '2' is used above since the protection start is assumed to be on trade_date + 1 if (rebatesAccrual) { FixedRateCoupon firstCoupon = leg_[0] as FixedRateCoupon; Date rebateDate = effectiveUpfrontDate; accrualRebate_ = new SimpleCashFlow(firstCoupon.accruedAmount(protectionStart_), rebateDate); } upfrontPayment_ = new SimpleCashFlow(0.0, effectiveUpfrontDate); if (claim_ == null) { claim_ = new FaceValueClaim(); } claim_.registerWith(update); maturity_ = schedule.dates().Last(); }
public void testBondFromScheduleWithDateVector() { // Testing South African R2048 bond price using Schedule constructor with Date vector SavedSettings backup = new SavedSettings(); //When pricing bond from Yield To Maturity, use NullCalendar() Calendar calendar = new NullCalendar(); int settlementDays = 3; Date issueDate = new Date(29, Month.June, 2012); Date today = new Date(7, Month.September, 2015); Date evaluationDate = calendar.adjust(today); Date settlementDate = calendar.advance(evaluationDate, new Period(settlementDays, TimeUnit.Days)); Settings.setEvaluationDate(evaluationDate); // For the schedule to generate correctly for Feb-28's, make maturity date on Feb 29 Date maturityDate = new Date(29, Month.February, 2048); double coupon = 0.0875; Compounding comp = Compounding.Compounded; Frequency freq = Frequency.Semiannual; DayCounter dc = new ActualActual(ActualActual.Convention.Bond); // Yield as quoted in market InterestRate yield = new InterestRate(0.09185, dc, comp, freq); Period tenor = new Period(6, TimeUnit.Months); Period exCouponPeriod = new Period(10, TimeUnit.Days); // Generate coupon dates for 31 Aug and end of Feb each year // For leap years, this will generate 29 Feb, but the bond // actually pays coupons on 28 Feb, regardsless of whether // it is a leap year or not. Schedule schedule = new Schedule(issueDate, maturityDate, tenor, new NullCalendar(), BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted, DateGeneration.Rule.Backward, true); // Adjust the 29 Feb's to 28 Feb List<Date> dates = new List<Date>(); for (int i = 0; i < schedule.Count; ++i) { Date d = schedule.date(i); if (d.Month == 2 && d.Day == 29) dates.Add(new Date(28, Month.February, d.Year)); else dates.Add(d); } schedule = new Schedule(dates, schedule.calendar(), schedule.businessDayConvention(), schedule.terminationDateBusinessDayConvention(), schedule.tenor(), schedule.rule(), schedule.endOfMonth(), schedule.isRegular()); FixedRateBond bond = new FixedRateBond( 0, 100.0, schedule, new List<double>() { coupon }, dc, BusinessDayConvention.Following, 100.0, issueDate, calendar, exCouponPeriod, calendar, BusinessDayConvention.Unadjusted, false); double calculatedPrice = BondFunctions.dirtyPrice(bond, yield, settlementDate); double expectedPrice = 95.75706; double tolerance = 1e-5; if (Math.Abs(calculatedPrice - expectedPrice) > tolerance) { Assert.Fail(string.Format("failed to reproduce R2048 dirty price\nexpected: {0}\ncalculated: {1}", expectedPrice, calculatedPrice)); } }
/// <summary> /// CDS quoted as upfront and running spread /// </summary> /// <param name="side">Whether the protection is bought or sold.</param> /// <param name="notional"> Notional value</param> /// <param name="upfront">Upfront in fractional units.</param> /// <param name="runningSpread">Running spread in fractional units.</param> /// <param name="schedule">Coupon schedule.</param> /// <param name="convention">Business-day convention for payment-date adjustment.</param> /// <param name="dayCounter">Day-count convention for accrual.</param> /// <param name="settlesAccrual">Whether or not the accrued coupon is due in the event of a default.</param> /// <param name="paysAtDefaultTime">If set to true, any payments triggered by a default event are /// due at default time. If set to false, they are due at the end of the accrual period.</param> /// <param name="protectionStart">The first date where a default event will trigger the contract.</param> /// <param name="upfrontDate">Settlement date for the upfront payment.</param> /// <param name="claim"></param> /// <param name="lastPeriodDayCounter">Day-count convention for accrual in last period</param> /// <param name="rebatesAccrual">The protection seller pays the accrued scheduled current coupon at the start /// of the contract. The rebate date is not provided but computed to be two days after protection start.</param> public CreditDefaultSwap(Protection.Side side, double notional, double upfront, double runningSpread, Schedule schedule, BusinessDayConvention convention, DayCounter dayCounter, bool settlesAccrual = true, bool paysAtDefaultTime = true, Date protectionStart = null, Date upfrontDate = null, Claim claim = null, DayCounter lastPeriodDayCounter = null, bool rebatesAccrual = true) { side_ = side; notional_ = notional; upfront_ = upfront; runningSpread_ = runningSpread; settlesAccrual_ = settlesAccrual; paysAtDefaultTime_ = paysAtDefaultTime; claim_ = claim; protectionStart_ = protectionStart ?? schedule[0]; Utils.QL_REQUIRE(protectionStart_ <= schedule[0] || schedule.rule() == DateGeneration.Rule.CDS , () => "protection can not start after accrual"); leg_ = new FixedRateLeg(schedule) .withLastPeriodDayCounter(lastPeriodDayCounter) .withCouponRates(runningSpread, dayCounter) .withNotionals(notional) .withPaymentAdjustment(convention); // If empty, adjust to T+3 standard settlement, alternatively add // an arbitrary date to the constructor Date effectiveUpfrontDate = upfrontDate == null? schedule.calendar().advance(protectionStart_, 2, TimeUnit.Days, convention) : upfrontDate; // '2' is used above since the protection start is assumed to be // on trade_date + 1 upfrontPayment_ = new SimpleCashFlow(notional * upfront, effectiveUpfrontDate); Utils.QL_REQUIRE(effectiveUpfrontDate >= protectionStart_, () => "upfront can not be due before contract start"); if (rebatesAccrual) { FixedRateCoupon firstCoupon = leg_[0] as FixedRateCoupon; // adjust to T+3 standard settlement, alternatively add // an arbitrary date to the constructor Date rebateDate = effectiveUpfrontDate; accrualRebate_ = new SimpleCashFlow(firstCoupon.accruedAmount(protectionStart_), rebateDate); } if (claim_ == null) { claim_ = new FaceValueClaim(); } claim_.registerWith(update); maturity_ = schedule.dates().Last(); }
public void testDateConstructor() { // Testing the constructor taking a vector of dates and possibly additional meta information List<Date> dates = new List<Date>(); dates.Add(new Date(16, Month.May, 2015)); dates.Add(new Date(18, Month.May, 2015)); dates.Add(new Date(18, Month.May, 2016)); dates.Add(new Date(31, Month.December, 2017)); // schedule without any additional information Schedule schedule1 = new Schedule(dates); if (schedule1.Count != dates.Count) Assert.Fail("schedule1 has size {0}, expected {1}", schedule1.Count, dates.Count); for (int i = 0; i < dates.Count; ++i) if (schedule1[i] != dates[i]) Assert.Fail("schedule1 has {0} at position {1}, expected {2}", schedule1[i], i, dates[i]); if (schedule1.calendar() != new NullCalendar()) Assert.Fail("schedule1 has calendar {0}, expected null calendar", schedule1.calendar().name()); if (schedule1.businessDayConvention() != BusinessDayConvention.Unadjusted) Assert.Fail("schedule1 has convention {0}, expected unadjusted", schedule1.businessDayConvention()); // schedule with metadata List<bool> regular = new List<bool>(); regular.Add(false); regular.Add(true); regular.Add(false); Schedule schedule2 = new Schedule(dates, new TARGET(), BusinessDayConvention.Following, BusinessDayConvention.ModifiedPreceding, new Period(1, TimeUnit.Years), DateGeneration.Rule.Backward, true, regular); for (int i = 1; i < dates.Count; ++i) if (schedule2.isRegular(i) != regular[i - 1]) Assert.Fail("schedule2 has a {0} period at position {1}, expected {2}", (schedule2.isRegular(i) ? "regular" : "irregular"), i, (regular[i - 1] ? "regular" : "irregular")); if (schedule2.calendar() != new TARGET()) Assert.Fail("schedule1 has calendar {0}, expected TARGET", schedule2.calendar().name()); if (schedule2.businessDayConvention() != BusinessDayConvention.Following) Assert.Fail("schedule2 has convention {0}, expected Following", schedule2.businessDayConvention()); if (schedule2.terminationDateBusinessDayConvention() != BusinessDayConvention.ModifiedPreceding) Assert.Fail("schedule2 has convention {0}, expected Modified Preceding", schedule2.terminationDateBusinessDayConvention()); if (schedule2.tenor() != new Period(1, TimeUnit.Years)) Assert.Fail("schedule2 has tenor {0}, expected 1Y", schedule2.tenor()); if (schedule2.rule() != DateGeneration.Rule.Backward) Assert.Fail("schedule2 has rule {0}, expected Backward", schedule2.rule()); if (schedule2.endOfMonth() != true) Assert.Fail("schedule2 has end of month flag false, expected true"); }