AnnualOverlap extends AChainLinking { @Override public void process() { if (input == null || input.isEmpty()) { results = null; return; } results = new InformationSet(); calculateMissingData(); TsDomain intersection = intersectAllDomains(findSmallestDomain()); if (intersection.getLength() == 0) { throw new IllegalArgumentException("The common domain is empty"); } if (refYear == - 1 || intersection.getStart().getYear() > refYear || intersection.getEnd().getYear() < refYear) { refYear = intersection.getStart().getYear(); } results.add(REF_YEAR, refYear); while (intersection.getStart().getYear() < refYear) { intersection = intersection.drop(1, 0); } List<Product> prds = cloneInputList(); for (int i = 0; i < prds.size(); i++) { prds.get(i).setQuantities(prds.get(i).getQuantities().fittoDomain(intersection)); prds.get(i).setPrice(prds.get(i).getPrice().fittoDomain(intersection)); prds.get(i).setValue(prds.get(i).getValue().fittoDomain(intersection)); } List<TsData> allPricesY = new ArrayList<>(); for (int i = 0; i < prds.size(); i++) { allPricesY.add(prds.get(i).getPrice().changeFrequency(TsFrequency.Yearly, TsAggregationType.Average, true)); } List<TsData> allQuantitiesQ = new ArrayList<>(); for (int i = 0; i < prds.size(); i++) { TsData ts = prds.get(i).getQuantities(); ts = ts.update(ts.changeFrequency(TsFrequency.Quarterly, TsAggregationType.Sum, true)); ts = ts.drop(4, 0); allQuantitiesQ.add(ts); } TsData totalValueQ = prds.get(0).getValue(); for (int i = 1; i < prds.size(); i++) { totalValueQ = TsData.add(totalValueQ, prds.get(i).getValue()); } results.add(TOTAL_VALUES, totalValueQ); TsData totalValueY = totalValueQ.changeFrequency(TsFrequency.Yearly, TsAggregationType.Sum, true); totalValueQ = totalValueQ.drop(4, 0); TsData Qq = new TsData(totalValueQ.getDomain()); YearIterator yq = new YearIterator(Qq); List<YearIterator> iterators = new ArrayList<>(); for (int i = 0; i < allQuantitiesQ.size(); i++) { iterators.add(new YearIterator(allQuantitiesQ.get(i))); } while (yq.hasMoreElements()) { TsDataBlock qcur = yq.nextElement(); List<TsDataBlock> dataBlocks = new ArrayList<>(); for (int i = 0; i < prds.size(); i++) { dataBlocks.add(iterators.get(i).nextElement()); } TsPeriod prev = TsPeriod.year(qcur.start.getYear() - 1); qcur.data.setAY(allPricesY.get(0).get(prev), dataBlocks.get(0).data); for (int i = 1; i < dataBlocks.size(); i++) { qcur.data.addAY(allPricesY.get(i).get(prev), dataBlocks.get(i).data); } } results.set(VALUES_PREVIOUS_PRICE, Qq.clone()); double idx = 100; int ifreq = Qq.getFrequency().intValue(); yq.reset(); while (yq.hasMoreElements()) { TsDataBlock qcur = yq.nextElement(); TsPeriod prev = TsPeriod.year(qcur.start.getYear() - 1); double val0 = totalValueY.get(prev); double val1 = qcur.data.sum(); qcur.data.mul(idx / (val0 / ifreq)); idx *= val1 / val0; } results.set(CHAIN_LINKED_INDEXES, Qq); }  @Override void process(); static final String TOTAL_VALUES; static final String VALUES_PREVIOUS_PRICE; static final String CHAIN_LINKED_INDEXES; static final String REF_YEAR; }
@Test public void testAnnualOverlap() { double[] qa = new double[]{56.4, 62.4, 65.7, 66.5, 67.4, 69.4, 71.5, 73.7, 76, 78.3, 80.6, 83.1, 85.5, 88.2, 90.8, 93.5}; double[] qb = new double[]{57.6, 58, 59, 61.4, 57.6, 57.1, 56.5, 55.8, 55.4, 54.8, 54.2, 53.6, 53.2, 52.7, 52.1, 52}; double[] pa = new double[]{6.2, 6.5, 7.6, 7.7, 6.1, 5.7, 5.3, 5, 4.5, 4.3, 3.8, 3.5, 3.4, 3.1, 2.8, 2.7}; double[] pb = new double[]{5.4, 5.6, 6.2, 6.8, 8.0, 8.6, 9.4, 10.0, 10.7, 11.5, 11.7, 12.1, 12.5, 13, 13.8, 14.7}; TsData QAq = new TsData(TsFrequency.Quarterly, 1997, 0, qa, true); TsData QBq = new TsData(TsFrequency.Quarterly, 1997, 0, qb, true); TsData PAq = new TsData(TsFrequency.Quarterly, 1997, 0, pa, true); TsData PBq = new TsData(TsFrequency.Quarterly, 1997, 0, pb, true); AnnualOverlap o = new AnnualOverlap(); o.setRefYear(1997); o.addProduct("Product A", QAq, PAq); o.addProduct("Product B", QBq, PBq); o.process(); }