public static ZonedDateTime[] getAdjustedMaturityDateSchedule( final ZonedDateTime effectiveDate, final ZonedDateTime[] dates, final BusinessDayConvention convention, final Calendar calendar, final Frequency frequency) { ArgumentChecker.notEmpty(dates, "dates"); ArgumentChecker.notNull(convention, "convention"); ArgumentChecker.notNull(calendar, "calendar"); ArgumentChecker.notNull(frequency, "frequency"); PeriodFrequency periodFrequency; if (frequency instanceof PeriodFrequency) { periodFrequency = (PeriodFrequency) frequency; } else if (frequency instanceof SimpleFrequency) { periodFrequency = ((SimpleFrequency) frequency).toPeriodFrequency(); } else { throw new IllegalArgumentException( "For the moment can only deal with PeriodFrequency and SimpleFrequency"); } final Period period = periodFrequency.getPeriod(); final int n = dates.length; final ZonedDateTime[] results = new ZonedDateTime[n]; results[0] = effectiveDate.plus(period); for (int i = 1; i < n; i++) { results[i] = convention.adjustDate( calendar, dates[i - 1].plus(period)); // TODO need to further shift these dates by a convention } return results; }
/** * Counts back from maturityDate, filling to equally spaced dates frequency times a year until the * last date <b>after</b> effective date. * * @param effectiveDate the date that terminates to back counting (i.e. the first date is after * this date), not null * @param maturityDate the date to count back from, not null * @param frequency how many times a year dates occur, not null * @return the first date after effectiveDate (i.e. effectiveDate is <b>not</b> included to the * maturityDate (included) */ public static ZonedDateTime[] getBackwardsUnadjustedDateSchedule( final ZonedDateTime effectiveDate, final ZonedDateTime maturityDate, final Frequency frequency) { ArgumentChecker.notNull(effectiveDate, "effective date"); ArgumentChecker.notNull(maturityDate, "maturity date"); ArgumentChecker.notNull(frequency, "frequency"); if (effectiveDate.isAfter(maturityDate)) { throw new IllegalArgumentException("Effective date was after maturity"); } PeriodFrequency periodFrequency; if (frequency instanceof PeriodFrequency) { periodFrequency = (PeriodFrequency) frequency; } else if (frequency instanceof SimpleFrequency) { periodFrequency = ((SimpleFrequency) frequency).toPeriodFrequency(); } else { throw new IllegalArgumentException( "For the moment can only deal with PeriodFrequency and SimpleFrequency"); } final Period period = periodFrequency.getPeriod(); final List<ZonedDateTime> dates = new ArrayList<>(); ZonedDateTime date = maturityDate; // TODO review the tolerance given while (date.isAfter(effectiveDate) && DateUtils.getExactDaysBetween(effectiveDate, date) > 4.0) { dates.add(date); date = date.minus(period); } Collections.sort(dates); return dates.toArray(EMPTY_ARRAY); }
/** * Convert a Frequency to a Period when possible. * * @param frequency The frequency. * @return The converted period. */ private static Period periodFromFrequency(final Frequency frequency) { PeriodFrequency periodFrequency; if (frequency instanceof PeriodFrequency) { periodFrequency = (PeriodFrequency) frequency; } else if (frequency instanceof SimpleFrequency) { periodFrequency = ((SimpleFrequency) frequency).toPeriodFrequency(); } else { throw new IllegalArgumentException( "For the moment can only deal with PeriodFrequency and SimpleFrequency"); } return periodFrequency.getPeriod(); }
private InterestRateSwapSecurity createFixedVsLibor3mSwap() { InterestRateSwapNotional notional = new InterestRateSwapNotional(Currency.USD, 100_000_000); PeriodFrequency freq6m = PeriodFrequency.of(Period.ofMonths(6)); PeriodFrequency freq3m = PeriodFrequency.of(Period.ofMonths(3)); Set<ExternalId> calendarUSNY = Sets.newHashSet(ExternalId.of(ExternalSchemes.ISDA_HOLIDAY, "USNY")); List<InterestRateSwapLeg> legs = new ArrayList<>(); FixedInterestRateSwapLeg payLeg = new FixedInterestRateSwapLeg(); payLeg.setNotional(notional); payLeg.setDayCountConvention(DayCounts.THIRTY_U_360); payLeg.setPaymentDateFrequency(freq6m); payLeg.setPaymentDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING); payLeg.setPaymentDateCalendars(calendarUSNY); payLeg.setMaturityDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING); payLeg.setAccrualPeriodFrequency(freq6m); payLeg.setAccrualPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING); payLeg.setAccrualPeriodCalendars(calendarUSNY); payLeg.setRate(new Rate(0.0150)); payLeg.setPayReceiveType(PayReceiveType.PAY); legs.add(payLeg); FloatingInterestRateSwapLeg receiveLeg = new FloatingInterestRateSwapLeg(); receiveLeg.setNotional(notional); receiveLeg.setDayCountConvention(DayCounts.ACT_360); receiveLeg.setPaymentDateFrequency(freq3m); receiveLeg.setPaymentDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING); receiveLeg.setPaymentDateCalendars(calendarUSNY); receiveLeg.setMaturityDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING); receiveLeg.setAccrualPeriodFrequency(freq3m); receiveLeg.setAccrualPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING); receiveLeg.setAccrualPeriodCalendars(calendarUSNY); receiveLeg.setResetPeriodFrequency(freq3m); receiveLeg.setResetPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING); receiveLeg.setResetPeriodCalendars(calendarUSNY); receiveLeg.setFixingDateBusinessDayConvention(BusinessDayConventions.PRECEDING); receiveLeg.setFixingDateCalendars(calendarUSNY); receiveLeg.setFixingDateOffset(-2); receiveLeg.setFloatingRateType(FloatingRateType.IBOR); receiveLeg.setFloatingReferenceRateId(InterestRateMockSources.getLiborIndexId()); receiveLeg.setPayReceiveType(PayReceiveType.RECEIVE); legs.add(receiveLeg); return new InterestRateSwapSecurity( ExternalIdBundle.of(ExternalId.of("UUID", GUIDGenerator.generate().toString())), "Fixed vs Libor 3m", LocalDate.of(2014, 9, 12), // effective date LocalDate.of(2021, 9, 12), // maturity date, legs); }
public static ZonedDateTime[] getAdjustedDateSchedule( final ZonedDateTime startDate, final ZonedDateTime endDate, final Frequency frequency, final BusinessDayConvention businessDayConvention, final Calendar calendar, final boolean isEOM) { PeriodFrequency periodFrequency; if (frequency instanceof PeriodFrequency) { periodFrequency = (PeriodFrequency) frequency; } else if (frequency instanceof SimpleFrequency) { periodFrequency = ((SimpleFrequency) frequency).toPeriodFrequency(); } else { throw new IllegalArgumentException( "For the moment can only deal with PeriodFrequency and SimpleFrequency"); } final Period period = periodFrequency.getPeriod(); return getAdjustedDateSchedule( startDate, endDate, period, businessDayConvention, calendar, isEOM, true); }
/** * Calculates the unadjusted date schedule. * * @param effectiveDate the effective date, not null * @param accrualDate the accrual date, not null * @param maturityDate the maturity date, not null * @param frequency how many times a year dates occur, not null * @return the schedule, not null */ public static ZonedDateTime[] getUnadjustedDateSchedule( final ZonedDateTime effectiveDate, final ZonedDateTime accrualDate, final ZonedDateTime maturityDate, final Frequency frequency) { ArgumentChecker.notNull(effectiveDate, "effective date"); ArgumentChecker.notNull(accrualDate, "accrual date"); ArgumentChecker.notNull(maturityDate, "maturity date"); ArgumentChecker.notNull(frequency, "frequency"); if (effectiveDate.isAfter(maturityDate)) { throw new IllegalArgumentException("Effective date was after maturity"); } if (accrualDate.isAfter(maturityDate)) { throw new IllegalArgumentException("Accrual date was after maturity"); } // TODO what if there's no valid date between accrual date and maturity date? PeriodFrequency periodFrequency; if (frequency instanceof PeriodFrequency) { periodFrequency = (PeriodFrequency) frequency; } else if (frequency instanceof SimpleFrequency) { periodFrequency = ((SimpleFrequency) frequency).toPeriodFrequency(); } else { throw new IllegalArgumentException( "For the moment can only deal with PeriodFrequency and SimpleFrequency"); } final Period period = periodFrequency.getPeriod(); final List<ZonedDateTime> dates = new ArrayList<>(); ZonedDateTime date = effectiveDate; // TODO this is only correct if effective date = accrual date date = date.plus(period); while (isWithinSwapLifetime( date, maturityDate)) { // REVIEW: could speed this up by working out how many periods between // start and end date? dates.add(date); date = date.plus(period); } return dates.toArray(EMPTY_ARRAY); }