package name.abuchen.portfolio.snapshot; import java.time.LocalDate; import java.time.temporal.TemporalAmount; import java.time.temporal.TemporalField; import java.time.temporal.WeekFields; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.ResourceBundle; public class Aggregation { public enum Period { WEEKLY { @Override public TemporalAmount getPeriod() { return java.time.Period.ofDays(7); } @Override public LocalDate getStartDateFor(LocalDate d) { TemporalField fieldISO = WeekFields.of(Locale.getDefault()).dayOfWeek(); return d.with(fieldISO, 1); } }, MONTHLY { @Override public TemporalAmount getPeriod() { return java.time.Period.ofMonths(1); } @Override public LocalDate getStartDateFor(LocalDate d) { return d.withDayOfMonth(1); } }, QUARTERLY { @Override public TemporalAmount getPeriod() { return java.time.Period.ofMonths(3); } @Override public LocalDate getStartDateFor(LocalDate d) { int month = (((d.getMonthValue() - 1) / 3) * 3) + 1; return LocalDate.of(d.getYear(), month, 1); } }, YEARLY { @Override public TemporalAmount getPeriod() { return java.time.Period.ofYears(1); } @Override public LocalDate getStartDateFor(LocalDate d) { return d.withDayOfYear(1); } }; public abstract TemporalAmount getPeriod(); public abstract LocalDate getStartDateFor(LocalDate d); private static final ResourceBundle RESOURCES = ResourceBundle .getBundle("name.abuchen.portfolio.snapshot.labels"); //$NON-NLS-1$ public String toString() { return RESOURCES.getString("aggregation." + name()); //$NON-NLS-1$ } } public static PerformanceIndex aggregate(PerformanceIndex index, Period period) { LocalDate[] dates = index.getDates(); double[] accumulated = index.getAccumulatedPercentage(); double[] delta = index.getDeltaPercentage(); long[] transferals = index.getTransferals(); long[] totals = index.getTotals(); LocalDate start = period.getStartDateFor(dates[0]).plus(period.getPeriod()); LocalDate kill = start.minusDays(1); List<LocalDate> cDates = new ArrayList<LocalDate>(); List<Double> cAccumulated = new ArrayList<Double>(); List<Double> cDelta = new ArrayList<Double>(); List<Long> cTransferals = new ArrayList<Long>(); List<Long> cTotals = new ArrayList<Long>(); double d = 0d; long t = 0; for (int ii = 0; ii < dates.length; ii++) { LocalDate current = dates[ii]; d = ((d + 1) * (delta[ii] + 1)) - 1; t += transferals[ii]; if (current.equals(kill) || ii == dates.length - 1) { cDates.add(current); cAccumulated.add(accumulated[ii]); cDelta.add(d); cTransferals.add(t); cTotals.add(totals[ii]); d = 0d; t = 0; start = start.plus(period.getPeriod()); kill = start.minusDays(1); } } PerformanceIndex answer = new PerformanceIndex(index.getClient(), index.getCurrencyConverter(), index.getReportInterval()); answer.dates = cDates.toArray(new LocalDate[0]); answer.accumulated = asArrayD(cAccumulated); answer.delta = asArrayD(cDelta); answer.transferals = asArrayL(cTransferals); answer.totals = asArrayL(cTotals); return answer; } private static double[] asArrayD(List<Double> cAccumulated) { double[] answer = new double[cAccumulated.size()]; for (int ii = 0; ii < answer.length; ii++) answer[ii] = cAccumulated.get(ii); return answer; } private static long[] asArrayL(List<Long> cAccumulated) { long[] answer = new long[cAccumulated.size()]; for (int ii = 0; ii < answer.length; ii++) answer[ii] = cAccumulated.get(ii); return answer; } }