private List <Date> getListOfPeriodDatesIncludingQuasiPayments(Schedule schedule) { // Process the schedule into an array of dates. Date issueDate = schedule.date(0); Date firstCoupon = schedule.date(1); Date notionalCoupon = schedule.calendar().advance(firstCoupon, -schedule.tenor(), schedule.businessDayConvention(), schedule.endOfMonth()); List <Date> newDates = schedule.dates(); newDates[0] = notionalCoupon; //long first coupon if (notionalCoupon > issueDate) { Date priorNotionalCoupon = schedule.calendar().advance(notionalCoupon, -schedule.tenor(), schedule.businessDayConvention(), schedule.endOfMonth()); newDates.Insert(0, priorNotionalCoupon); } return(newDates); }
protected CallableBond(int settlementDays, Schedule schedule, DayCounter paymentDayCounter, Date issueDate = null, CallabilitySchedule putCallSchedule = null) : base(settlementDays, schedule.calendar(), issueDate) { if (putCallSchedule == null) { putCallSchedule = new CallabilitySchedule(); } paymentDayCounter_ = paymentDayCounter; putCallSchedule_ = putCallSchedule; maturityDate_ = schedule.dates().Last(); if (!putCallSchedule_.empty()) { Date finalOptionDate = Date.minDate(); for (int i = 0; i < putCallSchedule_.Count; ++i) { finalOptionDate = Date.Max(finalOptionDate, putCallSchedule_[i].date()); } Utils.QL_REQUIRE(finalOptionDate <= maturityDate_, () => "Bond cannot mature before last call/put date"); } // derived classes must set cashflows_ and frequency_ }
/// <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(); }
private List <Date> getListOfPeriodDatesIncludingQuasiPayments(Schedule schedule) { // Process the schedule into an array of dates. Date issueDate = schedule.date(0); Date firstCoupon = schedule.date(1); Date notionalFirstCoupon = schedule.calendar().advance(firstCoupon, -schedule.tenor(), schedule.businessDayConvention(), schedule.endOfMonth()); List <Date> newDates = schedule.dates().ToList(); newDates[0] = notionalFirstCoupon; // The handling of the last coupon is is needed for odd final periods var notionalLastCoupon = schedule.calendar().advance( schedule.date(schedule.Count - 2), schedule.tenor(), schedule.businessDayConvention(), schedule.endOfMonth()); newDates[schedule.Count - 1] = notionalLastCoupon; //long first coupon if (notionalFirstCoupon > issueDate) { Date priorNotionalCoupon = schedule.calendar().advance(notionalFirstCoupon, -schedule.tenor(), schedule.businessDayConvention(), schedule.endOfMonth()); newDates.Insert(0, priorNotionalCoupon); } // long last coupon if (notionalLastCoupon < schedule.endDate()) { Date nextNotionalCoupon = schedule.calendar().advance( notionalLastCoupon, schedule.tenor(), schedule.businessDayConvention(), schedule.endOfMonth()); newDates.Add(nextNotionalCoupon); } return(newDates); }
public RangeAccrualFloatersCoupon(Date paymentDate, double nominal, IborIndex index, Date startDate, Date endDate, int fixingDays, DayCounter dayCounter, double gearing, double spread, Date refPeriodStart, Date refPeriodEnd, Schedule observationsSchedule, double lowerTrigger, double upperTrigger) : base(paymentDate, nominal, startDate, endDate, fixingDays, index, gearing, spread, refPeriodStart, refPeriodEnd, dayCounter) { observationsSchedule_ = observationsSchedule; lowerTrigger_ = lowerTrigger; upperTrigger_ = upperTrigger; Utils.QL_REQUIRE(lowerTrigger_ < upperTrigger, () => "lowerTrigger_>=upperTrigger"); Utils.QL_REQUIRE(observationsSchedule_.startDate() == startDate, () => "incompatible start date"); Utils.QL_REQUIRE(observationsSchedule_.endDate() == endDate, () => "incompatible end date"); observationDates_ = new List <Date>(observationsSchedule_.dates()); observationDates_.RemoveAt(observationDates_.Count - 1); //remove end date observationDates_.RemoveAt(0); //remove start date observationsNo_ = observationDates_.Count; Handle <YieldTermStructure> rateCurve = index.forwardingTermStructure(); Date referenceDate = rateCurve.link.referenceDate(); startTime_ = dayCounter.yearFraction(referenceDate, startDate); endTime_ = dayCounter.yearFraction(referenceDate, endDate); observationTimes_ = new List <double>(); for (int i = 0; i < observationsNo_; i++) { observationTimes_.Add(dayCounter.yearFraction(referenceDate, observationDates_[i])); } }
/// <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 CreditDefaultSwap value() { Date startDate; //double lastCdsPayementtime; if (effectiveDate_ != null) { startDate = effectiveDate_; } else { Date refDate = Settings.evaluationDate(); startDate = cdsCalendar_.adjust(refDate, BusinessDayConvention.Following); } // Standard CDS calendar dates Date startDateSchedule = new Date(20, Month.March, startDate.year()); Date endDateSchedule = new Date(20, Month.December, startDate.year() + 50); Period cdsSchedulePeriode = new Period(3, TimeUnit.Months); Schedule standardSchedule = new Schedule(startDateSchedule, endDateSchedule, cdsSchedulePeriode, cdsCalendar_, cdsConvention_, cdsConvention_, cdsRule_, false); Date endDate = new Date(); /* * // compute the last coverred date : the previous quaterly date (mod 0.25) * * double extratime = (1-discountingTermStructure_.link.timeFromReference(new Date(1, Month.Jan, startDate.year()+1)))% 0.25; * lastCdsPayementtime = discountingTermStructure_.link.timeFromReference(startDate + cdsTenor_) - extratime; * endDate = cdsCalendar_.advance(startDate, (int)(lastCdsPayementtime*365.0), TimeUnit.Days); */ Date previousDate = startDate; foreach (Date date in standardSchedule.dates()) { if (date > startDate + cdsTenor_) { endDate = previousDate; break; } previousDate = date; } Schedule cdsSchedule = new Schedule(startDate, endDate, cdsSchedulePeriode, cdsCalendar_, cdsConvention_, cdsConvention_, cdsRule_, false); DayCounter cdsDayCount = cdsDayCount_; CreditDefaultSwap cds = new CreditDefaultSwap(side_, nominal_, cdsSpread_, cdsSchedule, cdsConvention_, cdsDayCount); if (engine_ == null) { throw new Exception("No engine set for CDS"); } else { cds.setPricingEngine(engine_); } return(cds); }
//! fixing dates of the rates to be averaged public List <Date> fixingDates() { return(fixingSchedule_.dates()); }
public AssetSwap(bool parAssetSwap, Bond bond, double bondCleanPrice, double nonParRepayment, double gearing, IborIndex iborIndex, double spread = 0.0, DayCounter floatingDayCount = null, Date dealMaturity = null, bool payBondCoupon = false) : base(2) { bond_ = bond; bondCleanPrice_ = bondCleanPrice; nonParRepayment_ = nonParRepayment; spread_ = spread; parSwap_ = parAssetSwap; Schedule tempSch = new Schedule(bond_.settlementDate(), bond_.maturityDate(), iborIndex.tenor(), iborIndex.fixingCalendar(), iborIndex.businessDayConvention(), iborIndex.businessDayConvention(), DateGeneration.Rule.Backward, false); // endOfMonth if (dealMaturity == null) { dealMaturity = bond_.maturityDate(); } Utils.QL_REQUIRE(dealMaturity <= tempSch.dates().Last(), () => "deal maturity " + dealMaturity + " cannot be later than (adjusted) bond maturity " + tempSch.dates().Last()); Utils.QL_REQUIRE(dealMaturity > tempSch.dates()[0], () => "deal maturity " + dealMaturity + " must be later than swap start date " + tempSch.dates()[0]); // the following might become an input parameter BusinessDayConvention paymentAdjustment = BusinessDayConvention.Following; Date finalDate = tempSch.calendar().adjust(dealMaturity, paymentAdjustment); Schedule schedule = tempSch.until(finalDate); // bondCleanPrice must be the (forward) clean price // at the floating schedule start date upfrontDate_ = schedule.startDate(); double dirtyPrice = bondCleanPrice_ + bond_.accruedAmount(upfrontDate_); double notional = bond_.notional(upfrontDate_); /* In the market asset swap, the bond is purchased in return for * payment of the full price. The notional of the floating leg is * then scaled by the full price. */ if (!parSwap_) { notional *= dirtyPrice / 100.0; } if (floatingDayCount == null) { legs_[1] = new IborLeg(schedule, iborIndex) .withSpreads(spread) .withGearings(gearing) .withNotionals(notional) .withPaymentAdjustment(paymentAdjustment); } else { legs_[1] = new IborLeg(schedule, iborIndex) .withSpreads(spread) .withGearings(gearing) .withPaymentDayCounter(floatingDayCount) .withNotionals(notional) .withPaymentAdjustment(paymentAdjustment); } foreach (CashFlow c in legs_[1]) { c.registerWith(update); } List <CashFlow> bondLeg = bond_.cashflows(); // skip bond redemption int i; for (i = 0; i < bondLeg.Count && bondLeg[i].date() <= dealMaturity; ++i) { // whatever might be the choice for the discounting engine // bond flows on upfrontDate_ must be discarded bool upfrontDateBondFlows = false; if (!bondLeg[i].hasOccurred(upfrontDate_, upfrontDateBondFlows)) { legs_[0].Add(bondLeg[i]); } } // if the first skipped cashflow is not the redemption // and it is a coupon then add the accrued coupon if (i < bondLeg.Count - 1) { Coupon c = bondLeg[i] as Coupon; if (c != null) { CashFlow accruedCoupon = new SimpleCashFlow(c.accruedAmount(dealMaturity), finalDate); legs_[0].Add(accruedCoupon); } } // add the nonParRepayment_ CashFlow nonParRepaymentFlow = new SimpleCashFlow(nonParRepayment_, finalDate); legs_[0].Add(nonParRepaymentFlow); Utils.QL_REQUIRE(!legs_[0].empty(), () => "empty bond leg to start with"); // special flows if (parSwap_) { // upfront on the floating leg double upfront = (dirtyPrice - 100.0) / 100.0 * notional; CashFlow upfrontCashFlow = new SimpleCashFlow(upfront, upfrontDate_); legs_[1].Insert(0, upfrontCashFlow); // backpayment on the floating leg // (accounts for non-par redemption, if any) double backPayment = notional; CashFlow backPaymentCashFlow = new SimpleCashFlow(backPayment, finalDate); legs_[1].Add(backPaymentCashFlow); } else { // final notional exchange CashFlow finalCashFlow = new SimpleCashFlow(notional, finalDate); legs_[1].Add(finalCashFlow); } Utils.QL_REQUIRE(!legs_[0].empty(), () => "empty bond leg"); foreach (CashFlow c in legs_[0]) { c.registerWith(update); } if (payBondCoupon) { payer_[0] = -1.0; payer_[1] = +1.0; } else { payer_[0] = +1.0; payer_[1] = -1.0; } }
public AssetSwap(bool parAssetSwap, Bond bond, double bondCleanPrice, double nonParRepayment, double gearing, IborIndex iborIndex, double spread = 0.0, DayCounter floatingDayCount = null, Date dealMaturity = null, bool payBondCoupon = false) : base(2) { bond_ = bond; bondCleanPrice_ = bondCleanPrice; nonParRepayment_ = nonParRepayment; spread_ = spread; parSwap_ = parAssetSwap; Schedule tempSch = new Schedule(bond_.settlementDate(), bond_.maturityDate(), iborIndex.tenor(), iborIndex.fixingCalendar(), iborIndex.businessDayConvention(), iborIndex.businessDayConvention(), DateGeneration.Rule.Backward, false); // endOfMonth if (dealMaturity == null) dealMaturity = bond_.maturityDate(); Utils.QL_REQUIRE( dealMaturity <= tempSch.dates().Last(), () => "deal maturity " + dealMaturity + " cannot be later than (adjusted) bond maturity " + tempSch.dates().Last()); Utils.QL_REQUIRE( dealMaturity > tempSch.dates()[0], () => "deal maturity " + dealMaturity + " must be later than swap start date " + tempSch.dates()[0]); // the following might become an input parameter BusinessDayConvention paymentAdjustment = BusinessDayConvention.Following; Date finalDate = tempSch.calendar().adjust(dealMaturity, paymentAdjustment); Schedule schedule = tempSch.until(finalDate); // bondCleanPrice must be the (forward) clean price // at the floating schedule start date upfrontDate_ = schedule.startDate(); double dirtyPrice = bondCleanPrice_ + bond_.accruedAmount(upfrontDate_); double notional = bond_.notional(upfrontDate_); /* In the market asset swap, the bond is purchased in return for payment of the full price. The notional of the floating leg is then scaled by the full price. */ if (!parSwap_) notional *= dirtyPrice / 100.0; if (floatingDayCount == null) legs_[1] = new IborLeg(schedule, iborIndex) .withSpreads(spread) .withGearings(gearing) .withNotionals(notional) .withPaymentAdjustment(paymentAdjustment); else legs_[1] = new IborLeg(schedule, iborIndex) .withSpreads(spread) .withGearings(gearing) .withPaymentDayCounter(floatingDayCount) .withNotionals(notional) .withPaymentAdjustment(paymentAdjustment); foreach (CashFlow c in legs_[1]) c.registerWith(update); List<CashFlow> bondLeg = bond_.cashflows(); // skip bond redemption int i; for (i = 0; i < bondLeg.Count && bondLeg[i].date() <= dealMaturity; ++i) { // whatever might be the choice for the discounting engine // bond flows on upfrontDate_ must be discarded bool upfrontDateBondFlows = false; if (!bondLeg[i].hasOccurred(upfrontDate_, upfrontDateBondFlows)) legs_[0].Add(bondLeg[i]); } // if the first skipped cashflow is not the redemption // and it is a coupon then add the accrued coupon if (i < bondLeg.Count - 1) { Coupon c = bondLeg[i] as Coupon; if (c != null) { CashFlow accruedCoupon = new SimpleCashFlow(c.accruedAmount(dealMaturity), finalDate); legs_[0].Add(accruedCoupon); } } // add the nonParRepayment_ CashFlow nonParRepaymentFlow = new SimpleCashFlow(nonParRepayment_, finalDate); legs_[0].Add(nonParRepaymentFlow); Utils.QL_REQUIRE( !legs_[0].empty(), () => "empty bond leg to start with" ); // special flows if (parSwap_) { // upfront on the floating leg double upfront = (dirtyPrice - 100.0) / 100.0 * notional; CashFlow upfrontCashFlow = new SimpleCashFlow(upfront, upfrontDate_); legs_[1].Insert(0, upfrontCashFlow); // backpayment on the floating leg // (accounts for non-par redemption, if any) double backPayment = notional; CashFlow backPaymentCashFlow = new SimpleCashFlow(backPayment, finalDate); legs_[1].Add(backPaymentCashFlow); } else { // final notional exchange CashFlow finalCashFlow = new SimpleCashFlow(notional, finalDate); legs_[1].Add(finalCashFlow); } Utils.QL_REQUIRE( !legs_[0].empty(), () => "empty bond leg" ); foreach (CashFlow c in legs_[0]) c.registerWith(update); if (payBondCoupon) { payer_[0] = -1.0; payer_[1] = +1.0; } else { payer_[0] = +1.0; payer_[1] = -1.0; } }
//public ObservableCollection<DateTime> dates(int addingDays = 0) public void genDates(int addingDays = 0) { this.dates_.Clear(); //Period tenor = new Period(this.tenor_); QLNet.Calendar calendar = new SouthKorea(); Period tenor = new Period(this.frequencyEnum_); BusinessDayConvention bdc = this.businessDayConvEnum_; DateGeneration.Rule dateGen = this.dateGenEnum_; try { Schedule schedule = new Schedule(new Date(initialDate_), new Date(endDate_), tenor, calendar, bdc, bdc, dateGen, false); List<Date> ql_d = schedule.dates(); for (int i = 0; i < ql_d.Count; i++) { this.dates_.Add(ql_d[i]); } } catch (Exception) { OutputLogViewModel.addResult("schedule gen error"); } //test //for (int i = 0; i < 6; i++) //{ // this.dates_.Add(new DateTime()); //} //this.dates_ = d; //return d; }