Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ public static CurrencyParameterSensitivity of(
* Combines two or more instances to form a single sensitivity instance.
* <p>
* The result will store information about the separate instances allowing it to be {@link #split()} later.
* <p>
* If a single sensitivity is supplied and refers to the same market data then it will be returned unmodified.
* Otherwise a new instance will be returned with a single parameter split (the original sensitivity).
*
* @param marketDataName the combined name of the market data that the sensitivity refers to
* @param sensitivities the sensitivity instances to combine, two or more
Expand All @@ -214,25 +217,39 @@ public static CurrencyParameterSensitivity combine(
CurrencyParameterSensitivity... sensitivities) {

ArgChecker.notEmpty(sensitivities, "sensitivities");
if (sensitivities.length < 2) {
throw new IllegalArgumentException("At least two sensitivity instances must be specified");
}
Currency currency = Stream.of(sensitivities).map(s -> s.getCurrency()).distinct().reduce(ensureOnlyOne()).get();
int size = Stream.of(sensitivities).mapToInt(s -> s.getParameterCount()).sum();

if (sensitivities.length == 1) {
CurrencyParameterSensitivity first = sensitivities[0];
if (first.getMarketDataName().equals(marketDataName)) {
return first;
}
}

double[] combinedSensitivities = new double[size];
ImmutableList.Builder<ParameterMetadata> combinedMeta = ImmutableList.builder();
ImmutableList.Builder<ParameterSize> split = ImmutableList.builder();
int count = 0;
for (int i = 0; i < sensitivities.length; i++) {
CurrencyParameterSensitivity sens = sensitivities[i];
if (sens.getParameterCount() == 0) {
// Discard empty sensitivities
continue;
}
System.arraycopy(sens.getSensitivity().toArrayUnsafe(), 0, combinedSensitivities, count, sens.getParameterCount());
combinedMeta.addAll(sens.getParameterMetadata());
split.add(ParameterSize.of(sens.getMarketDataName(), sens.getParameterCount()));
count += sens.getParameterCount();
}

List<ParameterSize> parameterSplit = split.build();
return new CurrencyParameterSensitivity(
marketDataName, combinedMeta.build(), currency, DoubleArray.ofUnsafe(combinedSensitivities), split.build());
marketDataName,
combinedMeta.build(),
currency,
DoubleArray.ofUnsafe(combinedSensitivities),
parameterSplit.isEmpty() ? null : parameterSplit);
}

@ImmutableValidator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ public class CurrencyParameterSensitivityTest {
private static final List<ParameterMetadata> METADATA_BAD = ParameterMetadata.listOfEmpty(1);
private static final ImmutableList<ParameterMetadata> METADATA_COMBINED =
ImmutableList.<ParameterMetadata>builder().addAll(METADATA_USD1).addAll(METADATA_USD2).build();
private static final List<ParameterSize> PARAM_SPLIT = ImmutableList.of(ParameterSize.of(NAME1, 4), ParameterSize.of(NAME2, 5));
private static final ParameterSize PARAM1 = ParameterSize.of(NAME1, 4);
private static final ParameterSize PARAM2 = ParameterSize.of(NAME2, 5);
private static final List<ParameterSize> PARAM_SPLIT = ImmutableList.of(PARAM1, PARAM2);

//-------------------------------------------------------------------------
public void test_of_metadata() {
Expand Down Expand Up @@ -116,13 +118,46 @@ public void test_combine() {
assertEquals(test.getParameterSplit(), Optional.of(PARAM_SPLIT));
}

public void test_combine_empty() {
CurrencyParameterSensitivity base1 = CurrencyParameterSensitivity.of(NAME1, METADATA_USD1, USD, VECTOR_USD1);
CurrencyParameterSensitivity base2 = CurrencyParameterSensitivity.of(NAME2, ImmutableList.of(), USD, DoubleArray.of());
CurrencyParameterSensitivity test = CurrencyParameterSensitivity.combine(NAME_COMBINED, base1, base2);
assertEquals(test.getMarketDataName(), NAME_COMBINED);
assertEquals(test.getParameterCount(), VECTOR_USD1.size());
assertEquals(test.getParameterMetadata(), METADATA_USD1);
assertEquals(test.getSensitivity(), VECTOR_USD1);
assertEquals(test.getParameterSplit(), Optional.of(ImmutableList.of(PARAM1)));
}

public void test_combine_onlyEmpty() {
CurrencyParameterSensitivity base1 = CurrencyParameterSensitivity.of(NAME1, ImmutableList.of(), USD, DoubleArray.of());
CurrencyParameterSensitivity base2 = CurrencyParameterSensitivity.of(NAME2, ImmutableList.of(), USD, DoubleArray.of());
CurrencyParameterSensitivity test = CurrencyParameterSensitivity.combine(NAME_COMBINED, base1, base2);
assertEquals(test.getMarketDataName(), NAME_COMBINED);
assertEquals(test.getParameterCount(), 0);
assertEquals(test.getParameterMetadata(), ImmutableList.of());
assertEquals(test.getSensitivity(), DoubleArray.EMPTY);
assertEquals(test.getParameterSplit(), Optional.empty());
}

public void test_combine_arraySize0() {
assertThrowsIllegalArg(() -> CurrencyParameterSensitivity.combine(NAME_COMBINED));
}

public void test_combine_arraySize1() {
CurrencyParameterSensitivity base = CurrencyParameterSensitivity.of(NAME1, METADATA_USD1, USD, VECTOR_USD1);
assertThrowsIllegalArg(() -> CurrencyParameterSensitivity.combine(NAME_COMBINED, base));
CurrencyParameterSensitivity test = CurrencyParameterSensitivity.combine(NAME_COMBINED, base);
assertEquals(test.getMarketDataName(), NAME_COMBINED);
assertEquals(test.getParameterCount(), VECTOR_USD1.size());
assertEquals(test.getParameterMetadata(), METADATA_USD1);
assertEquals(test.getSensitivity(), VECTOR_USD1);
assertEquals(test.getParameterSplit(), Optional.of(ImmutableList.of(PARAM1)));
}

public void test_combine_arraySize1_matchingName() {
CurrencyParameterSensitivity base = CurrencyParameterSensitivity.of(NAME1, METADATA_USD1, USD, VECTOR_USD1);
CurrencyParameterSensitivity test = CurrencyParameterSensitivity.combine(NAME1, base);
assertEquals(test, base);
}

public void test_combine_duplicateNames() {
Expand Down