Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add parser for seasonality #1465

Merged
merged 1 commit into from Jan 12, 2017
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -42,6 +42,7 @@
import com.opengamma.strata.market.curve.CurveNodeDate;
import com.opengamma.strata.market.curve.CurveNodeDateOrder;
import com.opengamma.strata.market.curve.NodalCurveDefinition;
import com.opengamma.strata.market.curve.SeasonalityDefinition;
import com.opengamma.strata.market.curve.node.FixedIborSwapCurveNode;
import com.opengamma.strata.market.curve.node.FixedInflationSwapCurveNode;
import com.opengamma.strata.market.curve.node.FixedOvernightSwapCurveNode;
Expand Down Expand Up @@ -201,6 +202,32 @@ public static ImmutableMap<CurveGroupName, CurveGroupDefinition> load(
return parse(groupsResource.getCharSource(), settingsResource.getCharSource(), curveNodeCharSources);
}

/**
* Loads one or more CSV format curve calibration files with seasonality.
* <p>
* If the files contain a duplicate entry an exception will be thrown.
*
* @param groupsResource the curve groups CSV resource
* @param settingsResource the curve settings CSV resource
* @param seasonalityResource the curve seasonality CSV resource
* @param curveNodeResources the CSV resources for curve nodes
* @return the group definitions, mapped by name
* @throws IllegalArgumentException if the files contain a duplicate entry
*/
public static ImmutableMap<CurveGroupName, CurveGroupDefinition> loadWithSeasonality(
ResourceLocator groupsResource,
ResourceLocator settingsResource,
ResourceLocator seasonalityResource,
Collection<ResourceLocator> curveNodeResources) {

Collection<CharSource> curveNodeCharSources = curveNodeResources.stream().map(r -> r.getCharSource()).collect(toList());
return parseWithSeasonality(
groupsResource.getCharSource(),
settingsResource.getCharSource(),
seasonalityResource.getCharSource(),
curveNodeCharSources);
}

//-------------------------------------------------------------------------
/**
* Parses one or more CSV format curve calibration files.
Expand All @@ -218,6 +245,39 @@ public static ImmutableMap<CurveGroupName, CurveGroupDefinition> parse(
CharSource settingsCharSource,
Collection<CharSource> curveNodeCharSources) {

return parse0(groupsCharSource, settingsCharSource, ImmutableMap.of(), curveNodeCharSources);
}

/**
* Parses one or more CSV format curve calibration files with seasonality.
* <p>
* If the files contain a duplicate entry an exception will be thrown.
*
* @param groupsCharSource the curve groups CSV character source
* @param settingsCharSource the curve settings CSV character source
* @param seasonalityResource the seasonality CSV character source
* @param curveNodeCharSources the CSV character sources for curve nodes
* @return the group definitions, mapped by name
* @throws IllegalArgumentException if the files contain a duplicate entry
*/
public static ImmutableMap<CurveGroupName, CurveGroupDefinition> parseWithSeasonality(
CharSource groupsCharSource,
CharSource settingsCharSource,
CharSource seasonalityResource,
Collection<CharSource> curveNodeCharSources) {

Map<CurveName, SeasonalityDefinition> seasonality =
SeasonalityDefinitionCsvLoader.parseSeasonalityDefinitions(seasonalityResource);
return parse0(groupsCharSource, settingsCharSource, seasonality, curveNodeCharSources);
}

