/**
  * Tests that the high price for a date is greater than the low value for the same date and that
  * the close price falls in this (inclusive) range
  *
  * @param high The period high price time series
  * @param low The period low price time series
  * @param close The period close price time series
  * @throws IllegalArgumentException Strict calculation mode: if the low value for a date is
  *     greater than the high value or if the close value is not in the range bounded by the high
  *     and low prices. Lenient calculation mode: if the percentage of times that the low value for
  *     a date is greater than the high value or that the close value is not in the range bounded
  *     by the high and low values is greater than the maximum allowed
  */
 protected void testHighLowClose(
     final DoubleTimeSeries<?> high,
     final DoubleTimeSeries<?> low,
     final DoubleTimeSeries<?> close) {
   final double size = high.size();
   int count = 0;
   final Iterator<Double> highIter = high.valuesIterator();
   final Iterator<Double> lowIter = low.valuesIterator();
   final Iterator<Double> closeIter = close.valuesIterator();
   boolean compare;
   double highValue, lowValue, closeValue;
   while (highIter.hasNext()) {
     highValue = highIter.next();
     lowValue = lowIter.next();
     closeValue = closeIter.next();
     compare = highValue < lowValue || closeValue > highValue || closeValue < lowValue;
     if (compare) {
       if (_mode == CalculationMode.STRICT) {
         throw new TimeSeriesException(
             "Not all values in the high series were greater than the values in the low series");
       }
       count++;
     }
   }
   final double percent = count / size;
   if (percent > _percentBadDataPoints) {
     throw new TimeSeriesException(
         "Percent " + percent + " of bad data points is greater than " + _percentBadDataPoints);
   }
 }
 public void testCycle1() {
   DoubleTimeSeries<?> cycleObject = cycleObject(DoubleTimeSeries.class, ts);
   assertEquals(ImmutableLocalDateDoubleTimeSeries.class, cycleObject.getClass());
   assertEquals(ts, cycleObject);
   cycleObject =
       cycleObject(DoubleTimeSeries.class, ImmutableLocalDateDoubleTimeSeries.EMPTY_SERIES);
   assertEquals(ImmutableLocalDateDoubleTimeSeries.EMPTY_SERIES, cycleObject);
 }
  @Override
  public Coupon toDerivative(
      final ZonedDateTime date,
      final DoubleTimeSeries<ZonedDateTime> priceIndexTimeSeries,
      final String... yieldCurveNames) {
    ArgumentChecker.notNull(date, "date");
    ArgumentChecker.notNull(yieldCurveNames, "yield curve names");
    ArgumentChecker.isTrue(yieldCurveNames.length > 0, "at least one curve required");
    ArgumentChecker.isTrue(!date.isAfter(getPaymentDate()), "date is after payment date");
    final double lastKnownFixingTime =
        TimeCalculator.getTimeBetween(date, getLastKnownFixingDate());
    final LocalDate dayConversion = date.toLocalDate();
    final String discountingCurveName = yieldCurveNames[0];
    final double paymentTime = TimeCalculator.getTimeBetween(date, getPaymentDate());
    final LocalDate dayFixing = getReferenceEndDate()[1].toLocalDate();
    if (dayConversion.isAfter(dayFixing)) {
      final Double fixedEndIndex1 = priceIndexTimeSeries.getValue(getReferenceEndDate()[1]);

      if (fixedEndIndex1 != null) {
        final Double fixedEndIndex0 = priceIndexTimeSeries.getValue(getReferenceEndDate()[0]);
        final Double fixedEndIndex =
            getWeight() * fixedEndIndex0 + (1 - getWeight()) * fixedEndIndex1;
        final Double fixedRate = (fixedEndIndex / getIndexStartValue() - 1.0);
        return new CouponFixed(
            getCurrency(),
            paymentTime,
            discountingCurveName,
            getPaymentYearFraction(),
            getNotional(),
            payOff(fixedRate));
      }
    }
    final double[] referenceEndTime = new double[2];
    referenceEndTime[0] = TimeCalculator.getTimeBetween(date, _referenceEndDate[0]);
    referenceEndTime[1] = TimeCalculator.getTimeBetween(date, _referenceEndDate[1]);
    final ZonedDateTime naturalPaymentDate =
        getPaymentDate().minusMonths(_monthLag - _conventionalMonthLag);
    final double naturalPaymentEndTime = TimeCalculator.getTimeBetween(date, naturalPaymentDate);
    return new CapFloorInflationZeroCouponInterpolation(
        getCurrency(),
        paymentTime,
        getPaymentYearFraction(),
        getNotional(),
        getPriceIndex(),
        lastKnownFixingTime,
        _indexStartValue,
        referenceEndTime,
        naturalPaymentEndTime,
        _maturity,
        _weight,
        _strike,
        _isCap);
  }
 /**
  * {@inheritDoc} The definition is responsible for constructing a view of the variance swap as of
  * a particular date. In particular, it resolves calendars. The VarianceSwap needs an array of
  * observations, as well as its *expected* length. The actual number of observations may be less
  * than that expected at trade inception because of a market disruption event. ( For an example of
  * a market disruption event, see http://cfe.cboe.com/Products/Spec_VT.aspx )
  *
  * @param valueDate Date at which valuation will occur, not null
  * @param underlyingTimeSeries Time series of underlying observations, not null
  * @return VarianceSwap derivative as of date
  */
 @Override
 public EquityVarianceSwap toDerivative(
     final ZonedDateTime valueDate, final DoubleTimeSeries<LocalDate> underlyingTimeSeries) {
   ArgumentChecker.notNull(valueDate, "date");
   ArgumentChecker.notNull(
       underlyingTimeSeries,
       "A TimeSeries of observations must be provided. If observations have not begun, please pass an empty series.");
   final double timeToObsStart = TimeCalculator.getTimeBetween(valueDate, getObsStartDate());
   final double timeToObsEnd = TimeCalculator.getTimeBetween(valueDate, getObsEndDate());
   final double timeToSettlement = TimeCalculator.getTimeBetween(valueDate, getSettlementDate());
   DoubleTimeSeries<LocalDate> realizedTS;
   if (timeToObsStart > 0) {
     realizedTS = ImmutableLocalDateDoubleTimeSeries.EMPTY_SERIES;
   } else {
     realizedTS =
         underlyingTimeSeries.subSeries(
             getObsStartDate().toLocalDate(), true, valueDate.toLocalDate(), false);
   }
   final double[] observations = realizedTS.valuesArrayFast();
   final double[]
       observationWeights = {}; // TODO Case 2011-06-29 Calendar Add functionality for non-trivial
   // weighting of observations
   ZonedDateTime finalObsDate = getObsEndDate().isAfter(valueDate) ? valueDate : getObsEndDate();
   int nGoodBusinessDays =
       finalObsDate.isAfter(getObsStartDate())
           ? BusinessDayDateUtils.getWorkingDaysInclusive(
               getObsStartDate(), finalObsDate, getCalendar())
           : 0;
   final int nObsDisrupted = nGoodBusinessDays - observations.length;
   ArgumentChecker.isTrue(
       nObsDisrupted >= 0,
       "Have more observations {} than good business days {}",
       observations.length,
       nGoodBusinessDays);
   return new EquityVarianceSwap(
       timeToObsStart,
       timeToObsEnd,
       timeToSettlement,
       getVarStrike(),
       getVarNotional(),
       getCurrency(),
       getAnnualizationFactor(),
       getObsExpected(),
       nObsDisrupted,
       observations,
       observationWeights,
       correctForDividends());
 }
 /**
  * {@inheritDoc} If the fixing date is strictly before the conversion date and the fixing rate is
  * not available, an exception is thrown; if the fixing rate is available a fixed coupon is
  * returned. If the fixing date is equal to the conversion date, if the fixing rate is available a
  * fixed coupon is returned, if not a coupon Ibor with spread is returned. If the fixing date is
  * strictly after the conversion date, a coupon Ibor is returned. All the comparisons are between
  * dates without time.
  */
 @Override
 public Coupon toDerivative(
     final ZonedDateTime dateTime, final DoubleTimeSeries<ZonedDateTime> indexFixingTimeSeries) {
   ArgumentChecker.notNull(dateTime, "date");
   final LocalDate dayConversion = dateTime.toLocalDate();
   ArgumentChecker.notNull(indexFixingTimeSeries, "Index fixing time series");
   ArgumentChecker.isTrue(
       !dayConversion.isAfter(getPaymentDate().toLocalDate()), "date is after payment date");
   final double paymentTime = TimeCalculator.getTimeBetween(dateTime, getPaymentDate());
   final LocalDate dayFixing = getFixingDate().toLocalDate();
   if (dayConversion.equals(
       dayFixing)) { // The fixing is on the reference date; if known the fixing is used and if
                     // not, the floating coupon is created.
     final Double fixedRate = indexFixingTimeSeries.getValue(getFixingDate());
     if (fixedRate != null) {
       return new CouponFixed(
           getCurrency(), paymentTime, getPaymentYearFraction(), getNotional(), fixedRate);
     }
   }
   if (dayConversion.isAfter(dayFixing)) { // The fixing is required
     final ZonedDateTime rezonedFixingDate =
         getFixingDate().toLocalDate().atStartOfDay(ZoneOffset.UTC);
     final Double fixedRate =
         indexFixingTimeSeries.getValue(rezonedFixingDate); // TODO: remove time from fixing date.
     if (fixedRate == null) {
       throw new OpenGammaRuntimeException(
           "Could not get fixing value for date " + getFixingDate());
     }
     return new CouponFixed(
         getCurrency(), paymentTime, getPaymentYearFraction(), getNotional(), fixedRate);
   }
   final double fixingTime = TimeCalculator.getTimeBetween(dateTime, getFixingDate());
   final double fixingPeriodStartTime =
       TimeCalculator.getTimeBetween(dateTime, getFixingPeriodStartDate());
   final double fixingPeriodEndTime =
       TimeCalculator.getTimeBetween(dateTime, getFixingPeriodEndDate());
   return new CouponIbor(
       getCurrency(),
       paymentTime,
       getPaymentYearFraction(),
       getNotional(),
       fixingTime,
       getIndex(),
       fixingPeriodStartTime,
       fixingPeriodEndTime,
       getFixingPeriodAccrualFactor());
 }
 public void testEmptyCycle1() {
   DoubleTimeSeries<?> cycleObject = cycleObject(DoubleTimeSeries.class, empty);
   assertEquals(ImmutableLocalDateDoubleTimeSeries.class, cycleObject.getClass());
   assertEquals(empty, cycleObject);
 }