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); }
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 ConvertibleFixedCouponBond(Exercise exercise, double conversionRatio, DividendSchedule dividends, CallabilitySchedule callability, Handle <Quote> creditSpread, Date issueDate, int settlementDays, List <double> coupons, DayCounter dayCounter, Schedule schedule, double redemption = 100) : base( exercise, conversionRatio, dividends, callability, creditSpread, issueDate, settlementDays, schedule, redemption) { // !!! notional forcibly set to 100 cashflows_ = new FixedRateLeg(schedule) .withCouponRates(coupons, dayCounter) .withNotionals(100.0) .withPaymentAdjustment(schedule.businessDayConvention()); addRedemptionsToCashflows(new List <double>() { redemption }); Utils.QL_REQUIRE(redemptions_.Count == 1, () => "multiple redemptions created"); option_ = new option(this, exercise, conversionRatio, dividends, callability, creditSpread, cashflows_, dayCounter, schedule, issueDate, settlementDays, redemption); }
public ConvertibleFloatingRateBond(Exercise exercise, double conversionRatio, DividendSchedule dividends, CallabilitySchedule callability, Handle <Quote> creditSpread, Date issueDate, int settlementDays, IborIndex index, int fixingDays, List <double> spreads, DayCounter dayCounter, Schedule schedule, double redemption = 100) : base(exercise, conversionRatio, dividends, callability, creditSpread, issueDate, settlementDays, schedule, redemption) { // !!! notional forcibly set to 100 cashflows_ = new IborLeg(schedule, index) .withPaymentDayCounter(dayCounter) .withFixingDays(fixingDays) .withSpreads(spreads) .withNotionals(100.0) .withPaymentAdjustment(schedule.businessDayConvention()); addRedemptionsToCashflows(new List <double> { redemption }); Utils.QL_REQUIRE(redemptions_.Count == 1, "multiple redemptions created"); option_ = new option(this, exercise, conversionRatio, dividends, callability, creditSpread, cashflows_, dayCounter, schedule, issueDate, settlementDays, redemption); }
// constructor public VanillaSwap(Type type, double nominal, Schedule fixedSchedule, double fixedRate, DayCounter fixedDayCount, Schedule floatSchedule, IborIndex iborIndex, double spread, DayCounter floatingDayCount, BusinessDayConvention?paymentConvention = null) : base(2) { type_ = type; nominal_ = nominal; fixedSchedule_ = fixedSchedule; fixedRate_ = fixedRate; fixedDayCount_ = fixedDayCount; floatingSchedule_ = floatSchedule; iborIndex_ = iborIndex; spread_ = spread; floatingDayCount_ = floatingDayCount; if (paymentConvention.HasValue) { paymentConvention_ = paymentConvention.Value; } else { paymentConvention_ = floatingSchedule_.businessDayConvention(); } legs_[0] = new FixedRateLeg(fixedSchedule) .withCouponRates(fixedRate, fixedDayCount) .withPaymentAdjustment(paymentConvention_) .withNotionals(nominal); legs_[1] = new IborLeg(floatSchedule, iborIndex) .withPaymentDayCounter(floatingDayCount) //.withFixingDays(iborIndex.fixingDays()) .withSpreads(spread) .withNotionals(nominal) .withPaymentAdjustment(paymentConvention_); foreach (var cf in legs_[1]) { cf.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: Utils.QL_FAIL("Unknown vanilla-swap type"); break; } }
public FloatingLoan(Type type, double nominal, Schedule floatingSchedule, double floatingSpread, DayCounter floatingDayCount, Schedule principalSchedule, BusinessDayConvention?paymentConvention, IborIndex index) : base(2) { type_ = type; nominal_ = nominal; floatingSchedule_ = floatingSchedule; floatingSpread_ = floatingSpread; floatingDayCount_ = floatingDayCount; principalSchedule_ = principalSchedule; iborIndex_ = index; if (paymentConvention.HasValue) { paymentConvention_ = paymentConvention.Value; } else { paymentConvention_ = floatingSchedule_.businessDayConvention(); } List <CashFlow> principalLeg = new PricipalLeg(principalSchedule, floatingDayCount) .withNotionals(nominal) .withPaymentAdjustment(paymentConvention_) .withSign(type == Type.Loan ? -1 : 1); // temporary for (int i = 0; i < principalLeg.Count - 1; i++) { Principal p = (Principal)principalLeg[i]; notionals_.Add(p.nominal()); } List <CashFlow> floatingLeg = new IborLeg(floatingSchedule, iborIndex_) .withPaymentDayCounter(floatingDayCount_) .withSpreads(floatingSpread_) .withPaymentAdjustment(paymentConvention_) .withNotionals(notionals_); legs_[0] = floatingLeg; legs_[1] = principalLeg; if (type_ == Type.Loan) { payer_[0] = -1; payer_[1] = +1; } else { payer_[0] = +1; payer_[1] = -1; } }
public BasisSwap(Type type, double nominal, Schedule float1Schedule, IborIndex iborIndex1, double spread1, DayCounter float1DayCount, Schedule float2Schedule, IborIndex iborIndex2, double spread2, DayCounter float2DayCount, BusinessDayConvention? paymentConvention) : base(2) { type_ = type; nominal_ = nominal; floating1Schedule_ = float1Schedule; spread1_ = spread1; floating1DayCount_ = float1DayCount; iborIndex1_ = iborIndex1; floating2Schedule_ = float2Schedule; spread2_ = spread2; floating2DayCount_ = float2DayCount; iborIndex2_ = iborIndex2; if (paymentConvention.HasValue) paymentConvention_ = paymentConvention.Value; else paymentConvention_ = floating1Schedule_.businessDayConvention(); List<CashFlow> floating1Leg = new IborLeg(float1Schedule, iborIndex1) .withPaymentDayCounter(float1DayCount) .withSpreads(spread1) .withNotionals(nominal) .withPaymentAdjustment(paymentConvention_); List<CashFlow> floating2Leg = new IborLeg(float2Schedule, iborIndex2) .withPaymentDayCounter(float2DayCount) .withSpreads(spread2) .withNotionals(nominal) .withPaymentAdjustment(paymentConvention_); foreach (var cf in floating1Leg) cf.registerWith(update); foreach (var cf in floating2Leg) cf.registerWith(update); legs_[0] = floating1Leg; legs_[1] = floating2Leg; if (type_ == Type.Payer) { payer_[0] = -1; payer_[1] = +1; } else { payer_[0] = +1; payer_[1] = -1; } }
public FixedLoan(Type type, double nominal, Schedule fixedSchedule, double fixedRate, DayCounter fixedDayCount, Schedule principalSchedule, BusinessDayConvention?paymentConvention) : base(2) { type_ = type; nominal_ = nominal; fixedSchedule_ = fixedSchedule; fixedRate_ = fixedRate; fixedDayCount_ = fixedDayCount; principalSchedule_ = principalSchedule; if (paymentConvention.HasValue) { paymentConvention_ = paymentConvention.Value; } else { paymentConvention_ = fixedSchedule_.businessDayConvention(); } List <CashFlow> principalLeg = new PricipalLeg(principalSchedule, fixedDayCount) .withNotionals(nominal) .withPaymentAdjustment(paymentConvention_) .withSign(type == Type.Loan ? -1 : 1); // temporary for (int i = 0; i < principalLeg.Count - 1; i++) { Principal p = (Principal)principalLeg[i]; notionals_.Add(p.nominal()); } List <CashFlow> fixedLeg = new FixedRateLeg(fixedSchedule) .withCouponRates(fixedRate, fixedDayCount) .withPaymentAdjustment(paymentConvention_) .withNotionals(notionals_); legs_[0] = fixedLeg; legs_[1] = principalLeg; if (type_ == Type.Loan) { payer_[0] = +1; payer_[1] = -1; } else { payer_[0] = -1; payer_[1] = +1; } }
public BMASwap(Type type, double nominal, // Libor leg Schedule liborSchedule, double liborFraction, double liborSpread, IborIndex liborIndex, DayCounter liborDayCount, // BMA leg Schedule bmaSchedule, BMAIndex bmaIndex, DayCounter bmaDayCount) : base(2) { type_ = type; nominal_ = nominal; liborFraction_ = liborFraction; liborSpread_ = liborSpread; BusinessDayConvention convention = liborSchedule.businessDayConvention(); legs_[0] = new IborLeg(liborSchedule, liborIndex) .withPaymentDayCounter(liborDayCount) .withFixingDays(liborIndex.fixingDays()) .withGearings(liborFraction) .withSpreads(liborSpread) .withNotionals(nominal) .withPaymentAdjustment(convention); legs_[1] = new AverageBMALeg(bmaSchedule, bmaIndex) .withPaymentDayCounter(bmaDayCount) .withNotionals(nominal) .withPaymentAdjustment(bmaSchedule.businessDayConvention()); 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: Utils.QL_FAIL("Unknown BMA-swap type"); break; } }
public FloatingLoan(Type type, double nominal, Schedule floatingSchedule, double floatingSpread, DayCounter floatingDayCount, Schedule principalSchedule, BusinessDayConvention? paymentConvention, IborIndex index) : base(2) { type_ = type; nominal_ = nominal; floatingSchedule_ = floatingSchedule; floatingSpread_ = floatingSpread; floatingDayCount_ = floatingDayCount; principalSchedule_ = principalSchedule; iborIndex_ = index; if (paymentConvention.HasValue) paymentConvention_ = paymentConvention.Value; else paymentConvention_ = floatingSchedule_.businessDayConvention(); List<CashFlow> principalLeg = new PricipalLeg(principalSchedule, floatingDayCount) .withNotionals(nominal) .withPaymentAdjustment(paymentConvention_) .withSign(type == Type.Loan ? -1 : 1); // temporary for (int i = 0; i < principalLeg.Count - 1; i++) { Principal p = (Principal)principalLeg[i]; notionals_.Add(p.nominal()); } List<CashFlow> floatingLeg = new IborLeg(floatingSchedule, iborIndex_) .withPaymentDayCounter(floatingDayCount_) .withSpreads(floatingSpread_) .withPaymentAdjustment(paymentConvention_) .withNotionals(notionals_); legs_[0] = floatingLeg; legs_[1] = principalLeg; if (type_ == Type.Loan) { payer_[0] = -1; payer_[1] = +1; } else { payer_[0] = +1; payer_[1] = -1; } }
public FixedLoan(Type type, double nominal, Schedule fixedSchedule, double fixedRate, DayCounter fixedDayCount, Schedule principalSchedule, BusinessDayConvention? paymentConvention) : base(2) { type_ = type; nominal_ = nominal; fixedSchedule_ = fixedSchedule; fixedRate_ = fixedRate; fixedDayCount_ = fixedDayCount; principalSchedule_ = principalSchedule; if (paymentConvention.HasValue) paymentConvention_ = paymentConvention.Value; else paymentConvention_ = fixedSchedule_.businessDayConvention(); List<CashFlow> principalLeg = new PricipalLeg(principalSchedule, fixedDayCount) .withNotionals(nominal) .withPaymentAdjustment(paymentConvention_) .withSign(type == Type.Loan ? -1 : 1); // temporary for (int i = 0; i < principalLeg.Count - 1; i++) { Principal p = (Principal)principalLeg[i]; notionals_.Add(p.nominal()); } List<CashFlow> fixedLeg = new FixedRateLeg(fixedSchedule) .withCouponRates(fixedRate, fixedDayCount) .withPaymentAdjustment(paymentConvention_) .withNotionals(notionals_); legs_[0] = fixedLeg; legs_[1] = principalLeg; if (type_ == Type.Loan) { payer_[0] = +1; payer_[1] = -1; } else { payer_[0] = -1; payer_[1] = +1; } }
public BMASwap(Type type, double nominal, // Libor leg Schedule liborSchedule, double liborFraction, double liborSpread, IborIndex liborIndex, DayCounter liborDayCount, // BMA leg Schedule bmaSchedule, BMAIndex bmaIndex, DayCounter bmaDayCount) : base(2) { type_ = type; nominal_ = nominal; liborFraction_ = liborFraction; liborSpread_ = liborSpread; BusinessDayConvention convention = liborSchedule.businessDayConvention(); legs_[0] = new IborLeg(liborSchedule, liborIndex) .withPaymentDayCounter(liborDayCount) .withFixingDays(liborIndex.fixingDays()) .withGearings(liborFraction) .withSpreads(liborSpread) .withNotionals(nominal) .withPaymentAdjustment(convention); legs_[1] = new AverageBMALeg(bmaSchedule, bmaIndex) .withPaymentDayCounter(bmaDayCount) .withNotionals(nominal) .withPaymentAdjustment(bmaSchedule.businessDayConvention()); 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 BMA-swap type"); } }
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 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); }
public CommercialPaper(Type type, double nominal, Schedule fixedSchedule, double fixedRate, DayCounter fixedDayCount, Schedule principalSchedule, BusinessDayConvention?paymentConvention) : base(2) { type_ = type; nominal_ = nominal; fixedSchedule_ = fixedSchedule; fixedRate_ = fixedRate; fixedDayCount_ = fixedDayCount; principalSchedule_ = principalSchedule; if (paymentConvention.HasValue) { paymentConvention_ = paymentConvention.Value; } else { paymentConvention_ = fixedSchedule_.businessDayConvention(); } List <CashFlow> principalLeg = new PricipalLeg(principalSchedule, fixedDayCount) .withNotionals(nominal) .withPaymentAdjustment(paymentConvention_) .withSign(type == Type.Loan ? -1 : 1); // temporary for (int i = 0; i < principalLeg.Count - 1; i++) { Principal p = (Principal)principalLeg[i]; notionals_.Add(p.nominal()); } List <CashFlow> fixedLeg = new FixedRateLeg(fixedSchedule) .withCouponRates(fixedRate, fixedDayCount) .withPaymentAdjustment(paymentConvention_) .withNotionals(notionals_); // Discounting Pricipal notionals_.Clear(); double n; for (int i = 0; i < fixedLeg.Count; i++) { FixedRateCoupon c = (FixedRateCoupon)fixedLeg[i]; n = i > 0 ? notionals_.Last() : c.nominal(); notionals_.Add(n / (1 + (c.rate() * c.dayCounter().yearFraction(c.referencePeriodStart, c.referencePeriodEnd)))); } // New Leg List <CashFlow> discountedFixedLeg = new FixedRateLeg(fixedSchedule) .withCouponRates(fixedRate, fixedDayCount) .withPaymentAdjustment(paymentConvention_) .withNotionals(notionals_); // Adjust Principal Principal p0 = (Principal)principalLeg[0]; p0.setAmount(notionals_.Last()); legs_[0] = discountedFixedLeg; legs_[1] = principalLeg; if (type_ == Type.Loan) { payer_[0] = +1; payer_[1] = -1; } else { payer_[0] = -1; payer_[1] = +1; } }
public void testDateConstructor() { // Testing the constructor taking a vector of dates and possibly additional meta information List<Date> dates = new List<Date>(); dates.Add(new Date(16, Month.May, 2015)); dates.Add(new Date(18, Month.May, 2015)); dates.Add(new Date(18, Month.May, 2016)); dates.Add(new Date(31, Month.December, 2017)); // schedule without any additional information Schedule schedule1 = new Schedule(dates); if (schedule1.Count != dates.Count) Assert.Fail("schedule1 has size {0}, expected {1}", schedule1.Count, dates.Count); for (int i = 0; i < dates.Count; ++i) if (schedule1[i] != dates[i]) Assert.Fail("schedule1 has {0} at position {1}, expected {2}", schedule1[i], i, dates[i]); if (schedule1.calendar() != new NullCalendar()) Assert.Fail("schedule1 has calendar {0}, expected null calendar", schedule1.calendar().name()); if (schedule1.businessDayConvention() != BusinessDayConvention.Unadjusted) Assert.Fail("schedule1 has convention {0}, expected unadjusted", schedule1.businessDayConvention()); // schedule with metadata List<bool> regular = new List<bool>(); regular.Add(false); regular.Add(true); regular.Add(false); Schedule schedule2 = new Schedule(dates, new TARGET(), BusinessDayConvention.Following, BusinessDayConvention.ModifiedPreceding, new Period(1, TimeUnit.Years), DateGeneration.Rule.Backward, true, regular); for (int i = 1; i < dates.Count; ++i) if (schedule2.isRegular(i) != regular[i - 1]) Assert.Fail("schedule2 has a {0} period at position {1}, expected {2}", (schedule2.isRegular(i) ? "regular" : "irregular"), i, (regular[i - 1] ? "regular" : "irregular")); if (schedule2.calendar() != new TARGET()) Assert.Fail("schedule1 has calendar {0}, expected TARGET", schedule2.calendar().name()); if (schedule2.businessDayConvention() != BusinessDayConvention.Following) Assert.Fail("schedule2 has convention {0}, expected Following", schedule2.businessDayConvention()); if (schedule2.terminationDateBusinessDayConvention() != BusinessDayConvention.ModifiedPreceding) Assert.Fail("schedule2 has convention {0}, expected Modified Preceding", schedule2.terminationDateBusinessDayConvention()); if (schedule2.tenor() != new Period(1, TimeUnit.Years)) Assert.Fail("schedule2 has tenor {0}, expected 1Y", schedule2.tenor()); if (schedule2.rule() != DateGeneration.Rule.Backward) Assert.Fail("schedule2 has rule {0}, expected Backward", schedule2.rule()); if (schedule2.endOfMonth() != true) Assert.Fail("schedule2 has end of month flag false, expected true"); }
public void testBondFromScheduleWithDateVector() { // Testing South African R2048 bond price using Schedule constructor with Date vector SavedSettings backup = new SavedSettings(); //When pricing bond from Yield To Maturity, use NullCalendar() Calendar calendar = new NullCalendar(); int settlementDays = 3; Date issueDate = new Date(29, Month.June, 2012); Date today = new Date(7, Month.September, 2015); Date evaluationDate = calendar.adjust(today); Date settlementDate = calendar.advance(evaluationDate, new Period(settlementDays, TimeUnit.Days)); Settings.setEvaluationDate(evaluationDate); // For the schedule to generate correctly for Feb-28's, make maturity date on Feb 29 Date maturityDate = new Date(29, Month.February, 2048); double coupon = 0.0875; Compounding comp = Compounding.Compounded; Frequency freq = Frequency.Semiannual; DayCounter dc = new ActualActual(ActualActual.Convention.Bond); // Yield as quoted in market InterestRate yield = new InterestRate(0.09185, dc, comp, freq); Period tenor = new Period(6, TimeUnit.Months); Period exCouponPeriod = new Period(10, TimeUnit.Days); // Generate coupon dates for 31 Aug and end of Feb each year // For leap years, this will generate 29 Feb, but the bond // actually pays coupons on 28 Feb, regardsless of whether // it is a leap year or not. Schedule schedule = new Schedule(issueDate, maturityDate, tenor, new NullCalendar(), BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted, DateGeneration.Rule.Backward, true); // Adjust the 29 Feb's to 28 Feb List<Date> dates = new List<Date>(); for (int i = 0; i < schedule.Count; ++i) { Date d = schedule.date(i); if (d.Month == 2 && d.Day == 29) dates.Add(new Date(28, Month.February, d.Year)); else dates.Add(d); } schedule = new Schedule(dates, schedule.calendar(), schedule.businessDayConvention(), schedule.terminationDateBusinessDayConvention(), schedule.tenor(), schedule.rule(), schedule.endOfMonth(), schedule.isRegular()); FixedRateBond bond = new FixedRateBond( 0, 100.0, schedule, new List<double>() { coupon }, dc, BusinessDayConvention.Following, 100.0, issueDate, calendar, exCouponPeriod, calendar, BusinessDayConvention.Unadjusted, false); double calculatedPrice = BondFunctions.dirtyPrice(bond, yield, settlementDate); double expectedPrice = 95.75706; double tolerance = 1e-5; if (Math.Abs(calculatedPrice - expectedPrice) > tolerance) { Assert.Fail(string.Format("failed to reproduce R2048 dirty price\nexpected: {0}\ncalculated: {1}", expectedPrice, calculatedPrice)); } }
public ConvertibleFixedCouponBond( Exercise exercise, double conversionRatio, DividendSchedule dividends, CallabilitySchedule callability, Handle<Quote> creditSpread, Date issueDate, int settlementDays, List<double> coupons, DayCounter dayCounter, Schedule schedule, double redemption = 100) : base(exercise, conversionRatio, dividends, callability, creditSpread, issueDate, settlementDays, schedule, redemption) { // !!! notional forcibly set to 100 cashflows_ = new FixedRateLeg(schedule) .withCouponRates(coupons, dayCounter) .withNotionals(100.0) .withPaymentAdjustment(schedule.businessDayConvention()); addRedemptionsToCashflows(new List<double>(){redemption}); Utils.QL_REQUIRE(redemptions_.Count == 1, "multiple redemptions created"); option_ = new option(this, exercise, conversionRatio, dividends, callability, creditSpread, cashflows_, dayCounter, schedule, issueDate, settlementDays, redemption); }
// constructor public VanillaSwap(Type type, double nominal, Schedule fixedSchedule, double fixedRate, DayCounter fixedDayCount, Schedule floatSchedule, IborIndex iborIndex, double spread, DayCounter floatingDayCount, BusinessDayConvention? paymentConvention = null) : base(2) { type_ = type; nominal_ = nominal; fixedSchedule_ = fixedSchedule; fixedRate_ = fixedRate; fixedDayCount_ = fixedDayCount; floatingSchedule_ = floatSchedule; iborIndex_ = iborIndex; spread_ = spread; floatingDayCount_ = floatingDayCount; if (paymentConvention.HasValue) paymentConvention_ = paymentConvention.Value; else paymentConvention_ = floatingSchedule_.businessDayConvention(); legs_[0] = new FixedRateLeg(fixedSchedule) .withCouponRates(fixedRate, fixedDayCount) .withPaymentAdjustment(paymentConvention_) .withNotionals(nominal); legs_[1] = new IborLeg(floatSchedule, iborIndex) .withPaymentDayCounter(floatingDayCount) //.withFixingDays(iborIndex.fixingDays()) .withSpreads(spread) .withNotionals(nominal) .withPaymentAdjustment(paymentConvention_); foreach (var cf in legs_[1]) cf.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 vanilla-swap type"); } }
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 ConvertibleFloatingRateBond( Exercise exercise, double conversionRatio, DividendSchedule dividends, CallabilitySchedule callability, Handle<Quote> creditSpread, Date issueDate, int settlementDays, IborIndex index, int fixingDays, List<double> spreads, DayCounter dayCounter, Schedule schedule, double redemption = 100) : base(exercise, conversionRatio, dividends, callability, creditSpread, issueDate, settlementDays, schedule, redemption) { // !!! notional forcibly set to 100 cashflows_ = new IborLeg(schedule, index) .withPaymentDayCounter(dayCounter) .withFixingDays(fixingDays) .withSpreads(spreads) .withNotionals(100.0) .withPaymentAdjustment(schedule.businessDayConvention()); addRedemptionsToCashflows(new List<double>{redemption}); Utils.QL_REQUIRE( redemptions_.Count == 1, () => "multiple redemptions created" ); option_ = new option(this, exercise, conversionRatio, dividends, callability, creditSpread, cashflows_, dayCounter, schedule, issueDate, settlementDays, redemption); }
public BasisSwap(Type type, double nominal, Schedule float1Schedule, IborIndex iborIndex1, double spread1, DayCounter float1DayCount, Schedule float2Schedule, IborIndex iborIndex2, double spread2, DayCounter float2DayCount, BusinessDayConvention?paymentConvention) : base(2) { type_ = type; nominal_ = nominal; floating1Schedule_ = float1Schedule; spread1_ = spread1; floating1DayCount_ = float1DayCount; iborIndex1_ = iborIndex1; floating2Schedule_ = float2Schedule; spread2_ = spread2; floating2DayCount_ = float2DayCount; iborIndex2_ = iborIndex2; if (paymentConvention.HasValue) { paymentConvention_ = paymentConvention.Value; } else { paymentConvention_ = floating1Schedule_.businessDayConvention(); } List <CashFlow> floating1Leg = new IborLeg(float1Schedule, iborIndex1) .withPaymentDayCounter(float1DayCount) .withSpreads(spread1) .withNotionals(nominal) .withPaymentAdjustment(paymentConvention_); List <CashFlow> floating2Leg = new IborLeg(float2Schedule, iborIndex2) .withPaymentDayCounter(float2DayCount) .withSpreads(spread2) .withNotionals(nominal) .withPaymentAdjustment(paymentConvention_); foreach (var cf in floating1Leg) { cf.registerWith(update); } foreach (var cf in floating2Leg) { cf.registerWith(update); } legs_[0] = floating1Leg; legs_[1] = floating2Leg; if (type_ == Type.Payer) { payer_[0] = -1; payer_[1] = +1; } else { payer_[0] = +1; payer_[1] = -1; } }
public CommercialPaper(Loan.Type type, double nominal, Schedule fixedSchedule, double fixedRate, DayCounter fixedDayCount, Schedule principalSchedule, BusinessDayConvention? paymentConvention) : base(2) { type_ = type; nominal_ = nominal; fixedSchedule_ = fixedSchedule; fixedRate_ = fixedRate; fixedDayCount_ = fixedDayCount; principalSchedule_ = principalSchedule; if (paymentConvention.HasValue) paymentConvention_ = paymentConvention.Value; else paymentConvention_ = fixedSchedule_.businessDayConvention(); List<CashFlow> principalLeg = new PricipalLeg(principalSchedule, fixedDayCount) .withNotionals(nominal) .withPaymentAdjustment(paymentConvention_) .withSign(type == Type.Loan ? -1 : 1); // temporary for (int i = 0; i < principalLeg.Count - 1; i++) { Principal p = (Principal)principalLeg[i]; notionals_.Add(p.nominal()); } List<CashFlow> fixedLeg = new FixedRateLeg(fixedSchedule) .withCouponRates(fixedRate, fixedDayCount) .withPaymentAdjustment(paymentConvention_) .withNotionals(notionals_); // Discounting Pricipal notionals_.Clear(); double n; for (int i = 0; i < fixedLeg.Count; i++) { FixedRateCoupon c = (FixedRateCoupon)fixedLeg[i]; n = i > 0 ? notionals_.Last() : c.nominal(); notionals_.Add(n / (1 + (c.rate() * c.dayCounter().yearFraction(c.refPeriodStart, c.refPeriodEnd)))); } // New Leg List<CashFlow> discountedFixedLeg = new FixedRateLeg(fixedSchedule) .withCouponRates(fixedRate, fixedDayCount) .withPaymentAdjustment(paymentConvention_) .withNotionals(notionals_); // Adjust Principal Principal p0 = (Principal)principalLeg[0]; p0.setAmount(notionals_.Last()); legs_[0] = discountedFixedLeg; legs_[1] = principalLeg; if (type_ == Type.Loan) { payer_[0] = +1; payer_[1] = -1; } else { payer_[0] = -1; payer_[1] = +1; } }