/**
  * @param date The valuation date, not null
  * @param indexFixingTS The index fixing time series, not null
  * @param settlementDate The settlement date, not null
  * @param yieldCurveNames The yield curve names, not null, must have at least two entries
  * @return The security
  * @deprecated Use the version that does not take curve names
  */
 @Deprecated
 public BondIborSecurity toDerivative(
     final ZonedDateTime date,
     final DoubleTimeSeries<ZonedDateTime> indexFixingTS,
     final ZonedDateTime settlementDate,
     final String... yieldCurveNames) {
   // Implementation note: First yield curve used for coupon and notional (credit), the second for
   // risk free settlement.
   ArgumentChecker.notNull(date, "date");
   ArgumentChecker.notNull(indexFixingTS, "fixing time series");
   ArgumentChecker.notNull(settlementDate, "settlement date");
   ArgumentChecker.notNull(yieldCurveNames, "yield curve names");
   ArgumentChecker.isTrue(yieldCurveNames.length > 1, "at least two curves required");
   final String creditCurveName = yieldCurveNames[0];
   final String riskFreeCurveName = yieldCurveNames[1];
   double settlementTime;
   if (settlementDate.isBefore(date)) {
     settlementTime = 0.0;
   } else {
     settlementTime = TimeCalculator.getTimeBetween(date, settlementDate);
   }
   final AnnuityPaymentFixed nominal =
       (AnnuityPaymentFixed) getNominal().toDerivative(date, creditCurveName);
   final Annuity<Coupon> coupon =
       (Annuity<Coupon>) getCoupons().toDerivative(date, indexFixingTS, yieldCurveNames);
   return new BondIborSecurity(
       nominal.trimBefore(settlementTime),
       coupon.trimBefore(settlementTime),
       settlementTime,
       riskFreeCurveName);
 }
 @Override
 public PresentValueSABRSensitivityDataBundle visitGenericAnnuity(
     final Annuity<? extends Payment> annuity, final SABRSwaptionProviderInterface sabr) {
   ArgumentChecker.notNull(annuity, "Annuity");
   PresentValueSABRSensitivityDataBundle cs = visit(annuity.getNthPayment(0), sabr);
   for (int loopp = 1; loopp < annuity.getNumberOfPayments(); loopp++) {
     cs = cs.plus(visit(annuity.getNthPayment(loopp), sabr));
   }
   return cs;
 }
 @Override
 public double[] visitGenericAnnuity(
     final Annuity<? extends Payment> annuity, final YieldCurveBundle curves) {
   final int n = annuity.getNumberOfPayments();
   final double[] fractions = new double[n];
   for (int i = 0; i < n; i++) {
     fractions[i] = annuity.getNthPayment(i).accept(COUPON_VISITOR, curves);
   }
   return fractions;
 }
 @Override
 public MultipleCurrencyCurveSensitivityMarket visitGenericAnnuity(
     final Annuity<? extends Payment> annuity, final IMarketBundle market) {
   ArgumentChecker.notNull(annuity, "Annuity");
   ArgumentChecker.notNull(market, "Market");
   MultipleCurrencyCurveSensitivityMarket cs = visit(annuity.getNthPayment(0), market);
   for (int loopp = 1; loopp < annuity.getNumberOfPayments(); loopp++) {
     cs = cs.plus(visit(annuity.getNthPayment(loopp), market));
   }
   return cs;
 }
 /**
  * This gives you the bond coupon, for a given yield curve, that renders the bond par (present
  * value of all cash flows equal to 1.0)
  *
  * @param bond the bond
  * @param curves the input curves
  * @return the par rate
  */
 @Override
 public Double visitBondFixedSecurity(
     final BondFixedSecurity bond, final YieldCurveBundle curves) {
   final Annuity<CouponFixed> coupons = bond.getCoupon();
   final int n = coupons.getNumberOfPayments();
   final CouponFixed[] unitCoupons = new CouponFixed[n];
   for (int i = 0; i < n; i++) {
     unitCoupons[i] = coupons.getNthPayment(i).withUnitCoupon();
   }
   final Annuity<CouponFixed> unitCouponAnnuity = new Annuity<>(unitCoupons);
   final double pvann = unitCouponAnnuity.accept(PVC, curves);
   final double matPV = bond.getNominal().accept(PVC, curves);
   return (1 - matPV) / pvann;
 }
 /**
  * @param date The valuation date, not null
  * @param indexFixingTS The index fixing time series, not null
  * @param settlementDate The settlement date, not null
  * @return The security
  */
 public BondIborSecurity toDerivative(
     final ZonedDateTime date,
     final DoubleTimeSeries<ZonedDateTime> indexFixingTS,
     final ZonedDateTime settlementDate) {
   ArgumentChecker.notNull(date, "date");
   ArgumentChecker.notNull(indexFixingTS, "fixing time series");
   ArgumentChecker.notNull(settlementDate, "settlement date");
   double settlementTime;
   if (settlementDate.isBefore(date)) {
     settlementTime = 0.0;
   } else {
     settlementTime = TimeCalculator.getTimeBetween(date, settlementDate);
   }
   final AnnuityPaymentFixed nominal = (AnnuityPaymentFixed) getNominal().toDerivative(date);
   final Annuity<Coupon> coupon = (Annuity<Coupon>) getCoupons().toDerivative(date, indexFixingTS);
   return new BondIborSecurity(
       nominal.trimBefore(settlementTime), coupon.trimBefore(settlementTime), settlementTime);
 }
 @Override
 public Map<String, List<DoublesPair>> visitGenericAnnuity(
     final Annuity<? extends Payment> annuity, final YieldCurveBundle data) {
   final Map<String, List<DoublesPair>> map = new HashMap<String, List<DoublesPair>>();
   for (final Payment p : annuity.getPayments()) {
     final Map<String, List<DoublesPair>> tempMap = visit(p, data);
     for (final String name : tempMap.keySet()) {
       if (!map.containsKey(name)) {
         map.put(name, tempMap.get(name));
       } else {
         final List<DoublesPair> tempList = map.get(name);
         tempList.addAll(tempMap.get(name));
         map.put(name, tempList);
       }
     }
   }
   return map;
 }
 /**
  * @param date The date to use when converting to the derivative form, not null
  * @param settlementDate The settlement date, not null
  * @param data The index time series
  * @return The derivative form
  */
 public BondInterestIndexedSecurity<PaymentFixed, Coupon> toDerivative(
     final ZonedDateTime date,
     final ZonedDateTime settlementDate,
     final DoubleTimeSeries<ZonedDateTime> data) {
   ArgumentChecker.notNull(date, "date");
   ArgumentChecker.notNull(settlementDate, "settlement date");
   double settlementTime;
   if (settlementDate.isBefore(date)) {
     settlementTime = 0.0;
   } else {
     settlementTime = TimeCalculator.getTimeBetween(date, settlementDate);
   }
   final Annuity<PaymentFixed> nominal =
       (Annuity<PaymentFixed>) getNominal().toDerivative(date, data);
   final AnnuityDefinition<CouponDefinition> couponDefinition =
       (AnnuityDefinition<CouponDefinition>) getCoupons().trimBefore(settlementDate);
   final CouponDefinition[] couponExPeriodArray =
       new CouponDefinition[couponDefinition.getNumberOfPayments()];
   System.arraycopy(
       couponDefinition.getPayments(),
       0,
       couponExPeriodArray,
       0,
       couponDefinition.getNumberOfPayments());
   if (getExCouponDays() != 0) {
     final ZonedDateTime exDividendDate =
         ScheduleCalculator.getAdjustedDate(
             couponDefinition.getNthPayment(0).getPaymentDate(),
             -getExCouponDays(),
             getCalendar());
     if (settlementDate.isAfter(exDividendDate)) {
       // Implementation note: Ex-dividend period: the next coupon is not received but its date is
       // required for yield calculation
       couponExPeriodArray[0] = new CouponFixedDefinition(couponDefinition.getNthPayment(0), 0.0);
     }
   }
   final AnnuityDefinition<PaymentDefinition> couponDefinitionExPeriod =
       new AnnuityDefinition<PaymentDefinition>(couponExPeriodArray, getCalendar());
   final Annuity<Coupon> couponStandard =
       (Annuity<Coupon>) couponDefinitionExPeriod.toDerivative(date, data);
   final Annuity<PaymentFixed> nominalStandard = nominal.trimBefore(settlementTime);
   final double accruedInterest = accruedInterest(settlementDate);
   final double factorSpot =
       getDayCount()
           .getAccruedInterest(
               couponDefinition.getNthPayment(0).getAccrualStartDate(),
               settlementDate,
               couponDefinition.getNthPayment(0).getAccrualEndDate(),
               1.0,
               _couponPerYear);
   final double factorPeriod =
       getDayCount()
           .getAccruedInterest(
               couponDefinition.getNthPayment(0).getAccrualStartDate(),
               couponDefinition.getNthPayment(0).getAccrualEndDate(),
               couponDefinition.getNthPayment(0).getAccrualEndDate(),
               1.0,
               _couponPerYear);
   final double factorToNextCoupon = (factorPeriod - factorSpot) / factorPeriod;
   final PaymentFixedDefinition nominalLast =
       getNominal().getNthPayment(getNominal().getNumberOfPayments() - 1);
   final ZonedDateTime settlementDate2 = settlementDate.isBefore(date) ? date : settlementDate;
   final double notional = settlementDate.isBefore(date) ? 0.0 : 1.0;
   final PaymentFixedDefinition settlementDefinition =
       new PaymentFixedDefinition(nominalLast.getCurrency(), settlementDate2, notional);
   final PaymentFixed settlement = settlementDefinition.toDerivative(date);
   return new BondInterestIndexedSecurity<>(
       nominalStandard,
       couponStandard,
       settlementTime,
       accruedInterest,
       factorToNextCoupon,
       _yieldConvention,
       _couponPerYear,
       settlement,
       getIssuerEntity(),
       _priceIndex);
 }