SimpleGrossTimeSeriesReturnCalculator extends TimeSeriesReturnCalculator { @Override public LocalDateDoubleTimeSeries evaluate(final LocalDateDoubleTimeSeries... x) { ArgumentChecker.notEmpty(x, "x"); ArgumentChecker.notNull(x[0], "first time series"); final LocalDateDoubleTimeSeries ts = x[0]; if (ts.size() < 2) { throw new TimeSeriesException("Need at least two data points to calculate return series"); } LocalDateDoubleTimeSeries d = null; if (x.length > 1) { if (x[1] != null) { d = x[1]; } } final int[] resultDates = new int[ts.size() - 1]; final double[] resultValues = new double[ts.size() - 1]; int resultIndex = 0; final LocalDateDoubleEntryIterator it = ts.iterator(); it.nextTimeFast(); double previousValue = it.currentValue(); double dividend; Double dividendTSData; while (it.hasNext()) { final int date = it.nextTimeFast(); final double value = it.currentValue(); if (isValueNonZero(previousValue) && isValueNonZero(value)) { resultDates[resultIndex] = date; if (d == null) { dividend = 0; } else { dividendTSData = d.getValue(date); dividend = dividendTSData == null ? 0 : dividendTSData; } resultValues[resultIndex++] = (value + dividend) / previousValue; } previousValue = value; } return getSeries(resultDates, resultValues, resultIndex); } SimpleGrossTimeSeriesReturnCalculator(final CalculationMode mode); @Override LocalDateDoubleTimeSeries evaluate(final LocalDateDoubleTimeSeries... x);  }
@Test(expectedExceptions = IllegalArgumentException.class) public void testNullArray() { CALCULATOR.evaluate((LocalDateDoubleTimeSeries[]) null); }
@Test(expectedExceptions = IllegalArgumentException.class) public void testEmptyArray() { CALCULATOR.evaluate(new LocalDateDoubleTimeSeries[0]); }
@Test(expectedExceptions = TimeSeriesException.class) public void testWithBadInputs() { final LocalDateDoubleTimeSeries ts = ImmutableLocalDateDoubleTimeSeries.of(new LocalDate[] {LocalDate.ofEpochDay(1) }, new double[] {4}); CALCULATOR.evaluate(new LocalDateDoubleTimeSeries[] {ts}); }
@Test public void testReturnsWithoutDividends() { final int n = 20; final LocalDate[] times = new LocalDate[n]; final double[] data = new double[n]; final double[] returns = new double[n - 1]; double random; for (int i = 0; i < n; i++) { times[i] = LocalDate.ofEpochDay(i); random = RANDOM.nextDouble(); data[i] = random; if (i > 0) { returns[i - 1] = random / data[i - 1]; } } final LocalDateDoubleTimeSeries priceTS = ImmutableLocalDateDoubleTimeSeries.of(times, data); final LocalDateDoubleTimeSeries returnTS = ImmutableLocalDateDoubleTimeSeries.of(Arrays.copyOfRange(times, 1, n), returns); assertTrue(CALCULATOR.evaluate(new LocalDateDoubleTimeSeries[] {priceTS}).equals(returnTS)); }
@Test public void testReturnsWithZeroesInSeries() { final int n = 20; final LocalDate[] times = new LocalDate[n]; final double[] data = new double[n]; final double[] returns = new double[n - 3]; double random; for (int i = 0; i < n - 2; i++) { times[i] = LocalDate.ofEpochDay(i); random = RANDOM.nextDouble(); data[i] = random; if (i > 0) { returns[i - 1] = random / data[i - 1]; } } times[n - 2] = LocalDate.ofEpochDay(n - 2); data[n - 2] = 0; times[n - 1] = LocalDate.ofEpochDay(n - 1); data[n - 1] = RANDOM.nextDouble(); final LocalDateDoubleTimeSeries priceTS = ImmutableLocalDateDoubleTimeSeries.of(times, data); final LocalDateDoubleTimeSeries returnTS = ImmutableLocalDateDoubleTimeSeries.of(Arrays.copyOfRange(times, 1, n - 2), returns); final TimeSeriesReturnCalculator strict = new SimpleGrossTimeSeriesReturnCalculator(CalculationMode.STRICT); final LocalDateDoubleTimeSeries[] tsArray = new LocalDateDoubleTimeSeries[] {priceTS}; try { strict.evaluate(tsArray); Assert.fail(); } catch (final TimeSeriesException e) { } assertTrue(CALCULATOR.evaluate(tsArray).equals(returnTS)); }
@Test public void testReturnsWithDividendsAtDifferentTimes() { final int n = 20; final LocalDate[] times = new LocalDate[n]; final double[] data = new double[n]; final double[] returns = new double[n - 1]; double random; for (int i = 0; i < n; i++) { times[i] = LocalDate.ofEpochDay(i); random = RANDOM.nextDouble(); data[i] = random; if (i > 0) { returns[i - 1] = random / data[i - 1]; } } final LocalDateDoubleTimeSeries dividendTS = ImmutableLocalDateDoubleTimeSeries.of(new LocalDate[] { LocalDate.ofEpochDay(300) }, new double[] {3}); final LocalDateDoubleTimeSeries priceTS = ImmutableLocalDateDoubleTimeSeries.of(times, data); final LocalDateDoubleTimeSeries returnTS = ImmutableLocalDateDoubleTimeSeries.of(Arrays.copyOfRange(times, 1, n), returns); assertTrue(CALCULATOR.evaluate(new LocalDateDoubleTimeSeries[] {priceTS, dividendTS}).equals(returnTS)); }
@Test public void testReturnsWithDividend() { final int n = 20; final LocalDate[] times = new LocalDate[n]; final double[] data = new double[n]; final double[] returns = new double[n - 1]; final LocalDate[] dividendTimes = new LocalDate[] { LocalDate.ofEpochDay(1), LocalDate.ofEpochDay(4) }; final double[] dividendData = new double[] {0.4, 0.6}; double random; for (int i = 0; i < n; i++) { times[i] = LocalDate.ofEpochDay(i); random = RANDOM.nextDouble(); data[i] = random; if (i > 0) { if (i == 1) { returns[i - 1] = (random + dividendData[0]) / data[i - 1]; } else if (i == 4) { returns[i - 1] = (random + dividendData[1]) / data[i - 1]; } else { returns[i - 1] = random / data[i - 1]; } } } final LocalDateDoubleTimeSeries dividendTS = ImmutableLocalDateDoubleTimeSeries.of(dividendTimes, dividendData); final LocalDateDoubleTimeSeries priceTS = ImmutableLocalDateDoubleTimeSeries.of(times, data); final LocalDateDoubleTimeSeries returnTS = ImmutableLocalDateDoubleTimeSeries.of(Arrays.copyOfRange(times, 1, n), returns); assertTrue(CALCULATOR.evaluate(new LocalDateDoubleTimeSeries[] {priceTS, dividendTS}).equals(returnTS)); }