VaRCovarianceMatrixCalculator implements Function<SensitivityAndReturnDataBundle, Map<Integer, ParametricVaRDataBundle>> { @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<>(); final List<DoubleTimeSeries<?>> firstOrderTimeSeries = new ArrayList<>(); final List<DoubleTimeSeries<?>> secondOrderTimeSeries = new ArrayList<>(); 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<>(); } 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<>(); } 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<>(); 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[firstOrderSensitivity.size()])); 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; } VaRCovarianceMatrixCalculator(final CovarianceMatrixCalculator calculator); @Override Map<Integer, ParametricVaRDataBundle> evaluate(final SensitivityAndReturnDataBundle... data);  }
@Test(expectedExceptions = IllegalArgumentException.class) public void testNullData() { CALC.evaluate((SensitivityAndReturnDataBundle[]) null); }
@Test(expectedExceptions = IllegalArgumentException.class) public void testEmptyData() { CALC.evaluate(new SensitivityAndReturnDataBundle[0]); }
@Test(expectedExceptions = IllegalArgumentException.class) public void testNullDataValue() { CALC.evaluate(new SensitivityAndReturnDataBundle[] {null}); }
@Test(expectedExceptions = IllegalArgumentException.class) public void testThirdOrderSensitivity() { final SensitivityAndReturnDataBundle data = new SensitivityAndReturnDataBundle(new ValueGreekSensitivity(new ValueGreek(Greek.SPEED), "A"), 10, Collections.<UnderlyingType, DoubleTimeSeries<?>> singletonMap(UnderlyingType.SPOT_PRICE, ImmutableInstantDoubleTimeSeries.of(new long[] {1}, new double[] {1}))); CALC.evaluate(data); }
@Test public void testFirstOrderOnlyNoDuplicateGreeks() { final ParametricVaRDataBundle result = CALC.evaluate(A_DATA_FIRST_ORDER_1).get(1); final List<String> names = result.getNames(); assertEquals(names, Arrays.asList("A_IMPLIED_VOLATILITY", "A_SPOT_PRICE", "A_INTEREST_RATE")); final Matrix<?> sensitivities = result.getSensitivities(); assertEquals(sensitivities.getClass(), DoubleMatrix1D.class); final DoubleMatrix1D v = (DoubleMatrix1D) sensitivities; assertEquals(v.getNumberOfElements(), 3); assertArrayEquals(v.getData(), new double[] {VEGA_A_1, DELTA_A_1, RHO_A_1}, EPS); final Matrix<?> covariance = result.getCovarianceMatrix(); assertEquals(covariance.getClass(), DoubleMatrix2D.class); final DoubleMatrix2D m = (DoubleMatrix2D) covariance; assertEquals(m.getNumberOfRows(), 3); assertEquals(m.getNumberOfColumns(), 3); assertArrayEquals(m.getData()[0], C1[0], EPS); assertArrayEquals(m.getData()[1], C1[1], EPS); assertArrayEquals(m.getData()[2], C1[2], EPS); }
@Test public void testFirstOrderOneTradeOnly() { final ParametricVaRDataBundle result = CALC.evaluate(A_DATA_FIRST_ORDER_2).get(1); final List<String> names = result.getNames(); assertEquals(names, Arrays.asList("A_IMPLIED_VOLATILITY", "A_SPOT_PRICE", "A_INTEREST_RATE")); final Matrix<?> sensitivities = result.getSensitivities(); assertEquals(sensitivities.getClass(), DoubleMatrix1D.class); final DoubleMatrix1D v = (DoubleMatrix1D) sensitivities; assertEquals(v.getNumberOfElements(), 3); assertArrayEquals(v.getData(), new double[] {VEGA_A_1, DELTA_A_1 + DELTA_A_2, RHO_A_1 + RHO_A_2}, EPS); final Matrix<?> covariance = result.getCovarianceMatrix(); assertEquals(covariance.getClass(), DoubleMatrix2D.class); final DoubleMatrix2D m = (DoubleMatrix2D) covariance; assertEquals(m.getNumberOfRows(), 3); assertEquals(m.getNumberOfColumns(), 3); assertArrayEquals(m.getData()[0], C1[0], EPS); assertArrayEquals(m.getData()[1], C1[1], EPS); assertArrayEquals(m.getData()[2], C1[2], EPS); }
@Test public void testFirstOrderOnly() { final ParametricVaRDataBundle result = CALC.evaluate(DATA_FIRST_ORDER).get(1); final List<String> names = result.getNames(); assertEquals(names, Arrays.asList("A_IMPLIED_VOLATILITY", "A_SPOT_PRICE", "A_INTEREST_RATE", "B_INTEREST_RATE", "B_SPOT_PRICE", "B_IMPLIED_VOLATILITY", "C_SPOT_PRICE", "C_IMPLIED_VOLATILITY", "C_IMPLIED_VARIANCE")); final Matrix<?> sensitivities = result.getSensitivities(); assertEquals(sensitivities.getClass(), DoubleMatrix1D.class); final DoubleMatrix1D v = (DoubleMatrix1D) sensitivities; assertEquals(v.getNumberOfElements(), 9); assertArrayEquals(v.getData(), new double[] {VEGA_A_1, DELTA_A_1 + DELTA_A_2, RHO_A_1 + RHO_A_2, RHO_B, DELTA_B, VEGA_B, DELTA_C, VEGA_C, VARIANCE_VEGA_C}, EPS); final Matrix<?> covariance = result.getCovarianceMatrix(); assertEquals(covariance.getClass(), DoubleMatrix2D.class); final DoubleMatrix2D m = (DoubleMatrix2D) covariance; assertEquals(m.getNumberOfRows(), 9); assertEquals(m.getNumberOfColumns(), 9); for (int i = 0; i < 9; i++) { assertArrayEquals(m.getData()[i], C2[i], EPS); } }
@Test public void testSecondOrderDiagonalElementsOnlyNoDuplicateGreeks() { final ParametricVaRDataBundle result = CALC.evaluate(A_DATA_SECOND_ORDER_1).get(2); final List<String> names = result.getNames(); assertEquals(names, Arrays.asList("A_SPOT_PRICE", "A_IMPLIED_VOLATILITY", "A_STRIKE")); final Matrix<?> sensitivities = result.getSensitivities(); assertEquals(sensitivities.getClass(), DoubleMatrix2D.class); final DoubleMatrix2D m1 = (DoubleMatrix2D) sensitivities; assertEquals(m1.getNumberOfRows(), 3); assertEquals(m1.getNumberOfColumns(), 3); final double[][] s = new double[][] {new double[] {GAMMA_A_1, 0, 0}, new double[] {0, VOMMA_A_1, 0}, new double[] {0, 0, STRIKE_GAMMA_A_1}}; assertArrayEquals(m1.getData()[0], s[0], EPS); assertArrayEquals(m1.getData()[1], s[1], EPS); assertArrayEquals(m1.getData()[2], s[2], EPS); final Matrix<?> covariance = result.getCovarianceMatrix(); assertEquals(covariance.getClass(), DoubleMatrix2D.class); final DoubleMatrix2D m2 = (DoubleMatrix2D) covariance; assertEquals(m2.getNumberOfRows(), 3); assertEquals(m2.getNumberOfColumns(), 3); assertArrayEquals(m2.getData()[0], C3[0], EPS); assertArrayEquals(m2.getData()[1], C3[1], EPS); assertArrayEquals(m2.getData()[2], C3[2], EPS); }
@Test public void testSecondOrderDiagonalElementsOnly() { final ParametricVaRDataBundle result = CALC.evaluate(A_DATA_SECOND_ORDER_2).get(2); final List<String> names = result.getNames(); assertEquals(names, Arrays.asList("A_SPOT_PRICE", "A_IMPLIED_VOLATILITY", "A_STRIKE")); final Matrix<?> sensitivities = result.getSensitivities(); assertEquals(sensitivities.getClass(), DoubleMatrix2D.class); final DoubleMatrix2D m1 = (DoubleMatrix2D) sensitivities; assertEquals(m1.getNumberOfRows(), 3); assertEquals(m1.getNumberOfColumns(), 3); final double[][] s = new double[][] {new double[] {GAMMA_A_1 + GAMMA_A_2, 0, 0}, new double[] {0, VOMMA_A_1 + VOMMA_A_2, 0}, new double[] {0, 0, STRIKE_GAMMA_A_1}}; assertArrayEquals(m1.getData()[0], s[0], EPS); assertArrayEquals(m1.getData()[1], s[1], EPS); assertArrayEquals(m1.getData()[2], s[2], EPS); final Matrix<?> covariance = result.getCovarianceMatrix(); assertEquals(covariance.getClass(), DoubleMatrix2D.class); final DoubleMatrix2D m2 = (DoubleMatrix2D) covariance; assertEquals(m2.getNumberOfRows(), 3); assertEquals(m2.getNumberOfColumns(), 3); assertArrayEquals(m2.getData()[0], C3[0], EPS); assertArrayEquals(m2.getData()[1], C3[1], EPS); assertArrayEquals(m2.getData()[2], C3[2], EPS); }
@Test public void testSecondOrderOneTradeOnly() { final ParametricVaRDataBundle result = CALC.evaluate(A_DATA_SECOND_ORDER_3).get(2); final List<String> names = result.getNames(); assertEquals(names, Arrays.asList("A_SPOT_PRICE", "A_IMPLIED_VOLATILITY", "A_STRIKE", "A_TIME")); final Matrix<?> sensitivities = result.getSensitivities(); assertEquals(sensitivities.getClass(), DoubleMatrix2D.class); final DoubleMatrix2D m1 = (DoubleMatrix2D) sensitivities; assertEquals(m1.getNumberOfRows(), 4); assertEquals(m1.getNumberOfColumns(), 4); final double[][] s = new double[][] {new double[] {GAMMA_A_1 + GAMMA_A_2, VANNA_A, 0, DELTA_BLEED_A}, new double[] {VANNA_A, VOMMA_A_1 + VOMMA_A_2, 0, 0}, new double[] {0, 0, STRIKE_GAMMA_A_1, 0}, new double[] {DELTA_BLEED_A, 0, 0, 0}}; assertArrayEquals(m1.getData()[0], s[0], EPS); assertArrayEquals(m1.getData()[1], s[1], EPS); assertArrayEquals(m1.getData()[2], s[2], EPS); final Matrix<?> covariance = result.getCovarianceMatrix(); assertEquals(covariance.getClass(), DoubleMatrix2D.class); final DoubleMatrix2D m2 = (DoubleMatrix2D) covariance; assertEquals(m2.getNumberOfRows(), 4); assertEquals(m2.getNumberOfColumns(), 4); for (int i = 0; i < 4; i++) { assertArrayEquals(m2.getData()[i], C4[i], EPS); } }
@Test public void testSecondOrderOnly() { final ParametricVaRDataBundle result = CALC.evaluate(DATA_SECOND_ORDER).get(2); final List<String> names = result.getNames(); assertEquals(names, Arrays.asList("A_SPOT_PRICE", "A_IMPLIED_VOLATILITY", "A_STRIKE", "A_TIME", "B_SPOT_PRICE", "B_IMPLIED_VOLATILITY", "C_SPOT_PRICE", "C_IMPLIED_VOLATILITY", "A_YIELD")); final Matrix<?> sensitivities = result.getSensitivities(); assertEquals(sensitivities.getClass(), DoubleMatrix2D.class); final DoubleMatrix2D m1 = (DoubleMatrix2D) sensitivities; assertEquals(m1.getNumberOfRows(), 9); assertEquals(m1.getNumberOfColumns(), 9); final double[][] s = new double[][] {new double[] {GAMMA_A_1 + GAMMA_A_2, VANNA_A, 0, DELTA_BLEED_A, 0, 0, 0, 0, DUMMY_A}, new double[] {VANNA_A, VOMMA_A_1 + VOMMA_A_2, 0, 0, 0, 0, 0, 0, 0}, new double[] {0, 0, STRIKE_GAMMA_A_1, 0, 0, 0, 0, 0, 0}, new double[] {DELTA_BLEED_A, 0, 0, 0, 0, 0, 0, 0, 0}, new double[] {0, 0, 0, 0, GAMMA_B, 0, 0, 0, 0}, new double[] {0, 0, 0, 0, 0, VOMMA_B, 0, 0, 0}, new double[] {0, 0, 0, 0, 0, 0, GAMMA_C, VANNA_C, 0}, new double[] {0, 0, 0, 0, 0, 0, VANNA_C, 0, 0}, new double[] {DUMMY_A, 0, 0, 0, 0, 0, 0, 0, 0}}; for (int i = 0; i < 9; i++) { assertArrayEquals(m1.getData()[i], s[i], EPS); } final Matrix<?> covariance = result.getCovarianceMatrix(); assertEquals(covariance.getClass(), DoubleMatrix2D.class); final DoubleMatrix2D m2 = (DoubleMatrix2D) covariance; assertEquals(m2.getNumberOfRows(), 9); assertEquals(m2.getNumberOfColumns(), 9); for (int i = 0; i < 9; i++) { assertArrayEquals(m2.getData()[i], C5[i], EPS); } }
@Test public void test() { ParametricVaRDataBundle result = CALC.evaluate(DATA).get(1); List<String> names = result.getNames(); assertEquals(names, Arrays.asList("A_IMPLIED_VOLATILITY", "A_SPOT_PRICE", "A_INTEREST_RATE", "B_INTEREST_RATE", "B_SPOT_PRICE", "B_IMPLIED_VOLATILITY", "C_SPOT_PRICE", "C_IMPLIED_VOLATILITY", "C_IMPLIED_VARIANCE")); Matrix<?> sensitivities = result.getSensitivities(); assertEquals(sensitivities.getClass(), DoubleMatrix1D.class); final DoubleMatrix1D v = (DoubleMatrix1D) sensitivities; assertEquals(v.getNumberOfElements(), 9); assertArrayEquals(v.getData(), new double[] {VEGA_A_1, DELTA_A_1 + DELTA_A_2, RHO_A_1 + RHO_A_2, RHO_B, DELTA_B, VEGA_B, DELTA_C, VEGA_C, VARIANCE_VEGA_C}, EPS); Matrix<?> covariance = result.getCovarianceMatrix(); assertEquals(covariance.getClass(), DoubleMatrix2D.class); final DoubleMatrix2D m = (DoubleMatrix2D) covariance; assertEquals(m.getNumberOfRows(), 9); assertEquals(m.getNumberOfColumns(), 9); for (int i = 0; i < 9; i++) { assertArrayEquals(m.getData()[i], C2[i], EPS); } result = CALC.evaluate(DATA).get(2); names = result.getNames(); assertEquals(names, Arrays.asList("A_SPOT_PRICE", "A_IMPLIED_VOLATILITY", "A_STRIKE", "A_TIME", "B_SPOT_PRICE", "B_IMPLIED_VOLATILITY", "C_SPOT_PRICE", "C_IMPLIED_VOLATILITY", "A_YIELD")); sensitivities = result.getSensitivities(); assertEquals(sensitivities.getClass(), DoubleMatrix2D.class); final DoubleMatrix2D m1 = (DoubleMatrix2D) sensitivities; assertEquals(m1.getNumberOfRows(), 9); assertEquals(m1.getNumberOfColumns(), 9); final double[][] s = new double[][] {new double[] {GAMMA_A_1 + GAMMA_A_2, VANNA_A, 0, DELTA_BLEED_A, 0, 0, 0, 0, DUMMY_A}, new double[] {VANNA_A, VOMMA_A_1 + VOMMA_A_2, 0, 0, 0, 0, 0, 0, 0}, new double[] {0, 0, STRIKE_GAMMA_A_1, 0, 0, 0, 0, 0, 0}, new double[] {DELTA_BLEED_A, 0, 0, 0, 0, 0, 0, 0, 0}, new double[] {0, 0, 0, 0, GAMMA_B, 0, 0, 0, 0}, new double[] {0, 0, 0, 0, 0, VOMMA_B, 0, 0, 0}, new double[] {0, 0, 0, 0, 0, 0, GAMMA_C, VANNA_C, 0}, new double[] {0, 0, 0, 0, 0, 0, VANNA_C, 0, 0}, new double[] {DUMMY_A, 0, 0, 0, 0, 0, 0, 0, 0}}; for (int i = 0; i < 9; i++) { assertArrayEquals(m1.getData()[i], s[i], EPS); } covariance = result.getCovarianceMatrix(); assertEquals(covariance.getClass(), DoubleMatrix2D.class); final DoubleMatrix2D m2 = (DoubleMatrix2D) covariance; assertEquals(m2.getNumberOfRows(), 9); assertEquals(m2.getNumberOfColumns(), 9); for (int i = 0; i < 9; i++) { assertArrayEquals(m2.getData()[i], C5[i], EPS); } }