/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.sesame.marketdata;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.opengamma.core.link.ConfigLink;
import com.opengamma.core.value.MarketDataRequirementNames;
import com.opengamma.engine.target.ComputationTargetType;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.financial.currency.CurrencyMatrix;
import com.opengamma.financial.currency.CurrencyPair;
import com.opengamma.financial.currency.SimpleCurrencyMatrix;
import com.opengamma.id.ExternalId;
import com.opengamma.sesame.marketdata.builders.FxRateMarketDataBuilder;
import com.opengamma.sesame.marketdata.scenarios.CurrencyPairFilter;
import com.opengamma.sesame.marketdata.scenarios.CyclePerturbations;
import com.opengamma.sesame.marketdata.scenarios.FxRateShift;
import com.opengamma.sesame.marketdata.scenarios.MarketDataFilter;
import com.opengamma.sesame.marketdata.scenarios.Perturbation;
import com.opengamma.sesame.marketdata.scenarios.SinglePerturbationMapping;
import com.opengamma.sesame.marketdata.scenarios.SingleScenarioDefinition;
import com.opengamma.timeseries.date.DateTimeSeries;
import com.opengamma.timeseries.date.localdate.ImmutableLocalDateDoubleTimeSeries;
import com.opengamma.timeseries.date.localdate.LocalDateDoubleTimeSeries;
import com.opengamma.timeseries.date.localdate.LocalDateDoubleTimeSeriesBuilder;
import com.opengamma.util.money.Currency;
import com.opengamma.util.result.Result;
import com.opengamma.util.test.TestGroup;
import com.opengamma.util.time.LocalDateRange;
import org.testng.annotations.Test;
import org.threeten.bp.LocalDate;
import org.threeten.bp.ZonedDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static com.opengamma.util.result.ResultTestUtils.assertSuccess;
import static org.mockito.Mockito.mock;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertTrue;
@Test(groups = TestGroup.UNIT)
public class FxRateMarketDataBuilderTest {
private static final double TOLERANCE = 0.00001;
private static final FieldName MARKET_VALUE = FieldName.of(MarketDataRequirementNames.MARKET_VALUE);
private static final double GBPUSD_RATE = 1.61;
private static final double USDCHF_RATE = 0.91;
private static final double EURUSD_RATE = 1.35;
private static final CyclePerturbations EMPTY_PERTURBATIONS =
new CyclePerturbations(ImmutableSet.<MarketDataRequirement>of(), SingleScenarioDefinition.base());
private static SingleValueRequirement singleValueRequirement(String currencyPair) {
return SingleValueRequirement.of(FxRateId.of(CurrencyPair.parse(currencyPair)));
}
private static TimeSeriesRequirement timeSeriesRequirement(String currencyPair, LocalDateRange dateRange) {
return TimeSeriesRequirement.of(FxRateId.of(CurrencyPair.parse(currencyPair)), dateRange);
}
public void fixedRate() {
SimpleCurrencyMatrix matrix = new SimpleCurrencyMatrix();
matrix.setFixedConversion(Currency.GBP, Currency.USD, GBPUSD_RATE);
FxRateMarketDataBuilder builder = new FxRateMarketDataBuilder(ConfigLink.<CurrencyMatrix>resolved(matrix));
MarketDataBundle emptyBundle = MarketDataEnvironmentBuilder.empty().toBundle();
SingleValueRequirement gbpUsd = singleValueRequirement("GBP/USD");
SingleValueRequirement usdGbp = singleValueRequirement("USD/GBP");
Set<SingleValueRequirement> requirements = ImmutableSet.of(gbpUsd, usdGbp);
MarketDataSource marketDataSource = mock(MarketDataSource.class);
Map<SingleValueRequirement, Result<?>> values =
builder.buildSingleValues(emptyBundle, ZonedDateTime.now(), requirements, marketDataSource, EMPTY_PERTURBATIONS);
Result<?> gbpUsdResult = values.get(gbpUsd);
assertSuccess(gbpUsdResult);
assertEquals(GBPUSD_RATE, (Double) gbpUsdResult.getValue(), TOLERANCE);
Result<?> usdGbpResult = values.get(usdGbp);
assertSuccess(usdGbpResult);
assertEquals(1 / GBPUSD_RATE, (Double) usdGbpResult.getValue(), TOLERANCE);
}
public void lookUpRate() {
SimpleCurrencyMatrix matrix = new SimpleCurrencyMatrix();
ExternalId rateId = ExternalId.of("x", "GBPUSD");
ValueRequirement valueReq = new ValueRequirement(MARKET_VALUE.getName(), ComputationTargetType.PRIMITIVE, rateId);
matrix.setLiveData(Currency.GBP, Currency.USD, valueReq);
FxRateMarketDataBuilder builder = new FxRateMarketDataBuilder(ConfigLink.<CurrencyMatrix>resolved(matrix));
MarketDataSource marketDataSource = mock(MarketDataSource.class);
ZonedDateTime valuationTime = ZonedDateTime.now();
MarketDataBundle bundle =
new MarketDataEnvironmentBuilder()
.add(RawId.of(rateId.toBundle()), GBPUSD_RATE)
.valuationTime(valuationTime)
.build()
.toBundle();
SingleValueRequirement gbpUsd = singleValueRequirement("GBP/USD");
SingleValueRequirement usdGbp = singleValueRequirement("USD/GBP");
Set<SingleValueRequirement> requirements = ImmutableSet.of(gbpUsd, usdGbp);
Map<SingleValueRequirement, Result<?>> values =
builder.buildSingleValues(bundle, valuationTime, requirements, marketDataSource, EMPTY_PERTURBATIONS);
Result<?> gbpUsdResult = values.get(gbpUsd);
assertSuccess(gbpUsdResult);
assertEquals(GBPUSD_RATE, (Double) gbpUsdResult.getValue(), TOLERANCE);
Result<?> usdGbpResult = values.get(usdGbp);
assertSuccess(usdGbpResult);
assertEquals(1 / GBPUSD_RATE, (Double) usdGbpResult.getValue(), TOLERANCE);
}
public void crossFixed() {
SimpleCurrencyMatrix matrix = new SimpleCurrencyMatrix();
matrix.setFixedConversion(Currency.USD, Currency.CHF, USDCHF_RATE);
matrix.setFixedConversion(Currency.EUR, Currency.USD, EURUSD_RATE);
matrix.setCrossConversion(Currency.EUR, Currency.CHF, Currency.USD);
FxRateMarketDataBuilder builder = new FxRateMarketDataBuilder(ConfigLink.<CurrencyMatrix>resolved(matrix));
SingleValueRequirement eurChf = singleValueRequirement("EUR/CHF");
SingleValueRequirement chfEur = singleValueRequirement("CHF/EUR");
Set<SingleValueRequirement> requirements = ImmutableSet.of(eurChf, chfEur);
MarketDataBundle bundle = MarketDataEnvironmentBuilder.empty().toBundle();
MarketDataSource marketDataSource = mock(MarketDataSource.class);
Map<SingleValueRequirement, Result<?>> values =
builder.buildSingleValues(bundle, ZonedDateTime.now(), requirements, marketDataSource, EMPTY_PERTURBATIONS);
Result<?> eurChfResult = values.get(eurChf);
assertSuccess(eurChfResult);
assertEquals(USDCHF_RATE * EURUSD_RATE, (Double) eurChfResult.getValue(), TOLERANCE);
Result<?> chfEurResult = values.get(chfEur);
assertSuccess(chfEurResult);
assertEquals(1 / (USDCHF_RATE * EURUSD_RATE), (Double) chfEurResult.getValue(), TOLERANCE);
}
public void crossLookup() {
SimpleCurrencyMatrix matrix = new SimpleCurrencyMatrix();
ExternalId usdchfRateId = ExternalId.of("x", "USDCHF");
ValueRequirement usdchfReq = new ValueRequirement(MARKET_VALUE.getName(), ComputationTargetType.PRIMITIVE, usdchfRateId);
matrix.setLiveData(Currency.USD, Currency.CHF, usdchfReq);
double usdchfValue = USDCHF_RATE;
ExternalId eurusdRateId = ExternalId.of("x", "EURUSD");
ValueRequirement eurusdReq = new ValueRequirement(MARKET_VALUE.getName(), ComputationTargetType.PRIMITIVE, eurusdRateId);
matrix.setLiveData(Currency.EUR, Currency.USD, eurusdReq);
double eurusdValue = EURUSD_RATE;
matrix.setCrossConversion(Currency.EUR, Currency.CHF, Currency.USD);
FxRateMarketDataBuilder builder = new FxRateMarketDataBuilder(ConfigLink.<CurrencyMatrix>resolved(matrix));
ZonedDateTime valuationTime = ZonedDateTime.now();
MarketDataBundle bundle =
new MarketDataEnvironmentBuilder()
.add(RawId.of(usdchfRateId.toBundle()), usdchfValue)
.add(RawId.of(eurusdRateId.toBundle()), eurusdValue)
.valuationTime(valuationTime)
.build()
.toBundle();
SingleValueRequirement eurChf = singleValueRequirement("EUR/CHF");
SingleValueRequirement chfEur = singleValueRequirement("CHF/EUR");
Set<SingleValueRequirement> requirements = ImmutableSet.of(eurChf, chfEur);
MarketDataSource marketDataSource = mock(MarketDataSource.class);
Map<SingleValueRequirement, Result<?>> values =
builder.buildSingleValues(bundle, valuationTime, requirements, marketDataSource, EMPTY_PERTURBATIONS);
Result<?> eurChfResult = values.get(eurChf);
assertSuccess(eurChfResult);
assertEquals(USDCHF_RATE * EURUSD_RATE, (Double) eurChfResult.getValue(), TOLERANCE);
Result<?> chfEurResult = values.get(chfEur);
assertSuccess(chfEurResult);
assertEquals(1 / (USDCHF_RATE * EURUSD_RATE), (Double) chfEurResult.getValue(), TOLERANCE);
}
public void getTimeSeriesRequirements() {
SimpleCurrencyMatrix matrix = new SimpleCurrencyMatrix();
ExternalId rateId = ExternalId.of("x", "GBPUSD");
ValueRequirement valueReq = new ValueRequirement(MARKET_VALUE.getName(), ComputationTargetType.PRIMITIVE, rateId);
matrix.setLiveData(Currency.GBP, Currency.USD, valueReq);
FxRateMarketDataBuilder builder = new FxRateMarketDataBuilder(ConfigLink.<CurrencyMatrix>resolved(matrix));
LocalDateRange dateRange = LocalDateRange.of(LocalDate.of(2010, 5, 17), LocalDate.of(2012, 6, 4), true);
FxRateId fxRateId = FxRateId.of(Currency.GBP, Currency.USD);
TimeSeriesRequirement requirement = TimeSeriesRequirement.of(fxRateId, dateRange);
Map<MarketDataId<?>, DateTimeSeries<LocalDate, ?>> suppliedData = ImmutableMap.of();
Set<MarketDataRequirement> requirements = builder.getTimeSeriesRequirements(requirement, suppliedData);
assertEquals(1, requirements.size());
MarketDataRequirement rawReq = requirements.iterator().next();
assertTrue(rawReq instanceof TimeSeriesRequirement);
MarketDataId marketDataId = rawReq.getMarketDataId();
assertTrue(marketDataId instanceof RawId);
assertEquals(rateId.toBundle(), ((RawId) marketDataId).getId());
assertEquals(dateRange, rawReq.getMarketDataTime().getDateRange());
FxRateId inverseFxRateId = FxRateId.of(Currency.GBP, Currency.USD);
TimeSeriesRequirement inverseRequirement = TimeSeriesRequirement.of(inverseFxRateId, dateRange);
Set<MarketDataRequirement> inverseRequirements = builder.getTimeSeriesRequirements(inverseRequirement, suppliedData);
assertEquals(1, inverseRequirements.size());
MarketDataRequirement inverseRawReq = requirements.iterator().next();
assertTrue(inverseRawReq instanceof TimeSeriesRequirement);
MarketDataId inverseMarketDataId = inverseRawReq.getMarketDataId();
assertTrue(inverseMarketDataId instanceof RawId);
assertEquals(rateId.toBundle(), ((RawId) inverseMarketDataId).getId());
assertEquals(dateRange, inverseRawReq.getMarketDataTime().getDateRange());
}
/**
* checks that no requirements are returned if the supplied data contains the inverse rate over the required
* date range
*/
public void getTimeSeriesRequirementsInverseRateSupplied() {
SimpleCurrencyMatrix matrix = new SimpleCurrencyMatrix();
ExternalId rateId = ExternalId.of("x", "GBPUSD");
FxRateId fxRateId = FxRateId.of(Currency.GBP, Currency.USD);
FxRateId inverseRateId = FxRateId.of(Currency.USD, Currency.GBP);
ValueRequirement valueReq = new ValueRequirement(MARKET_VALUE.getName(), ComputationTargetType.PRIMITIVE, rateId);
matrix.setLiveData(Currency.GBP, Currency.USD, valueReq);
FxRateMarketDataBuilder builder = new FxRateMarketDataBuilder(ConfigLink.<CurrencyMatrix>resolved(matrix));
LocalDateRange dateRange = LocalDateRange.of(LocalDate.of(2011, 5, 17), LocalDate.of(2011, 6, 4), true);
LocalDateDoubleTimeSeriesBuilder timeSeriesBuilder = ImmutableLocalDateDoubleTimeSeries.builder();
timeSeriesBuilder.put(LocalDate.of(2010, 5, 17), 1);
timeSeriesBuilder.put(LocalDate.of(2012, 6, 4), 2);
DateTimeSeries<LocalDate, Double> timeSeries = timeSeriesBuilder.build();
Map<MarketDataId<?>, DateTimeSeries<LocalDate, ?>> suppliedData =
ImmutableMap.<MarketDataId<?>, DateTimeSeries<LocalDate, ?>>of(inverseRateId, timeSeries);
TimeSeriesRequirement requirement = TimeSeriesRequirement.of(fxRateId, dateRange);
Set<MarketDataRequirement> requirements = builder.getTimeSeriesRequirements(requirement, suppliedData);
assertTrue(requirements.isEmpty());
}
/**
* checks that no requirements are returned if the supplied data contains the inverse rate but not over the required
* date range
*/
public void getTimeSeriesRequirementsInverseRateSuppliedWrongRange() {
SimpleCurrencyMatrix matrix = new SimpleCurrencyMatrix();
ExternalId rateId = ExternalId.of("x", "GBPUSD");
FxRateId fxRateId = FxRateId.of(Currency.GBP, Currency.USD);
FxRateId inverseRateId = FxRateId.of(Currency.USD, Currency.GBP);
ValueRequirement valueReq = new ValueRequirement(MARKET_VALUE.getName(), ComputationTargetType.PRIMITIVE, rateId);
matrix.setLiveData(Currency.GBP, Currency.USD, valueReq);
FxRateMarketDataBuilder builder = new FxRateMarketDataBuilder(ConfigLink.<CurrencyMatrix>resolved(matrix));
LocalDateRange dateRange = LocalDateRange.of(LocalDate.of(2009, 5, 17), LocalDate.of(2011, 6, 4), true);
LocalDateDoubleTimeSeriesBuilder timeSeriesBuilder = ImmutableLocalDateDoubleTimeSeries.builder();
timeSeriesBuilder.put(LocalDate.of(2010, 5, 17), 1);
timeSeriesBuilder.put(LocalDate.of(2012, 6, 4), 2);
DateTimeSeries<LocalDate, Double> timeSeries = timeSeriesBuilder.build();
Map<MarketDataId<?>, DateTimeSeries<LocalDate, ?>> suppliedData =
ImmutableMap.<MarketDataId<?>, DateTimeSeries<LocalDate, ?>>of(inverseRateId, timeSeries);
TimeSeriesRequirement requirement = TimeSeriesRequirement.of(fxRateId, dateRange);
Set<MarketDataRequirement> requirements = builder.getTimeSeriesRequirements(requirement, suppliedData);
assertEquals(1, requirements.size());
MarketDataRequirement rawReq = requirements.iterator().next();
assertTrue(rawReq instanceof TimeSeriesRequirement);
MarketDataId marketDataId = rawReq.getMarketDataId();
assertTrue(marketDataId instanceof RawId);
assertEquals(rateId.toBundle(), ((RawId) marketDataId).getId());
assertEquals(dateRange, rawReq.getMarketDataTime().getDateRange());
}
public void lookUpTimeSeries() {
LocalDateDoubleTimeSeriesBuilder timeSeriesBuilder = ImmutableLocalDateDoubleTimeSeries.builder();
LocalDate date1 = LocalDate.of(2010, 5, 17);
LocalDate date2 = LocalDate.of(2011, 5, 17);
LocalDate date3 = LocalDate.of(2012, 5, 17);
timeSeriesBuilder.put(date1, 1);
timeSeriesBuilder.put(date2, 2);
timeSeriesBuilder.put(date3, 3);
DateTimeSeries<LocalDate, Double> timeSeries = timeSeriesBuilder.build();
SimpleCurrencyMatrix matrix = new SimpleCurrencyMatrix();
ExternalId rateId = ExternalId.of("x", "GBPUSD");
FxRateId fxRateId = FxRateId.of(Currency.GBP, Currency.USD);
ValueRequirement valueReq = new ValueRequirement(MARKET_VALUE.getName(), ComputationTargetType.PRIMITIVE, rateId);
matrix.setLiveData(Currency.GBP, Currency.USD, valueReq);
FxRateMarketDataBuilder builder = new FxRateMarketDataBuilder(ConfigLink.<CurrencyMatrix>resolved(matrix));
MarketDataEnvironment marketData =
new MarketDataEnvironmentBuilder()
.add(RawId.of(rateId.toBundle()), timeSeries)
.valuationTime(ZonedDateTime.now())
.build();
LocalDateRange dateRange = LocalDateRange.of(date1, date3, true);
TimeSeriesRequirement requirement = TimeSeriesRequirement.of(fxRateId, dateRange);
Set<TimeSeriesRequirement> requirements = ImmutableSet.of(requirement);
Map<TimeSeriesRequirement, Result<? extends DateTimeSeries<LocalDate, ?>>> timeSeriesMap =
builder.buildTimeSeries(
marketData.toBundle(),
requirements,
new EmptyMarketDataFactory.DataSource(),
EMPTY_PERTURBATIONS);
Result<? extends DateTimeSeries<LocalDate, ?>> timeSeriesResult = timeSeriesMap.get(requirement);
assertSuccess(timeSeriesResult);
DateTimeSeries<LocalDate, ?> rateTimeSeries = timeSeriesResult.getValue();
assertEquals(1d, rateTimeSeries.getValue(date1));
assertEquals(2d, rateTimeSeries.getValue(date2));
assertEquals(3d, rateTimeSeries.getValue(date3));
}
public void lookUpTimeSeriesInverse() {
LocalDate date1 = LocalDate.of(2010, 5, 17);
LocalDate date2 = LocalDate.of(2011, 5, 17);
LocalDate date3 = LocalDate.of(2012, 5, 17);
LocalDateDoubleTimeSeries timeSeries =
ImmutableLocalDateDoubleTimeSeries.builder()
.put(date1, 1)
.put(date2, 2)
.put(date3, 3)
.build();
SimpleCurrencyMatrix matrix = new SimpleCurrencyMatrix();
ExternalId rateId = ExternalId.of("x", "GBPUSD");
FxRateId fxRateId = FxRateId.of(Currency.USD, Currency.GBP);
ValueRequirement valueReq = new ValueRequirement(MARKET_VALUE.getName(), ComputationTargetType.PRIMITIVE, rateId);
matrix.setLiveData(Currency.GBP, Currency.USD, valueReq);
FxRateMarketDataBuilder builder = new FxRateMarketDataBuilder(ConfigLink.<CurrencyMatrix>resolved(matrix));
MarketDataEnvironment marketData =
new MarketDataEnvironmentBuilder()
.add(RawId.of(rateId.toBundle()), timeSeries)
.valuationTime(ZonedDateTime.now())
.build();
LocalDateRange dateRange = LocalDateRange.of(date1, date3, true);
TimeSeriesRequirement requirement = TimeSeriesRequirement.of(fxRateId, dateRange);
Set<TimeSeriesRequirement> requirements = ImmutableSet.of(requirement);
Map<TimeSeriesRequirement, Result<? extends DateTimeSeries<LocalDate, ?>>> timeSeriesMap =
builder.buildTimeSeries(
marketData.toBundle(),
requirements,
new EmptyMarketDataFactory.DataSource(),
EMPTY_PERTURBATIONS);
Result<? extends DateTimeSeries<LocalDate, ?>> timeSeriesResult = timeSeriesMap.get(requirement);
assertSuccess(timeSeriesResult);
DateTimeSeries<LocalDate, ?> rateTimeSeries = timeSeriesResult.getValue();
assertEquals(1 / 1d, rateTimeSeries.getValue(date1));
assertEquals(1 / 2d, rateTimeSeries.getValue(date2));
assertEquals(1 / 3d, rateTimeSeries.getValue(date3));
}
public void crossTimeSeries() {
LocalDate date1 = LocalDate.of(2010, 5, 17);
LocalDate date2 = LocalDate.of(2011, 5, 17);
LocalDate date3 = LocalDate.of(2012, 5, 17);
LocalDateRange dateRange = LocalDateRange.of(date1, date3, true);
LocalDateDoubleTimeSeries usdChfSeries =
ImmutableLocalDateDoubleTimeSeries.builder().put(date1, 1).put(date2, 2).put(date3, 3).build();
LocalDateDoubleTimeSeries eurUsdSeries =
ImmutableLocalDateDoubleTimeSeries.builder().put(date1, 2).put(date2, 4).put(date3, 6).build();
SimpleCurrencyMatrix matrix = new SimpleCurrencyMatrix();
ExternalId usdChfId = ExternalId.of("x", "USDCHF");
ValueRequirement usdChfValueReq =
new ValueRequirement(MARKET_VALUE.getName(), ComputationTargetType.PRIMITIVE, usdChfId);
matrix.setLiveData(Currency.USD, Currency.CHF, usdChfValueReq);
ExternalId eurUsdId = ExternalId.of("x", "EURUSD");
ValueRequirement eurUsdValueReq =
new ValueRequirement(MARKET_VALUE.getName(), ComputationTargetType.PRIMITIVE, eurUsdId);
matrix.setLiveData(Currency.EUR, Currency.USD, eurUsdValueReq);
matrix.setCrossConversion(Currency.EUR, Currency.CHF, Currency.USD);
FxRateMarketDataBuilder builder = new FxRateMarketDataBuilder(ConfigLink.<CurrencyMatrix>resolved(matrix));
RawId usdChfFxRateId = RawId.of(usdChfId.toBundle());
RawId eurUsdFxRateId = RawId.of(eurUsdId.toBundle());
TimeSeriesRequirement eurChf = timeSeriesRequirement("EUR/CHF", dateRange);
TimeSeriesRequirement chfEur = timeSeriesRequirement("CHF/EUR", dateRange);
Set<TimeSeriesRequirement> requirements = ImmutableSet.of(eurChf, chfEur);
MarketDataBundle bundle =
new MarketDataEnvironmentBuilder()
.add(eurUsdFxRateId, eurUsdSeries)
.add(usdChfFxRateId, usdChfSeries)
.valuationTime(ZonedDateTime.now())
.build()
.toBundle();
MarketDataSource marketDataSource = mock(MarketDataSource.class);
Map<TimeSeriesRequirement, Result<? extends DateTimeSeries<LocalDate, ?>>> values =
builder.buildTimeSeries(bundle, requirements, marketDataSource, EMPTY_PERTURBATIONS);
Result<? extends DateTimeSeries<LocalDate, ?>> eurChfResult = values.get(eurChf);
assertSuccess(eurChfResult);
DateTimeSeries<LocalDate, ?> eurChfSeries = eurChfResult.getValue();
assertEquals(2d, (Double) eurChfSeries.getValue(date1), TOLERANCE);
assertEquals(8d, (Double) eurChfSeries.getValue(date2), TOLERANCE);
assertEquals(18d, (Double) eurChfSeries.getValue(date3), TOLERANCE);
Result<? extends DateTimeSeries<LocalDate, ?>> chfEurResult = values.get(chfEur);
assertSuccess(chfEurResult);
DateTimeSeries<LocalDate, ?> chfEurSeries = chfEurResult.getValue();
assertEquals(1 / 2d, (Double) chfEurSeries.getValue(date1), TOLERANCE);
assertEquals(1 / 8d, (Double) chfEurSeries.getValue(date2), TOLERANCE);
assertEquals(1 / 18d, (Double) chfEurSeries.getValue(date3), TOLERANCE);
}
public void shiftFixed() {
SimpleCurrencyMatrix matrix = new SimpleCurrencyMatrix();
matrix.setFixedConversion(Currency.GBP, Currency.USD, GBPUSD_RATE);
FxRateMarketDataBuilder builder = new FxRateMarketDataBuilder(ConfigLink.<CurrencyMatrix>resolved(matrix));
MarketDataBundle emptyBundle = MarketDataEnvironmentBuilder.empty().toBundle();
SingleValueRequirement gbpUsd = singleValueRequirement("GBP/USD");
SingleValueRequirement usdGbp = singleValueRequirement("USD/GBP");
Set<SingleValueRequirement> requirements = ImmutableSet.of(gbpUsd, usdGbp);
MarketDataFilter filter = new CurrencyPairFilter(Currency.GBP, Currency.USD);
Perturbation perturbation = FxRateShift.absolute(0.1);
SinglePerturbationMapping mapping = SinglePerturbationMapping.of(filter, perturbation);
List<SinglePerturbationMapping> mappings = ImmutableList.of(mapping);
SingleScenarioDefinition scenario = SingleScenarioDefinition.of("scenarioName", mappings);
CyclePerturbations perturbations = new CyclePerturbations(requirements, scenario);
MarketDataSource marketDataSource = mock(MarketDataSource.class);
Map<SingleValueRequirement, Result<?>> values =
builder.buildSingleValues(emptyBundle, ZonedDateTime.now(), requirements, marketDataSource, perturbations);
Result<?> gbpUsdResult = values.get(gbpUsd);
assertSuccess(gbpUsdResult);
assertEquals(GBPUSD_RATE + 0.1, (Double) gbpUsdResult.getValue(), TOLERANCE);
Result<?> usdGbpResult = values.get(usdGbp);
assertSuccess(usdGbpResult);
assertEquals(1 / (GBPUSD_RATE + 0.1), (Double) usdGbpResult.getValue(), TOLERANCE);
}
public void shiftLookup() {
SimpleCurrencyMatrix matrix = new SimpleCurrencyMatrix();
ExternalId rateId = ExternalId.of("x", "GBPUSD");
ValueRequirement valueReq = new ValueRequirement(MARKET_VALUE.getName(), ComputationTargetType.PRIMITIVE, rateId);
matrix.setLiveData(Currency.GBP, Currency.USD, valueReq);
FxRateMarketDataBuilder builder = new FxRateMarketDataBuilder(ConfigLink.<CurrencyMatrix>resolved(matrix));
MarketDataSource marketDataSource = mock(MarketDataSource.class);
ZonedDateTime valuationTime = ZonedDateTime.now();
MarketDataBundle bundle =
new MarketDataEnvironmentBuilder()
.add(RawId.of(rateId.toBundle()), GBPUSD_RATE)
.valuationTime(valuationTime)
.build()
.toBundle();
SingleValueRequirement gbpUsd = singleValueRequirement("GBP/USD");
SingleValueRequirement usdGbp = singleValueRequirement("USD/GBP");
Set<SingleValueRequirement> requirements = ImmutableSet.of(gbpUsd, usdGbp);
MarketDataFilter filter = new CurrencyPairFilter(Currency.GBP, Currency.USD);
Perturbation perturbation = FxRateShift.absolute(0.1);
SinglePerturbationMapping mapping = SinglePerturbationMapping.of(filter, perturbation);
List<SinglePerturbationMapping> mappings = ImmutableList.of(mapping);
SingleScenarioDefinition scenario = SingleScenarioDefinition.of("scenarioName", mappings);
CyclePerturbations perturbations = new CyclePerturbations(requirements, scenario);
Map<SingleValueRequirement, Result<?>> values =
builder.buildSingleValues(bundle, valuationTime, requirements, marketDataSource, perturbations);
Result<?> gbpUsdResult = values.get(gbpUsd);
assertSuccess(gbpUsdResult);
assertEquals(GBPUSD_RATE + 0.1, (Double) gbpUsdResult.getValue(), TOLERANCE);
Result<?> usdGbpResult = values.get(usdGbp);
assertSuccess(usdGbpResult);
assertEquals(1 / (GBPUSD_RATE + 0.1), (Double) usdGbpResult.getValue(), TOLERANCE);
}
/**
* Tests that shifting the rates underlying a cross rate has the expected effect on the derived cross rate
*/
public void shiftCrossUnderlying() {
SimpleCurrencyMatrix matrix = new SimpleCurrencyMatrix();
matrix.setFixedConversion(Currency.USD, Currency.CHF, USDCHF_RATE);
matrix.setFixedConversion(Currency.EUR, Currency.USD, EURUSD_RATE);
matrix.setCrossConversion(Currency.EUR, Currency.CHF, Currency.USD);
FxRateMarketDataBuilder builder = new FxRateMarketDataBuilder(ConfigLink.<CurrencyMatrix>resolved(matrix));
SingleValueRequirement eurChf = singleValueRequirement("EUR/CHF");
SingleValueRequirement chfEur = singleValueRequirement("CHF/EUR");
Set<SingleValueRequirement> requirements = ImmutableSet.of(eurChf, chfEur);
MarketDataFilter usdChfFilter = new CurrencyPairFilter(Currency.USD, Currency.CHF);
Perturbation usdChfPerturbation = FxRateShift.relative(0.1);
SinglePerturbationMapping usdChfMapping = SinglePerturbationMapping.of(usdChfFilter, usdChfPerturbation);
MarketDataFilter eurUsdFilter = new CurrencyPairFilter(Currency.EUR, Currency.USD);
Perturbation eurUsdPerturbation = FxRateShift.relative(0.2);
SinglePerturbationMapping eurUsdMapping = SinglePerturbationMapping.of(eurUsdFilter, eurUsdPerturbation);
List<SinglePerturbationMapping> mappings = ImmutableList.of(usdChfMapping, eurUsdMapping);
SingleScenarioDefinition scenario = SingleScenarioDefinition.of("scenarioName", mappings);
CyclePerturbations perturbations = new CyclePerturbations(requirements, scenario);
MarketDataBundle bundle = MarketDataEnvironmentBuilder.empty().toBundle();
MarketDataSource marketDataSource = mock(MarketDataSource.class);
Map<SingleValueRequirement, Result<?>> values =
builder.buildSingleValues(bundle, ZonedDateTime.now(), requirements, marketDataSource, perturbations);
Result<?> eurChfResult = values.get(eurChf);
assertSuccess(eurChfResult);
assertEquals(USDCHF_RATE * 1.1 * EURUSD_RATE * 1.2, (Double) eurChfResult.getValue(), TOLERANCE);
Result<?> chfEurResult = values.get(chfEur);
assertSuccess(chfEurResult);
assertEquals(1 / (USDCHF_RATE * 1.1 * EURUSD_RATE * 1.2), (Double) chfEurResult.getValue(), TOLERANCE);
}
/**
* Tests that applying a shift to a cross rate returns a failure. Shifting cross rates isn't supported because
* it would introduce inconsistent rates. The underlying observable rates should be shifted.
*/
public void shiftCross() {
SimpleCurrencyMatrix matrix = new SimpleCurrencyMatrix();
ExternalId usdchfRateId = ExternalId.of("x", "USDCHF");
ValueRequirement usdchfReq = new ValueRequirement(MARKET_VALUE.getName(), ComputationTargetType.PRIMITIVE, usdchfRateId);
matrix.setLiveData(Currency.USD, Currency.CHF, usdchfReq);
double usdchfValue = USDCHF_RATE;
ExternalId eurusdRateId = ExternalId.of("x", "EURUSD");
ValueRequirement eurusdReq = new ValueRequirement(MARKET_VALUE.getName(), ComputationTargetType.PRIMITIVE, eurusdRateId);
matrix.setLiveData(Currency.EUR, Currency.USD, eurusdReq);
double eurusdValue = EURUSD_RATE;
matrix.setCrossConversion(Currency.EUR, Currency.CHF, Currency.USD);
FxRateMarketDataBuilder builder = new FxRateMarketDataBuilder(ConfigLink.<CurrencyMatrix>resolved(matrix));
ZonedDateTime valuationTime = ZonedDateTime.now();
MarketDataBundle bundle =
new MarketDataEnvironmentBuilder()
.add(RawId.of(usdchfRateId.toBundle()), usdchfValue)
.add(RawId.of(eurusdRateId.toBundle()), eurusdValue)
.valuationTime(valuationTime)
.build()
.toBundle();
SingleValueRequirement eurChf = singleValueRequirement("EUR/CHF");
SingleValueRequirement chfEur = singleValueRequirement("CHF/EUR");
Set<SingleValueRequirement> requirements = ImmutableSet.of(eurChf, chfEur);
MarketDataFilter filter = new CurrencyPairFilter(Currency.EUR, Currency.CHF);
Perturbation perturbation = FxRateShift.absolute(0.1);
SinglePerturbationMapping mapping = SinglePerturbationMapping.of(filter, perturbation);
List<SinglePerturbationMapping> mappings = ImmutableList.of(mapping);
SingleScenarioDefinition scenario = SingleScenarioDefinition.of("scenarioName", mappings);
CyclePerturbations perturbations = new CyclePerturbations(requirements, scenario);
MarketDataSource marketDataSource = mock(MarketDataSource.class);
Map<SingleValueRequirement, Result<?>> values =
builder.buildSingleValues(bundle, valuationTime, requirements, marketDataSource, perturbations);
Result<?> eurChfResult = values.get(eurChf);
assertFalse(eurChfResult.isSuccess());
Result<?> chfEurResult = values.get(chfEur);
assertFalse(chfEurResult.isSuccess());
}
/**
* Tests applying a shift defined using an inverse currency pair compared to the market data.
* The underlying market data is the rate for GBP/USD and the shift is defined to apply to USD/GBP
*/
public void shiftInverse() {
SimpleCurrencyMatrix matrix = new SimpleCurrencyMatrix();
ExternalId rateId = ExternalId.of("x", "GBPUSD");
ValueRequirement valueReq = new ValueRequirement(MARKET_VALUE.getName(), ComputationTargetType.PRIMITIVE, rateId);
matrix.setLiveData(Currency.GBP, Currency.USD, valueReq);
FxRateMarketDataBuilder builder = new FxRateMarketDataBuilder(ConfigLink.<CurrencyMatrix>resolved(matrix));
MarketDataSource marketDataSource = mock(MarketDataSource.class);
ZonedDateTime valuationTime = ZonedDateTime.now();
MarketDataBundle bundle =
new MarketDataEnvironmentBuilder()
.add(RawId.of(rateId.toBundle()), GBPUSD_RATE)
.valuationTime(valuationTime)
.build()
.toBundle();
SingleValueRequirement gbpUsd = singleValueRequirement("GBP/USD");
SingleValueRequirement usdGbp = singleValueRequirement("USD/GBP");
Set<SingleValueRequirement> requirements = ImmutableSet.of(gbpUsd, usdGbp);
// the shift is defined for the inverse pair of the raw market data
MarketDataFilter filter = new CurrencyPairFilter(Currency.USD, Currency.GBP);
Perturbation perturbation = FxRateShift.absolute(0.1);
SinglePerturbationMapping mapping = SinglePerturbationMapping.of(filter, perturbation);
List<SinglePerturbationMapping> mappings = ImmutableList.of(mapping);
SingleScenarioDefinition scenario = SingleScenarioDefinition.of("scenarioName", mappings);
CyclePerturbations perturbations = new CyclePerturbations(requirements, scenario);
Map<SingleValueRequirement, Result<?>> values =
builder.buildSingleValues(bundle, valuationTime, requirements, marketDataSource, perturbations);
Result<?> gbpUsdResult = values.get(gbpUsd);
assertSuccess(gbpUsdResult);
assertEquals(1 / ((1 / GBPUSD_RATE) + 0.1), (Double) gbpUsdResult.getValue(), TOLERANCE);
Result<?> usdGbpResult = values.get(usdGbp);
assertSuccess(usdGbpResult);
assertEquals((1 / GBPUSD_RATE) + 0.1, (Double) usdGbpResult.getValue(), TOLERANCE);
}
/**
* Tests that getting the requirements fails gracefully if there is no configuration in the currency matrix.
*/
public void getRequirementWithMissingConfig() {
SimpleCurrencyMatrix matrix = new SimpleCurrencyMatrix();
FxRateMarketDataBuilder builder = new FxRateMarketDataBuilder(ConfigLink.<CurrencyMatrix>resolved(matrix));
SingleValueRequirement gbpUsd = singleValueRequirement("GBP/USD");
ZonedDateTime valuationTime = ZonedDateTime.now();
Set<MarketDataRequirement> requirements =
builder.getSingleValueRequirements(gbpUsd, valuationTime, ImmutableSet.<MarketDataRequirement>of());
assertTrue(requirements.isEmpty());
}
}