/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.sesame.marketdata; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.threeten.bp.LocalDate; import org.threeten.bp.ZonedDateTime; import com.google.common.collect.Lists; import com.opengamma.analytics.financial.forex.method.FXMatrix; import com.opengamma.financial.currency.CurrencyPair; import com.opengamma.sesame.marketdata.builders.MarketDataBuilder; import com.opengamma.sesame.marketdata.scenarios.CyclePerturbations; import com.opengamma.timeseries.date.DateTimeSeries; import com.opengamma.util.money.Currency; import com.opengamma.util.result.Result; /** * Market data builder that creates matrices of FX rates. */ public class FxMatrixMarketDataBuilder implements MarketDataBuilder { @SuppressWarnings("unchecked") @Override public Set<MarketDataRequirement> getSingleValueRequirements(SingleValueRequirement requirement, ZonedDateTime valuationTime, Set<? extends MarketDataRequirement> suppliedData) { FxMatrixId id = (FxMatrixId) requirement.getMarketDataId(); Set<Currency> currencies = id.getCurrencies(); ArrayList<Currency> currencyList = Lists.newArrayList(currencies); // sort the currencies so the order is predictable. otherwise the currency pairs can be reversed between // runs and the market data requested in the first won't necessarily match what's requested in the second Collections.sort(currencyList); // arbitrarily choose the first currency as the base Iterator<Currency> itr = currencyList.iterator(); Currency baseCurrency = itr.next(); Set<MarketDataRequirement> requirements = new HashSet<>(); while (itr.hasNext()) { CurrencyPair currencyPair = CurrencyPair.of(baseCurrency, itr.next()); FxRateId rateId = FxRateId.of(currencyPair); requirements.add(SingleValueRequirement.of(rateId, requirement.getMarketDataTime())); } return requirements; } @Override public Set<MarketDataRequirement> getTimeSeriesRequirements( TimeSeriesRequirement requirement, Map<MarketDataId<?>, DateTimeSeries<LocalDate, ?>> suppliedData) { // TODO implement getTimeSeriesRequirements() throw new UnsupportedOperationException("getTimeSeriesRequirements not implemented"); } @SuppressWarnings("unchecked") @Override public Map<SingleValueRequirement, Result<?>> buildSingleValues(MarketDataBundle marketDataBundle, ZonedDateTime valuationTime, Set<SingleValueRequirement> requirements, MarketDataSource marketDataSource, CyclePerturbations cyclePerturbations) { Map<SingleValueRequirement, Result<?>> results = new HashMap<>(); for (SingleValueRequirement requirement : requirements) { FxMatrixId id = (FxMatrixId) requirement.getMarketDataId(); Set<Currency> currencies = id.getCurrencies(); results.put(requirement, buildFxMatrix(marketDataBundle, currencies)); } return results; } @Override public Map<TimeSeriesRequirement, Result<? extends DateTimeSeries<LocalDate, ?>>> buildTimeSeries( MarketDataBundle marketDataBundle, Set<TimeSeriesRequirement> requirements, MarketDataSource marketDataSource, CyclePerturbations cyclePerturbations) { // TODO implement return Collections.emptyMap(); } private Result<FXMatrix> buildFxMatrix(MarketDataBundle marketDataBundle, Set<Currency> currencies) { FXMatrix fxMatrix = new FXMatrix(); ArrayList<Currency> currencyList = Lists.newArrayList(currencies); // sort the currencies so the order is predictable. otherwise the currency pairs can be reversed between // runs and the market data requested in the first won't necessarily match what's requested in the second Collections.sort(currencyList); // arbitrarily choose the first currency as the base Iterator<Currency> itr = currencyList.iterator(); Currency baseCurrency = itr.next(); while (itr.hasNext()) { Currency counterCurrency = itr.next(); FxRateId rateId = FxRateId.of(CurrencyPair.of(baseCurrency, counterCurrency)); Result<Double> rate = marketDataBundle.get(rateId, Double.class); if (!rate.isSuccess()) { return Result.failure(rate); } fxMatrix.addCurrency(counterCurrency, baseCurrency, rate.getValue()); } return Result.success(fxMatrix); } @Override public Class<? extends MarketDataId> getKeyType() { return FxMatrixId.class; } }