@Override public Map<Integer, ParametricVaRDataBundle> evaluate( final SensitivityAndReturnDataBundle... data) { Validate.notNull(data, "data"); Validate.notEmpty(data, "data"); Validate.noNullElements(data, "data"); List<String> firstOrderNames = null; final List<Double> firstOrderSensitivity = new ArrayList<Double>(); final List<DoubleTimeSeries<?>> firstOrderTimeSeries = new ArrayList<DoubleTimeSeries<?>>(); final List<DoubleTimeSeries<?>> secondOrderTimeSeries = new ArrayList<DoubleTimeSeries<?>>(); List<String> secondOrderNames = null; for (final SensitivityAndReturnDataBundle dataForSensitivity : data) { final Sensitivity<?> sensitivity = dataForSensitivity.getSensitivity(); final String identifier = sensitivity.getIdentifier(); if (sensitivity.getOrder() == 1) { final UnderlyingType type = sensitivity.getUnderlyingTypes().get(0); final String name = identifier + "_" + type; if (firstOrderNames == null) { firstOrderNames = new ArrayList<String>(); } if (!firstOrderNames.contains(name)) { firstOrderNames.add(name); firstOrderSensitivity.add(dataForSensitivity.getValue()); firstOrderTimeSeries.add(dataForSensitivity.getReturnTimeSeriesForUnderlying(type)); } else { final int index = firstOrderNames.indexOf(name); firstOrderSensitivity.set( index, firstOrderSensitivity.get(index) + dataForSensitivity.getValue()); } } else if (sensitivity.getOrder() == 2) { if (secondOrderNames == null) { secondOrderNames = new ArrayList<String>(); } if (sensitivity.getUnderlying() instanceof NthOrderUnderlying) { final UnderlyingType type = sensitivity.getUnderlyingTypes().get(0); final String name = identifier + "_" + type; if (!secondOrderNames.contains(name)) { secondOrderNames.add(name); secondOrderTimeSeries.add(dataForSensitivity.getReturnTimeSeriesForUnderlying(type)); } } else if (sensitivity.getUnderlying() instanceof MixedOrderUnderlying) { final UnderlyingType type1 = sensitivity.getUnderlyingTypes().get(0); final UnderlyingType type2 = sensitivity.getUnderlyingTypes().get(1); final String name1 = identifier + "_" + type1; final String name2 = identifier + "_" + type2; if (!secondOrderNames.contains(name1)) { secondOrderNames.add(name1); secondOrderTimeSeries.add(dataForSensitivity.getReturnTimeSeriesForUnderlying(type1)); } if (!secondOrderNames.contains(name2)) { secondOrderNames.add(name2); secondOrderTimeSeries.add(dataForSensitivity.getReturnTimeSeriesForUnderlying(type2)); } } } else { throw new IllegalArgumentException("Can only handle first and second order sensitivities"); } } final Map<Integer, ParametricVaRDataBundle> result = new HashMap<Integer, ParametricVaRDataBundle>(); DoubleMatrix2D firstOrderCovarianceMatrix = null; DoubleMatrix1D firstOrderSensitivityMatrix = null; DoubleMatrix2D secondOrderCovarianceMatrix = null; DoubleMatrix2D secondOrderSensitivityMatrix = null; if (firstOrderNames != null) { firstOrderCovarianceMatrix = _calculator.evaluate(firstOrderTimeSeries.toArray(EMPTY)); firstOrderSensitivityMatrix = new DoubleMatrix1D(firstOrderSensitivity.toArray(new Double[0])); result.put( 1, new ParametricVaRDataBundle( firstOrderNames, firstOrderSensitivityMatrix, firstOrderCovarianceMatrix, 1)); } if (secondOrderNames != null) { final int n = secondOrderNames.size(); final double[][] secondOrderSensitivities = new double[n][n]; for (final SensitivityAndReturnDataBundle bundle : data) { final Sensitivity<?> sensitivity = bundle.getSensitivity(); final String identifier = sensitivity.getIdentifier(); if (sensitivity.getOrder() == 2) { if (sensitivity.getUnderlying() instanceof NthOrderUnderlying) { final UnderlyingType type = sensitivity.getUnderlyingTypes().get(0); final String name = identifier + "_" + type; final int index = secondOrderNames.indexOf(name); secondOrderSensitivities[index][index] += bundle.getValue(); } else if (sensitivity.getUnderlying() instanceof MixedOrderUnderlying) { final UnderlyingType type1 = sensitivity.getUnderlyingTypes().get(0); final UnderlyingType type2 = sensitivity.getUnderlyingTypes().get(1); final String name1 = identifier + "_" + type1; final String name2 = identifier + "_" + type2; final int index1 = secondOrderNames.indexOf(name1); final int index2 = secondOrderNames.indexOf(name2); secondOrderSensitivities[index1][index2] += bundle.getValue(); secondOrderSensitivities[index2][index1] = secondOrderSensitivities[index1][index2]; } } } secondOrderCovarianceMatrix = _calculator.evaluate(secondOrderTimeSeries.toArray(EMPTY)); secondOrderSensitivityMatrix = new DoubleMatrix2D(secondOrderSensitivities); result.put( 2, new ParametricVaRDataBundle( secondOrderNames, secondOrderSensitivityMatrix, secondOrderCovarianceMatrix, 2)); } return result; }