/**
* Copyright (C) 2016 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.basics.currency;
import static com.opengamma.strata.basics.currency.Currency.CAD;
import static com.opengamma.strata.basics.currency.Currency.EUR;
import static com.opengamma.strata.basics.currency.Currency.GBP;
import static com.opengamma.strata.basics.currency.Currency.USD;
import static com.opengamma.strata.basics.currency.MultiCurrencyAmountArray.toMultiCurrencyAmountArray;
import static com.opengamma.strata.collect.TestHelper.assertThrows;
import static com.opengamma.strata.collect.TestHelper.assertThrowsIllegalArg;
import static com.opengamma.strata.collect.TestHelper.coverBeanEquals;
import static com.opengamma.strata.collect.TestHelper.coverImmutableBean;
import static java.util.stream.Collectors.toList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.data.Offset.offset;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;
import java.util.Map;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.opengamma.strata.collect.array.DoubleArray;
/**
* Test {@link MultiCurrencyAmountArray}.
*/
@Test
public class MultiCurrencyAmountArrayTest {
private static final MultiCurrencyAmountArray VALUES_ARRAY =
MultiCurrencyAmountArray.of(
ImmutableList.of(
MultiCurrencyAmount.of(
CurrencyAmount.of(Currency.GBP, 20),
CurrencyAmount.of(Currency.USD, 30),
CurrencyAmount.of(Currency.EUR, 40)),
MultiCurrencyAmount.of(
CurrencyAmount.of(Currency.GBP, 21),
CurrencyAmount.of(Currency.USD, 32),
CurrencyAmount.of(Currency.EUR, 43)),
MultiCurrencyAmount.of(
CurrencyAmount.of(Currency.GBP, 22),
CurrencyAmount.of(Currency.USD, 33),
CurrencyAmount.of(Currency.EUR, 44))));
//-------------------------------------------------------------------------
public void test_of() {
assertThat(VALUES_ARRAY.getValues(Currency.GBP)).isEqualTo(DoubleArray.of(20, 21, 22));
assertThat(VALUES_ARRAY.getValues(Currency.USD)).isEqualTo(DoubleArray.of(30, 32, 33));
assertThat(VALUES_ARRAY.getValues(Currency.EUR)).isEqualTo(DoubleArray.of(40, 43, 44));
MultiCurrencyAmountArray raggedArray = MultiCurrencyAmountArray.of(
ImmutableList.of(
MultiCurrencyAmount.of(
CurrencyAmount.of(Currency.EUR, 4)),
MultiCurrencyAmount.of(
CurrencyAmount.of(Currency.GBP, 21),
CurrencyAmount.of(Currency.USD, 32),
CurrencyAmount.of(Currency.EUR, 43)),
MultiCurrencyAmount.of(
CurrencyAmount.of(Currency.EUR, 44))));
assertThat(raggedArray.size()).isEqualTo(3);
assertThat(VALUES_ARRAY.getCurrencies()).isEqualTo(ImmutableSet.of(Currency.GBP, Currency.USD, Currency.EUR));
assertThat(raggedArray.getValues(Currency.GBP)).isEqualTo(DoubleArray.of(0, 21, 0));
assertThat(raggedArray.getValues(Currency.USD)).isEqualTo(DoubleArray.of(0, 32, 0));
assertThat(raggedArray.getValues(Currency.EUR)).isEqualTo(DoubleArray.of(4, 43, 44));
assertThrowsIllegalArg(() -> raggedArray.getValues(Currency.AUD));
}
public void test_empty_amounts() {
MultiCurrencyAmountArray array = MultiCurrencyAmountArray.of(
MultiCurrencyAmount.empty(),
MultiCurrencyAmount.empty());
assertThat(array.size()).isEqualTo(2);
assertThat(array.get(0)).isEqualTo(MultiCurrencyAmount.empty());
assertThat(array.get(1)).isEqualTo(MultiCurrencyAmount.empty());
}
public void test_of_function() {
MultiCurrencyAmount mca1 = MultiCurrencyAmount.of(CurrencyAmount.of(Currency.GBP, 10), CurrencyAmount.of(Currency.USD, 20));
MultiCurrencyAmount mca2 = MultiCurrencyAmount.of(CurrencyAmount.of(Currency.GBP, 10), CurrencyAmount.of(Currency.EUR, 30));
MultiCurrencyAmount mca3 = MultiCurrencyAmount.of(CurrencyAmount.of(Currency.USD, 40));
List<MultiCurrencyAmount> amounts = ImmutableList.of(mca1, mca2, mca3);
MultiCurrencyAmountArray test = MultiCurrencyAmountArray.of(3, i -> amounts.get(i));
assertThat(test.get(0)).isEqualTo(mca1.plus(Currency.EUR, 0));
assertThat(test.get(1)).isEqualTo(mca2.plus(Currency.USD, 0));
assertThat(test.get(2)).isEqualTo(mca3.plus(Currency.GBP, 0).plus(Currency.EUR, 0));
}
// Test that the size is correctly restored after deserialization.
public void serializeSize() throws Exception {
MultiCurrencyAmountArray deserialized = serializedDeserialize(VALUES_ARRAY);
assertThat(deserialized.size()).isEqualTo(3);
MultiCurrencyAmountArray empty = MultiCurrencyAmountArray.of(
MultiCurrencyAmount.empty(),
MultiCurrencyAmount.empty());
MultiCurrencyAmountArray deserializedEmpty = serializedDeserialize(empty);
assertThat(deserializedEmpty.size()).isEqualTo(2);
}
public void test_of_function_empty_amounts() {
MultiCurrencyAmountArray test = MultiCurrencyAmountArray.of(3, i -> MultiCurrencyAmount.empty());
assertThat(test.size()).isEqualTo(3);
}
public void test_of_map() {
MultiCurrencyAmountArray array = MultiCurrencyAmountArray.of(
ImmutableMap.of(
Currency.GBP, DoubleArray.of(20, 21, 22),
Currency.EUR, DoubleArray.of(40, 43, 44)));
MultiCurrencyAmountArray expected = MultiCurrencyAmountArray.of(
ImmutableList.of(
MultiCurrencyAmount.of(
CurrencyAmount.of(Currency.GBP, 20),
CurrencyAmount.of(Currency.EUR, 40)),
MultiCurrencyAmount.of(
CurrencyAmount.of(Currency.GBP, 21),
CurrencyAmount.of(Currency.EUR, 43)),
MultiCurrencyAmount.of(
CurrencyAmount.of(Currency.GBP, 22),
CurrencyAmount.of(Currency.EUR, 44))));
assertThat(array.size()).isEqualTo(3);
assertThat(array).isEqualTo(expected);
assertThrowsIllegalArg(
() -> MultiCurrencyAmountArray.of(
ImmutableMap.of(
Currency.GBP, DoubleArray.of(20, 21),
Currency.EUR, DoubleArray.of(40, 43, 44))),
"Arrays must have the same size.*");
MultiCurrencyAmountArray empty = MultiCurrencyAmountArray.of(ImmutableMap.of());
assertThat(empty.size()).isEqualTo(0);
}
public void test_getValues() {
Map<Currency, DoubleArray> expected = ImmutableMap.of(
Currency.GBP, DoubleArray.of(20, 21, 22),
Currency.USD, DoubleArray.of(30, 32, 33),
Currency.EUR, DoubleArray.of(40, 43, 44));
assertThat(VALUES_ARRAY.getValues()).isEqualTo(expected);
}
public void test_get() {
MultiCurrencyAmount expected = MultiCurrencyAmount.of(
CurrencyAmount.of(Currency.GBP, 22),
CurrencyAmount.of(Currency.USD, 33),
CurrencyAmount.of(Currency.EUR, 44));
assertThat(VALUES_ARRAY.get(2)).isEqualTo(expected);
assertThrows(() -> VALUES_ARRAY.get(3), IndexOutOfBoundsException.class);
assertThrows(() -> VALUES_ARRAY.get(-1), IndexOutOfBoundsException.class);
}
public void test_stream() {
List<MultiCurrencyAmount> expected = ImmutableList.of(
MultiCurrencyAmount.of(
CurrencyAmount.of(Currency.GBP, 20),
CurrencyAmount.of(Currency.USD, 30),
CurrencyAmount.of(Currency.EUR, 40)),
MultiCurrencyAmount.of(
CurrencyAmount.of(Currency.GBP, 21),
CurrencyAmount.of(Currency.USD, 32),
CurrencyAmount.of(Currency.EUR, 43)),
MultiCurrencyAmount.of(
CurrencyAmount.of(Currency.GBP, 22),
CurrencyAmount.of(Currency.USD, 33),
CurrencyAmount.of(Currency.EUR, 44)));
assertThat(VALUES_ARRAY.stream().collect(toList())).isEqualTo(expected);
}
public void test_convertedTo() {
FxMatrix fxMatrix = FxMatrix.builder()
.addRate(GBP, CAD, 2)
.addRate(USD, CAD, 1.3)
.addRate(EUR, CAD, 1.4)
.build();
CurrencyAmountArray convertedArray = VALUES_ARRAY.convertedTo(Currency.CAD, fxMatrix);
DoubleArray expected = DoubleArray.of(
20 * 2 + 30 * 1.3 + 40 * 1.4,
21 * 2 + 32 * 1.3 + 43 * 1.4,
22 * 2 + 33 * 1.3 + 44 * 1.4);
assertThat(convertedArray.getValues()).isEqualTo(expected);
}
public void test_convertedTo_existingCurrency() {
FxMatrix fxMatrix = FxMatrix.builder()
.addRate(USD, GBP, 1 / 1.5)
.addRate(EUR, GBP, 0.7)
.build();
CurrencyAmountArray convertedArray = VALUES_ARRAY.convertedTo(Currency.GBP, fxMatrix);
assertThat(convertedArray.getCurrency()).isEqualTo(Currency.GBP);
double[] expected = new double[] {
20 + 30 / 1.5 + 40 * 0.7,
21 + 32 / 1.5 + 43 * 0.7,
22 + 33 / 1.5 + 44 * 0.7};
for (int i = 0; i < 3; i++) {
assertThat(convertedArray.get(i).getAmount()).isEqualTo(expected[i], offset(1e-6));
}
}
//-------------------------------------------------------------------------
// Test hand-written equals and hashCode methods which correctly handle maps with array values
public void test_equalsHashCode() {
MultiCurrencyAmountArray array =
MultiCurrencyAmountArray.of(
ImmutableList.of(
MultiCurrencyAmount.of(
CurrencyAmount.of(Currency.GBP, 20),
CurrencyAmount.of(Currency.USD, 30),
CurrencyAmount.of(Currency.EUR, 40)),
MultiCurrencyAmount.of(
CurrencyAmount.of(Currency.GBP, 21),
CurrencyAmount.of(Currency.USD, 32),
CurrencyAmount.of(Currency.EUR, 43)),
MultiCurrencyAmount.of(
CurrencyAmount.of(Currency.GBP, 22),
CurrencyAmount.of(Currency.USD, 33),
CurrencyAmount.of(Currency.EUR, 44))));
assertThat(array).isEqualTo(VALUES_ARRAY);
assertThat(array.hashCode()).isEqualTo(VALUES_ARRAY.hashCode());
}
//-------------------------------------------------------------------------
public void coverage() {
coverImmutableBean(VALUES_ARRAY);
MultiCurrencyAmountArray test2 = MultiCurrencyAmountArray.of(
MultiCurrencyAmount.of(
CurrencyAmount.of(Currency.GBP, 21),
CurrencyAmount.of(Currency.USD, 31),
CurrencyAmount.of(Currency.EUR, 41)),
MultiCurrencyAmount.of(
CurrencyAmount.of(Currency.GBP, 22),
CurrencyAmount.of(Currency.USD, 33),
CurrencyAmount.of(Currency.EUR, 44)));
coverBeanEquals(VALUES_ARRAY, test2);
}
//-------------------------------------------------------------------------
public void test_plusArray() {
MultiCurrencyAmountArray array1 = MultiCurrencyAmountArray.of(
ImmutableMap.of(
Currency.USD, DoubleArray.of(30, 32, 33),
Currency.EUR, DoubleArray.of(40, 43, 44),
Currency.CHF, DoubleArray.of(50, 54, 56)));
MultiCurrencyAmountArray array2 = MultiCurrencyAmountArray.of(
ImmutableMap.of(
Currency.GBP, DoubleArray.of(20, 21, 22),
Currency.EUR, DoubleArray.of(140, 143, 144),
Currency.CHF, DoubleArray.of(250, 254, 256)));
MultiCurrencyAmountArray expected = MultiCurrencyAmountArray.of(
ImmutableMap.of(
Currency.GBP, DoubleArray.of(20, 21, 22),
Currency.USD, DoubleArray.of(30, 32, 33),
Currency.EUR, DoubleArray.of(180, 186, 188),
Currency.CHF, DoubleArray.of(300, 308, 312)));
assertThat(array1.plus(array2)).isEqualTo(expected);
}
public void test_plusAmount() {
MultiCurrencyAmountArray array = MultiCurrencyAmountArray.of(
ImmutableMap.of(
Currency.USD, DoubleArray.of(30, 32, 33),
Currency.EUR, DoubleArray.of(40, 43, 44),
Currency.CHF, DoubleArray.of(50, 54, 56)));
MultiCurrencyAmount amount = MultiCurrencyAmount.of(
ImmutableMap.of(
Currency.GBP, 21d,
Currency.EUR, 143d,
Currency.CHF, 254d));
MultiCurrencyAmountArray expected = MultiCurrencyAmountArray.of(
ImmutableMap.of(
Currency.GBP, DoubleArray.of(21, 21, 21),
Currency.USD, DoubleArray.of(30, 32, 33),
Currency.EUR, DoubleArray.of(183, 186, 187),
Currency.CHF, DoubleArray.of(304, 308, 310)));
assertThat(array.plus(amount)).isEqualTo(expected);
}
public void test_plusDifferentSize() {
MultiCurrencyAmountArray array1 = MultiCurrencyAmountArray.of(
ImmutableMap.of(
Currency.USD, DoubleArray.of(30, 32),
Currency.EUR, DoubleArray.of(40, 43),
Currency.CHF, DoubleArray.of(50, 54)));
MultiCurrencyAmountArray array2 = MultiCurrencyAmountArray.of(
ImmutableMap.of(
Currency.GBP, DoubleArray.of(20, 21, 22),
Currency.EUR, DoubleArray.of(140, 143, 144),
Currency.CHF, DoubleArray.of(250, 254, 256)));
assertThrowsIllegalArg(() -> array1.plus(array2));
}
public void test_minusArray() {
MultiCurrencyAmountArray array1 = MultiCurrencyAmountArray.of(
ImmutableMap.of(
Currency.USD, DoubleArray.of(30, 32, 33),
Currency.EUR, DoubleArray.of(40, 43, 44),
Currency.CHF, DoubleArray.of(50, 54, 56)));
MultiCurrencyAmountArray array2 = MultiCurrencyAmountArray.of(
ImmutableMap.of(
Currency.GBP, DoubleArray.of(20, 21, 22),
Currency.EUR, DoubleArray.of(140, 143, 144),
Currency.CHF, DoubleArray.of(250, 254, 256)));
MultiCurrencyAmountArray expected = MultiCurrencyAmountArray.of(
ImmutableMap.of(
Currency.GBP, DoubleArray.of(-20, -21, -22),
Currency.USD, DoubleArray.of(30, 32, 33),
Currency.EUR, DoubleArray.of(-100, -100, -100),
Currency.CHF, DoubleArray.of(-200, -200, -200)));
assertThat(array1.minus(array2)).isEqualTo(expected);
}
public void test_minusAmount() {
MultiCurrencyAmountArray array = MultiCurrencyAmountArray.of(
ImmutableMap.of(
Currency.USD, DoubleArray.of(30, 32, 33),
Currency.EUR, DoubleArray.of(40, 43, 44),
Currency.CHF, DoubleArray.of(50, 54, 56)));
MultiCurrencyAmount amount = MultiCurrencyAmount.of(
ImmutableMap.of(
Currency.GBP, 21d,
Currency.EUR, 143d,
Currency.CHF, 254d));
MultiCurrencyAmountArray expected = MultiCurrencyAmountArray.of(
ImmutableMap.of(
Currency.GBP, DoubleArray.of(-21, -21, -21),
Currency.USD, DoubleArray.of(30, 32, 33),
Currency.EUR, DoubleArray.of(-103, -100, -99),
Currency.CHF, DoubleArray.of(-204, -200, -198)));
assertThat(array.minus(amount)).isEqualTo(expected);
}
public void test_minusDifferentSize() {
MultiCurrencyAmountArray array1 = MultiCurrencyAmountArray.of(
ImmutableMap.of(
Currency.USD, DoubleArray.of(30, 32),
Currency.EUR, DoubleArray.of(40, 43),
Currency.CHF, DoubleArray.of(50, 54)));
MultiCurrencyAmountArray array2 = MultiCurrencyAmountArray.of(
ImmutableMap.of(
Currency.GBP, DoubleArray.of(20, 21, 22),
Currency.EUR, DoubleArray.of(140, 143, 144),
Currency.CHF, DoubleArray.of(250, 254, 256)));
assertThrowsIllegalArg(() -> array1.minus(array2));
}
public void collector() {
List<CurrencyAmountArray> arrays = ImmutableList.of(
CurrencyAmountArray.of(USD, DoubleArray.of(10, 20, 30)),
CurrencyAmountArray.of(USD, DoubleArray.of(5, 6, 7)),
CurrencyAmountArray.of(EUR, DoubleArray.of(2, 4, 6)),
CurrencyAmountArray.of(GBP, DoubleArray.of(11, 12, 13)),
CurrencyAmountArray.of(GBP, DoubleArray.of(1, 2, 3)));
Map<Currency, DoubleArray> expectedMap = ImmutableMap.of(
USD, DoubleArray.of(15, 26, 37),
EUR, DoubleArray.of(2, 4, 6),
GBP, DoubleArray.of(12, 14, 16));
MultiCurrencyAmountArray expected = MultiCurrencyAmountArray.of(expectedMap);
assertThat(arrays.stream().collect(toMultiCurrencyAmountArray())).isEqualTo(expected);
}
public void total() {
List<CurrencyAmountArray> arrays = ImmutableList.of(
CurrencyAmountArray.of(USD, DoubleArray.of(10, 20, 30)),
CurrencyAmountArray.of(USD, DoubleArray.of(5, 6, 7)),
CurrencyAmountArray.of(EUR, DoubleArray.of(2, 4, 6)),
CurrencyAmountArray.of(GBP, DoubleArray.of(11, 12, 13)),
CurrencyAmountArray.of(GBP, DoubleArray.of(1, 2, 3)));
Map<Currency, DoubleArray> expectedMap = ImmutableMap.of(
USD, DoubleArray.of(15, 26, 37),
EUR, DoubleArray.of(2, 4, 6),
GBP, DoubleArray.of(12, 14, 16));
MultiCurrencyAmountArray expected = MultiCurrencyAmountArray.of(expectedMap);
assertThat(MultiCurrencyAmountArray.total(arrays)).isEqualTo(expected);
}
public void collectorDifferentArrayLengths() {
List<CurrencyAmountArray> arrays = ImmutableList.of(
CurrencyAmountArray.of(USD, DoubleArray.of(10, 20, 30)),
CurrencyAmountArray.of(GBP, DoubleArray.of(1, 2)));
assertThrowsIllegalArg(() -> arrays.stream().collect(toMultiCurrencyAmountArray()));
}
//--------------------------------------------------------------------------------------------------
/**
* Serializes and deserializes an array using default serialization.
*/
private static MultiCurrencyAmountArray serializedDeserialize(MultiCurrencyAmountArray array) throws Exception {
ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteOutputStream);
objectOutputStream.writeObject(array);
objectOutputStream.flush();
ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteOutputStream.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(byteInputStream);
return (MultiCurrencyAmountArray) objectInputStream.readObject();
}
}