public static List <CashFlow> OvernightLeg(List <double> nominals, Schedule schedule, BusinessDayConvention paymentAdjustment, OvernightIndex overnightIndex, List <double> gearings, List <double> spreads, DayCounter paymentDayCounter ) { if (nominals.Count == 0) { throw new ArgumentException("no nominal given"); } List <CashFlow> leg = new List <CashFlow>(); // the following is not always correct Calendar calendar = schedule.calendar(); Date refStart, start, refEnd, end; Date paymentDate; int n = schedule.Count; for (int i = 0; i < n - 1; ++i) { refStart = start = schedule.date(i); refEnd = end = schedule.date(i + 1); paymentDate = calendar.adjust(end, paymentAdjustment); if (i == 0 && !schedule.isRegular(i + 1)) { refStart = calendar.adjust(end - schedule.tenor(), paymentAdjustment); } if (i == n - 1 && !schedule.isRegular(i + 1)) { refEnd = calendar.adjust(start + schedule.tenor(), paymentAdjustment); } leg.Add(new OvernightIndexedCoupon(paymentDate, Utils.Get(nominals, i), start, end, overnightIndex, Utils.Get(gearings, i, 1.0), Utils.Get(spreads, i, 0.0), refStart, refEnd, paymentDayCounter)); } return(leg); }
public void BuildDates(QLNet.Calendar calendar, QLNet.DayCounter dc) { _dates.Resize(_tenors.Count); Date today = Settings.evaluationDate(); for (int i = 0; i < _tenors.Count; i++) { if (_tenors[i].units() == TimeUnit.Days) { _dates[i] = calendar.adjust(today + _tenors[i]); } else { _dates[i] = calendar.advance(today, _tenors[i], BusinessDayConvention.Following, true); } } QLNet.Utils.QL_REQUIRE(_dates.Count == _tenors.Count, () => "Date/Tenor mismatch"); // Build times _times.Resize(_dates.Count); for (int i = 0; i < _dates.Count; i++) { _times[i] = dc.yearFraction(today, _dates[i]); } _timeGrid = new TimeGrid(_times, _times.Count); // Log the date grid //log(); }
// setup public CommonVars() { calendar = new TARGET(); today = calendar.adjust(Date.Today); Settings.setEvaluationDate(today); faceAmount = 1000000.0; }
// todo // cleanup // SavedSettings backup; // setup public CommonVars() { calendar = new TARGET(); today = calendar.adjust(Date.Today); Settings.setEvaluationDate(today); faceAmount = 1000000.0; }
public override List <CashFlow> value() { if (notionals_.Count == 0) { throw new Exception("no notional given"); } List <CashFlow> cashflows = new List <CashFlow>(); // the following is not always correct Calendar calendar = schedule_.calendar(); Date refStart, start, refEnd, end; Date paymentDate; int n = schedule_.Count - 1; for (int i = 0; i < n; ++i) { refStart = start = schedule_.date(i); refEnd = end = schedule_.date(i + 1); paymentDate = calendar.adjust(end, paymentAdjustment_); if (i == 0 && !schedule_.isRegular(i + 1)) { refStart = calendar.adjust(end - schedule_.tenor(), paymentAdjustment_); } if (i == n - 1 && !schedule_.isRegular(i + 1)) { refEnd = calendar.adjust(start + schedule_.tenor(), paymentAdjustment_); } cashflows.Add(new AverageBMACoupon(paymentDate, Utils.Get <double>(notionals_, i, notionals_.Last()), start, end, index_, Utils.Get <double>(gearings_, i, 1.0), Utils.Get <double>(spreads_, i, 0.0), refStart, refEnd, paymentDayCounter_)); } return(cashflows); }
// creator public override List <CashFlow> value() { List <CashFlow> leg = new List <CashFlow>(); // the following is not always correct Calendar calendar = schedule_.calendar(); // first period might be short or long Date start = schedule_[0], end = schedule_[1]; Date paymentDate = calendar.adjust(start, paymentAdjustment_); double nominal = notionals_[0]; leg.Add(new Principal(nominal, nominal, paymentDate, start, end, dayCounter_, start, end)); paymentDate = calendar.adjust(end, paymentAdjustment_); leg.Add(new Principal(nominal * -1, 0, paymentDate, start, end, dayCounter_, start, end)); return(leg); }
// creator public override List <CashFlow> value() { List <CashFlow> leg = new List <CashFlow>(); // the following is not always correct Calendar calendar = schedule_.calendar(); // first period Date start = schedule_[0], end = schedule_[schedule_.Count - 1]; Date paymentDate = calendar.adjust(start, paymentAdjustment_); double nominal = notionals_[0]; double quota = nominal / (schedule_.Count - 1); leg.Add(new Principal(nominal * sign_, nominal, paymentDate, start, end, dayCounter_, start, end)); if (schedule_.Count == 2) { paymentDate = calendar.adjust(end, paymentAdjustment_); leg.Add(new Principal(nominal * sign_ * -1, 0, paymentDate, start, end, dayCounter_, start, end)); } else { end = schedule_[0]; // regular periods for (int i = 1; i <= schedule_.Count - 1; ++i) { start = end; end = schedule_[i]; paymentDate = calendar.adjust(start, paymentAdjustment_); nominal -= quota; leg.Add(new Principal(quota * sign_ * -1, nominal, paymentDate, start, end, dayCounter_, start, end)); } } return(leg); }
//protected Forward(DayCounter dayCounter, Calendar calendar, BusinessDayConvention businessDayConvention, // int settlementDays, Payoff payoff, Date valueDate, Date maturityDate, // Handle<YieldTermStructure> discountCurve = Handle<YieldTermStructure>()) { protected Forward(DayCounter dayCounter, Calendar calendar, BusinessDayConvention businessDayConvention, int settlementDays, Payoff payoff, Date valueDate, Date maturityDate, Handle<YieldTermStructure> discountCurve) { dayCounter_ = dayCounter; calendar_ = calendar; businessDayConvention_ = businessDayConvention; settlementDays_ = settlementDays; payoff_ = payoff; valueDate_ = valueDate; maturityDate_ = maturityDate; discountCurve_ = discountCurve; maturityDate_ = calendar_.adjust(maturityDate_, businessDayConvention_); Settings.registerWith(update); discountCurve_.registerWith(update); }
//protected Forward(DayCounter dayCounter, Calendar calendar, BusinessDayConvention businessDayConvention, // int settlementDays, Payoff payoff, Date valueDate, Date maturityDate, // Handle<YieldTermStructure> discountCurve = Handle<YieldTermStructure>()) { protected Forward(DayCounter dayCounter, Calendar calendar, BusinessDayConvention businessDayConvention, int settlementDays, Payoff payoff, Date valueDate, Date maturityDate, Handle <YieldTermStructure> discountCurve) { dayCounter_ = dayCounter; calendar_ = calendar; businessDayConvention_ = businessDayConvention; settlementDays_ = settlementDays; payoff_ = payoff; valueDate_ = valueDate; maturityDate_ = maturityDate; discountCurve_ = discountCurve; maturityDate_ = calendar_.adjust(maturityDate_, businessDayConvention_); Settings.registerWith(update); discountCurve_.registerWith(update); }
/*! \name Date calculations * * See <https://www.theice.com/marketdata/reports/170>. * @{ */ public override Date valueDate(Date fixingDate) { if (!isValidFixingDate(fixingDate)) { throw new Exception("Fixing date " + fixingDate + " is not valid"); } // http://www.bba.org.uk/bba/jsp/polopoly.jsp?d=225&a=1412 : // For all currencies other than EUR and GBP the period between // Fixing Date and Value Date will be two London business days // after the Fixing Date, or if that day is not both a London // business day and a business day in the principal financial centre // of the currency concerned, the next following day which is a // business day in both centres shall be the Value Date. Date d = fixingCalendar().advance(fixingDate, fixingDays_, TimeUnit.Days); return(jointCalendar_.adjust(d)); }
protected override void initializeDates() { earliestDate_ = calendar_.advance(evaluationDate_, new Period(settlementDays_, TimeUnit.Days), BusinessDayConvention.Following); Date maturity = earliestDate_ + tenor_; // dummy BMA index with curve/swap arguments BMAIndex clonedIndex = new BMAIndex(termStructureHandle_); Schedule bmaSchedule = new MakeSchedule().from(earliestDate_).to(maturity) .withTenor(bmaPeriod_) .withCalendar(bmaIndex_.fixingCalendar()) .withConvention(bmaConvention_) .backwards() .value(); Schedule liborSchedule = new MakeSchedule().from(earliestDate_).to(maturity) .withTenor(iborIndex_.tenor()) .withCalendar(iborIndex_.fixingCalendar()) .withConvention(iborIndex_.businessDayConvention()) .endOfMonth(iborIndex_.endOfMonth()) .backwards() .value(); swap_ = new BMASwap(BMASwap.Type.Payer, 100.0, liborSchedule, 0.75, // arbitrary 0.0, iborIndex_, iborIndex_.dayCounter(), bmaSchedule, clonedIndex, bmaDayCount_); swap_.setPricingEngine(new DiscountingSwapEngine(iborIndex_.forwardingTermStructure())); Date d = calendar_.adjust(swap_.maturityDate(), BusinessDayConvention.Following); int w = d.weekday(); Date nextWednesday = (w >= 4) ? d + new Period((11 - w), TimeUnit.Days) : d + new Period((4 - w), TimeUnit.Days); latestDate_ = clonedIndex.valueDate(clonedIndex.fixingCalendar().adjust(nextWednesday)); }
public CommonVars() { settlementDays = 2; nominal = 1000000.0; fixedConvention = BusinessDayConvention.Unadjusted; fixedFrequency = Frequency.Annual; fixedDayCount = new Thirty360(); index =new Euribor6M(termStructure); floatingConvention = index.businessDayConvention(); floatingTenor = index.tenor(); calendar = index.fixingCalendar(); today = calendar.adjust(Date.Today); Settings.setEvaluationDate(today); settlement = calendar.advance(today, settlementDays, TimeUnit.Days); termStructure.linkTo(Utilities.flatRate(settlement, 0.05, new Actual365Fixed())); }
public void setConventions() { calendar = new TARGET(); Date today = calendar.adjust(Date.Today); Settings.setEvaluationDate(today); optionBdc = BusinessDayConvention.ModifiedFollowing; dayCounter = new Actual365Fixed(); }
public Schedule( Date effectiveDate, Date terminationDate, Period tenor, Calendar calendar, BusinessDayConvention convention, BusinessDayConvention terminationDateConvention, DateGeneration.Rule rule, bool endOfMonth, Date firstDate, Date nextToLastDate) { // first save the properties fullInterface_ = true; tenor_ = tenor; calendar_ = calendar; convention_ = convention; terminationDateConvention_ = terminationDateConvention; rule_ = rule; endOfMonth_ = endOfMonth; if ( firstDate == effectiveDate ) firstDate_ = null; else firstDate_ = firstDate; if ( nextToLastDate == terminationDate ) nextToLastDate_ = null; else nextToLastDate_ = nextToLastDate; // sanity checks Utils.QL_REQUIRE(terminationDate != null, "null termination date"); // in many cases (e.g. non-expired bonds) the effective date is not // really necessary. In these cases a decent placeholder is enough if ( effectiveDate == null && firstDate == null && rule== DateGeneration.Rule.Backward) { Date evalDate = Settings.evaluationDate(); Utils.QL_REQUIRE(evalDate < terminationDate, "null effective date"); int y; if (nextToLastDate != null) { y = (nextToLastDate - evalDate)/366 + 1; effectiveDate = nextToLastDate - new Period(y,TimeUnit.Years); } else { y = (terminationDate - evalDate)/366 + 1; effectiveDate = terminationDate - new Period(y,TimeUnit.Years); } } else Utils.QL_REQUIRE(effectiveDate != null, "null effective date"); if (tenor_.length() == 0) rule_ = DateGeneration.Rule.Zero; else Utils.QL_REQUIRE(tenor.length()>0, "non positive tenor (" + tenor + ") not allowed"); if (firstDate_ != null) { switch (rule_) { case DateGeneration.Rule.Backward: case DateGeneration.Rule.Forward: Utils.QL_REQUIRE(firstDate_ > effectiveDate && firstDate_ < terminationDate, "first date (" + firstDate_ + ") out of effective-termination date range [" + effectiveDate + ", " + terminationDate + ")"); // we should ensure that the above condition is still verified after adjustment break; case DateGeneration.Rule.ThirdWednesday: Utils.QL_REQUIRE(IMM.isIMMdate(firstDate_, false),"first date (" + firstDate_ + ") is not an IMM date"); break; case DateGeneration.Rule.Zero: case DateGeneration.Rule.Twentieth: case DateGeneration.Rule.TwentiethIMM: case DateGeneration.Rule.OldCDS: case DateGeneration.Rule.CDS: Utils.QL_FAIL("first date incompatible with " + rule_ + " date generation rule"); break; default: Utils.QL_FAIL("unknown rule (" + rule_ + ")"); break; } } if (nextToLastDate_ != null) { switch (rule_) { case DateGeneration.Rule.Backward: case DateGeneration.Rule.Forward: Utils.QL_REQUIRE(nextToLastDate_ > effectiveDate && nextToLastDate_ < terminationDate, "next to last date (" + nextToLastDate_ + ") out of effective-termination date range (" + effectiveDate + ", " + terminationDate + "]"); // we should ensure that the above condition is still verified after adjustment break; case DateGeneration.Rule.ThirdWednesday: Utils.QL_REQUIRE(IMM.isIMMdate(nextToLastDate_, false), "next-to-last date (" + nextToLastDate_ + ") is not an IMM date"); break; case DateGeneration.Rule.Zero: case DateGeneration.Rule.Twentieth: case DateGeneration.Rule.TwentiethIMM: case DateGeneration.Rule.OldCDS: case DateGeneration.Rule.CDS: Utils.QL_FAIL("next to last date incompatible with " + rule_ + " date generation rule"); break; default: Utils.QL_FAIL("unknown rule (" + rule_ + ")"); break; } } // calendar needed for endOfMonth adjustment Calendar nullCalendar = new NullCalendar(); int periods = 1; Date seed = new Date() , exitDate; switch (rule_) { case DateGeneration.Rule.Zero: tenor_ = new Period(0, TimeUnit.Years); dates_.Add(effectiveDate); dates_.Add(terminationDate); isRegular_.Add(true); break; case DateGeneration.Rule.Backward: dates_.Add(terminationDate); seed = terminationDate; if (nextToLastDate_ != null) { dates_.Insert(0, nextToLastDate_); Date temp = nullCalendar.advance(seed, -periods * tenor_, convention_, endOfMonth_); if (temp != nextToLastDate_) isRegular_.Insert(0, false); else isRegular_.Insert(0, true); seed = nextToLastDate_; } exitDate = effectiveDate; if (firstDate_ != null) exitDate = firstDate_; while (true) { Date temp = nullCalendar.advance(seed, -periods * tenor_, convention_, endOfMonth_); if (temp < exitDate) { if (firstDate_ != null && (calendar_.adjust(dates_.First(), convention_) != calendar_.adjust(firstDate_, convention_))) { dates_.Insert(0, firstDate_); isRegular_.Insert(0, false); } break; } else { // skip dates that would result in duplicates // after adjustment if (calendar_.adjust(dates_.First(), convention_) != calendar_.adjust(temp, convention_)) { dates_.Insert(0, temp); isRegular_.Insert(0, true); } ++periods; } } if (calendar_.adjust(dates_.First(), convention) != calendar_.adjust(effectiveDate, convention)) { dates_.Insert(0, effectiveDate); isRegular_.Insert(0, false); } break; case DateGeneration.Rule.Twentieth: case DateGeneration.Rule.TwentiethIMM: case DateGeneration.Rule.ThirdWednesday: case DateGeneration.Rule.OldCDS: case DateGeneration.Rule.CDS: Utils.QL_REQUIRE(!endOfMonth,"endOfMonth convention incompatible with " + rule_ + " date generation rule"); goto case DateGeneration.Rule.Forward; // fall through case DateGeneration.Rule.Forward: if (rule_ == DateGeneration.Rule.CDS) { dates_.Add(previousTwentieth(effectiveDate, DateGeneration.Rule.CDS)); } else { dates_.Add(effectiveDate); } seed = dates_.Last(); if (firstDate_ != null) { dates_.Add(firstDate_); Date temp = nullCalendar.advance(seed, periods * tenor_, convention_, endOfMonth_); if (temp != firstDate_) isRegular_.Add(false); else isRegular_.Add(true); seed = firstDate_; } else if (rule_ == DateGeneration.Rule.Twentieth || rule_ == DateGeneration.Rule.TwentiethIMM || rule_ == DateGeneration.Rule.OldCDS || rule_ == DateGeneration.Rule.CDS) { Date next20th = nextTwentieth(effectiveDate, rule_); if (rule_ == DateGeneration.Rule.OldCDS) { // distance rule inforced in natural days long stubDays = 30; if (next20th - effectiveDate < stubDays) { // +1 will skip this one and get the next next20th = nextTwentieth(next20th + 1, rule_); } } if (next20th != effectiveDate) { dates_.Add(next20th); isRegular_.Add(false); seed = next20th; } } exitDate = terminationDate; if (nextToLastDate_ != null) exitDate = nextToLastDate_; while (true) { Date temp = nullCalendar.advance(seed, periods * tenor_, convention_, endOfMonth_); if (temp > exitDate) { if (nextToLastDate_ != null && (calendar_.adjust(dates_.Last(), convention_) != calendar_.adjust(nextToLastDate_, convention_))) { dates_.Add(nextToLastDate_); isRegular_.Add(false); } break; } else { // skip dates that would result in duplicates // after adjustment if (calendar_.adjust(dates_.Last(), convention_) != calendar_.adjust(temp, convention_)) { dates_.Add(temp); isRegular_.Add(true); } ++periods; } } if (calendar_.adjust(dates_.Last(), terminationDateConvention_) != calendar_.adjust(terminationDate, terminationDateConvention_)) { if (rule_ == DateGeneration.Rule.Twentieth || rule_ == DateGeneration.Rule.TwentiethIMM || rule_ == DateGeneration.Rule.OldCDS || rule_ == DateGeneration.Rule.CDS) { dates_.Add(nextTwentieth(terminationDate, rule_)); isRegular_.Add(true); } else { dates_.Add(terminationDate); isRegular_.Add(false); } } break; default: Utils.QL_FAIL("unknown rule (" + rule_ + ")"); break; } // adjustments if (rule_ == DateGeneration.Rule.ThirdWednesday) for (int i = 1; i < dates_.Count-1; ++i) dates_[i] = Date.nthWeekday(3, DayOfWeek.Wednesday, dates_[i].Month, dates_[i].Year); if (endOfMonth && calendar_.isEndOfMonth(seed)) { // adjust to end of month if (convention_ == BusinessDayConvention.Unadjusted) { for (int i = 0; i < dates_.Count-1; ++i) dates_[i] = Date.endOfMonth(dates_[i]); } else { for (int i = 0; i < dates_.Count-1; ++i) dates_[i] = calendar_.endOfMonth(dates_[i]); } if (terminationDateConvention_ != BusinessDayConvention.Unadjusted) dates_[dates_.Count - 1] = calendar_.endOfMonth(dates_.Last()); } else { // first date not adjusted for CDS schedules if (rule_ != DateGeneration.Rule.OldCDS) dates_[0] = calendar_.adjust(dates_[0], convention_); for (int i = 1; i < dates_.Count-1; ++i) dates_[i] = calendar_.adjust(dates_[i], convention_); // termination date is NOT adjusted as per ISDA specifications, unless otherwise specified in the // confirmation of the deal or unless we're creating a CDS schedule if (terminationDateConvention_ != BusinessDayConvention.Unadjusted || rule_ == DateGeneration.Rule.Twentieth || rule_ == DateGeneration.Rule.TwentiethIMM || rule_ == DateGeneration.Rule.OldCDS || rule_ == DateGeneration.Rule.CDS) dates_[dates_.Count - 1] = calendar_.adjust(dates_.Last(), terminationDateConvention_); } // final safety check to remove duplicated last dates, if any // it can happen if EOM is applied to two near dates if (dates_.Count >= 2 && dates_[dates_.Count - 2] >= dates_.Last()) { isRegular_[dates_.Count() - 2] = (dates_[dates_.Count() - 2] == dates_.Last()); dates_[dates_.Count() - 2] = dates_.Last(); dates_.RemoveAt(dates_.Count - 1); isRegular_.RemoveAt(isRegular_.Count - 1); } }
public ZeroCouponInflationSwap(Type type, double nominal, Date startDate, // start date of contract (only) Date maturity, // this is pre-adjustment! Calendar fixCalendar, BusinessDayConvention fixConvention, DayCounter dayCounter, double fixedRate, ZeroInflationIndex infIndex, Period observationLag, bool adjustInfObsDates, Calendar infCalendar, BusinessDayConvention infConvention) : base(2) { type_ = type; nominal_ = nominal; fixedRate_ = fixedRate; infIndex_ = infIndex; observationLag_ = observationLag; dayCounter_ = dayCounter; // first check compatibility of index and swap definitions if (infIndex_.interpolated()) { Period pShift = new Period(infIndex_.frequency()); if ((observationLag_ - pShift) <= infIndex_.availabilityLag()) { throw new ApplicationException( "inconsistency between swap observation of index " + observationLag_ + " index availability " + infIndex_.availabilityLag() + " interpolated index period " + pShift + " and index availability " + infIndex_.availabilityLag() + " need (obsLag-index period) > availLag"); } } else { if (infIndex_.availabilityLag() >= observationLag_) { throw new ApplicationException( "index tries to observe inflation fixings that do not yet exist: " + " availability lag " + infIndex_.availabilityLag() + " versus obs lag = " + observationLag_); } } if (infCalendar == null) { infCalendar = fixCalendar; } if (infConvention == new BusinessDayConvention()) { infConvention = fixConvention; } if (adjustInfObsDates) { baseDate_ = infCalendar.adjust(startDate - observationLag_, infConvention); obsDate_ = infCalendar.adjust(maturity - observationLag_, infConvention); } else { baseDate_ = startDate - observationLag_; obsDate_ = maturity - observationLag_; } Date infPayDate = infCalendar.adjust(maturity, infConvention); Date fixedPayDate = fixCalendar.adjust(maturity, fixConvention); // At this point the index may not be able to forecast // i.e. do not want to force the existence of an inflation // term structure before allowing users to create instruments. double T = Utils.inflationYearFraction(infIndex_.frequency(), infIndex_.interpolated(), dayCounter_, baseDate_, obsDate_); // N.B. the -1.0 is because swaps only exchange growth, not notionals as well double fixedAmount = nominal * (Math.Pow(1.0 + fixedRate, T) - 1.0); legs_[0].Add(new SimpleCashFlow(fixedAmount, fixedPayDate)); bool growthOnly = true; legs_[1].Add(new IndexedCashFlow(nominal, infIndex, baseDate_, obsDate_, infPayDate, growthOnly)); for (int j = 0; j < 2; ++j) { for (int i = 0; i < legs_[j].Count; i++) { legs_[j][i].registerWith(update); } } switch (type_) { case Type.Payer: payer_[0] = +1.0; payer_[1] = -1.0; break; case Type.Receiver: payer_[0] = -1.0; payer_[1] = +1.0; break; default: throw new ApplicationException("Unknown zero-inflation-swap type"); } }
public OvernightIndexedSwap value() { Date startDate; if (effectiveDate_ != null) { startDate = effectiveDate_; } else { Date refDate = Settings.evaluationDate(); // if the evaluation date is not a business day // then move to the next business day refDate = calendar_.adjust(refDate); Date spotDate = calendar_.advance(refDate, new Period(settlementDays_, TimeUnit.Days)); startDate = spotDate + forwardStart_; if (forwardStart_.length() < 0) { startDate = calendar_.adjust(startDate, BusinessDayConvention.Preceding); } else { startDate = calendar_.adjust(startDate, BusinessDayConvention.Following); } } // OIS end of month default bool usedEndOfMonth = isDefaultEOM_ ? calendar_.isEndOfMonth(startDate) : endOfMonth_; Date endDate = terminationDate_; if (endDate == null) { if (usedEndOfMonth) { endDate = calendar_.advance(startDate, swapTenor_, BusinessDayConvention.ModifiedFollowing, usedEndOfMonth); } else { endDate = startDate + swapTenor_; } } Schedule schedule = new Schedule(startDate, endDate, new Period(paymentFrequency_), calendar_, BusinessDayConvention.ModifiedFollowing, BusinessDayConvention.ModifiedFollowing, rule_, usedEndOfMonth); double?usedFixedRate = fixedRate_; if (fixedRate_ == null) { OvernightIndexedSwap temp = new OvernightIndexedSwap(type_, nominal_, schedule, 0.0, // fixed rate fixedDayCount_, overnightIndex_, overnightSpread_); if (engine_ == null) { Handle <YieldTermStructure> disc = overnightIndex_.forwardingTermStructure(); Utils.QL_REQUIRE(!disc.empty(), () => "null term structure set to this instance of " + overnightIndex_.name()); bool includeSettlementDateFlows = false; IPricingEngine engine = new DiscountingSwapEngine(disc, includeSettlementDateFlows); temp.setPricingEngine(engine); } else { temp.setPricingEngine(engine_); } usedFixedRate = temp.fairRate(); } OvernightIndexedSwap ois = new OvernightIndexedSwap(type_, nominal_, schedule, usedFixedRate.Value, fixedDayCount_, overnightIndex_, overnightSpread_); if (engine_ == null) { Handle <YieldTermStructure> disc = overnightIndex_.forwardingTermStructure(); bool includeSettlementDateFlows = false; IPricingEngine engine = new DiscountingSwapEngine(disc, includeSettlementDateFlows); ois.setPricingEngine(engine); } else { ois.setPricingEngine(engine_); } return(ois); }
public Schedule(Date effectiveDate, Date terminationDate, Period tenor, Calendar calendar, BusinessDayConvention convention, BusinessDayConvention terminationDateConvention, DateGeneration.Rule rule, bool endOfMonth, Date firstDate = null, Date nextToLastDate = null) { // first save the properties tenor_ = tenor; if (calendar == null) { calendar_ = new NullCalendar(); } else { calendar_ = calendar; } convention_ = convention; terminationDateConvention_ = terminationDateConvention; rule_ = rule; endOfMonth_ = (tenor != null && tenor < new Period(1, TimeUnit.Months)) ? false : endOfMonth; if (firstDate == effectiveDate) { firstDate_ = null; } else { firstDate_ = firstDate; } if (nextToLastDate == terminationDate) { nextToLastDate_ = null; } else { nextToLastDate_ = nextToLastDate; } // sanity checks Utils.QL_REQUIRE(terminationDate != null, () => "null termination date"); // in many cases (e.g. non-expired bonds) the effective date is not // really necessary. In these cases a decent placeholder is enough if (effectiveDate == null && firstDate == null && rule == DateGeneration.Rule.Backward) { Date evalDate = Settings.evaluationDate(); Utils.QL_REQUIRE(evalDate < terminationDate, () => "null effective date"); int y; if (nextToLastDate != null) { y = (nextToLastDate - evalDate) / 366 + 1; effectiveDate = nextToLastDate - new Period(y, TimeUnit.Years); } else { y = (terminationDate - evalDate) / 366 + 1; effectiveDate = terminationDate - new Period(y, TimeUnit.Years); } } else { Utils.QL_REQUIRE(effectiveDate != null, () => "null effective date"); } Utils.QL_REQUIRE(effectiveDate < terminationDate, () => "effective date (" + effectiveDate + ") later than or equal to termination date (" + terminationDate + ")" ); if (tenor_.length() == 0) { rule_ = DateGeneration.Rule.Zero; } else { Utils.QL_REQUIRE(tenor.length() > 0, () => "non positive tenor (" + tenor + ") not allowed"); } if (firstDate_ != null) { switch (rule_.Value) { case DateGeneration.Rule.Backward: case DateGeneration.Rule.Forward: Utils.QL_REQUIRE(firstDate_ > effectiveDate && firstDate_ < terminationDate, () => "first date (" + firstDate_ + ") out of effective-termination date range [" + effectiveDate + ", " + terminationDate + ")"); // we should ensure that the above condition is still verified after adjustment break; case DateGeneration.Rule.ThirdWednesday: Utils.QL_REQUIRE(IMM.isIMMdate(firstDate_, false), () => "first date (" + firstDate_ + ") is not an IMM date"); break; case DateGeneration.Rule.Zero: case DateGeneration.Rule.Twentieth: case DateGeneration.Rule.TwentiethIMM: case DateGeneration.Rule.OldCDS: case DateGeneration.Rule.CDS: Utils.QL_FAIL("first date incompatible with " + rule_.Value + " date generation rule"); break; default: Utils.QL_FAIL("unknown rule (" + rule_.Value + ")"); break; } } if (nextToLastDate_ != null) { switch (rule_.Value) { case DateGeneration.Rule.Backward: case DateGeneration.Rule.Forward: Utils.QL_REQUIRE(nextToLastDate_ > effectiveDate && nextToLastDate_ < terminationDate, () => "next to last date (" + nextToLastDate_ + ") out of effective-termination date range (" + effectiveDate + ", " + terminationDate + "]"); // we should ensure that the above condition is still verified after adjustment break; case DateGeneration.Rule.ThirdWednesday: Utils.QL_REQUIRE(IMM.isIMMdate(nextToLastDate_, false), () => "next-to-last date (" + nextToLastDate_ + ") is not an IMM date"); break; case DateGeneration.Rule.Zero: case DateGeneration.Rule.Twentieth: case DateGeneration.Rule.TwentiethIMM: case DateGeneration.Rule.OldCDS: case DateGeneration.Rule.CDS: Utils.QL_FAIL("next to last date incompatible with " + rule_.Value + " date generation rule"); break; default: Utils.QL_FAIL("unknown rule (" + rule_.Value + ")"); break; } } // calendar needed for endOfMonth adjustment Calendar nullCalendar = new NullCalendar(); int periods = 1; Date seed = new Date(), exitDate = new Date(); switch (rule_.Value) { case DateGeneration.Rule.Zero: tenor_ = new Period(0, TimeUnit.Years); dates_.Add(effectiveDate); dates_.Add(terminationDate); isRegular_.Add(true); break; case DateGeneration.Rule.Backward: dates_.Add(terminationDate); seed = terminationDate; if (nextToLastDate_ != null) { dates_.Insert(0, nextToLastDate_); Date temp = nullCalendar.advance(seed, -periods * tenor_, convention_, endOfMonth_.Value); if (temp != nextToLastDate_) { isRegular_.Insert(0, false); } else { isRegular_.Insert(0, true); } seed = nextToLastDate_; } exitDate = effectiveDate; if (firstDate_ != null) { exitDate = firstDate_; } while (true) { Date temp = nullCalendar.advance(seed, -periods * tenor_, convention_, endOfMonth_.Value); if (temp < exitDate) { if (firstDate_ != null && (calendar_.adjust(dates_.First(), convention_) != calendar_.adjust(firstDate_, convention_))) { dates_.Insert(0, firstDate_); isRegular_.Insert(0, false); } break; } else { // skip dates that would result in duplicates // after adjustment if (calendar_.adjust(dates_.First(), convention_) != calendar_.adjust(temp, convention_)) { dates_.Insert(0, temp); isRegular_.Insert(0, true); } ++periods; } } if (calendar_.adjust(dates_.First(), convention) != calendar_.adjust(effectiveDate, convention)) { dates_.Insert(0, effectiveDate); isRegular_.Insert(0, false); } break; case DateGeneration.Rule.Twentieth: case DateGeneration.Rule.TwentiethIMM: case DateGeneration.Rule.ThirdWednesday: case DateGeneration.Rule.OldCDS: case DateGeneration.Rule.CDS: Utils.QL_REQUIRE(!endOfMonth, () => "endOfMonth convention incompatible with " + rule_.Value + " date generation rule"); goto case DateGeneration.Rule.Forward; // fall through case DateGeneration.Rule.Forward: if (rule_.Value == DateGeneration.Rule.CDS) { dates_.Add(previousTwentieth(effectiveDate, DateGeneration.Rule.CDS)); } else { dates_.Add(effectiveDate); } seed = dates_.Last(); if (firstDate_ != null) { dates_.Add(firstDate_); Date temp = nullCalendar.advance(seed, periods * tenor_, convention_, endOfMonth_.Value); if (temp != firstDate_) { isRegular_.Add(false); } else { isRegular_.Add(true); } seed = firstDate_; } else if (rule_.Value == DateGeneration.Rule.Twentieth || rule_.Value == DateGeneration.Rule.TwentiethIMM || rule_.Value == DateGeneration.Rule.OldCDS || rule_.Value == DateGeneration.Rule.CDS) { Date next20th = nextTwentieth(effectiveDate, rule_.Value); if (rule_ == DateGeneration.Rule.OldCDS) { // distance rule inforced in natural days long stubDays = 30; if (next20th - effectiveDate < stubDays) { // +1 will skip this one and get the next next20th = nextTwentieth(next20th + 1, rule_.Value); } } if (next20th != effectiveDate) { dates_.Add(next20th); isRegular_.Add(false); seed = next20th; } } exitDate = terminationDate; if (nextToLastDate_ != null) { exitDate = nextToLastDate_; } while (true) { Date temp = nullCalendar.advance(seed, periods * tenor_, convention_, endOfMonth_.Value); if (temp > exitDate) { if (nextToLastDate_ != null && (calendar_.adjust(dates_.Last(), convention_) != calendar_.adjust(nextToLastDate_, convention_))) { dates_.Add(nextToLastDate_); isRegular_.Add(false); } break; } else { // skip dates that would result in duplicates // after adjustment if (calendar_.adjust(dates_.Last(), convention_) != calendar_.adjust(temp, convention_)) { dates_.Add(temp); isRegular_.Add(true); } ++periods; } } if (calendar_.adjust(dates_.Last(), terminationDateConvention_.Value) != calendar_.adjust(terminationDate, terminationDateConvention_.Value)) { if (rule_.Value == DateGeneration.Rule.Twentieth || rule_.Value == DateGeneration.Rule.TwentiethIMM || rule_.Value == DateGeneration.Rule.OldCDS || rule_.Value == DateGeneration.Rule.CDS) { dates_.Add(nextTwentieth(terminationDate, rule_.Value)); isRegular_.Add(true); } else { dates_.Add(terminationDate); isRegular_.Add(false); } } break; default: Utils.QL_FAIL("unknown rule (" + rule_.Value + ")"); break; } // adjustments if (rule_ == DateGeneration.Rule.ThirdWednesday) { for (int i = 1; i < dates_.Count - 1; ++i) { dates_[i] = Date.nthWeekday(3, DayOfWeek.Wednesday, dates_[i].Month, dates_[i].Year); } } if (endOfMonth && calendar_.isEndOfMonth(seed)) { // adjust to end of month if (convention_ == BusinessDayConvention.Unadjusted) { for (int i = 1; i < dates_.Count - 1; ++i) { dates_[i] = Date.endOfMonth(dates_[i]); } } else { for (int i = 1; i < dates_.Count - 1; ++i) { dates_[i] = calendar_.endOfMonth(dates_[i]); } } if (terminationDateConvention_ != BusinessDayConvention.Unadjusted) { dates_[0] = calendar_.endOfMonth(dates_.First()); dates_[dates_.Count - 1] = calendar_.endOfMonth(dates_.Last()); } else { // the termination date is the first if going backwards, // the last otherwise. if (rule_ == DateGeneration.Rule.Backward) { dates_[dates_.Count - 1] = Date.endOfMonth(dates_.Last()); } else { dates_[0] = Date.endOfMonth(dates_.First()); } } } else { // first date not adjusted for CDS schedules if (rule_ != DateGeneration.Rule.OldCDS) { dates_[0] = calendar_.adjust(dates_[0], convention_); } for (int i = 1; i < dates_.Count - 1; ++i) { dates_[i] = calendar_.adjust(dates_[i], convention_); } // termination date is NOT adjusted as per ISDA specifications, unless otherwise specified in the // confirmation of the deal or unless we're creating a CDS schedule if (terminationDateConvention_.Value != BusinessDayConvention.Unadjusted || rule_.Value == DateGeneration.Rule.Twentieth || rule_.Value == DateGeneration.Rule.TwentiethIMM || rule_.Value == DateGeneration.Rule.OldCDS || rule_.Value == DateGeneration.Rule.CDS) { dates_[dates_.Count - 1] = calendar_.adjust(dates_.Last(), terminationDateConvention_.Value); } } // Final safety checks to remove extra next-to-last date, if // necessary. It can happen to be equal or later than the end // date due to EOM adjustments (see the Schedule test suite // for an example). if (dates_.Count >= 2 && dates_[dates_.Count - 2] >= dates_.Last()) { isRegular_[isRegular_.Count - 2] = (dates_[dates_.Count - 2] == dates_.Last()); dates_[dates_.Count - 2] = dates_.Last(); dates_.RemoveAt(dates_.Count - 1); isRegular_.RemoveAt(isRegular_.Count - 1); } if (dates_.Count >= 2 && dates_[1] <= dates_.First()) { isRegular_[1] = (dates_[1] == dates_.First()); dates_[1] = dates_.First(); dates_.RemoveAt(0); isRegular_.RemoveAt(0); } Utils.QL_REQUIRE(dates_.Count > 1, () => "degenerate single date (" + dates_[0] + ") schedule" + "\n seed date: " + seed + "\n exit date: " + exitDate + "\n effective date: " + effectiveDate + "\n first date: " + firstDate + "\n next to last date: " + nextToLastDate + "\n termination date: " + terminationDate + "\n generation rule: " + rule_.Value + "\n end of month: " + endOfMonth_.Value); }
// setup public CommonVars() { // option variables nominals = new List<double>{1000000}; frequency = Frequency.Annual; // usual setup calendar = new UnitedKingdom(); convention = BusinessDayConvention.ModifiedFollowing; Date today = new Date(13, Month.August, 2007); evaluationDate = calendar.adjust(today); Settings.setEvaluationDate(evaluationDate); settlementDays = 0; fixingDays = 0; settlement = calendar.advance(today,settlementDays,TimeUnit.Days); dc = new Thirty360(); // yoy index // fixing data Date from = new Date(1, Month.January, 2005); Date to = new Date(13, Month.August, 2007); Schedule rpiSchedule = new MakeSchedule().from(from).to(to) .withConvention(BusinessDayConvention.ModifiedFollowing) .withCalendar(new UnitedKingdom()) .withTenor(new Period(1,TimeUnit.Months)).value(); double[] fixData = { 189.9, 189.9, 189.6, 190.5, 191.6, 192.0, 192.2, 192.2, 192.6, 193.1, 193.3, 193.6, 194.1, 193.4, 194.2, 195.0, 196.5, 197.7, 198.5, 198.5, 199.2, 200.1, 200.4, 201.1, 202.7, 201.6, 203.1, 204.4, 205.4, 206.2, 207.3, -999.0, -999 }; // link from yoy index to yoy TS bool interp = false; iir = new YYUKRPIr(interp, hy); for (int i=0; i<rpiSchedule.Count;i++) { iir.addFixing(rpiSchedule[i], fixData[i]); } YieldTermStructure nominalFF = new FlatForward(evaluationDate, 0.05, new ActualActual()); nominalTS.linkTo(nominalFF); // now build the YoY inflation curve Period observationLag = new Period(2,TimeUnit.Months); Datum[] yyData = { new Datum( new Date(13, Month.August, 2008), 2.95 ), new Datum( new Date(13, Month.August, 2009), 2.95 ), new Datum( new Date(13, Month.August, 2010), 2.93 ), new Datum( new Date(15, Month.August, 2011), 2.955 ), new Datum( new Date(13, Month.August, 2012), 2.945 ), new Datum( new Date(13, Month.August, 2013), 2.985 ), new Datum( new Date(13, Month.August, 2014), 3.01 ), new Datum( new Date(13, Month.August, 2015), 3.035 ), new Datum( new Date(13, Month.August, 2016), 3.055 ), // note that new Datum( new Date(13, Month.August, 2017), 3.075 ), // some dates will be on new Datum( new Date(13, Month.August, 2019), 3.105 ), // holidays but the payment new Datum( new Date(15, Month.August, 2022), 3.135 ), // calendar will roll them new Datum( new Date(13, Month.August, 2027), 3.155 ), new Datum( new Date(13, Month.August, 2032), 3.145 ), new Datum( new Date(13, Month.August, 2037), 3.145 ) }; // now build the helpers ... List<BootstrapHelper<YoYInflationTermStructure>> helpers = makeHelpers(yyData, yyData.Length, iir, observationLag, calendar, convention, dc); double baseYYRate = yyData[0].rate/100.0; PiecewiseYoYInflationCurve<Linear> pYYTS = new PiecewiseYoYInflationCurve<Linear>( evaluationDate, calendar, dc, observationLag, iir.frequency(),iir.interpolated(), baseYYRate, new Handle<YieldTermStructure>(nominalTS), helpers); pYYTS.recalculate(); yoyTS = pYYTS as YoYInflationTermStructure; // make sure that the index has the latest yoy term structure hy.linkTo(pYYTS); }
// creator public override List <CashFlow> value() { if (couponRates_.Count == 0) { throw new ArgumentException("no coupon rates given"); } if (notionals_.Count == 0) { throw new ArgumentException("no nominals given"); } List <CashFlow> leg = new List <CashFlow>(); Calendar schCalendar = schedule_.calendar(); // first period might be short or long Date start = schedule_[0], end = schedule_[1]; Date paymentDate = calendar_.adjust(end, paymentAdjustment_); Date exCouponDate = null; InterestRate rate = couponRates_[0]; double nominal = notionals_[0]; if (exCouponPeriod_ != null) { exCouponDate = exCouponCalendar_.advance(paymentDate, -exCouponPeriod_, exCouponAdjustment_, exCouponEndOfMonth_); } if (schedule_.isRegular(1)) { if (!(firstPeriodDC_ == null || firstPeriodDC_ == rate.dayCounter())) { throw new ArgumentException("regular first coupon does not allow a first-period day count"); } leg.Add(new FixedRateCoupon(nominal, paymentDate, rate, start, end, start, end, exCouponDate)); } else { Date refer = end - schedule_.tenor(); refer = schCalendar.adjust(refer, schedule_.businessDayConvention()); InterestRate r = new InterestRate(rate.rate(), (firstPeriodDC_ == null || firstPeriodDC_.empty()) ? rate.dayCounter() : firstPeriodDC_, rate.compounding(), rate.frequency()); leg.Add(new FixedRateCoupon(nominal, paymentDate, r, start, end, refer, end, exCouponDate)); } // regular periods for (int i = 2; i < schedule_.Count - 1; ++i) { start = end; end = schedule_[i]; paymentDate = calendar_.adjust(end, paymentAdjustment_); if (exCouponPeriod_ != null) { exCouponDate = exCouponCalendar_.advance(paymentDate, -exCouponPeriod_, exCouponAdjustment_, exCouponEndOfMonth_); } if ((i - 1) < couponRates_.Count) { rate = couponRates_[i - 1]; } else { rate = couponRates_.Last(); } if ((i - 1) < notionals_.Count) { nominal = notionals_[i - 1]; } else { nominal = notionals_.Last(); } leg.Add(new FixedRateCoupon(nominal, paymentDate, rate, start, end, start, end, exCouponDate)); } if (schedule_.Count > 2) { // last period might be short or long int N = schedule_.Count; start = end; end = schedule_[N - 1]; paymentDate = calendar_.adjust(end, paymentAdjustment_); if (exCouponPeriod_ != null) { exCouponDate = exCouponCalendar_.advance(paymentDate, -exCouponPeriod_, exCouponAdjustment_, exCouponEndOfMonth_); } if ((N - 2) < couponRates_.Count) { rate = couponRates_[N - 2]; } else { rate = couponRates_.Last(); } if ((N - 2) < notionals_.Count) { nominal = notionals_[N - 2]; } else { nominal = notionals_.Last(); } if (schedule_.isRegular(N - 1)) { leg.Add(new FixedRateCoupon(nominal, paymentDate, rate, start, end, start, end, exCouponDate)); } else { Date refer = start + schedule_.tenor(); refer = schCalendar.adjust(refer, schedule_.businessDayConvention()); leg.Add(new FixedRateCoupon(nominal, paymentDate, rate, start, end, start, refer, exCouponDate)); } } return(leg); }
public CommonVars() { type = VanillaSwap.Type.Payer; settlementDays = 2; nominal = 100.0; fixedConvention = BusinessDayConvention.Unadjusted; floatingConvention = BusinessDayConvention.ModifiedFollowing; fixedFrequency = Frequency.Annual; floatingFrequency = Frequency.Semiannual; fixedDayCount = new Thirty360(); index = new Euribor(new Period(floatingFrequency), termStructure); calendar = index.fixingCalendar(); today = calendar.adjust(Date.Today); Settings.setEvaluationDate(today); settlement = calendar.advance(today, settlementDays, TimeUnit.Days); termStructure.linkTo(Utilities.flatRate(settlement, 0.05, new Actual365Fixed())); }
public Schedule(Date effectiveDate__, Date terminationDate__, Period tenor__, Calendar calendar__, BusinessDayConvention convention__, BusinessDayConvention terminationDateConvention__, DateGeneration.Rule rule__, bool endOfMonth__, Date firstDate__, Date nextToLastDate__) { // first save the properties fullInterface_ = true; tenor_ = tenor__; calendar_ = calendar__; convention_ = convention__; terminationDateConvention_ = terminationDateConvention__; rule_ = rule__; endOfMonth_ = endOfMonth__; firstDate_ = firstDate__; nextToLastDate_ = nextToLastDate__; // sanity checks if (effectiveDate__ == null) { throw new ArgumentException("Null effective date"); } if (terminationDate__ == null) { throw new ArgumentException("Null termination date"); } if (effectiveDate__ >= terminationDate__) { throw new ArgumentException("Effective date (" + effectiveDate__ + ") is later than or equal to termination date (" + terminationDate__ + ")"); } if (tenor_.length() == 0) { rule_ = DateGeneration.Rule.Zero; } else if (tenor_.length() < 0) { throw new ArgumentException("Non positive tenor (" + tenor_ + ") is not allowed"); } if (firstDate_ != null) { switch (rule_) { case DateGeneration.Rule.Backward: case DateGeneration.Rule.Forward: if (!(firstDate_ > effectiveDate__ && firstDate_ < terminationDate__)) { throw new ArgumentException("First date (" + firstDate_ + ") is out of range [effective date (" + effectiveDate__ + "), termination date (" + terminationDate__ + ")]"); } // we should ensure that the above condition is still verified after adjustment break; case DateGeneration.Rule.ThirdWednesday: if (!IMM.isIMMdate(firstDate_, false)) { throw new ArgumentException("first date (" + firstDate_ + ") is not an IMM date"); } break; case DateGeneration.Rule.Zero: case DateGeneration.Rule.Twentieth: case DateGeneration.Rule.TwentiethIMM: case DateGeneration.Rule.OldCDS: case DateGeneration.Rule.CDS: throw new ArgumentException("First date is incompatible with " + rule_ + " date generation rule"); default: throw new ArgumentException("Unknown DateGeneration rule: " + rule_); } } if (nextToLastDate_ != null) { switch (rule_) { case DateGeneration.Rule.Backward: case DateGeneration.Rule.Forward: if (!(nextToLastDate_ > effectiveDate__ && nextToLastDate_ < terminationDate__)) { throw new ArgumentException("Next to last date (" + nextToLastDate_ + ") out of range [effective date (" + effectiveDate__ + "), termination date (" + terminationDate__ + ")]"); } // we should ensure that the above condition is still verified after adjustment break; case DateGeneration.Rule.ThirdWednesday: if (!IMM.isIMMdate(firstDate_, false)) { throw new ArgumentException("first date (" + firstDate_ + ") is not an IMM date"); } break; case DateGeneration.Rule.Zero: case DateGeneration.Rule.Twentieth: case DateGeneration.Rule.TwentiethIMM: case DateGeneration.Rule.OldCDS: case DateGeneration.Rule.CDS: throw new ArgumentException("next to last is incompatible with " + rule_ + " date generation rule"); default: throw new ArgumentException("Unknown DateGeneration rule: " + rule_); } } // calendar needed for endOfMonth adjustment Calendar nullCalendar = new NullCalendar(); int periods = 1; Date seed = new Date(), exitDate; switch (rule_) { case DateGeneration.Rule.Zero: tenor_ = new Period(0, TimeUnit.Years); originalDates_.Add(effectiveDate__); originalDates_.Add(terminationDate__); isRegular_.Add(true); break; case DateGeneration.Rule.Backward: originalDates_.Add(terminationDate__); seed = terminationDate__; if (nextToLastDate_ != null) { originalDates_.Insert(0, nextToLastDate_); Date temp = nullCalendar.advance(seed, -periods * tenor_, convention_, endOfMonth_); isRegular_.Insert(0, temp == nextToLastDate_); seed = nextToLastDate_; } exitDate = effectiveDate__; if (firstDate_ != null) { exitDate = firstDate_; } while (true) { Date temp = nullCalendar.advance(seed, -periods * tenor_, convention_, endOfMonth_); if (temp < exitDate) { if (firstDate_ != null && (calendar_.adjust(originalDates_.First(), convention_) != calendar_.adjust(firstDate_, convention_))) { originalDates_.Insert(0, firstDate_); isRegular_.Insert(0, false); } break; } else { originalDates_.Insert(0, temp); isRegular_.Insert(0, true); ++periods; } } if (endOfMonth_ && calendar_.isEndOfMonth(seed)) { convention_ = BusinessDayConvention.Preceding; } if (calendar_.adjust(originalDates_[0], convention_) != calendar_.adjust(effectiveDate__, convention_)) { originalDates_.Insert(0, effectiveDate__); isRegular_.Insert(0, false); } break; case DateGeneration.Rule.Twentieth: case DateGeneration.Rule.TwentiethIMM: case DateGeneration.Rule.ThirdWednesday: case DateGeneration.Rule.OldCDS: case DateGeneration.Rule.CDS: if (endOfMonth_) { throw new ArgumentException("endOfMonth convention is incompatible with " + rule_ + " date generation rule"); } goto case DateGeneration.Rule.Forward; // fall through case DateGeneration.Rule.Forward: if (rule_ == DateGeneration.Rule.CDS) { originalDates_.Add(previousTwentieth(effectiveDate__, DateGeneration.Rule.CDS)); } else { originalDates_.Add(effectiveDate__); } seed = effectiveDate__; if (firstDate_ != null) { originalDates_.Add(firstDate_); Date temp = nullCalendar.advance(seed, periods * tenor_, convention_, endOfMonth_); isRegular_.Add(temp == firstDate_); seed = firstDate_; } else if (rule_ == DateGeneration.Rule.Twentieth || rule_ == DateGeneration.Rule.TwentiethIMM || rule_ == DateGeneration.Rule.OldCDS || rule_ == DateGeneration.Rule.CDS) { Date next20th = nextTwentieth(effectiveDate__, rule_); if (rule_ == DateGeneration.Rule.OldCDS) { // distance rule inforced in natural days long stubDays = 30; if (next20th - effectiveDate__ < stubDays) { // +1 will skip this one and get the next next20th = nextTwentieth(next20th + 1, rule_); } } if (next20th != effectiveDate__) { originalDates_.Add(next20th); isRegular_.Add(false); seed = next20th; } } exitDate = terminationDate__; if (nextToLastDate_ != null) { exitDate = nextToLastDate_; } while (true) { Date temp = nullCalendar.advance(seed, periods * tenor_, convention_, endOfMonth_); if (temp > exitDate) { if (nextToLastDate_ != null && (calendar_.adjust(originalDates_.Last(), convention_) != calendar_.adjust(nextToLastDate_, convention_))) { originalDates_.Add(nextToLastDate_); isRegular_.Add(false); } break; } else { originalDates_.Add(temp); isRegular_.Add(true); ++periods; } } if (endOfMonth_ && calendar_.isEndOfMonth(seed)) { convention_ = BusinessDayConvention.Preceding; } if (calendar_.adjust(originalDates_.Last(), terminationDateConvention_) != calendar_.adjust(terminationDate__, terminationDateConvention_)) { if (rule_ == DateGeneration.Rule.Twentieth || rule_ == DateGeneration.Rule.TwentiethIMM || rule_ == DateGeneration.Rule.OldCDS || rule_ == DateGeneration.Rule.CDS) { originalDates_.Add(nextTwentieth(terminationDate__, rule_)); isRegular_.Add(true); } else { originalDates_.Add(terminationDate__); isRegular_.Add(false); } } break; default: throw new ArgumentException("Unknown DateGeneration rule: " + rule_); } // adjustments to holidays, etc. if (rule_ == DateGeneration.Rule.ThirdWednesday) { for (int i = 1; i < originalDates_.Count; ++i) { originalDates_[i] = Date.nthWeekday(3, DayOfWeek.Wednesday, originalDates_[i].Month, originalDates_[i].Year); } } if (endOfMonth && calendar_.isEndOfMonth(seed)) { // adjust to end of month if (convention_ == BusinessDayConvention.Unadjusted) { for (int i = 0; i < originalDates_.Count; ++i) { originalDates_[i] = Date.endOfMonth(originalDates_[i]); } } else { for (int i = 0; i < originalDates_.Count; ++i) { originalDates_[i] = calendar_.endOfMonth(originalDates_[i]); } } if (terminationDateConvention_ == BusinessDayConvention.Unadjusted) { originalDates_[originalDates_.Count - 1] = Date.endOfMonth(originalDates_.Last()); } else { originalDates_[originalDates_.Count - 1] = calendar_.endOfMonth(originalDates_.Last()); } } else { // first date not adjusted for CDS schedules if (rule_ != DateGeneration.Rule.OldCDS) { originalDates_[0] = calendar_.adjust(originalDates_[0], convention_); } for (int i = 1; i < originalDates_.Count; ++i) { originalDates_[i] = calendar_.adjust(originalDates_[i], convention_); } foreach (Date d in originalDates_) { adjustedDates_.Add(d); } // termination date is NOT adjusted as per ISDA specifications, unless otherwise specified in the // confirmation of the deal or unless we're creating a CDS schedule if (terminationDateConvention_ != BusinessDayConvention.Unadjusted || rule_ == DateGeneration.Rule.Twentieth || rule_ == DateGeneration.Rule.TwentiethIMM || rule_ == DateGeneration.Rule.OldCDS || rule_ == DateGeneration.Rule.CDS) { adjustedDates_[adjustedDates_.Count - 1] = calendar_.adjust(originalDates_.Last(), terminationDateConvention_); } } }
public static List <CashFlow> yoyInflationLeg(List <double> notionals_, Schedule schedule_, BusinessDayConvention paymentAdjustment_, YoYInflationIndex index_, List <double> gearings_, List <double> spreads_, DayCounter paymentDayCounter_, List <double> caps_, List <double> floors_, Calendar paymentCalendar_, List <int> fixingDays_, Period observationLag_) { int n = schedule_.Count - 1; Utils.QL_REQUIRE(!notionals_.empty(), () => "no notional given"); Utils.QL_REQUIRE(notionals_.Count <= n, () => "too many nominals (" + notionals_.Count + "), only " + n + " required"); if (gearings_ != null) { Utils.QL_REQUIRE(gearings_.Count <= n, () => "too many gearings (" + gearings_.Count + "), only " + n + " required"); } if (spreads_ != null) { Utils.QL_REQUIRE(spreads_.Count <= n, () => "too many spreads (" + spreads_.Count + "), only " + n + " required"); } if (caps_ != null) { Utils.QL_REQUIRE(caps_.Count <= n, () => "too many caps (" + caps_.Count + "), only " + n + " required"); } if (floors_ != null) { Utils.QL_REQUIRE(floors_.Count <= n, () => "too many floors (" + floors_.Count + "), only " + n + " required"); } List <CashFlow> leg = new List <CashFlow>(n); Calendar calendar = paymentCalendar_; Date refStart, start, refEnd, end; for (int i = 0; i < n; ++i) { refStart = start = schedule_.date(i); refEnd = end = schedule_.date(i + 1); Date paymentDate = calendar.adjust(end, paymentAdjustment_); if (i == 0 && !schedule_.isRegular(i + 1)) { BusinessDayConvention bdc = schedule_.businessDayConvention(); refStart = schedule_.calendar().adjust(end - schedule_.tenor(), bdc); } if (i == n - 1 && !schedule_.isRegular(i + 1)) { BusinessDayConvention bdc = schedule_.businessDayConvention(); refEnd = schedule_.calendar().adjust(start + schedule_.tenor(), bdc); } if (Utils.Get(gearings_, i, 1.0).IsEqual(0.0)) { // fixed coupon leg.Add(new FixedRateCoupon(paymentDate, Utils.Get(notionals_, i, 1.0), Utils.effectiveFixedRate(spreads_, caps_, floors_, i), paymentDayCounter_, start, end, refStart, refEnd)); } else { // yoy inflation coupon if (Utils.noOption(caps_, floors_, i)) { // just swaplet YoYInflationCoupon coup = new YoYInflationCoupon(paymentDate, Utils.Get(notionals_, i, 1.0), start, end, Utils.Get(fixingDays_, i, 0), index_, observationLag_, paymentDayCounter_, Utils.Get(gearings_, i, 1.0), Utils.Get(spreads_, i, 0.0), refStart, refEnd); // in this case you can set a pricer // straight away because it only provides computation - not data YoYInflationCouponPricer pricer = new YoYInflationCouponPricer(); coup.setPricer(pricer); leg.Add(coup); } else { // cap/floorlet leg.Add(new CappedFlooredYoYInflationCoupon( paymentDate, Utils.Get(notionals_, i, 1.0), start, end, Utils.Get(fixingDays_, i, 0), index_, observationLag_, paymentDayCounter_, Utils.Get(gearings_, i, 1.0), Utils.Get(spreads_, i, 0.0), Utils.toNullable(Utils.Get(caps_, i, Double.MinValue)), Utils.toNullable(Utils.Get(floors_, i, Double.MinValue)), refStart, refEnd)); } } } return(leg); }
public override List <CashFlow> value() { if (notionals_.empty()) { throw new ApplicationException("no notional given"); } int n = schedule_.Count; Calendar calendar = schedule_.calendar(); List <CashFlow> leg = new List <CashFlow>(n + 1); if (n > 0) { if (fixedRates_.empty() && spreads_.empty()) { throw new ApplicationException("no fixedRates or spreads given"); } Date refStart, start, refEnd, end; Date lastPaymentDate = calendar.adjust(schedule_.date(n), paymentAdjustment_); for (int i = 0; i < n; ++i) { refStart = start = schedule_.date(i); refEnd = end = schedule_.date(i + 1); Date paymentDate = calendar.adjust(end, paymentAdjustment_); if (i == 0 && !schedule_.isRegular(i + 1)) { BusinessDayConvention bdc = schedule_.businessDayConvention(); refStart = schedule_.calendar().adjust(end - schedule_.tenor(), bdc); } if (i == n - 1 && !schedule_.isRegular(i + 1)) { BusinessDayConvention bdc = schedule_.businessDayConvention(); refEnd = schedule_.calendar().adjust(start + schedule_.tenor(), bdc); } if (Utils.Get(fixedRates_, i, 1.0) == 0.0) { // fixed coupon leg.Add(new FixedRateCoupon(Utils.Get(notionals_, i, 0.0), paymentDate, Utils.effectiveFixedRate(spreads_, caps_, floors_, i), paymentDayCounter_, start, end, refStart, refEnd)); } else { // zero inflation coupon if (Utils.noOption(caps_, floors_, i)) { // just swaplet CPICoupon coup; coup = new CPICoupon(baseCPI_, // all have same base for ratio paymentDate, Utils.Get(notionals_, i, 0.0), start, end, Utils.Get(fixingDays_, i, 0), index_, observationLag_, observationInterpolation_, paymentDayCounter_, Utils.Get(fixedRates_, i, 0.0), Utils.Get(spreads_, i, 0.0), refStart, refEnd); // in this case you can set a pricer // straight away because it only provides computation - not data CPICouponPricer pricer = new CPICouponPricer(); coup.setPricer(pricer); leg.Add(coup); } else { // cap/floorlet throw new ApplicationException("caps/floors on CPI coupons not implemented."); } } } } // in CPI legs you always have a notional flow of some sort Date pDate = calendar.adjust(schedule_.date(n), paymentAdjustment_); Date fixingDate = pDate - observationLag_; CashFlow xnl = new CPICashFlow (Utils.Get(notionals_, n, 0.0), index_, new Date(), // is fake, i.e. you do not have one baseCPI_, fixingDate, pDate, subtractInflationNominal_, observationInterpolation_, index_.frequency()); leg.Add(xnl); return(leg); }
public List <CashFlow> Leg() { Utils.QL_REQUIRE(!notionals_.empty(), () => "no notional given"); int n = schedule_.Count - 1; Utils.QL_REQUIRE(notionals_.Count <= n, () => "too many nominals (" + notionals_.Count + "), only " + n + " required"); Utils.QL_REQUIRE(fixingDays_.Count <= n, () => "too many fixingDays (" + fixingDays_.Count + "), only " + n + " required"); Utils.QL_REQUIRE(gearings_.Count <= n, () => "too many gearings (" + gearings_.Count + "), only " + n + " required"); Utils.QL_REQUIRE(spreads_.Count <= n, () => "too many spreads (" + spreads_.Count + "), only " + n + " required"); Utils.QL_REQUIRE(lowerTriggers_.Count <= n, () => "too many lowerTriggers (" + lowerTriggers_.Count + "), only " + n + " required"); Utils.QL_REQUIRE(upperTriggers_.Count <= n, () => "too many upperTriggers (" + upperTriggers_.Count + "), only " + n + " required"); List <CashFlow> leg = new List <CashFlow>(); // the following is not always correct Calendar calendar = schedule_.calendar(); Date refStart, start, refEnd, end; Date paymentDate; List <Schedule> observationsSchedules = new List <Schedule>(); for (int i = 0; i < n; ++i) { refStart = start = schedule_.date(i); refEnd = end = schedule_.date(i + 1); paymentDate = calendar.adjust(end, paymentAdjustment_); if (i == 0 && !schedule_.isRegular(i + 1)) { BusinessDayConvention bdc = schedule_.businessDayConvention(); refStart = calendar.adjust(end - schedule_.tenor(), bdc); } if (i == n - 1 && !schedule_.isRegular(i + 1)) { BusinessDayConvention bdc = schedule_.businessDayConvention(); refEnd = calendar.adjust(start + schedule_.tenor(), bdc); } if (Utils.Get(gearings_, i, 1.0).IsEqual(0.0)) { // fixed coupon leg.Add(new FixedRateCoupon(paymentDate, Utils.Get(notionals_, i), Utils.Get(spreads_, i, 0.0), paymentDayCounter_, start, end, refStart, refEnd)); } else { // floating coupon observationsSchedules.Add(new Schedule(start, end, observationTenor_, calendar, observationConvention_, observationConvention_, DateGeneration.Rule.Forward, false)); leg.Add(new RangeAccrualFloatersCoupon(paymentDate, Utils.Get(notionals_, i), index_, start, end, Utils.Get(fixingDays_, i, 2), paymentDayCounter_, Utils.Get(gearings_, i, 1.0), Utils.Get(spreads_, i, 0.0), refStart, refEnd, observationsSchedules.Last(), Utils.Get(lowerTriggers_, i), Utils.Get(upperTriggers_, i))); } } return(leg); }
// cleanup // SavedSettings backup; // setup public CommonVars() { calendar = new TARGET(); settlementDays = 2; Date today = calendar.adjust(Date.Today); Settings.setEvaluationDate(today); Date settlement = calendar.advance(today, settlementDays, TimeUnit.Days); int deposits = depositData.Length, swaps = swapData.Length; var instruments = new List<RateHelper>(deposits + swaps); for (int i = 0; i < deposits; i++) { instruments.Add(new DepositRateHelper(depositData[i].rate / 100, new Period(depositData[i].n, depositData[i].units), settlementDays, calendar, BusinessDayConvention.ModifiedFollowing, true, new Actual360())); } IborIndex index = new IborIndex("dummy", new Period(6, TimeUnit.Months), settlementDays, new Currency(), calendar, BusinessDayConvention.ModifiedFollowing, false, new Actual360()); for (int i = 0; i < swaps; ++i) { instruments.Add(new SwapRateHelper(swapData[i].rate / 100, new Period(swapData[i].n, swapData[i].units), calendar, Frequency.Annual, BusinessDayConvention.Unadjusted, new Thirty360(), index)); } termStructure = new PiecewiseYieldCurve<Discount, LogLinear>(settlement, instruments, new Actual360()); dummyTermStructure = new PiecewiseYieldCurve<Discount, LogLinear>(settlement, instruments, new Actual360()); }
// setup public CommonVars() { nominals = new List<double>() { 100 }; frequency = Frequency.Semiannual; index = (IborIndex)new Euribor6M(termStructure); calendar = index.fixingCalendar(); convention = BusinessDayConvention.ModifiedFollowing; Date today = calendar.adjust(Date.Today); Settings.setEvaluationDate(today); int settlementDays = 2; fixingDays = 2; settlement = calendar.advance(today, settlementDays, TimeUnit.Days); termStructure.linkTo(Utilities.flatRate(settlement, 0.05, new ActualActual(ActualActual.Convention.ISDA))); }
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); }
public static List <CashFlow> FloatingDigitalLeg <InterestRateIndexType, FloatingCouponType, DigitalCouponType>( List <double> nominals, Schedule schedule, InterestRateIndexType index, DayCounter paymentDayCounter, BusinessDayConvention paymentAdj, List <int> fixingDays, List <double> gearings, List <double> spreads, bool isInArrears, List <double> callStrikes, Position.Type callPosition, bool isCallATMIncluded, List <double> callDigitalPayoffs, List <double> putStrikes, Position.Type putPosition, bool isPutATMIncluded, List <double> putDigitalPayoffs, DigitalReplication replication) where InterestRateIndexType : InterestRateIndex, new() where FloatingCouponType : FloatingRateCoupon, new() where DigitalCouponType : DigitalCoupon, new() { int n = schedule.Count; Utils.QL_REQUIRE(!nominals.empty(), () => "no notional given"); Utils.QL_REQUIRE(nominals.Count <= n, () => "too many nominals (" + nominals.Count + "), only " + n + " required"); if (gearings != null) { Utils.QL_REQUIRE(gearings.Count <= n, () => "too many gearings (" + gearings.Count + "), only " + n + " required"); } if (spreads != null) { Utils.QL_REQUIRE(spreads.Count <= n, () => "too many spreads (" + spreads.Count + "), only " + n + " required"); } if (callStrikes != null) { Utils.QL_REQUIRE(callStrikes.Count <= n, () => "too many nominals (" + callStrikes.Count + "), only " + n + " required"); } if (putStrikes != null) { Utils.QL_REQUIRE(putStrikes.Count <= n, () => "too many nominals (" + putStrikes.Count + "), only " + n + " required"); } List <CashFlow> leg = new List <CashFlow>(); // the following is not always correct Calendar calendar = schedule.calendar(); Date refStart, start, refEnd, end; Date paymentDate; for (int i = 0; i < n; ++i) { refStart = start = schedule.date(i); refEnd = end = schedule.date(i + 1); paymentDate = calendar.adjust(end, paymentAdj); if (i == 0 && !schedule.isRegular(i + 1)) { BusinessDayConvention bdc = schedule.businessDayConvention(); refStart = calendar.adjust(end - schedule.tenor(), bdc); } if (i == n - 1 && !schedule.isRegular(i + 1)) { BusinessDayConvention bdc = schedule.businessDayConvention(); refEnd = calendar.adjust(start + schedule.tenor(), bdc); } if (Utils.Get(gearings, i, 1.0).IsEqual(0.0)) { // fixed coupon leg.Add(new FixedRateCoupon(paymentDate, Utils.Get(nominals, i, 1.0), Utils.Get(spreads, i, 1.0), paymentDayCounter, start, end, refStart, refEnd)); } else { // floating digital coupon FloatingCouponType underlying = FastActivator <FloatingCouponType> .Create().factory( Utils.Get(nominals, i, 1.0), paymentDate, start, end, Utils.Get(fixingDays, i, index.fixingDays()), index, Utils.Get(gearings, i, 1.0), Utils.Get(spreads, i, 0.0), refStart, refEnd, paymentDayCounter, isInArrears) as FloatingCouponType; DigitalCouponType digitalCoupon = FastActivator <DigitalCouponType> .Create().factory( underlying, Utils.toNullable(Utils.Get(callStrikes, i, Double.MinValue)), callPosition, isCallATMIncluded, Utils.toNullable(Utils.Get(callDigitalPayoffs, i, Double.MinValue)), Utils.toNullable(Utils.Get(putStrikes, i, Double.MinValue)), putPosition, isPutATMIncluded, Utils.toNullable(Utils.Get(putDigitalPayoffs, i, Double.MinValue)), replication) as DigitalCouponType; leg.Add(digitalCoupon); } } return(leg); }
// setup public CommonVars() { startYears = 1; length = 5; type = VanillaSwap.Type.Payer; nominal = 1000.0; settlementDays = 2; fixedConvention = BusinessDayConvention.Unadjusted; floatingConvention = BusinessDayConvention.ModifiedFollowing; fixedFrequency = Frequency.Annual; floatingFrequency = Frequency.Semiannual; fixedDayCount = new Thirty360(); termStructure = new RelinkableHandle<YieldTermStructure>(); termStructure.linkTo(Utilities.flatRate(new Date(19, Month.February, 2002), 0.04875825, new Actual365Fixed())); index = new Euribor6M(termStructure); calendar = index.fixingCalendar(); today = calendar.adjust(Date.Today); settlement = calendar.advance(today, settlementDays, TimeUnit.Days); }
public static List <CashFlow> FloatingLeg <InterestRateIndexType, FloatingCouponType, CappedFlooredCouponType>( List <double> nominals, Schedule schedule, InterestRateIndexType index, DayCounter paymentDayCounter, BusinessDayConvention paymentAdj, List <int> fixingDays, List <double> gearings, List <double> spreads, List <double> caps, List <double> floors, bool isInArrears, bool isZero) where InterestRateIndexType : InterestRateIndex, new() where FloatingCouponType : FloatingRateCoupon, new() where CappedFlooredCouponType : CappedFlooredCoupon, new() { int n = schedule.Count; Utils.QL_REQUIRE(!nominals.empty(), () => "no notional given"); Utils.QL_REQUIRE(nominals.Count <= n, () => "too many nominals (" + nominals.Count + "), only " + n + " required"); if (gearings != null) { Utils.QL_REQUIRE(gearings.Count <= n, () => "too many gearings (" + gearings.Count + "), only " + n + " required"); } if (spreads != null) { Utils.QL_REQUIRE(spreads.Count <= n, () => "too many spreads (" + spreads.Count + "), only " + n + " required"); } if (caps != null) { Utils.QL_REQUIRE(caps.Count <= n, () => "too many caps (" + caps.Count + "), only " + n + " required"); } if (floors != null) { Utils.QL_REQUIRE(floors.Count <= n, () => "too many floors (" + floors.Count + "), only " + n + " required"); } Utils.QL_REQUIRE(!isZero || !isInArrears, () => "in-arrears and zero features are not compatible"); List <CashFlow> leg = new List <CashFlow>(); // the following is not always correct Calendar calendar = schedule.calendar(); Date lastPaymentDate = calendar.adjust(schedule[n - 1], paymentAdj); for (int i = 0; i < n - 1; ++i) { Date refStart, start, refEnd, end; refStart = start = schedule[i]; refEnd = end = schedule[i + 1]; Date paymentDate = isZero ? lastPaymentDate : calendar.adjust(end, paymentAdj); if (i == 0 && !schedule.isRegular(i + 1)) { refStart = calendar.adjust(end - schedule.tenor(), schedule.businessDayConvention()); } if (i == n - 1 && !schedule.isRegular(i + 1)) { refEnd = calendar.adjust(start + schedule.tenor(), schedule.businessDayConvention()); } if (Utils.Get(gearings, i, 1).IsEqual(0.0)) { // fixed coupon leg.Add(new FixedRateCoupon(paymentDate, Utils.Get(nominals, i), Utils.effectiveFixedRate(spreads, caps, floors, i), paymentDayCounter, start, end, refStart, refEnd)); } else { if (Utils.noOption(caps, floors, i)) { leg.Add(FastActivator <FloatingCouponType> .Create().factory( Utils.Get(nominals, i), paymentDate, start, end, Utils.Get(fixingDays, i, index.fixingDays()), index, Utils.Get(gearings, i, 1), Utils.Get(spreads, i), refStart, refEnd, paymentDayCounter, isInArrears)); } else { leg.Add(FastActivator <CappedFlooredCouponType> .Create().factory( Utils.Get(nominals, i), paymentDate, start, end, Utils.Get(fixingDays, i, index.fixingDays()), index, Utils.Get(gearings, i, 1), Utils.Get(spreads, i), Utils.toNullable(Utils.Get(caps, i, Double.MinValue)), Utils.toNullable(Utils.Get(floors, i, Double.MinValue)), refStart, refEnd, paymentDayCounter, isInArrears)); } } } return(leg); }
public Schedule(Date effectiveDate__, Date terminationDate__, Period tenor__, Calendar calendar__, BusinessDayConvention convention__, BusinessDayConvention terminationDateConvention__, DateGeneration.Rule rule__, bool endOfMonth__, Date firstDate__, Date nextToLastDate__) { // first save the properties fullInterface_ = true; tenor_ = tenor__; calendar_ = calendar__; convention_ = convention__; terminationDateConvention_ = terminationDateConvention__; rule_ = rule__; endOfMonth_ = endOfMonth__; firstDate_ = firstDate__; nextToLastDate_ = nextToLastDate__; // sanity checks if (effectiveDate__ == null) throw new ArgumentException("Null effective date"); if (terminationDate__ == null) throw new ArgumentException("Null termination date"); if (effectiveDate__ >= terminationDate__) throw new ArgumentException("Effective date (" + effectiveDate__ + ") is later than or equal to termination date (" + terminationDate__ + ")"); if (tenor_.length() == 0) rule_ = DateGeneration.Rule.Zero; else if (tenor_.length() < 0) throw new ArgumentException("Non positive tenor (" + tenor_ + ") is not allowed"); if (firstDate_ != null) { switch (rule_) { case DateGeneration.Rule.Backward: case DateGeneration.Rule.Forward: if (!(firstDate_ > effectiveDate__ && firstDate_ < terminationDate__)) throw new ArgumentException("First date (" + firstDate_ + ") is out of range [effective date (" + effectiveDate__ + "), termination date (" + terminationDate__ + ")]"); // we should ensure that the above condition is still verified after adjustment break; case DateGeneration.Rule.ThirdWednesday: if (!IMM.isIMMdate(firstDate_, false)) throw new ArgumentException("first date (" + firstDate_ + ") is not an IMM date"); break; case DateGeneration.Rule.Zero: case DateGeneration.Rule.Twentieth: case DateGeneration.Rule.TwentiethIMM: case DateGeneration.Rule.OldCDS: case DateGeneration.Rule.CDS: throw new ArgumentException("First date is incompatible with " + rule_ + " date generation rule"); default: throw new ArgumentException("Unknown DateGeneration rule: " + rule_); } } if (nextToLastDate_ != null) { switch (rule_) { case DateGeneration.Rule.Backward: case DateGeneration.Rule.Forward: if (!(nextToLastDate_ > effectiveDate__ && nextToLastDate_ < terminationDate__)) throw new ArgumentException("Next to last date (" + nextToLastDate_ + ") out of range [effective date (" + effectiveDate__ + "), termination date (" + terminationDate__ + ")]"); // we should ensure that the above condition is still verified after adjustment break; case DateGeneration.Rule.ThirdWednesday: if (!IMM.isIMMdate(firstDate_, false)) throw new ArgumentException("first date (" + firstDate_ + ") is not an IMM date"); break; case DateGeneration.Rule.Zero: case DateGeneration.Rule.Twentieth: case DateGeneration.Rule.TwentiethIMM: case DateGeneration.Rule.OldCDS: case DateGeneration.Rule.CDS: throw new ArgumentException("next to last is incompatible with " + rule_ + " date generation rule"); default: throw new ArgumentException("Unknown DateGeneration rule: " + rule_); } } // calendar needed for endOfMonth adjustment Calendar nullCalendar = new NullCalendar(); int periods = 1; Date seed = new Date(), exitDate; switch (rule_) { case DateGeneration.Rule.Zero: tenor_ = new Period(0, TimeUnit.Years); originalDates_.Add(effectiveDate__); originalDates_.Add(terminationDate__); isRegular_.Add(true); break; case DateGeneration.Rule.Backward: originalDates_.Add(terminationDate__); seed = terminationDate__; if (nextToLastDate_ != null) { originalDates_.Insert(0, nextToLastDate_); Date temp = nullCalendar.advance(seed, -periods * tenor_, convention_, endOfMonth_); isRegular_.Insert(0, temp == nextToLastDate_); seed = nextToLastDate_; } exitDate = effectiveDate__; if (firstDate_ != null) exitDate = firstDate_; while (true) { Date temp = nullCalendar.advance(seed, -periods * tenor_, convention_, endOfMonth_); if (temp < exitDate) { if (firstDate_ != null && (calendar_.adjust(originalDates_.First(), convention_) != calendar_.adjust(firstDate_, convention_))) { originalDates_.Insert(0, firstDate_); isRegular_.Insert(0, false); } break; } else { originalDates_.Insert(0, temp); isRegular_.Insert(0, true); ++periods; } } if (endOfMonth_ && calendar_.isEndOfMonth(seed)) convention_ = BusinessDayConvention.Preceding; if (calendar_.adjust(originalDates_[0], convention_) != calendar_.adjust(effectiveDate__, convention_)) { originalDates_.Insert(0, effectiveDate__); isRegular_.Insert(0, false); } break; case DateGeneration.Rule.Twentieth: case DateGeneration.Rule.TwentiethIMM: case DateGeneration.Rule.ThirdWednesday: case DateGeneration.Rule.OldCDS: case DateGeneration.Rule.CDS: if (endOfMonth_) throw new ArgumentException("endOfMonth convention is incompatible with " + rule_ + " date generation rule"); goto case DateGeneration.Rule.Forward; // fall through case DateGeneration.Rule.Forward: if (rule_ == DateGeneration.Rule.CDS) { originalDates_.Add(previousTwentieth(effectiveDate__,DateGeneration.Rule.CDS)); } else { originalDates_.Add(effectiveDate__); } seed = effectiveDate__; if (firstDate_ != null) { originalDates_.Add(firstDate_); Date temp = nullCalendar.advance(seed, periods * tenor_, convention_, endOfMonth_); isRegular_.Add(temp == firstDate_); seed = firstDate_; } else if (rule_ == DateGeneration.Rule.Twentieth || rule_ == DateGeneration.Rule.TwentiethIMM || rule_ == DateGeneration.Rule.OldCDS || rule_ == DateGeneration.Rule.CDS) { Date next20th = nextTwentieth(effectiveDate__, rule_); if (rule_ == DateGeneration.Rule.OldCDS) { // distance rule inforced in natural days long stubDays = 30; if (next20th - effectiveDate__ < stubDays) { // +1 will skip this one and get the next next20th = nextTwentieth(next20th + 1, rule_); } } if (next20th != effectiveDate__) { originalDates_.Add(next20th); isRegular_.Add(false); seed = next20th; } } exitDate = terminationDate__; if (nextToLastDate_ != null) exitDate = nextToLastDate_; while (true) { Date temp = nullCalendar.advance(seed, periods * tenor_, convention_, endOfMonth_); if (temp > exitDate) { if (nextToLastDate_ != null && (calendar_.adjust(originalDates_.Last(), convention_) != calendar_.adjust(nextToLastDate_, convention_))) { originalDates_.Add(nextToLastDate_); isRegular_.Add(false); } break; } else { originalDates_.Add(temp); isRegular_.Add(true); ++periods; } } if (endOfMonth_ && calendar_.isEndOfMonth(seed)) convention_ = BusinessDayConvention.Preceding; if (calendar_.adjust(originalDates_.Last(), terminationDateConvention_) != calendar_.adjust(terminationDate__, terminationDateConvention_)) { if (rule_ == DateGeneration.Rule.Twentieth || rule_ == DateGeneration.Rule.TwentiethIMM || rule_ == DateGeneration.Rule.OldCDS || rule_ == DateGeneration.Rule.CDS ) { originalDates_.Add(nextTwentieth(terminationDate__, rule_)); isRegular_.Add(true); } else { originalDates_.Add(terminationDate__); isRegular_.Add(false); } } break; default: throw new ArgumentException("Unknown DateGeneration rule: " + rule_); } // adjustments to holidays, etc. if (rule_ == DateGeneration.Rule.ThirdWednesday) for (int i = 1; i < originalDates_.Count; ++i) originalDates_[i] = Date.nthWeekday(3, DayOfWeek.Wednesday, originalDates_[i].Month, originalDates_[i].Year); if (endOfMonth && calendar_.isEndOfMonth(seed)) { // adjust to end of month if (convention_ == BusinessDayConvention.Unadjusted) { for (int i = 0; i < originalDates_.Count; ++i) originalDates_[i] = Date.endOfMonth(originalDates_[i]); } else { for (int i = 0; i < originalDates_.Count; ++i) originalDates_[i] = calendar_.endOfMonth(originalDates_[i]); } if (terminationDateConvention_ == BusinessDayConvention.Unadjusted) originalDates_[originalDates_.Count - 1] = Date.endOfMonth(originalDates_.Last()); else originalDates_[originalDates_.Count - 1] = calendar_.endOfMonth(originalDates_.Last()); } else { // first date not adjusted for CDS schedules if (rule_ != DateGeneration.Rule.OldCDS) originalDates_[0] = calendar_.adjust(originalDates_[0], convention_); for (int i = 1; i < originalDates_.Count; ++i) originalDates_[i] = calendar_.adjust(originalDates_[i], convention_); foreach (Date d in originalDates_) adjustedDates_.Add(d); // termination date is NOT adjusted as per ISDA specifications, unless otherwise specified in the // confirmation of the deal or unless we're creating a CDS schedule if (terminationDateConvention_ != BusinessDayConvention.Unadjusted || rule_ == DateGeneration.Rule.Twentieth || rule_ == DateGeneration.Rule.TwentiethIMM || rule_ == DateGeneration.Rule.OldCDS || rule_ == DateGeneration.Rule.CDS) adjustedDates_[adjustedDates_.Count - 1] = calendar_.adjust(originalDates_.Last(), terminationDateConvention_); } }