com.opengamma.strata.loader.csv.FixingSeriesCsvLoader Maven / Gradle / Ivy
Show all versions of strata-loader Show documentation
/*
* Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.loader.csv;
import static com.opengamma.strata.collect.Guavate.toImmutableList;
import static java.util.stream.Collectors.toList;
import java.time.LocalDate;
import java.time.YearMonth;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.CharSource;
import com.opengamma.strata.basics.index.Index;
import com.opengamma.strata.basics.index.PriceIndex;
import com.opengamma.strata.collect.MapStream;
import com.opengamma.strata.collect.io.CharSources;
import com.opengamma.strata.collect.io.CsvFile;
import com.opengamma.strata.collect.io.CsvRow;
import com.opengamma.strata.collect.io.ResourceLocator;
import com.opengamma.strata.collect.io.UnicodeBom;
import com.opengamma.strata.collect.result.ParseFailureException;
import com.opengamma.strata.collect.timeseries.LocalDateDoubleTimeSeries;
import com.opengamma.strata.collect.timeseries.LocalDateDoubleTimeSeriesBuilder;
import com.opengamma.strata.data.ObservableId;
import com.opengamma.strata.loader.LoaderUtils;
import com.opengamma.strata.market.observable.IndexQuoteId;
/**
* Loads a set of historical fixing series into memory from CSV resources.
*
* The resources are expected to be in a CSV format, with the following header row:
* {@code Reference, Date, Value}.
*
* - The 'Reference' column is the name of the index that the data is for, such as 'USD-LIBOR-3M'.
*
- The 'Date' column is the date that the fixing was taken, this should be a year-month for price indices.
*
- The 'Value' column is the fixed value.
*
*
* Each fixing series must be contained entirely within a single resource, but each resource may
* contain more than one series. The fixing series points do not need to be ordered.
*
* For example:
*
* Reference, Date, Value
* USD-LIBOR-3M, 1971-01-04, 0.065
* USD-LIBOR-3M, 1971-01-05, 0.0638
* USD-LIBOR-3M, 1971-01-06, 0.0638
*
* Note that Microsoft Excel prefers the CSV file to have no space after the comma.
*
* CSV files sometimes contain a Unicode Byte Order Mark.
* Callers are responsible for handling this, such as by using {@link UnicodeBom}.
*/
public final class FixingSeriesCsvLoader {
// CSV column headers
private static final String REFERENCE_FIELD = "Reference";
private static final String DATE_FIELD = "Date";
private static final String VALUE_FIELD = "Value";
//-------------------------------------------------------------------------
/**
* Loads one or more CSV format fixing series files.
*
* If the files contain a duplicate entry an exception will be thrown.
*
* @param resources the fixing series CSV resources
* @return the loaded fixing series, mapped by {@linkplain ObservableId observable ID}
* @throws IllegalArgumentException if the files contain a duplicate entry
*/
public static ImmutableMap load(ResourceLocator... resources) {
return load(Arrays.asList(resources));
}
/**
* Loads one or more CSV format fixing series files.
*
* If the files contain a duplicate entry an exception will be thrown.
*
* @param resources the fixing series CSV resources
* @return the loaded fixing series, mapped by {@linkplain ObservableId observable ID}
* @throws IllegalArgumentException if the files contain a duplicate entry
*/
public static ImmutableMap load(Collection resources) {
Collection charSources = resources.stream().map(r -> r.getCharSource()).collect(toList());
return parse(charSources);
}
//-------------------------------------------------------------------------
/**
* Parses one or more CSV format fixing series files.
*
* If the files contain a duplicate entry an exception will be thrown.
*
* @param charSources the fixing series CSV character sources
* @return the loaded fixing series, mapped by {@linkplain ObservableId observable ID}
* @throws IllegalArgumentException if the files contain a duplicate entry
*/
public static ImmutableMap parse(Collection charSources) {
// builder ensures keys can only be seen once
try {
ImmutableMap.Builder builder = ImmutableMap.builder();
for (CharSource charSource : charSources) {
builder.putAll(parseSingle(charSource));
}
return builder.build();
} catch (ParseFailureException ex) {
throw ex;
} catch (RuntimeException ex) {
throw new ParseFailureException(
ex,
"Error parsing CSV files '{fileName}': {exceptionMessage}",
charSources.stream().map(source -> CharSources.extractFileName(source)).collect(toImmutableList()),
ex.getMessage());
}
}
//-------------------------------------------------------------------------
// loads a single fixing series CSV file
private static ImmutableMap parseSingle(CharSource resource) {
Map builders = new HashMap<>();
try {
CsvFile csv = CsvFile.of(resource, true);
for (CsvRow row : csv.rows()) {
String referenceStr = row.getField(REFERENCE_FIELD);
String dateStr = row.getField(DATE_FIELD);
String valueStr = row.getField(VALUE_FIELD);
Index index = LoaderUtils.findIndex(referenceStr);
ObservableId id = IndexQuoteId.of(index);
double value = Double.parseDouble(valueStr);
LocalDate date;
if (index instanceof PriceIndex) {
try {
YearMonth ym = LoaderUtils.parseYearMonth(dateStr);
date = ym.atEndOfMonth();
} catch (RuntimeException ex) {
date = LoaderUtils.parseDate(dateStr);
if (date.getDayOfMonth() != date.lengthOfMonth()) {
throw new ParseFailureException(
"Unable to parse price index from '{fileName}', must have date at end of month",
CharSources.extractFileName(resource));
}
}
} else {
date = LoaderUtils.parseDate(dateStr);
}
LocalDateDoubleTimeSeriesBuilder builder = builders.computeIfAbsent(id, k -> LocalDateDoubleTimeSeries.builder());
builder.put(date, value);
}
return MapStream.of(builders).mapValues(builder -> builder.build()).toMap();
} catch (RuntimeException ex) {
throw new ParseFailureException(
ex,
"Error parsing CSV file '{fileName}': {exceptionMessage}",
CharSources.extractFileName(resource),
ex.getMessage());
}
}
//-------------------------------------------------------------------------
/**
* Restricted constructor.
*/
private FixingSeriesCsvLoader() {
}
}