/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.forex.method; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertTrue; import org.testng.annotations.Test; import com.opengamma.util.money.Currency; import com.opengamma.util.money.CurrencyAmount; import com.opengamma.util.money.MultipleCurrencyAmount; import com.opengamma.util.test.TestGroup; /** * Tests related to the FXMatrix. */ @Test(groups = TestGroup.UNIT) public class FXMatrixTest { private static final Currency USD = Currency.USD; private static final Currency EUR = Currency.EUR; private static final Currency GBP = Currency.GBP; private static final Currency KRW = Currency.of("KRW"); private static final double EUR_USD = 1.40; private static final double GBP_EUR = 1.20; private static final double USD_KRW = 1123.45; private static final double TOLERANCE_RATE = 1.0E-10; @Test(expectedExceptions = IllegalArgumentException.class) public void nullCurrencyConstructor1() { new FXMatrix((Currency) null); } @Test(expectedExceptions = IllegalArgumentException.class) public void nullCurrency1() { final FXMatrix fxMatrix = new FXMatrix(); fxMatrix.addCurrency(null, USD, EUR_USD); } @Test(expectedExceptions = IllegalArgumentException.class) public void nullCurrency2() { final FXMatrix fxMatrix = new FXMatrix(); fxMatrix.addCurrency(EUR, null, EUR_USD); } @Test(expectedExceptions = IllegalArgumentException.class) public void sameCurrency() { final FXMatrix fxMatrix = new FXMatrix(); fxMatrix.addCurrency(EUR, EUR, EUR_USD); } @Test(expectedExceptions = IllegalArgumentException.class) public void currency1NotPresent() { final FXMatrix fxMatrix = new FXMatrix(); fxMatrix.addCurrency(EUR, USD, EUR_USD); fxMatrix.getFxRate(GBP, USD); } @Test(expectedExceptions = IllegalArgumentException.class) public void currency2NotPresent() { final FXMatrix fxMatrix = new FXMatrix(); fxMatrix.addCurrency(EUR, USD, EUR_USD); fxMatrix.getFxRate(USD, GBP); } @Test(expectedExceptions = IllegalArgumentException.class) public void currencyAlreadyPresent() { final FXMatrix fxMatrix = new FXMatrix(); fxMatrix.addCurrency(EUR, USD, EUR_USD); fxMatrix.addCurrency(GBP, EUR, GBP_EUR); fxMatrix.addCurrency(GBP, USD, 1.234); } @Test public void onePair() { final FXMatrix fxMatrix = new FXMatrix(); fxMatrix.addCurrency(EUR, USD, EUR_USD); assertEquals("FXMatrix - first pair", EUR_USD, fxMatrix.getFxRate(EUR, USD), TOLERANCE_RATE); assertEquals("FXMatrix - first pair", 1.0 / EUR_USD, fxMatrix.getFxRate(USD, EUR), TOLERANCE_RATE); assertEquals("FXMatrix - first pair", 1.0, fxMatrix.getFxRate(USD, USD), TOLERANCE_RATE); // Is this useful? At least it is correct! assertEquals("FXMatrix - first pair", 1.0, fxMatrix.getFxRate(EUR, EUR), TOLERANCE_RATE); } @Test public void onePairSecondConstructor() { final FXMatrix fxMatrix = new FXMatrix(EUR, USD, EUR_USD); assertEquals("FXMatrix - first pair", EUR_USD, fxMatrix.getFxRate(EUR, USD), TOLERANCE_RATE); assertEquals("FXMatrix - first pair", 1.0 / EUR_USD, fxMatrix.getFxRate(USD, EUR), TOLERANCE_RATE); assertEquals("FXMatrix - first pair", 1.0, fxMatrix.getFxRate(USD, USD), TOLERANCE_RATE); // Is this useful? At least it is correct! assertEquals("FXMatrix - first pair", 1.0, fxMatrix.getFxRate(EUR, EUR), TOLERANCE_RATE); } @Test public void onePairThirdConstructor() { final FXMatrix fxMatrix = new FXMatrix(USD); fxMatrix.addCurrency(EUR, USD, EUR_USD); assertEquals("FXMatrix - first pair", EUR_USD, fxMatrix.getFxRate(EUR, USD), TOLERANCE_RATE); assertEquals("FXMatrix - first pair", 1.0 / EUR_USD, fxMatrix.getFxRate(USD, EUR), TOLERANCE_RATE); assertEquals("FXMatrix - first pair", 1.0, fxMatrix.getFxRate(USD, USD), TOLERANCE_RATE); assertEquals("FXMatrix - first pair", 1.0, fxMatrix.getFxRate(EUR, EUR), TOLERANCE_RATE); } @Test public void twoPairs() { final FXMatrix fxMatrix = new FXMatrix(); fxMatrix.addCurrency(EUR, USD, EUR_USD); fxMatrix.addCurrency(GBP, EUR, GBP_EUR); assertEquals("FXMatrix - two pairs", EUR_USD, fxMatrix.getFxRate(EUR, USD), 1.0E-10); assertEquals("FXMatrix - two pairs", GBP_EUR, fxMatrix.getFxRate(GBP, EUR), 1.0E-10); assertEquals("FXMatrix - two pairs", GBP_EUR * EUR_USD, fxMatrix.getFxRate(GBP, USD), 1.0E-10); assertEquals("FXMatrix - two pairs", 1.0 / EUR_USD, fxMatrix.getFxRate(USD, EUR), 1.0E-10); assertEquals("FXMatrix - two pairs", 1.0 / GBP_EUR, fxMatrix.getFxRate(EUR, GBP), 1.0E-10); assertEquals("FXMatrix - two pairs", 1.0 / (GBP_EUR * EUR_USD), fxMatrix.getFxRate(USD, GBP), 1.0E-10); assertEquals("FXMatrix - two pairs", 1.0, fxMatrix.getFxRate(GBP, GBP), 1.0E-10); // Is this useful? At least it is correct! } @Test public void threePairs() { final FXMatrix fxMatrix = new FXMatrix(); fxMatrix.addCurrency(EUR, USD, EUR_USD); fxMatrix.addCurrency(GBP, EUR, GBP_EUR); fxMatrix.addCurrency(KRW, USD, 1.0 / USD_KRW); assertEquals("FXMatrix - three pairs", EUR_USD, fxMatrix.getFxRate(EUR, USD), 1.0E-10); assertEquals("FXMatrix - three pairs", GBP_EUR, fxMatrix.getFxRate(GBP, EUR), 1.0E-10); assertEquals("FXMatrix - three pairs", GBP_EUR * EUR_USD, fxMatrix.getFxRate(GBP, USD), 1.0E-10); assertEquals("FXMatrix - three pairs", USD_KRW, fxMatrix.getFxRate(USD, KRW), 1.0E-10); assertEquals("FXMatrix - three pairs", 1.0 / EUR_USD, fxMatrix.getFxRate(USD, EUR), 1.0E-10); assertEquals("FXMatrix - three pairs", 1.0 / GBP_EUR, fxMatrix.getFxRate(EUR, GBP), 1.0E-10); assertEquals("FXMatrix - three pairs", 1.0 / (GBP_EUR * EUR_USD), fxMatrix.getFxRate(USD, GBP), 1.0E-10); assertEquals("FXMatrix - three pairs", 1.0 / USD_KRW, fxMatrix.getFxRate(KRW, USD), 1.0E-10); assertEquals("FXMatrix - three pairs", GBP_EUR * EUR_USD * USD_KRW, fxMatrix.getFxRate(GBP, KRW), 1.0E-10); } @Test public void constructorFromExisitingFxMatrix() { final FXMatrix fxMatrix1 = new FXMatrix(EUR, USD, EUR_USD); final FXMatrix fxMatrix2 = new FXMatrix(fxMatrix1); assertEquals("FXMatrix - constructor", fxMatrix1, fxMatrix2); fxMatrix2.addCurrency(GBP, EUR, GBP_EUR); assertFalse("FXMatrix - constructor", fxMatrix1.equals(fxMatrix2)); } @Test /** * Check the conversion of a multiple currency amount. */ public void convert() { final FXMatrix fxMatrix = new FXMatrix(); fxMatrix.addCurrency(EUR, USD, EUR_USD); fxMatrix.addCurrency(GBP, EUR, GBP_EUR); final double amountGBP = 1.0; final double amountEUR = 2.0; final double amountUSD = 3.0; MultipleCurrencyAmount amount = MultipleCurrencyAmount.of(GBP, amountGBP); amount = amount.plus(EUR, amountEUR); amount = amount.plus(USD, amountUSD); final CurrencyAmount totalUSDCalculated = fxMatrix.convert(amount, USD); final double totalUSDExpected = amountUSD + amountEUR * EUR_USD + amountGBP * GBP_EUR * EUR_USD; assertEquals("FXMatrix - convert", totalUSDExpected, totalUSDCalculated.getAmount(), 1.0E-10); assertEquals("FXMatrix - convert", USD, totalUSDCalculated.getCurrency()); } @Test /** * Check the update of one exchange rate in matrix. */ public void update() { final FXMatrix fxMatrix = new FXMatrix(); fxMatrix.addCurrency(EUR, USD, EUR_USD); fxMatrix.addCurrency(GBP, EUR, GBP_EUR); fxMatrix.addCurrency(KRW, USD, 1.0 / USD_KRW); assertEquals("FXMatrix - update", EUR_USD, fxMatrix.getFxRate(EUR, USD), TOLERANCE_RATE); assertEquals("FXMatrix - update", GBP_EUR, fxMatrix.getFxRate(GBP, EUR), TOLERANCE_RATE); assertEquals("FXMatrix - update", GBP_EUR * EUR_USD, fxMatrix.getFxRate(GBP, USD), TOLERANCE_RATE); assertEquals("FXMatrix - update", USD_KRW, fxMatrix.getFxRate(USD, KRW), TOLERANCE_RATE); final double newGBPEUR = 1.10; fxMatrix.updateRates(GBP, EUR, newGBPEUR); assertEquals("FXMatrix - update", EUR_USD, fxMatrix.getFxRate(EUR, USD), TOLERANCE_RATE); assertEquals("FXMatrix - update", newGBPEUR, fxMatrix.getFxRate(GBP, EUR), TOLERANCE_RATE); assertEquals("FXMatrix - update", newGBPEUR * EUR_USD, fxMatrix.getFxRate(GBP, USD), TOLERANCE_RATE); assertEquals("FXMatrix - update", USD_KRW, fxMatrix.getFxRate(USD, KRW), TOLERANCE_RATE); assertEquals("FXMatrix - update", 1.0 / EUR_USD, fxMatrix.getFxRate(USD, EUR), TOLERANCE_RATE); assertEquals("FXMatrix - update", 1.0 / newGBPEUR, fxMatrix.getFxRate(EUR, GBP), TOLERANCE_RATE); assertEquals("FXMatrix - update", 1.0 / (newGBPEUR * EUR_USD), fxMatrix.getFxRate(USD, GBP), TOLERANCE_RATE); assertEquals("FXMatrix - update", 1.0 / USD_KRW, fxMatrix.getFxRate(KRW, USD), TOLERANCE_RATE); assertEquals("FXMatrix - update", newGBPEUR * EUR_USD * USD_KRW, fxMatrix.getFxRate(GBP, KRW), TOLERANCE_RATE); } @Test public void testHashCodeEquals() { final FXMatrix fxMatrix = new FXMatrix(); fxMatrix.addCurrency(EUR, USD, EUR_USD); fxMatrix.addCurrency(GBP, EUR, GBP_EUR); fxMatrix.addCurrency(KRW, USD, 1.0 / USD_KRW); FXMatrix other = new FXMatrix(); other.addCurrency(EUR, USD, EUR_USD); other.addCurrency(GBP, EUR, GBP_EUR); other.addCurrency(KRW, USD, 1.0 / USD_KRW); assertEquals(fxMatrix, other); assertEquals(fxMatrix.hashCode(), other.hashCode()); other = new FXMatrix(); other.addCurrency(EUR, USD, EUR_USD); other.addCurrency(GBP, EUR, GBP_EUR); assertFalse(fxMatrix.equals(other)); } @Test /** * Tests that a matrix merged with itself is equal with itself. */ public void mergeWithItself() { final FXMatrix fxMatrix = new FXMatrix(); fxMatrix.addCurrency(EUR, USD, EUR_USD); fxMatrix.addCurrency(GBP, EUR, GBP_EUR); final FXMatrix merged = FXMatrixUtils.merge(fxMatrix, fxMatrix); assertEquals("FXMatrixUtils - merge", fxMatrix, merged); } @Test /** * Tests that a matrix constructed by adding currencies one by one or by merging by blocks returns the same result. */ public void merge1() { final FXMatrix fxMatrixEURUSD = new FXMatrix(); fxMatrixEURUSD.addCurrency(EUR, USD, EUR_USD); // assertTrue("FXMatrixUtils - merge", FXMatrixUtils.compare(fxMatrixEURUSD, FXMatrixUtils.merge(fxMatrixEURUSD, new FXMatrix()), TOLERANCE_RATE)); // assertTrue("FXMatrixUtils - merge", FXMatrixUtils.compare(fxMatrixEURUSD, FXMatrixUtils.merge(new FXMatrix(), fxMatrixEURUSD), TOLERANCE_RATE)); assertTrue("FXMatrixUtils - merge", FXMatrixUtils.compare(fxMatrixEURUSD, FXMatrixUtils.merge(fxMatrixEURUSD, new FXMatrix(USD)), TOLERANCE_RATE)); assertTrue("FXMatrixUtils - merge", FXMatrixUtils.compare(fxMatrixEURUSD, FXMatrixUtils.merge(fxMatrixEURUSD, new FXMatrix(EUR)), TOLERANCE_RATE)); assertTrue("FXMatrixUtils - merge", FXMatrixUtils.compare(fxMatrixEURUSD, FXMatrixUtils.merge(new FXMatrix(USD), fxMatrixEURUSD), TOLERANCE_RATE)); assertTrue("FXMatrixUtils - merge", FXMatrixUtils.compare(fxMatrixEURUSD, FXMatrixUtils.merge(new FXMatrix(EUR), fxMatrixEURUSD), TOLERANCE_RATE)); final FXMatrix fxMatrixGBPEUR = new FXMatrix(); fxMatrixGBPEUR.addCurrency(GBP, EUR, GBP_EUR); final FXMatrix fxMatrixEURUSDGBP = new FXMatrix(); fxMatrixEURUSDGBP.addCurrency(EUR, USD, EUR_USD); fxMatrixEURUSDGBP.addCurrency(GBP, EUR, GBP_EUR); final FXMatrix merged = FXMatrixUtils.merge(fxMatrixEURUSD, fxMatrixGBPEUR); assertTrue("FXMatrixUtils - merge", FXMatrixUtils.compare(merged, fxMatrixEURUSDGBP, TOLERANCE_RATE)); } @Test /** * Tests that a matrix constructed by adding currencies one by one or by merging by blocks returns the same result. */ public void merge2() { final FXMatrix fxMatrix1 = new FXMatrix(); fxMatrix1.addCurrency(EUR, USD, EUR_USD); fxMatrix1.addCurrency(KRW, USD, 1.0 / USD_KRW); final FXMatrix fxMatrix2 = new FXMatrix(); fxMatrix2.addCurrency(EUR, USD, EUR_USD); fxMatrix2.addCurrency(GBP, EUR, GBP_EUR); final FXMatrix fxMatrixMergeExpected = new FXMatrix(); fxMatrixMergeExpected.addCurrency(EUR, USD, EUR_USD); fxMatrixMergeExpected.addCurrency(GBP, EUR, GBP_EUR); fxMatrixMergeExpected.addCurrency(KRW, USD, 1.0 / USD_KRW); final FXMatrix merged = FXMatrixUtils.merge(fxMatrix1, fxMatrix2); assertEquals("FXMatrixUtils - merge", merged.getFxRate(USD, EUR), fxMatrixMergeExpected.getFxRate(USD, EUR), TOLERANCE_RATE); assertEquals("FXMatrixUtils - merge", merged.getFxRate(USD, GBP), fxMatrixMergeExpected.getFxRate(USD, GBP), TOLERANCE_RATE); assertEquals("FXMatrixUtils - merge", merged.getFxRate(USD, KRW), fxMatrixMergeExpected.getFxRate(USD, KRW), TOLERANCE_RATE); } @Test /** * Tests the merge with an empty matrix. */ public void merge3() { final FXMatrix fxMatrix1 = new FXMatrix(); fxMatrix1.addCurrency(EUR, USD, EUR_USD); fxMatrix1.addCurrency(KRW, USD, 1.0 / USD_KRW); assertTrue("FXMatrixUtils - merge", FXMatrixUtils.compare(fxMatrix1, FXMatrixUtils.merge(fxMatrix1, new FXMatrix()), TOLERANCE_RATE)); assertTrue("FXMatrixUtils - merge", FXMatrixUtils.compare(fxMatrix1, FXMatrixUtils.merge(new FXMatrix(), fxMatrix1), TOLERANCE_RATE)); assertTrue("FXMatrixUtils - merge", FXMatrixUtils.compare(fxMatrix1, FXMatrixUtils.merge(new FXMatrix(USD), fxMatrix1), TOLERANCE_RATE)); assertTrue("FXMatrixUtils - merge", FXMatrixUtils.compare(new FXMatrix(), FXMatrixUtils.merge(new FXMatrix(), new FXMatrix()), TOLERANCE_RATE)); } @Test /** * Tests the comparison tool. */ public void compare() { // Matrix with itself final FXMatrix fxMatrix1 = new FXMatrix(); fxMatrix1.addCurrency(GBP, EUR, GBP_EUR); fxMatrix1.addCurrency(USD, EUR, 1.0d / EUR_USD); assertTrue("FXMatrixUtils - compare", FXMatrixUtils.compare(fxMatrix1, fxMatrix1, TOLERANCE_RATE)); // Matrix in a different order final FXMatrix fxMatrix2 = new FXMatrix(); fxMatrix2.addCurrency(EUR, USD, EUR_USD); fxMatrix2.addCurrency(GBP, EUR, GBP_EUR); assertTrue("FXMatrixUtils - compare", FXMatrixUtils.compare(fxMatrix1, fxMatrix2, TOLERANCE_RATE)); // Matrix with different order rate final FXMatrix fxMatrix3 = new FXMatrix(); fxMatrix3.addCurrency(EUR, USD, EUR_USD + 1.0E-5); fxMatrix3.addCurrency(GBP, EUR, GBP_EUR); assertFalse("FXMatrixUtils - compare", FXMatrixUtils.compare(fxMatrix1, fxMatrix3, TOLERANCE_RATE)); // Matrix with different currencies final FXMatrix fxMatrix4 = new FXMatrix(); fxMatrix4.addCurrency(GBP, EUR, GBP_EUR); fxMatrix4.addCurrency(USD, EUR, 1.0d / EUR_USD); fxMatrix4.addCurrency(KRW, USD, 1.0 / USD_KRW); assertFalse("FXMatrixUtils - compare", FXMatrixUtils.compare(fxMatrix1, fxMatrix4, TOLERANCE_RATE)); } }