// parse based on pre-parsed seasonality
private static ImmutableMap<CurveGroupName, CurveGroupDefinition> parse0(
CharSource groupsCharSource,
CharSource settingsCharSource,
Map<CurveName, SeasonalityDefinition> seasonality,
Collection<CharSource> curveNodeCharSources) {

// load curve groups and settings
List<CurveGroupDefinition> curveGroups = CurveGroupDefinitionCsvLoader.parseCurveGroupDefinitions(groupsCharSource);
Map<CurveName, LoadedCurveSettings> settingsMap = RatesCurvesCsvLoader.parseCurveSettings(settingsCharSource);
Expand All @@ -229,7 +289,7 @@ public static ImmutableMap<CurveGroupName, CurveGroupDefinition> parse(

// Add the curve definitions to the curve group definitions
return curveGroups.stream()
.map(groupDefinition -> groupDefinition.withCurveDefinitions(curveDefinitions))
.map(groupDefinition -> groupDefinition.withCurveDefinitions(curveDefinitions).withSeasonalityDefinitions(seasonality))
.collect(toImmutableMap(groupDefinition -> groupDefinition.getName()));
}

Expand Down
@@ -0,0 +1,91 @@
/**
* Copyright (C) 2017 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.loader.csv;

import java.util.Locale;
import java.util.Map;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.CharSource;
import com.opengamma.strata.collect.array.DoubleArray;
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.market.ShiftType;
import com.opengamma.strata.market.curve.CurveName;
import com.opengamma.strata.market.curve.SeasonalityDefinition;

/**
* Loads a set of seasonality definitions into memory by reading from CSV resources.
* <p>
* The CSV file has the following header row:<br />
* {@code Curve Name,Shift Type,Jan-Feb,Feb-Mar,Mar-Apr,Apr-May,May-Jun,Jun-Jul,Jul-Aug,Aug-Sep,Sep-Oct,Oct-Nov,Nov-Dec,Dec-Jan}.
*
* <ul>
* <li>The 'Curve Name' column is the name of the curve.
* <li>The 'Shift Type' column is the type of the shift, "Scaled" (multiplicative) or "Absolute" (additive).
* <li>The 'Jan-Feb' and similar columns are the seasonality values month-on-month.
* </ul>
*/
public final class SeasonalityDefinitionCsvLoader {

// Column headers
private static final String CURVE_NAME = "Curve Name";
private static final String SHIFT_TYPE = "Shift Type";
private static final ImmutableList<String> MONTH_PAIRS = ImmutableList.of(
"Jan-Feb",
"Feb-Mar",
"Mar-Apr",
"Apr-May",
"May-Jun",
"Jun-Jul",
"Jul-Aug",
"Aug-Sep",
"Sep-Oct",
"Oct-Nov",
"Nov-Dec",
"Dec-Jan");

//-------------------------------------------------------------------------
/**
* Loads the seasonality definition CSV file.
*
* @param resource the seasonality CSV resource
* @return the map of seasonality definitions
*/
public static Map<CurveName, SeasonalityDefinition> loadSeasonalityDefinitions(ResourceLocator resource) {
return parseSeasonalityDefinitions(resource.getCharSource());
}

//-------------------------------------------------------------------------
/**
* Parses the seasonality definition CSV file.
*
* @param charSource the seasonality CSV character source
* @return the map of seasonality definitions
*/
public static Map<CurveName, SeasonalityDefinition> parseSeasonalityDefinitions(CharSource charSource) {
ImmutableMap.Builder<CurveName, SeasonalityDefinition> builder = ImmutableMap.builder();
CsvFile csv = CsvFile.of(charSource, true);
for (CsvRow row : csv.rows()) {
String curveNameStr = row.getField(CURVE_NAME);
String shiftTypeStr = row.getField(SHIFT_TYPE);
DoubleArray values = DoubleArray.of(12, i -> Double.parseDouble(row.getField(MONTH_PAIRS.get(i))));

CurveName curveName = CurveName.of(curveNameStr);
ShiftType shiftType = ShiftType.valueOf(shiftTypeStr.toUpperCase(Locale.ENGLISH));
builder.put(curveName, SeasonalityDefinition.of(values, shiftType));
}
return builder.build();
}

//-------------------------------------------------------------------------
// this class only has static methods
private SeasonalityDefinitionCsvLoader() {
}

}
Expand Up @@ -16,7 +16,9 @@
import com.google.common.collect.ImmutableSet;
import com.opengamma.strata.basics.currency.Currency;
import com.opengamma.strata.basics.index.IborIndices;
import com.opengamma.strata.basics.index.PriceIndices;
import com.opengamma.strata.collect.io.ResourceLocator;
import com.opengamma.strata.market.ShiftType;
import com.opengamma.strata.market.ValueType;
import com.opengamma.strata.market.curve.CurveGroupDefinition;
import com.opengamma.strata.market.curve.CurveGroupEntry;
Expand All @@ -32,6 +34,7 @@ public class RatesCalibrationCsvLoaderTest {

private static final String GROUPS_1 = "classpath:com/opengamma/strata/loader/csv/groups.csv";
private static final String SETTINGS_1 = "classpath:com/opengamma/strata/loader/csv/settings.csv";
private static final String SEASONALITY_1 = "classpath:com/opengamma/strata/loader/csv/seasonality.csv";
private static final String CALIBRATION_1 = "classpath:com/opengamma/strata/loader/csv/calibration-1.csv";

private static final String SETTINGS_EMPTY = "classpath:com/opengamma/strata/loader/csv/settings-empty.csv";
Expand All @@ -40,10 +43,11 @@ public class RatesCalibrationCsvLoaderTest {

//-------------------------------------------------------------------------
public void test_parsing() {
Map<CurveGroupName, CurveGroupDefinition> test = RatesCalibrationCsvLoader.load(
Map<CurveGroupName, CurveGroupDefinition> test = RatesCalibrationCsvLoader.loadWithSeasonality(
ResourceLocator.of(GROUPS_1),
ResourceLocator.of(SETTINGS_1),
ResourceLocator.of(CALIBRATION_1));
ResourceLocator.of(SEASONALITY_1),
ImmutableList.of(ResourceLocator.of(CALIBRATION_1)));
assertEquals(test.size(), 1);

assertDefinition(test.get(CurveGroupName.of("Default")));
Expand Down Expand Up @@ -79,16 +83,15 @@ public void test_invalid_curve_duplicate_points() {
private void assertDefinition(CurveGroupDefinition defn) {
assertEquals(defn.getName(), CurveGroupName.of("Default"));
assertEquals(defn.getEntries().size(), 3);
assertEquals(defn.getSeasonalityDefinitions().size(), 1);
assertEquals(defn.getSeasonalityDefinitions().get(CurveName.of("USD-CPI")).getAdjustmentType(), ShiftType.SCALED);

CurveGroupEntry entry0 = defn.getEntries().get(0);
CurveGroupEntry entry1 = defn.getEntries().get(1);
if (entry0.getCurveName().equals(CurveName.of("USD-3ML"))) {
CurveGroupEntry temp = entry0;
entry0 = entry1;
entry1 = temp;
}
CurveGroupEntry entry0 = findEntry(defn, "USD-Disc");
CurveGroupEntry entry1 = findEntry(defn, "USD-3ML");
CurveGroupEntry entry2 = findEntry(defn, "USD-CPI");
NodalCurveDefinition defn0 = defn.findCurveDefinition(entry0.getCurveName()).get();
NodalCurveDefinition defn1 = defn.findCurveDefinition(entry1.getCurveName()).get();
NodalCurveDefinition defn2 = defn.findCurveDefinition(entry2.getCurveName()).get();

assertEquals(entry0.getDiscountCurrencies(), ImmutableSet.of(Currency.USD));
assertEquals(entry0.getIndices(), ImmutableSet.of());
Expand All @@ -101,6 +104,16 @@ private void assertDefinition(CurveGroupDefinition defn) {
assertEquals(defn1.getName(), CurveName.of("USD-3ML"));
assertEquals(defn1.getYValueType(), ValueType.ZERO_RATE);
assertEquals(defn1.getParameterCount(), 27);

assertEquals(entry2.getDiscountCurrencies(), ImmutableSet.of());
assertEquals(entry2.getIndices(), ImmutableSet.of(PriceIndices.US_CPI_U));
assertEquals(defn2.getName(), CurveName.of("USD-CPI"));
assertEquals(defn2.getYValueType(), ValueType.PRICE_INDEX);
assertEquals(defn2.getParameterCount(), 2);
}

private CurveGroupEntry findEntry(CurveGroupDefinition defn, String curveName) {
return defn.getEntries().stream().filter(d -> d.getCurveName().getName().equals(curveName)).findFirst().get();
}

//-------------------------------------------------------------------------
Expand Down
@@ -0,0 +1,43 @@
/**
* Copyright (C) 2017 - 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.TestHelper.coverPrivateConstructor;
import static org.testng.Assert.assertEquals;

import java.util.Map;

import org.testng.annotations.Test;

import com.opengamma.strata.collect.io.ResourceLocator;
import com.opengamma.strata.market.ShiftType;
import com.opengamma.strata.market.curve.CurveName;
import com.opengamma.strata.market.curve.SeasonalityDefinition;

/**
* Test {@link SeasonalityDefinitionCsvLoader}.
*/
@Test
public class SeasonalityDefinitionCsvLoaderTest {

private static final String GROUPS_1 = "classpath:com/opengamma/strata/loader/csv/seasonality.csv";

//-------------------------------------------------------------------------
public void test_loadSeasonalityDefinition() {
Map<CurveName, SeasonalityDefinition> defns =
SeasonalityDefinitionCsvLoader.loadSeasonalityDefinitions(ResourceLocator.of(GROUPS_1));
assertEquals(defns.size(), 1);
SeasonalityDefinition defn = defns.get(CurveName.of("USD-CPI"));
assertEquals(defn.getAdjustmentType(), ShiftType.SCALED);
assertEquals(defn.getSeasonalityMonthOnMonth().size(), 12);
}

//-------------------------------------------------------------------------
public void coverage() {
coverPrivateConstructor(SeasonalityDefinitionCsvLoader.class);
}

}
@@ -0,0 +1,2 @@
Curve Name,Shift Type,Jan-Feb,Feb-Mar,Mar-Apr,Apr-May,May-Jun,Jun-Jul,Jul-Aug,Aug-Sep,Sep-Oct,Oct-Nov,Nov-Dec,Dec-Jan
USD-CPI,Scaled,1.00275,1.00105,1.00639,1.00086,0.99888,0.99557,1.00141,1.00166,0.99914,0.99837,0.99957,0.99434
Expand Up @@ -42,6 +42,7 @@
import com.opengamma.strata.basics.index.Index;
import com.opengamma.strata.basics.index.PriceIndex;
import com.opengamma.strata.collect.ArgChecker;
import com.opengamma.strata.collect.MapStream;
import com.opengamma.strata.collect.timeseries.LocalDateDoubleTimeSeries;
import com.opengamma.strata.data.MarketData;
import com.opengamma.strata.market.ValueType;
Expand Down Expand Up @@ -376,6 +377,22 @@ public CurveGroupDefinition withCurveDefinitions(List<NodalCurveDefinition> curv
name, entries, filteredDefinitions, seasonalityDefinitions, computeJacobian, computePvSensitivityToMarketQuote);
}

/**
* Returns a copy of this object containing the specified seasonality definitions.
* <p>
* Seasonality definitions are ignored if there is no entry in this definition with the same curve name.
*
* @param seasonalityDefinitions seasonality definitions
* @return a copy of this object containing the specified seasonality definitions
*/
public CurveGroupDefinition withSeasonalityDefinitions(Map<CurveName, SeasonalityDefinition> seasonalityDefinitions) {
Set<CurveName> curveNames = entries.stream().map(entry -> entry.getCurveName()).collect(toSet());
Map<CurveName, SeasonalityDefinition> filteredDefinitions = MapStream.of(seasonalityDefinitions)
.filterKeys(cn -> curveNames.contains(cn)).toMap();
return new CurveGroupDefinition(
name, entries, curveDefinitions, filteredDefinitions, computeJacobian, computePvSensitivityToMarketQuote);
}

/**
* Returns a copy of this definition with a different name.
*
Expand Down