class DiscountingFixedCouponBondProductPricer {

  public double macaulayDurationFromYield(ResolvedFixedCouponBond bond, LocalDate settlementDate, double yield) {
    ImmutableList<FixedCouponBondPaymentPeriod> payments = bond.getPeriodicPayments();
    int nCoupon = payments.size() - couponIndex(payments, settlementDate);
    FixedCouponBondYieldConvention yieldConv = bond.getYieldConvention();
    if ((yieldConv.equals(US_STREET)) && (nCoupon == 1)) {
      return factorToNextCoupon(bond, settlementDate) /
          bond.getFrequency().eventsPerYear();
    }
    if ((yieldConv.equals(US_STREET)) || (yieldConv.equals(GB_BUMP_DMO)) || (yieldConv.equals(DE_BONDS))) {
      return modifiedDurationFromYield(bond, settlementDate, yield) *
          (1d + yield / bond.getFrequency().eventsPerYear());
    }
    throw new UnsupportedOperationException("The convention " + yieldConv.name() + " is not supported.");
  }

  public  DiscountingFixedCouponBondProductPricer(
      DiscountingFixedCouponBondPaymentPeriodPricer periodPricer,
      DiscountingPaymentPricer nominalPricer);

}