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);
  }