/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.financial.analytics; import static com.opengamma.engine.value.ValueRequirementNames.ALL_PV01S; import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.opengamma.analytics.financial.provider.sensitivity.inflation.InflationSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.inflation.MultipleCurrencyInflationSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MulticurveSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyMulticurveSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyParameterSensitivity; import com.opengamma.analytics.util.amount.ReferenceAmount; import com.opengamma.engine.value.ValueProperties; import com.opengamma.engine.value.ValueRequirementNames; import com.opengamma.financial.analytics.cashflow.FixedPaymentMatrix; import com.opengamma.financial.analytics.cashflow.FloatingPaymentMatrix; import com.opengamma.timeseries.DoubleTimeSeries; import com.opengamma.util.money.Currency; import com.opengamma.util.money.CurrencyAmount; import com.opengamma.util.money.MultipleCurrencyAmount; import com.opengamma.util.tuple.DoublesPair; import com.opengamma.util.tuple.Pair; /** * */ public class SumUtils { public static Object addValue(final Object currentTotal, final Object value, final String valueName) { if (currentTotal == null) { return value; } if (currentTotal.getClass() != value.getClass()) { if (!(currentTotal.getClass() == MultipleCurrencyAmount.class && value.getClass() == CurrencyAmount.class) && !(currentTotal.getClass() == CurrencyAmount.class && value.getClass() == MultipleCurrencyAmount.class)) { throw new IllegalArgumentException("Inputs have different value types for requirement " + valueName + " currentTotal type = " + currentTotal.getClass() + " value type = " + value.getClass()); } } if (value instanceof Double) { final Double previousDouble = (Double) currentTotal; return previousDouble + (Double) value; } else if (value instanceof BigDecimal) { final BigDecimal previousDecimal = (BigDecimal) currentTotal; return previousDecimal.add((BigDecimal) value); } else if (value instanceof DoubleTimeSeries<?>) { final DoubleTimeSeries<?> previousTS = (DoubleTimeSeries<?>) currentTotal; return previousTS.add((DoubleTimeSeries<?>) value); } else if (value instanceof DoubleLabelledMatrix1D) { final DoubleLabelledMatrix1D previousMatrix = (DoubleLabelledMatrix1D) currentTotal; final DoubleLabelledMatrix1D currentMatrix = (DoubleLabelledMatrix1D) value; return previousMatrix.add(currentMatrix); } else if (value instanceof LocalDateLabelledMatrix1D) { final LocalDateLabelledMatrix1D previousMatrix = (LocalDateLabelledMatrix1D) currentTotal; final LocalDateLabelledMatrix1D currentMatrix = (LocalDateLabelledMatrix1D) value; return previousMatrix.add(currentMatrix); } else if (value instanceof TenorLabelledMatrix1D) { final TenorLabelledMatrix1D previousMatrix = (TenorLabelledMatrix1D) currentTotal; final TenorLabelledMatrix1D currentMatrix = (TenorLabelledMatrix1D) value; return previousMatrix.add(currentMatrix); } else if (value instanceof ZonedDateTimeLabelledMatrix1D) { final ZonedDateTimeLabelledMatrix1D previousMatrix = (ZonedDateTimeLabelledMatrix1D) currentTotal; final ZonedDateTimeLabelledMatrix1D currentMatrix = (ZonedDateTimeLabelledMatrix1D) value; return previousMatrix.add(currentMatrix); } else if (value instanceof CurrencyLabelledMatrix1D) { final CurrencyLabelledMatrix1D previousMatrix = (CurrencyLabelledMatrix1D) currentTotal; final CurrencyLabelledMatrix1D currentMatrix = (CurrencyLabelledMatrix1D) value; return previousMatrix.addIgnoringLabel(currentMatrix); } else if (value instanceof CurrencyAmount) { return calculateCurrencyAmount(currentTotal, (CurrencyAmount) value); } else if (value instanceof MultipleCurrencyAmount) { return calculateCurrencyAmount(currentTotal, (MultipleCurrencyAmount) value); } else if (value instanceof StringLabelledMatrix1D) { final StringLabelledMatrix1D previousMatrix = (StringLabelledMatrix1D) currentTotal; final StringLabelledMatrix1D currentMatrix = (StringLabelledMatrix1D) value; return previousMatrix.addIgnoringLabel(currentMatrix); } else if (valueName.equals(ValueRequirementNames.PRESENT_VALUE_CURVE_SENSITIVITY)) { //TODO this should probably not be done like this @SuppressWarnings("unchecked") final Map<String, List<DoublesPair>> previousMap = (Map<String, List<DoublesPair>>) currentTotal; @SuppressWarnings("unchecked") final Map<String, List<DoublesPair>> currentMap = (Map<String, List<DoublesPair>>) value; final Map<String, List<DoublesPair>> result = new HashMap<>(); for (final String name : previousMap.keySet()) { final List<DoublesPair> temp = new ArrayList<>(); for (final DoublesPair pair : previousMap.get(name)) { temp.add(pair); } if (currentMap.containsKey(name)) { for (final DoublesPair pair : currentMap.get(name)) { temp.add(pair); } } result.put(name, temp); } for (final String name : currentMap.keySet()) { if (!result.containsKey(name)) { final List<DoublesPair> temp = new ArrayList<>(); for (final DoublesPair pair : currentMap.get(name)) { temp.add(pair); } result.put(name, temp); } } return result; } else if (value instanceof DoubleLabelledMatrix2D) { final DoubleLabelledMatrix2D previousMatrix = (DoubleLabelledMatrix2D) currentTotal; final DoubleLabelledMatrix2D currentMatrix = (DoubleLabelledMatrix2D) value; return previousMatrix.add(currentMatrix, 0.005, 0.005); } else if (value instanceof DoubleLabelledMatrix3D) { final DoubleLabelledMatrix3D previousMatrix = (DoubleLabelledMatrix3D) currentTotal; final DoubleLabelledMatrix3D currentMatrix = (DoubleLabelledMatrix3D) value; return previousMatrix.add(currentMatrix, 0.005, 0.005, 0.005); } else if (value instanceof FixedPaymentMatrix) { final FixedPaymentMatrix previousMatrix = (FixedPaymentMatrix) currentTotal; final FixedPaymentMatrix currentMatrix = (FixedPaymentMatrix) value; return previousMatrix.add(currentMatrix); } else if (value instanceof FloatingPaymentMatrix) { final FloatingPaymentMatrix previousMatrix = (FloatingPaymentMatrix) currentTotal; final FloatingPaymentMatrix currentMatrix = (FloatingPaymentMatrix) value; return previousMatrix.add(currentMatrix); } else if (value instanceof MulticurveSensitivity) { final MulticurveSensitivity previousSensitivity = (MulticurveSensitivity) currentTotal; final MulticurveSensitivity currentSensitivity = (MulticurveSensitivity) value; return previousSensitivity.plus(currentSensitivity); } else if (value instanceof MultipleCurrencyMulticurveSensitivity) { final MultipleCurrencyMulticurveSensitivity previousSensitivity = (MultipleCurrencyMulticurveSensitivity) currentTotal; final MultipleCurrencyMulticurveSensitivity currentSensitivity = (MultipleCurrencyMulticurveSensitivity) value; return previousSensitivity.plus(currentSensitivity); } else if (value instanceof MultipleCurrencyParameterSensitivity) { final MultipleCurrencyParameterSensitivity previousSensitivity = (MultipleCurrencyParameterSensitivity) currentTotal; final MultipleCurrencyParameterSensitivity currentSensitivity = (MultipleCurrencyParameterSensitivity) value; return previousSensitivity.plus(currentSensitivity); } else if (value instanceof InflationSensitivity) { final InflationSensitivity previousSensitivity = (InflationSensitivity) currentTotal; final InflationSensitivity currentSensitivity = (InflationSensitivity) value; return previousSensitivity.plus(currentSensitivity); } else if (value instanceof MultipleCurrencyInflationSensitivity) { final MultipleCurrencyInflationSensitivity previousSensitivity = (MultipleCurrencyInflationSensitivity) currentTotal; final MultipleCurrencyInflationSensitivity currentSensitivity = (MultipleCurrencyInflationSensitivity) value; return previousSensitivity.plus(currentSensitivity); } else if (valueName.equals(ALL_PV01S)) { @SuppressWarnings("unchecked") final Map<Pair<String, Currency>, Double> previousAmount = (Map<Pair<String, Currency>, Double>) currentTotal; final ReferenceAmount<Pair<String, Currency>> referenceAmount = new ReferenceAmount<>(); for (final Map.Entry<Pair<String, Currency>, Double> entry : previousAmount.entrySet()) { referenceAmount.add(entry.getKey(), entry.getValue()); } @SuppressWarnings("unchecked") final Map<Pair<String, Currency>, Double> currentAmount = (Map<Pair<String, Currency>, Double>) value; for (final Map.Entry<Pair<String, Currency>, Double> entry : currentAmount.entrySet()) { referenceAmount.add(entry.getKey(), entry.getValue()); } return referenceAmount.getMap(); } else { throw new IllegalArgumentException("Cannot sum results of type " + value.getClass()); } } private static Object calculateCurrencyAmount(final Object currentTotal, final CurrencyAmount currentAmount) { // if we have a currency amount and the requested addition is the same currency then we add to it // If we have a multiple currency amount we use it, // Otherwise we create a new MultipleCurrencyAmount if (currentTotal instanceof CurrencyAmount) { final CurrencyAmount total = (CurrencyAmount) currentTotal; if (total.getCurrency() == currentAmount.getCurrency()) { return total.plus(currentAmount); } else { return MultipleCurrencyAmount.of(total).plus(currentAmount); } } else if (currentTotal instanceof MultipleCurrencyAmount) { return ((MultipleCurrencyAmount) currentTotal).plus(currentAmount); } else { throw new IllegalArgumentException("Expected current total to be of type " + CurrencyAmount.class + " or " + MultipleCurrencyAmount.class + " but was: " + currentTotal.getClass()); } } private static Object calculateCurrencyAmount(final Object currentTotal, final MultipleCurrencyAmount currentAmount) { // if we have a currency amount and the requested addition is the same currency then we add to it // If we have a multiple currency amount we use it, // Otherwise we create a new MultipleCurrencyAmount if (currentTotal instanceof CurrencyAmount) { return currentAmount.plus((CurrencyAmount) currentTotal); } else if (currentTotal instanceof MultipleCurrencyAmount) { return ((MultipleCurrencyAmount) currentTotal).plus(currentAmount); } else { throw new IllegalArgumentException("Expected current total to be of type " + CurrencyAmount.class + " or " + MultipleCurrencyAmount.class + " but was: " + currentTotal.getClass()); } } /** * Gets the intersection of two sets of properties. * * @param currentIntersection The current intersection of the properties * @param properties The new set of properties * @return The intersection of the two sets of properties */ public static ValueProperties addProperties(final ValueProperties currentIntersection, final ValueProperties properties) { if (currentIntersection == null) { return properties; } return currentIntersection.intersect(properties); } }