/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.util; import static org.testng.AssertJUnit.assertTrue; import java.util.List; import java.util.Map; import com.opengamma.analytics.financial.forex.method.MultipleCurrencyInterestRateCurveSensitivity; import com.opengamma.analytics.financial.interestrate.InterestRateCurveSensitivity; import com.opengamma.analytics.financial.interestrate.InterestRateCurveSensitivityUtils; 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.ForwardSensitivity; 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.financial.provider.sensitivity.multicurve.SimpleParameterSensitivity; import com.opengamma.analytics.math.matrix.DoubleMatrix1D; import com.opengamma.analytics.math.matrix.MatrixAlgebra; import com.opengamma.analytics.math.matrix.MatrixAlgebraFactory; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.money.Currency; import com.opengamma.util.tuple.Pair; /** * Class used in test to assert that two sensitivity objects are the same or different. */ public class AssertSensitivityObjects { /** * Compare two sensitivities with a given tolerance. The tolerance is used for both the time and the value. The two sensitivities are suppose to be in the same time order. * The comparison is done on the discounting curve and forward curves sensitivities. * @param msg The message. * @param sensitivity1 The first sensitivity. * @param sensitivity2 The second sensitivity. * @param tolerance The tolerance. * @param opposite The flag indicating if the opposite result should be used. * @return True if the difference is below the tolerance and False if not. If the curves are not the same it returns False. */ private static boolean compare(final String msg, final MulticurveSensitivity sensitivity1, final MulticurveSensitivity sensitivity2, final double tolerance, final boolean opposite) { boolean cmp = true; if (!InterestRateCurveSensitivityUtils.compare(sensitivity1.getYieldDiscountingSensitivities(), sensitivity2.getYieldDiscountingSensitivities(), tolerance)) { cmp = false; } if (!compareFwd(sensitivity1.getForwardSensitivities(), sensitivity2.getForwardSensitivities(), tolerance)) { cmp = false; } if (opposite) { cmp = !cmp; } assertTrue(msg, cmp); return cmp; } /** * Compare two sensitivities with a given tolerance. The tolerance is used for both the time and the value. The two sensitivities are suppose to be in the same time order. * The comparison is done on the discounting curve and forward curves sensitivities. * @param msg The message. * @param sensitivity1 The first sensitivity. * @param sensitivity2 The second sensitivity. * @param tolerance The tolerance. * @return True if the difference is below the tolerance and False if not. If the curves are not the same it returns False. */ public static boolean assertEquals(final String msg, final MulticurveSensitivity sensitivity1, final MulticurveSensitivity sensitivity2, final double tolerance) { return compare(msg, sensitivity1, sensitivity2, tolerance, false); } public static boolean assertDoesNotEqual(final String msg, final MulticurveSensitivity sensitivity1, final MulticurveSensitivity sensitivity2, final double tolerance) { return compare(msg, sensitivity1, sensitivity2, tolerance, true); } /** * Compare two maps of sensitivities with a given tolerance. The tolerance is used for both the time and the value. The two sensitivities are suppose to be in the same time order. * @param sensi1 The first sensitivity (as a map). * @param sensi2 The second sensitivity (as a map). * @param tolerance The tolerance. * @return True if the difference is below the tolerance and False if not. If the curves are not the same it returns False. */ private static boolean compareFwd(final Map<String, List<ForwardSensitivity>> sensi1, final Map<String, List<ForwardSensitivity>> sensi2, final double tolerance) { ArgumentChecker.notNull(sensi1, "sensitivity"); ArgumentChecker.notNull(sensi2, "sensitivity"); for (final Map.Entry<String, List<ForwardSensitivity>> entry : sensi1.entrySet()) { final String name = entry.getKey(); if (sensi2.containsKey(name)) { if (!compareFwd(entry.getValue(), sensi2.get(name), tolerance)) { return false; } } else { return false; } } for (final Map.Entry<String, List<ForwardSensitivity>> entry : sensi2.entrySet()) { if (!(sensi1.containsKey(entry.getKey()))) { return false; } } return true; } /** * Compare two lists of sensitivities with a given tolerance. The tolerance is used for both the time and the value. The two sensitivities are suppose to be in the same time order. * @param sensi1 The first sensitivity (as a list). * @param sensi2 The second sensitivity (as a list). * @param tolerance The tolerance. * @return True if the difference is below the tolerance and False if not. */ private static boolean compareFwd(final List<ForwardSensitivity> sensi1, final List<ForwardSensitivity> sensi2, final double tolerance) { for (int looptime = 0; looptime < sensi1.size(); looptime++) { final double startTime1 = sensi1.get(looptime).getStartTime(); final double startTime2 = sensi2.get(looptime).getStartTime(); if ((Math.abs(startTime1 - startTime2) > tolerance) || (Math.abs(sensi1.get(looptime).getValue() - sensi2.get(looptime).getValue()) > tolerance)) { return false; } } return true; } /** * Compare two sensitivities with a given tolerance. The tolerance is used for both the time and the value. The two sensitivities are suppose to be in the same time order. * The comparison is done on the discounting curve and forward curves sensitivities. * @param msg The message. * @param sensi1 The first sensitivity. * @param sensi2 The second sensitivity. * @param tolerance The tolerance. * @return True if the difference is below the tolerance and False if not. If the curves are not the same it returns False. */ public static boolean assertEquals(final String msg, final InflationSensitivity sensi1, final InflationSensitivity sensi2, final double tolerance) { boolean cmp = true; if (!InterestRateCurveSensitivityUtils.compare(sensi1.getYieldDiscountingSensitivities(), sensi2.getYieldDiscountingSensitivities(), tolerance)) { cmp = false; } if (!compareFwd(sensi1.getForwardSensitivities(), sensi2.getForwardSensitivities(), tolerance)) { cmp = false; } if (!InterestRateCurveSensitivityUtils.compare(sensi1.getPriceCurveSensitivities(), sensi2.getPriceCurveSensitivities(), tolerance)) { cmp = false; } assertTrue(msg, cmp); return cmp; } /** * Compare two sensitivities with a given tolerance. The tolerance is used for both the time and the value. * For each currency, the two sensitivities are suppose to be in the same time order. * @param msg The message. * @param sensi1 The first sensitivity. * @param sensi2 The second sensitivity. * @param tolerance The tolerance. * @return True if the difference is below the tolerance and False if not. If the currencies or the curves are not the same it returns False. */ public static boolean assertEquals(final String msg, final MultipleCurrencyMulticurveSensitivity sensi1, final MultipleCurrencyMulticurveSensitivity sensi2, final double tolerance) { boolean cmp = true; final boolean keycmp = sensi1.getCurrencies().equals(sensi2.getCurrencies()); if (!keycmp) { cmp = false; } for (final Currency loopccy : sensi1.getCurrencies()) { if (!assertEquals(msg, sensi1.getSensitivity(loopccy), sensi2.getSensitivity(loopccy), tolerance)) { cmp = false; } } assertTrue(msg, cmp); return cmp; } /** * Compare two sensitivities with a given tolerance. The tolerance is used for both the time and the value. * For each currency, the two sensitivities are suppose to be in the same time order. * @param msg The message. * @param sensi1 The first sensitivity. * @param sensi2 The second sensitivity. * @param tolerance The tolerance. * @return True if the difference is below the tolerance and False if not. If the currencies or the curves are not the same it returns False. */ public static boolean assertEquals(final String msg, final MultipleCurrencyInflationSensitivity sensi1, final MultipleCurrencyInflationSensitivity sensi2, final double tolerance) { boolean cmp = true; final boolean keycmp = sensi1.getCurrencies().equals(sensi2.getCurrencies()); if (!keycmp) { cmp = false; } for (final Currency loopccy : sensi1.getCurrencies()) { if (!assertEquals(msg, sensi1.getSensitivity(loopccy), sensi2.getSensitivity(loopccy), tolerance)) { cmp = false; } } assertTrue(msg, cmp); return cmp; } /** * Compare two sensitivities with a given tolerance. * @param msg The message. * @param sensitivity1 The first sensitivity. * @param sensitivity2 The second sensitivity. * @param tolerance The tolerance. * @param opposite The flag indicating if the opposite result should be used. * @return True if the difference is below the tolerance and False if not. If the curves are not the same it returns False. */ private static boolean compare(final String msg, final MultipleCurrencyParameterSensitivity sensitivity1, final MultipleCurrencyParameterSensitivity sensitivity2, final double tolerance, final boolean opposite) { ArgumentChecker.notNull(sensitivity1, "sensitivity1"); ArgumentChecker.notNull(sensitivity2, "sensitivity2"); ArgumentChecker.isTrue(tolerance > 0, "tolerance must be greater than 0; have {}", tolerance); boolean cmp = true; final MatrixAlgebra algebra = MatrixAlgebraFactory.COMMONS_ALGEBRA; final Map<Pair<String, Currency>, DoubleMatrix1D> map1 = sensitivity1.getSensitivities(); final Map<Pair<String, Currency>, DoubleMatrix1D> map2 = sensitivity2.getSensitivities(); for (final Map.Entry<Pair<String, Currency>, DoubleMatrix1D> entry : map1.entrySet()) { final Pair<String, Currency> nameCcy = entry.getKey(); if (map2.get(nameCcy) == null) { if (algebra.getNormInfinity(entry.getValue()) > tolerance) { cmp = false; } } else { if (entry.getValue().getNumberOfElements() != map2.get(nameCcy).getNumberOfElements()) { cmp = false; } else { if (algebra.getNormInfinity(algebra.add(entry.getValue(), algebra.scale(map2.get(nameCcy), -1.0))) > tolerance) { cmp = false; } } } } for (final Map.Entry<Pair<String, Currency>, DoubleMatrix1D> entry : map2.entrySet()) { final Pair<String, Currency> nameCcy = entry.getKey(); if (map1.get(nameCcy) == null) { if (algebra.getNormInfinity(entry.getValue()) > tolerance) { cmp = false; } } else { if (entry.getValue().getNumberOfElements() != map1.get(nameCcy).getNumberOfElements()) { cmp = false; } else { if (algebra.getNormInfinity(algebra.add(entry.getValue(), algebra.scale(map1.get(nameCcy), -1.0))) > tolerance) { cmp = false; } } } } if (opposite) { cmp = !cmp; } assertTrue(msg, cmp); return cmp; } /** * Assert that two sensitivities are equal within a given tolerance. The tolerance is applied for each value (not to the total). * @param msg The message. * @param sensitivity1 The first sensitivity. * @param sensitivity2 The second sensitivity. * @param tolerance The tolerance. * @return True if the difference is below the tolerance and False if not. If the curves are not the same it returns False. */ public static boolean assertEquals(final String msg, final MultipleCurrencyParameterSensitivity sensitivity1, final MultipleCurrencyParameterSensitivity sensitivity2, final double tolerance) { return compare(msg, sensitivity1, sensitivity2, tolerance, false); } /** * Compare two sensitivities with a given tolerance. * @param msg The message. * @param sensitivity1 The first sensitivity. * @param sensitivity2 The second sensitivity. * @param tolerance The tolerance. * @return True if the difference is above the tolerance and False if not. */ public static boolean assertDoesNotEqual(final String msg, final MultipleCurrencyParameterSensitivity sensitivity1, final MultipleCurrencyParameterSensitivity sensitivity2, final double tolerance) { return compare(msg, sensitivity1, sensitivity2, tolerance, true); } /** * Compare two sensitivities with a given tolerance. * @param msg The message. * @param sensitivity1 The first sensitivity. * @param sensitivity2 The second sensitivity. * @param tolerance The tolerance. * @param opposite The flag indicating if the opposite result should be used. * @return True if the difference is below the tolerance and False if not. If the curves are not the same it returns False. */ private static boolean compare(final String msg, final SimpleParameterSensitivity sensitivity1, final SimpleParameterSensitivity sensitivity2, final double tolerance, final boolean opposite) { ArgumentChecker.notNull(sensitivity1, "sensitivity1"); ArgumentChecker.notNull(sensitivity2, "sensitivity2"); ArgumentChecker.isTrue(tolerance > 0, "tolerance must be greater than 0; have {}", tolerance); boolean cmp = true; final MatrixAlgebra algebra = MatrixAlgebraFactory.COMMONS_ALGEBRA; final Map<String, DoubleMatrix1D> map1 = sensitivity1.getSensitivities(); final Map<String, DoubleMatrix1D> map2 = sensitivity2.getSensitivities(); for (final Map.Entry<String, DoubleMatrix1D> entry : map1.entrySet()) { final String name = entry.getKey(); if (map2.get(name) == null) { if (algebra.getNormInfinity(entry.getValue()) > tolerance) { cmp = false; } } else { if (algebra.getNormInfinity(algebra.add(entry.getValue(), algebra.scale(map2.get(name), -1.0))) > tolerance) { cmp = false; } } } if (opposite) { cmp = !cmp; } assertTrue(msg, cmp); return cmp; } /** * Assert that two sensitivities are equal within a given tolerance. The tolerance is applied for each value (not to the total). * @param msg The message. * @param sensitivity1 The first sensitivity. * @param sensitivity2 The second sensitivity. * @param tolerance The tolerance. * @return True if the difference is below the tolerance and False if not. If the curves are not the same it returns False. */ public static boolean assertEquals(final String msg, final SimpleParameterSensitivity sensitivity1, final SimpleParameterSensitivity sensitivity2, final double tolerance) { return compare(msg, sensitivity1, sensitivity2, tolerance, false); } /** * Compare two sensitivities with a given tolerance. * @param msg The message. * @param sensitivity1 The first sensitivity. * @param sensitivity2 The second sensitivity. * @param tolerance The tolerance. * @return True if the difference is above the tolerance and False if not. */ public static boolean assertDoesNotEqual(final String msg, final SimpleParameterSensitivity sensitivity1, final SimpleParameterSensitivity sensitivity2, final double tolerance) { return compare(msg, sensitivity1, sensitivity2, tolerance, true); } /** * Compare two sensitivities with a given tolerance. The tolerance is used for both the time and the value. The two sensitivities are suppose to be in the same time order. * @param msg The message. * @param sensitivity1 The first sensitivity. * @param sensitivity2 The second sensitivity. * @param tolerance The tolerance. * @param opposite The flag indicating if the opposite result should be used. * @return True if the difference is below the tolerance and False if not. If the curves are not the same it returns False. */ private static boolean compare(final String msg, final InterestRateCurveSensitivity sensitivity1, final InterestRateCurveSensitivity sensitivity2, final double tolerance, final boolean opposite) { boolean cmp = true; cmp = InterestRateCurveSensitivityUtils.compare(sensitivity1.getSensitivities(), sensitivity2.getSensitivities(), tolerance); if (opposite) { cmp = !cmp; } assertTrue(msg, cmp); return cmp; } public static boolean assertEquals(final String msg, final InterestRateCurveSensitivity sensitivity1, final InterestRateCurveSensitivity sensitivity2, final double tolerance) { return compare(msg, sensitivity1, sensitivity2, tolerance, false); } public static boolean assertDoesNotEqual(final String msg, final InterestRateCurveSensitivity sensitivity1, final InterestRateCurveSensitivity sensitivity2, final double tolerance) { return compare(msg, sensitivity1, sensitivity2, tolerance, true); } /** * Compare two sensitivities with a given tolerance. The tolerance is used for both the time and the value. * @param msg The message. * For each currency, the two sensitivities are suppose to be in the same time order. * @param sensi1 The first sensitivity. * @param sensi2 The second sensitivity. * @param tolerance The tolerance. * @return True if the difference is below the tolerance and False if not. If the currencies or the curves are not the same it returns False. */ public static boolean assertEquals(final String msg, final MultipleCurrencyInterestRateCurveSensitivity sensi1, final MultipleCurrencyInterestRateCurveSensitivity sensi2, final double tolerance) { boolean cmp = true; final boolean keycmp = sensi1.getCurrencies().equals(sensi2.getCurrencies()); if (!keycmp) { cmp = false; } for (final Currency loopccy : sensi1.getCurrencies()) { if (!assertEquals(msg, sensi1.getSensitivity(loopccy), sensi2.getSensitivity(loopccy), tolerance)) { cmp = false; } } assertTrue(msg, cmp); return cmp; } }