class AnnuityCouponIborRatchetDefinition extends AnnuityCouponDefinition<CouponDefinition> {

  public static AnnuityCouponIborRatchetDefinition withFirstCouponFixed(final ZonedDateTime settlementDate, final Period annuityTenor, final double notional, final IborIndex index,
      final boolean isPayer, final double firstCouponFixedRate, final double[] mainCoefficients, final double[] floorCoefficients, final double[] capCoefficients,
      final Calendar calendar) {
    final ZonedDateTime[] paymentDates = ScheduleCalculator.getAdjustedDateSchedule(settlementDate, annuityTenor, index.getTenor(), index.getBusinessDayConvention(), calendar,
        index.isEndOfMonth());
    final CouponDefinition[] coupons = new CouponDefinition[paymentDates.length];
    final double notionalSign = notional * (isPayer ? -1.0 : 1.0);
    coupons[0] = new CouponFixedDefinition(index.getCurrency(), paymentDates[0], settlementDate, paymentDates[0],
        index.getDayCount().getDayCountFraction(settlementDate, paymentDates[0], calendar), notionalSign, firstCouponFixedRate);
    for (int loopcpn = 1; loopcpn < paymentDates.length; loopcpn++) {
      coupons[loopcpn] = new CouponIborRatchetDefinition(index.getCurrency(), paymentDates[loopcpn], paymentDates[loopcpn - 1], paymentDates[loopcpn],
          index.getDayCount().getDayCountFraction(paymentDates[loopcpn - 1], paymentDates[loopcpn], calendar), notionalSign,
          ScheduleCalculator.getAdjustedDate(paymentDates[loopcpn - 1], -index.getSpotLag(), calendar), index, mainCoefficients, floorCoefficients,
          capCoefficients, calendar);
    }
    return new AnnuityCouponIborRatchetDefinition(coupons, calendar);
  }

  public  AnnuityCouponIborRatchetDefinition(final CouponDefinition[] payments, final Calendar calendar);

}