@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;
 }