@Override public synchronized YieldCurveDefinitionDocument get( ObjectIdentifiable objectIdable, VersionCorrection versionCorrection) { ArgumentChecker.notNull(objectIdable, "objectIdable"); ObjectId objectId = objectIdable.getObjectId(); if (!getUniqueIdScheme().equals(objectId.getScheme())) { throw new DataNotFoundException( "Scheme '" + objectId.getScheme() + "' not valid for '" + getUniqueIdScheme() + "'"); } final int i = objectId.getValue().indexOf('_'); if (i <= 0) { throw new DataNotFoundException( "Identifier '" + objectId.getValue() + "' not valid for '" + getUniqueIdScheme() + "'"); } final String name = objectId.getValue().substring(0, i); final String iso = objectId.getValue().substring(i + 1); final Currency currency; try { currency = Currency.of(iso); } catch (IllegalArgumentException e) { throw new DataNotFoundException( "Identifier '" + objectId.getValue() + "' not valid for '" + getUniqueIdScheme() + "'", e); } final TreeMap<Instant, YieldCurveDefinition> definitions = _definitions.get(Pair.of(currency, name)); if (definitions == null) { throw new DataNotFoundException("Curve definition not found"); } final YieldCurveDefinition definition = definitions.lastEntry().getValue(); if (definition == null) { throw new DataNotFoundException("Curve definition not found"); } return new YieldCurveDefinitionDocument(objectId.atLatestVersion(), definition); }
@Override public IndexON buildObject(final FudgeDeserializer deserializer, final FudgeMsg message) { final String name = message.getString(NAME_FIELD); final Currency currency = Currency.of(message.getString(CURRENCY_FIELD)); final DayCount dayCount = DayCountFactory.INSTANCE.getDayCount(message.getString(DAY_COUNT_FIELD)); final int publicationLag = message.getInt(PUBLICATION_LAG_FIELD); return new IndexON(name, currency, dayCount, publicationLag); }
@Override public synchronized void remove(ObjectIdentifiable objectIdentifiable) { ArgumentChecker.notNull(objectIdentifiable, "objectIdentifiable"); if (!getUniqueIdScheme().equals(objectIdentifiable.getObjectId().getScheme())) { throw new DataNotFoundException( "Scheme '" + objectIdentifiable.getObjectId().getScheme() + "' not valid for '" + getUniqueIdScheme() + "'"); } final int i = objectIdentifiable.getObjectId().getValue().indexOf('_'); if (i <= 0) { throw new DataNotFoundException( "Identifier '" + objectIdentifiable.getObjectId().getValue() + "' not valid for '" + getUniqueIdScheme() + "'"); } final String name = objectIdentifiable.getObjectId().getValue().substring(0, i); final String iso = objectIdentifiable.getObjectId().getValue().substring(i + 1); final Currency currency; try { currency = Currency.of(iso); } catch (IllegalArgumentException e) { throw new DataNotFoundException( "Identifier '" + objectIdentifiable.getObjectId().getValue() + "' not valid for '" + getUniqueIdScheme() + "'", e); } final Pair<Currency, String> key = Pair.of(currency, name); if (_sourceVersionCorrection.getVersionAsOf() != null) { final TreeMap<Instant, YieldCurveDefinition> value = _definitions.get(key); if (value == null) { throw new DataNotFoundException("Curve definition not found"); } // Don't need to keep the old values before the one needed by "versionAsOfInstant" final Instant oldestNeeded = value.floorKey(_sourceVersionCorrection.getVersionAsOf()); if (oldestNeeded != null) { value.headMap(oldestNeeded).clear(); } // Store a null to indicate the delete value.put(Instant.now(), null); } else { if (_definitions.remove(key) == null) { throw new DataNotFoundException("Curve definition not found"); } } changeManager() .entityChanged( ChangeType.REMOVED, objectIdentifiable.getObjectId(), null, null, Instant.now()); }
@SuppressWarnings("synthetic-access") @Override public CurrencyLabelledMatrix1D buildObject( final FudgeDeserializer deserializer, final FudgeMsg message) { final FudgeMsg msg = message.getMessage(MATRIX_FIELD_NAME); final Queue<String> labelTypes = new LinkedList<String>(); final Queue<FudgeField> labelValues = new LinkedList<FudgeField>(); final List<Currency> keys = new LinkedList<Currency>(); final List<Object> labels = new LinkedList<Object>(); final List<Double> values = new LinkedList<Double>(); for (final FudgeField field : msg) { switch (field.getOrdinal()) { case LABEL_TYPE_ORDINAL: labelTypes.add((String) field.getValue()); break; case KEY_ORDINAL: keys.add(Currency.of((String) field.getValue())); break; case LABEL_ORDINAL: labelValues.add(field); break; case VALUE_ORDINAL: values.add((Double) field.getValue()); break; } if (!labelTypes.isEmpty() && !labelValues.isEmpty()) { // Have a type and a value, which can be consumed final String labelType = labelTypes.remove(); Class<?> labelClass; try { labelClass = LabelledMatrix1DBuilder.getLabelClass(labelType, _loadedClasses); } catch (final ClassNotFoundException ex) { throw new OpenGammaRuntimeException( "Could not deserialize label of type " + labelType, ex); } final FudgeField labelValue = labelValues.remove(); final Object label = deserializer.fieldValueToObject(labelClass, labelValue); // labels.add(Currency.of((String) label)); labels.add(label); } } final int matrixSize = keys.size(); final Currency[] keysArray = new Currency[matrixSize]; keys.toArray(keysArray); final Object[] labelsArray = new Object[matrixSize]; labels.toArray(labelsArray); final double[] valuesArray = Doubles.toArray(values); return new CurrencyLabelledMatrix1D(keysArray, labelsArray, valuesArray); }
@Override public IborIndex buildObject(final FudgeDeserializer deserializer, final FudgeMsg message) { final Currency currency = Currency.of(message.getString(CURRENCY_FIELD)); final int spotLag = message.getInt(SPOT_LAG_FIELD); final DayCount dayCount = DayCountFactory.INSTANCE.getDayCount(message.getString(DAY_COUNT_FIELD)); final BusinessDayConvention businessDayConvention = BusinessDayConventionFactory.INSTANCE.getBusinessDayConvention( message.getString(BUSINESS_DAY_CONVENTION_FIELD)); final boolean isEOM = message.getBoolean(EOM_FIELD); final Period tenor = Period.parse(message.getString(TENOR_FIELD)); final String name = message.getString(NAME_FIELD); return new IborIndex(currency, tenor, spotLag, dayCount, businessDayConvention, isEOM, name); }
// ------------------------------------------------------------------------- @Override protected void doRun() { ToolContext toolContext = getToolContext(); CommandLine commandLine = getCommandLine(); boolean verbose = commandLine.hasOption("verbose"); if ((commandLine.hasOption("today") && commandLine.hasOption("yesterday")) || (commandLine.hasOption("date") && commandLine.hasOption("today")) || (commandLine.hasOption("date") && commandLine.hasOption("yesterday"))) { System.err.println("Can only return today OR yesterday OR date!"); System.exit(2); } String ccyStr = commandLine.getOptionValue("ccy"); try { Currency ccy = Currency.of(ccyStr); LocalDate date = null; if (commandLine.hasOption("yesterday")) { date = LocalDate.now().minusDays(1); } else if (commandLine.hasOption("today")) { date = LocalDate.now(); } else if (commandLine.hasOption("date")) { try { date = (LocalDate) DateTimeFormatter.BASIC_ISO_DATE.parse(commandLine.getOptionValue("date")); } catch (Exception e) { System.err.println("Could not parse date, should be YYYYMMDD format"); System.exit(2); } } else { System.err.println("Must specify either today or yesterday option"); System.exit(2); } boolean isHoliday = toolContext.getHolidaySource().isHoliday(date, ccy); if (isHoliday) { if (verbose) { System.out.println("Day was a holiday"); } System.exit(0); } else { if (verbose) { System.out.println("Day was not a holiday"); } System.exit(1); } } catch (IllegalArgumentException iae) { System.err.println("Invalid currency code"); System.exit(2); } }
@Override public MulticurveProviderDiscount buildObject( final FudgeDeserializer deserializer, final FudgeMsg message) { final Map<Currency, YieldAndDiscountCurve> discountingCurves = new LinkedHashMap<>(); final List<FudgeField> currencyFields = message.getAllByName(CURRENCY_FIELD); final List<FudgeField> discountingCurveFields = message.getAllByName(DISCOUNTING_CURVE_FIELD); for (int i = 0; i < currencyFields.size(); i++) { final Currency currency = Currency.of((String) currencyFields.get(i).getValue()); final YieldAndDiscountCurve curve = deserializer.fudgeMsgToObject( YieldAndDiscountCurve.class, (FudgeMsg) discountingCurveFields.get(i).getValue()); discountingCurves.put(currency, curve); } final Map<IborIndex, YieldAndDiscountCurve> forwardIborCurves = new LinkedHashMap<>(); final List<FudgeField> indexIborFields = message.getAllByName(INDEX_IBOR_FIELD); final List<FudgeField> forwardIborCurveFields = message.getAllByName(INDEX_IBOR_CURVE); for (int i = 0; i < currencyFields.size(); i++) { final IborIndex index = deserializer.fudgeMsgToObject( IborIndex.class, (FudgeMsg) indexIborFields.get(i).getValue()); final YieldAndDiscountCurve curve = deserializer.fudgeMsgToObject( YieldAndDiscountCurve.class, (FudgeMsg) forwardIborCurveFields.get(i).getValue()); forwardIborCurves.put(index, curve); } final Map<IndexON, YieldAndDiscountCurve> forwardONCurves = new LinkedHashMap<>(); final List<FudgeField> indexONFields = message.getAllByName(INDEX_ON_FIELD); final List<FudgeField> forwardONCurveFields = message.getAllByName(OVERNIGHT_CURVE_FIELD); for (int i = 0; i < currencyFields.size(); i++) { final IndexON index = deserializer.fudgeMsgToObject( IndexON.class, (FudgeMsg) indexONFields.get(i).getValue()); final YieldAndDiscountCurve curve = deserializer.fudgeMsgToObject( YieldAndDiscountCurve.class, (FudgeMsg) forwardONCurveFields.get(i).getValue()); forwardONCurves.put(index, curve); } final FXMatrix fxMatrix = deserializer.fieldValueToObject(FXMatrix.class, message.getByName(FX_MATRIX_FIELD)); return new MulticurveProviderDiscount( discountingCurves, forwardIborCurves, forwardONCurves, fxMatrix); }
@Override public FXMatrix buildObject(final FudgeDeserializer deserializer, final FudgeMsg message) { final List<FudgeField> currencies = message.getAllByName(CURRENCY_FIELD); final List<FudgeField> orders = message.getAllByName(ORDER_FIELD); final Map<Currency, Integer> map = new HashMap<>(); for (int i = 0; i < currencies.size(); i++) { final Currency currency = Currency.of((String) currencies.get(i).getValue()); final Integer order = ((Number) orders.get(i).getValue()).intValue(); map.put(currency, order); } final List<FudgeField> entries = message.getAllByName(ENTRIES_FIELD); final List<FudgeField> arrays = message.getAllByName(FX_RATES_FIELD); final double[][] fxRates = new double[entries.size()][]; for (int i = 0; i < entries.size(); i++) { final FudgeMsg msg = (FudgeMsg) arrays.get(i).getValue(); final double[] row = deserializer.fieldValueToObject(double[].class, msg.getByName(ROW_FIELD)); fxRates[i] = row; } return new FXMatrix(map, fxRates); }
@Override public synchronized YieldCurveDefinitionDocument get(UniqueId uid) { ArgumentChecker.notNull(uid, "objectIdentifiable"); if (!uid.isLatest()) { throw new IllegalArgumentException( "Only latest version supported by '" + getUniqueIdScheme() + "'"); } if (!getUniqueIdScheme().equals(uid.getScheme())) { throw new DataNotFoundException( "Scheme '" + uid.getScheme() + "' not valid for '" + getUniqueIdScheme() + "'"); } final int i = uid.getValue().indexOf('_'); if (i <= 0) { throw new DataNotFoundException( "Identifier '" + uid.getValue() + "' not valid for '" + getUniqueIdScheme() + "'"); } final String name = uid.getValue().substring(0, i); final String iso = uid.getValue().substring(i + 1); final Currency currency; try { currency = Currency.of(iso); } catch (IllegalArgumentException e) { throw new DataNotFoundException( "Identifier '" + uid.getValue() + "' not valid for '" + getUniqueIdScheme() + "'", e); } final TreeMap<Instant, YieldCurveDefinition> definitions = _definitions.get(Pair.of(currency, name)); if (definitions == null) { throw new DataNotFoundException("Curve definition not found"); } final YieldCurveDefinition definition = definitions.lastEntry().getValue(); if (definition == null) { throw new DataNotFoundException("Curve definition not found"); } return new YieldCurveDefinitionDocument(uid, definition); }
public class ForexNonDeliverableOptionDefinitionTest { private static final Currency KRW = Currency.of("KRW"); private static final Currency USD = Currency.EUR; private static final ZonedDateTime FIXING_DATE = DateUtils.getUTCDate(2012, 5, 2); private static final ZonedDateTime PAYMENT_DATE = DateUtils.getUTCDate(2012, 5, 4); private static final double NOMINAL_USD = 1000000; // 1m private static final double STRIKE_USD_KRW = 1123.45; private static final ForexNonDeliverableForwardDefinition NDF_DEFINITION = new ForexNonDeliverableForwardDefinition( KRW, USD, NOMINAL_USD, STRIKE_USD_KRW, FIXING_DATE, PAYMENT_DATE); private static final boolean IS_CALL = true; private static final boolean IS_LONG = true; private static final ForexNonDeliverableOptionDefinition NDO_DEFINITION = new ForexNonDeliverableOptionDefinition(NDF_DEFINITION, IS_CALL, IS_LONG); private static final ZonedDateTime REFERENCE_DATE = DateUtils.getUTCDate(2011, 11, 10); private static final String KRW_DSC = "Discounting KRW"; private static final String USD_DSC = "Discounting USD"; private static final String[] CURVE_NAMES = new String[] {KRW_DSC, USD_DSC}; @Test(expectedExceptions = IllegalArgumentException.class) public void testNullFX() { new ForexNonDeliverableOptionDefinition(null, IS_CALL, IS_LONG); } @Test public void getter() { assertEquals( "Forex non-deliverable option - getter", NDF_DEFINITION, NDO_DEFINITION.getUnderlyingNDF()); assertEquals("Forex non-deliverable option - getter", IS_CALL, NDO_DEFINITION.isCall()); assertEquals("Forex non-deliverable option - getter", IS_LONG, NDO_DEFINITION.isLong()); } @Test /** Tests the class toDerivative method. */ public void toDerivative() { ForexNonDeliverableOption ndoConverted = NDO_DEFINITION.toDerivative(REFERENCE_DATE, CURVE_NAMES); ForexNonDeliverableOption ndoExpected = new ForexNonDeliverableOption( NDF_DEFINITION.toDerivative(REFERENCE_DATE, CURVE_NAMES), IS_CALL, IS_LONG); assertEquals("Forex NDO - toDerivatives", ndoExpected, ndoConverted); } @Test /** Tests the class equal and hashCode */ public void equalHash() { assertEquals( "ForexNonDeliverableOptionDefinition: equal/hash code", NDO_DEFINITION, NDO_DEFINITION); assertFalse( "ForexNonDeliverableOptionDefinition: equal/hash code", NDO_DEFINITION.equals(CURVE_NAMES)); assertFalse( "ForexNonDeliverableOptionDefinition: equal/hash code", NDO_DEFINITION.equals(null)); final ForexNonDeliverableOptionDefinition newNdo = new ForexNonDeliverableOptionDefinition(NDF_DEFINITION, IS_CALL, IS_LONG); assertTrue( "ForexNonDeliverableOptionDefinition: equal/hash code", NDO_DEFINITION.equals(newNdo)); assertTrue( "ForexNonDeliverableOptionDefinition: equal/hash code", NDO_DEFINITION.hashCode() == newNdo.hashCode()); final ForexNonDeliverableOptionDefinition newNdo2 = new ForexNonDeliverableOptionDefinition(NDF_DEFINITION, !IS_CALL, !IS_LONG); final ForexNonDeliverableOptionDefinition newNdo3 = new ForexNonDeliverableOptionDefinition(NDF_DEFINITION, !IS_CALL, !IS_LONG); assertEquals( "ForexNonDeliverableOptionDefinition: equal/hash code", newNdo2.hashCode(), newNdo3.hashCode()); ForexNonDeliverableOptionDefinition modifiedNdo; modifiedNdo = new ForexNonDeliverableOptionDefinition( new ForexNonDeliverableForwardDefinition( KRW, USD, NOMINAL_USD, STRIKE_USD_KRW + 1.0, FIXING_DATE, PAYMENT_DATE), IS_CALL, IS_LONG); assertFalse("Forex NDF: equal - hash code", NDO_DEFINITION.equals(modifiedNdo)); modifiedNdo = new ForexNonDeliverableOptionDefinition(NDF_DEFINITION, !IS_CALL, IS_LONG); assertFalse("Forex NDF: equal - hash code", NDO_DEFINITION.equals(modifiedNdo)); modifiedNdo = new ForexNonDeliverableOptionDefinition(NDF_DEFINITION, IS_CALL, !IS_LONG); assertFalse("Forex NDF: equal - hash code", NDO_DEFINITION.equals(modifiedNdo)); assertFalse(NDF_DEFINITION.equals(USD)); assertFalse(NDF_DEFINITION.equals(null)); } }
/** * Parses the specified file to populate the master. * * @param in the input reader to read, not closed, not null */ public void parse(Reader in) { String name = null; try { Map<String, ManageableRegion> regions = new HashMap<String, ManageableRegion>(); Map<UniqueId, Set<String>> subRegions = new HashMap<UniqueId, Set<String>>(); // open CSV file @SuppressWarnings("resource") CSVReader reader = new CSVReader(in); List<String> columns = Arrays.asList(reader.readNext()); // identify columns final int nameColumnIdx = columns.indexOf(NAME_COLUMN); final int formalNameColumnIdx = columns.indexOf(FORMAL_NAME_COLUMN); final int classificationColumnIdx = columns.indexOf(CLASSIFICATION_COLUMN); final int sovereignityColumnIdx = columns.indexOf(SOVEREIGNITY_COLUMN); final int countryColumnIdx = columns.indexOf(ISO_COUNTRY_2_COLUMN); final int currencyColumnIdx = columns.indexOf(ISO_CURRENCY_3_COLUMN); final int subRegionsColumnIdx = columns.indexOf(SUB_REGIONS_COLUMN); // parse String[] row = null; while ((row = reader.readNext()) != null) { name = row[nameColumnIdx].trim(); // the primary key String fullName = StringUtils.trimToNull(row[formalNameColumnIdx]); if (fullName == null) { fullName = name; } RegionClassification classification = RegionClassification.valueOf(row[classificationColumnIdx].trim()); String sovereignity = StringUtils.trimToNull(row[sovereignityColumnIdx]); String countryISO = StringUtils.trimToNull(row[countryColumnIdx]); String currencyISO = StringUtils.trimToNull(row[currencyColumnIdx]); Set<String> rowSubRegions = new HashSet<String>(Arrays.asList(row[subRegionsColumnIdx].split(";"))); rowSubRegions = trim(rowSubRegions); ManageableRegion region = new ManageableRegion(); region.setClassification(classification); region.setName(name); region.setFullName(fullName); if (countryISO != null) { region.setCountry(Country.of(countryISO)); region.addExternalId(ExternalSchemes.financialRegionId(countryISO)); // TODO: looks odd } if (currencyISO != null) { region.setCurrency(Currency.of(currencyISO)); } if (sovereignity != null) { ManageableRegion parent = regions.get(sovereignity); if (parent == null) { throw new OpenGammaRuntimeException( "Cannot find parent '" + sovereignity + "' for '" + name + "'"); } region.getParentRegionIds().add(parent.getUniqueId()); } for (Entry<UniqueId, Set<String>> entry : subRegions.entrySet()) { if (entry.getValue().remove(name)) { region.getParentRegionIds().add(entry.getKey()); } } // store RegionDocument doc = getRegionMaster().add(new RegionDocument(region)); if (rowSubRegions.size() > 0) { subRegions.put(doc.getUniqueId(), rowSubRegions); } regions.put(name, region); } for (Set<String> set : subRegions.values()) { if (set.size() > 0) { throw new OpenGammaRuntimeException("Cannot find children: " + set); } } } catch (Exception ex) { String detail = (name != null ? " while processing " + name : ""); throw new OpenGammaRuntimeException( "Cannot open region data file (or file I/O problem)" + detail, ex); } }
public YieldCurveMarketDataFunction(final String currency, final String curveDefinitionName) { this(Currency.of(currency), curveDefinitionName); }
/** * Gets the currency. * * @return the value of the property */ public Currency getCurrency() { String code = _externalIdBundle.getValue(ExternalSchemes.ISO_CURRENCY_ALPHA3); return (code != null ? Currency.of(code) : null); }
@Override public Set<ValueRequirement> getRequirements( final FunctionCompilationContext context, final ComputationTarget target, final ValueRequirement desiredValue) { final ValueProperties constraints = desiredValue.getConstraints(); final Set<String> payCurveNames = constraints.getValues(ValuePropertyNames.PAY_CURVE); if (payCurveNames == null || payCurveNames.size() != 1) { return null; } final Set<String> payCurveCalculationConfigs = constraints.getValues(ValuePropertyNames.PAY_CURVE_CALCULATION_CONFIG); if (payCurveCalculationConfigs == null || payCurveCalculationConfigs.size() != 1) { return null; } final Set<String> receiveCurveNames = constraints.getValues(ValuePropertyNames.RECEIVE_CURVE); if (receiveCurveNames == null || receiveCurveNames.size() != 1) { return null; } final Set<String> receiveCurveCalculationConfigs = constraints.getValues(ValuePropertyNames.RECEIVE_CURVE_CALCULATION_CONFIG); if (receiveCurveCalculationConfigs == null || receiveCurveCalculationConfigs.size() != 1) { return null; } final Set<String> calculationMethods = constraints.getValues(ValuePropertyNames.CALCULATION_METHOD); if (calculationMethods == null || calculationMethods.size() != 1) { final ValueProperties newConstraints = constraints .copy() .withoutAny(ValuePropertyNames.CALCULATION_METHOD) .with( ValuePropertyNames.CALCULATION_METHOD, CalculationPropertyNamesAndValues.DISCOUNTING) .get(); return Collections.singleton( new ValueRequirement( ValueRequirementNames.PNL_SERIES, target.toSpecification(), newConstraints)); } final Set<ValueRequirement> requirements = new HashSet<>(); final String calculationMethod = Iterables.getOnlyElement(calculationMethods); final FinancialSecurity security = (FinancialSecurity) target.getPosition().getSecurity(); if (CalculationPropertyNamesAndValues.DISCOUNTING.equals(calculationMethod)) { requirements.add( new ValueRequirement( ValueRequirementNames.FX_CURRENCY_EXPOSURE, ComputationTargetSpecification.of(target.getPosition().getSecurity()), ValueProperties.builder() .with( ValuePropertyNames.CALCULATION_METHOD, CalculationPropertyNamesAndValues.DISCOUNTING) .with(ValuePropertyNames.PAY_CURVE, payCurveNames.iterator().next()) .with( ValuePropertyNames.PAY_CURVE_CALCULATION_CONFIG, payCurveCalculationConfigs.iterator().next()) .with(ValuePropertyNames.RECEIVE_CURVE, receiveCurveNames.iterator().next()) .with( ValuePropertyNames.RECEIVE_CURVE_CALCULATION_CONFIG, receiveCurveCalculationConfigs.iterator().next()) .get())); } else if (CalculationPropertyNamesAndValues.FORWARD_POINTS.equals(calculationMethod)) { final Set<String> forwardCurveNames = constraints.getValues(ValuePropertyNames.FORWARD_CURVE_NAME); if (forwardCurveNames == null || forwardCurveNames.size() != 1) { return null; } final String forwardCurveName = Iterables.getOnlyElement(forwardCurveNames); requirements.add( new ValueRequirement( ValueRequirementNames.FX_CURRENCY_EXPOSURE, ComputationTargetSpecification.of(target.getPosition().getSecurity()), ValueProperties.builder() .with( ValuePropertyNames.CALCULATION_METHOD, CalculationPropertyNamesAndValues.FORWARD_POINTS) .with(ValuePropertyNames.PAY_CURVE, payCurveNames.iterator().next()) .with( ValuePropertyNames.PAY_CURVE_CALCULATION_CONFIG, payCurveCalculationConfigs.iterator().next()) .with(ValuePropertyNames.RECEIVE_CURVE, receiveCurveNames.iterator().next()) .with( ValuePropertyNames.RECEIVE_CURVE_CALCULATION_CONFIG, receiveCurveCalculationConfigs.iterator().next()) .with(ValuePropertyNames.FORWARD_CURVE_NAME, forwardCurveName) .get())); } else { return null; } final Set<String> resultCurrencies = constraints.getValues(CURRENCY); final Currency payCurrency = security.accept(ForexVisitors.getPayCurrencyVisitor()); final Currency receiveCurrency = security.accept(ForexVisitors.getReceiveCurrencyVisitor()); final String resultCurrency; final CurrencyPair baseQuotePair = _currencyPairs.getCurrencyPair(payCurrency, receiveCurrency); final Currency baseCurrency = baseQuotePair.getBase(); final Currency nonBaseCurrency = baseQuotePair.getCounter(); if (resultCurrencies != null && resultCurrencies.size() == 1) { final Currency ccy = Currency.of(Iterables.getOnlyElement(resultCurrencies)); if (!(ccy.equals(payCurrency) || ccy.equals(receiveCurrency))) { requirements.add( ConventionBasedFXRateFunction.getHistoricalTimeSeriesRequirement( UnorderedCurrencyPair.of(baseCurrency, ccy))); resultCurrency = ccy.getCode(); } else if (ccy.equals(nonBaseCurrency)) { requirements.add( ConventionBasedFXRateFunction.getHistoricalTimeSeriesRequirement( UnorderedCurrencyPair.of(nonBaseCurrency, baseCurrency))); resultCurrency = nonBaseCurrency.getCode(); } else { requirements.add( ConventionBasedFXRateFunction.getHistoricalTimeSeriesRequirement( UnorderedCurrencyPair.of(baseCurrency, nonBaseCurrency))); resultCurrency = baseCurrency.getCode(); } } else { resultCurrency = baseCurrency.getCode(); } final ValueProperties fxSpotConstraints = desiredValue .getConstraints() .copy() .withoutAny(ValuePropertyNames.PAY_CURVE) .withoutAny(ValuePropertyNames.PAY_CURVE_CALCULATION_CONFIG) .withoutAny(ValuePropertyNames.RECEIVE_CURVE) .withoutAny(ValuePropertyNames.RECEIVE_CURVE_CALCULATION_CONFIG) .withoutAny(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS) .withoutAny(ValuePropertyNames.CURVE_CURRENCY) .withoutAny(ValuePropertyNames.CALCULATION_METHOD) .withoutAny(ValuePropertyNames.FORWARD_CURVE_NAME) .with(CURRENCY, resultCurrency) .withOptional(CURRENCY) .get(); final ComputationTargetSpecification fxSpotReturnSeriesSpec = ComputationTargetType.UNORDERED_CURRENCY_PAIR.specification( UnorderedCurrencyPair.of(payCurrency, receiveCurrency)); requirements.add( new ValueRequirement( ValueRequirementNames.RETURN_SERIES, fxSpotReturnSeriesSpec, fxSpotConstraints)); return requirements; }
/** 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)); } }
@Override public Set<ComputedValue> execute( final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target, final Set<ValueRequirement> desiredValues) { final Position position = target.getPosition(); final ValueRequirement desiredValue = desiredValues.iterator().next(); final ValueProperties constraints = desiredValue.getConstraints(); final Set<String> resultCurrencies = constraints.getValues(CURRENCY); final FXForwardSecurity security = (FXForwardSecurity) position.getSecurity(); final MultipleCurrencyAmount mca = (MultipleCurrencyAmount) inputs.getValue(ValueRequirementNames.FX_CURRENCY_EXPOSURE); final Currency payCurrency = security.getPayCurrency(); final Currency receiveCurrency = security.getReceiveCurrency(); final CurrencyPair currencyPair = _currencyPairs.getCurrencyPair(payCurrency, receiveCurrency); final Currency baseCurrency = currencyPair.getBase(); final Currency currencyNonBase = currencyPair.getCounter(); // The non-base currency final double exposure = mca.getAmount(currencyNonBase); final ValueSpecification spec = new ValueSpecification( ValueRequirementNames.PNL_SERIES, target.toSpecification(), desiredValue.getConstraints()); if (resultCurrencies == null || resultCurrencies.size() != 1) { s_logger.warn("No Currency property - returning result in base currency"); final LocalDateDoubleTimeSeries fxSpotReturnSeries = (LocalDateDoubleTimeSeries) inputs.getValue(ValueRequirementNames.RETURN_SERIES); final LocalDateDoubleTimeSeries pnlSeries = fxSpotReturnSeries.multiply( position.getQuantity().doubleValue() * exposure); // The P/L time series is in the base currency return Collections.singleton(new ComputedValue(spec, pnlSeries)); } final Currency resultCurrency = Currency.of(Iterables.getOnlyElement(resultCurrencies)); final LocalDateDoubleTimeSeries conversionTS = (LocalDateDoubleTimeSeries) inputs.getValue(HISTORICAL_FX_TIME_SERIES); if (conversionTS == null) { throw new OpenGammaRuntimeException( "Asked for result in " + resultCurrency + " but could not get " + baseCurrency + "/" + resultCurrency + " conversion series"); } if (resultCurrency.equals(baseCurrency)) { final LocalDateDoubleTimeSeries fxSpotReturnSeries = (LocalDateDoubleTimeSeries) inputs.getValue(ValueRequirementNames.RETURN_SERIES); final LocalDateDoubleTimeSeries convertedSeries = conversionTS .reciprocal() .multiply( position.getQuantity().doubleValue() * exposure); // The P/L time series is in the base currency final LocalDateDoubleTimeSeries pnlSeries = fxSpotReturnSeries.multiply( convertedSeries); // The P/L time series is in the base currency return Collections.singleton(new ComputedValue(spec, pnlSeries)); } final LocalDateDoubleTimeSeries fxSpotReturnSeries = (LocalDateDoubleTimeSeries) inputs.getValue(ValueRequirementNames.RETURN_SERIES); final LocalDateDoubleTimeSeries convertedSeries = conversionTS.multiply( position.getQuantity().doubleValue() * exposure); // The P/L time series is in the base currency final LocalDateDoubleTimeSeries pnlSeries = convertedSeries.multiply(fxSpotReturnSeries); return Collections.singleton(new ComputedValue(spec, pnlSeries)); }
@Override public IndexPrice buildObject(final FudgeDeserializer deserializer, final FudgeMsg message) { final String name = message.getString(NAME_FIELD); final Currency currency = Currency.of(message.getString(CURRENCY_FIELD)); return new IndexPrice(name, currency); }