/** * Writes the curve groups definition in a CSV format to a file. * * @param file the file * @param valuationDate the valuation date * @param group the curve group */ public static void writeCurveNodes(File file, LocalDate valuationDate, RatesCurveGroup group) { try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)) { writeCurveNodes(writer, valuationDate, group); } catch (IOException ex) { throw new UncheckedIOException(ex); } }
/** * Writes the curve settings in a CSV format to a file. * * @param file the file * @param group the curve group */ public static void writeCurveSettings(File file, RatesCurveGroup group) { try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)) { writeCurveSettings(writer, group); } catch (IOException ex) { throw new UncheckedIOException(ex); } }
/** * Writes the curve nodes in a CSV format to an appendable. * * @param underlying the underlying appendable destination * @param valuationDate the valuation date * @param group the curve group */ public static void writeCurveNodes(Appendable underlying, LocalDate valuationDate, RatesCurveGroup group) { CsvOutput csv = CsvOutput.standard(underlying); // header csv.writeLine(HEADERS_NODES); // rows String valuationDateStr = valuationDate.toString(); Map<Currency, Curve> discountingCurves = group.getDiscountCurves(); Set<CurveName> names = new HashSet<>(); for (Entry<Currency, Curve> entry : discountingCurves.entrySet()) { Curve curve = entry.getValue(); nodeLines(valuationDateStr, curve, csv); names.add(curve.getName()); } Map<Index, Curve> forwardCurves = group.getForwardCurves(); for (Entry<Index, Curve> entry : forwardCurves.entrySet()) { Curve curve = entry.getValue(); if (!names.contains(curve.getName())) { nodeLines(valuationDateStr, curve, csv); names.add(curve.getName()); } } }
private static Map<LocalDate, Map<CurveName, Curve>> parseCurves( Predicate<LocalDate> datePredicate, CharSource settingsResource, Collection<CharSource> curvesResources) { // load curve settings Map<CurveName, LoadedCurveSettings> settingsMap = parseCurveSettings(settingsResource); // load curves, ensuring curves only be seen once within a date Map<LocalDate, Map<CurveName, Curve>> resultMap = new TreeMap<>(); for (CharSource curvesResource : curvesResources) { Multimap<LocalDate, Curve> fileCurvesByDate = parseSingle(datePredicate, curvesResource, settingsMap); // Ensure curve names are unique, with a good error message for (LocalDate date : fileCurvesByDate.keySet()) { Collection<Curve> fileCurves = fileCurvesByDate.get(date); Map<CurveName, Curve> resultCurves = resultMap.computeIfAbsent(date, d -> new HashMap<>()); for (Curve fileCurve : fileCurves) { if (resultCurves.put(fileCurve.getName(), fileCurve) != null) { throw new IllegalArgumentException( "Rates curve loader found multiple curves with the same name: " + fileCurve.getName()); } } } } return resultMap; }
public void test_writer_curve_settings() { List<RatesCurveGroup> curveGroups = RatesCurvesCsvLoader.load( CURVE_DATE, ResourceLocator.of(GROUPS_1), ResourceLocator.of(SETTINGS_1), ImmutableList.of(ResourceLocator.of(CURVES_1), ResourceLocator.of(CURVES_2))); Appendable underlying = new StringBuilder(); RatesCurvesCsvLoader.writeCurveSettings(underlying, curveGroups.get(0)); String created = underlying.toString(); String expected = "Curve Name,Value Type,Day Count,Interpolator,Left Extrapolator,Right Extrapolator" + System.lineSeparator() + "USD-Disc,zero,Act/Act ISDA,Linear,Flat,Flat" + System.lineSeparator() + "USD-3ML,zero,Act/Act ISDA,Linear,Flat,Flat" + System.lineSeparator(); assertEquals(created, expected); }
public void test_writer_curve_nodes() { List<RatesCurveGroup> curveGroups = RatesCurvesCsvLoader.load( CURVE_DATE, ResourceLocator.of(GROUPS_1), ResourceLocator.of(SETTINGS_1), ImmutableList.of(ResourceLocator.of(CURVES_1), ResourceLocator.of(CURVES_2))); Appendable underlying = new StringBuilder(); RatesCurvesCsvLoader.writeCurveNodes(underlying, CURVE_DATE, curveGroups.get(0)); String created = underlying.toString(); String expected = "Valuation Date,Curve Name,Date,Value,Label" + System.lineSeparator() + "2009-07-31,USD-Disc,2009-11-06,0.001763775,3M" + System.lineSeparator() + "2009-07-31,USD-Disc,2010-02-08,0.002187884,6M" + System.lineSeparator() + "2009-07-31,USD-Disc,2010-08-06,0.004437206,1Y" + System.lineSeparator() + "2009-07-31,USD-Disc,2011-08-08,0.011476741,2Y" + System.lineSeparator() + "2009-07-31,USD-Disc,2012-08-08,0.017859057,3Y" + System.lineSeparator() + "2009-07-31,USD-Disc,2014-08-06,0.026257102,5Y" + System.lineSeparator() + "2009-07-31,USD-Disc,2019-08-07,0.035521988,10Y" + System.lineSeparator() + "2009-07-31,USD-3ML,2009-11-04,0.007596889,3M" + System.lineSeparator() + "2009-07-31,USD-3ML,2010-08-04,0.008091541,1Y" + System.lineSeparator() + "2009-07-31,USD-3ML,2011-08-04,0.015244398,2Y" + System.lineSeparator() + "2009-07-31,USD-3ML,2012-08-06,0.021598026,3Y" + System.lineSeparator() + "2009-07-31,USD-3ML,2014-08-05,0.029984216,5Y" + System.lineSeparator() + "2009-07-31,USD-3ML,2019-08-06,0.039245812,10Y" + System.lineSeparator(); assertEquals(created, expected); }
@Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Missing settings for curve: .*") public void test_noSettings() { List<RatesCurveGroup> curveGroups = RatesCurvesCsvLoader.load( CURVE_DATE, ResourceLocator.of(GROUPS_1), ResourceLocator.of(SETTINGS_EMPTY), ImmutableList.of(ResourceLocator.of(CURVES_1))); assertEquals(curveGroups.size(), 1); RatesCurveGroup curveGroup = Iterables.getOnlyElement(curveGroups); assertUsdDisc(curveGroup.findDiscountCurve(Currency.USD).get()); }
/** * Loads one or more CSV format curve files for all available dates. * <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 curveValueResources the CSV resources for curves * @return the loaded curves, mapped by date and identifier * @throws IllegalArgumentException if the files contain a duplicate entry */ public static ImmutableListMultimap<LocalDate, RatesCurveGroup> loadAllDates( ResourceLocator groupsResource, ResourceLocator settingsResource, Collection<ResourceLocator> curveValueResources) { Collection<CharSource> curveCharSources = curveValueResources.stream().map(r -> r.getCharSource()).collect(toList()); return parse(d -> true, groupsResource.getCharSource(), settingsResource.getCharSource(), curveCharSources); }
private static ImmutableMap<CurveGroupName, RatesCurveGroupDefinition> parse0( CharSource groupsCharSource, CharSource settingsCharSource, Map<CurveName, SeasonalityDefinition> seasonality, Collection<CharSource> curveNodeCharSources) { // load curve groups and settings List<RatesCurveGroupDefinition> curveGroups = RatesCurveGroupDefinitionCsvLoader.parseCurveGroupDefinitions(groupsCharSource); Map<CurveName, LoadedCurveSettings> settingsMap = RatesCurvesCsvLoader.parseCurveSettings(settingsCharSource); // load curve definitions List<CurveDefinition> curveDefinitions = curveNodeCharSources.stream() .flatMap(res -> parseSingle(res, settingsMap).stream()) .collect(toImmutableList()); // Add the curve definitions to the curve group definitions return curveGroups.stream() .map(groupDefinition -> groupDefinition.withCurveDefinitions(curveDefinitions).withSeasonalityDefinitions(seasonality)) .collect(toImmutableMap(groupDefinition -> groupDefinition.getName())); }
/** * Writes the curve settings in a CSV format to an appendable. * * @param underlying the underlying appendable destination * @param group the curve group */ public static void writeCurveSettings(Appendable underlying, RatesCurveGroup group) { CsvOutput csv = CsvOutput.standard(underlying); // header csv.writeLine(HEADERS_SETTINGS); // rows Map<Currency, Curve> discountingCurves = group.getDiscountCurves(); Set<CurveName> names = new HashSet<>(); for (Entry<Currency, Curve> entry : discountingCurves.entrySet()) { Curve curve = entry.getValue(); csv.writeLine(curveSettings(curve)); names.add(curve.getName()); } Map<Index, Curve> forwardCurves = group.getForwardCurves(); for (Entry<Index, Curve> entry : forwardCurves.entrySet()) { Curve curve = entry.getValue(); if (!names.contains(curve.getName())) { csv.writeLine(curveSettings(curve)); names.add(curve.getName()); } } }
parseCurves(datePredicate, settingsCharSource, curveValueCharSources); ImmutableListMultimap.Builder<LocalDate, RatesCurveGroup> builder = ImmutableListMultimap.builder();
private static Multimap<LocalDate, Curve> parseSingle( Predicate<LocalDate> datePredicate, CharSource curvesResource, Map<CurveName, LoadedCurveSettings> settingsMap) { CsvFile csv = CsvFile.of(curvesResource, true); Map<LoadedCurveKey, List<LoadedCurveNode>> allNodes = new HashMap<>(); for (CsvRow row : csv.rows()) { String dateStr = row.getField(CURVE_DATE); String curveNameStr = row.getField(CURVE_NAME); String pointDateStr = row.getField(CURVE_POINT_DATE); String pointValueStr = row.getField(CURVE_POINT_VALUE); String pointLabel = row.getField(CURVE_POINT_LABEL); LocalDate date = LoaderUtils.parseDate(dateStr); if (datePredicate.test(date)) { LocalDate pointDate = LoaderUtils.parseDate(pointDateStr); double pointValue = Double.valueOf(pointValueStr); LoadedCurveKey key = LoadedCurveKey.of(date, CurveName.of(curveNameStr)); List<LoadedCurveNode> curveNodes = allNodes.computeIfAbsent(key, k -> new ArrayList<>()); curveNodes.add(LoadedCurveNode.of(pointDate, pointValue, pointLabel)); } } return buildCurves(settingsMap, allNodes); }
public void test_load_all_curves() { ListMultimap<LocalDate, RatesCurveGroup> allGroups = RatesCurvesCsvLoader.loadAllDates( ResourceLocator.of(GROUPS_1), ResourceLocator.of(SETTINGS_1), ImmutableList.of(ResourceLocator.of(CURVES_1), ResourceLocator.of(CURVES_2), ResourceLocator.of(CURVES_3))); assertEquals(allGroups.size(), 2); assertCurves(allGroups.get(CURVE_DATE)); List<RatesCurveGroup> curves3 = allGroups.get(CURVE_DATE_CURVES_3); assertEquals(curves3.size(), 1); RatesCurveGroup group = curves3.get(0); // All curve points are set to 0 in test data to ensure these are really different curve instances Curve usdDisc = group.findDiscountCurve(Currency.USD).get(); InterpolatedNodalCurve usdDiscNodal = (InterpolatedNodalCurve) usdDisc; assertEquals(usdDiscNodal.getMetadata().getCurveName(), CurveName.of("USD-Disc")); assertTrue(usdDiscNodal.getYValues().equalZeroWithTolerance(0d)); Curve usd3ml = group.findForwardCurve(IborIndices.USD_LIBOR_3M).get(); InterpolatedNodalCurve usd3mlNodal = (InterpolatedNodalCurve) usd3ml; assertEquals(usd3mlNodal.getMetadata().getCurveName(), CurveName.of("USD-3ML")); assertTrue(usd3mlNodal.getYValues().equalZeroWithTolerance(0d)); }
@Test(expectedExceptions = IllegalArgumentException.class) public void test_invalid_curve_duplicate_points() { RatesCurvesCsvLoader.load( CURVE_DATE, ResourceLocator.of(GROUPS_1), ResourceLocator.of(SETTINGS_1), ImmutableList.of(ResourceLocator.of(CURVES_INVALID_DUPLICATE_POINTS))); }
/** * Loads one or more CSV format curve files for a specific date. * <p> * Only those quotes that match the specified date will be loaded. * <p> * If the files contain a duplicate entry an exception will be thrown. * * @param marketDataDate the curve date to load * @param groupsResource the curve groups CSV resource * @param settingsResource the curve settings CSV resource * @param curveValueResources the CSV resources for curves * @return the loaded curves, mapped by an identifying key * @throws IllegalArgumentException if the files contain a duplicate entry */ public static ImmutableList<RatesCurveGroup> load( LocalDate marketDataDate, ResourceLocator groupsResource, ResourceLocator settingsResource, Collection<ResourceLocator> curveValueResources) { Collection<CharSource> curveCharSources = curveValueResources.stream().map(r -> r.getCharSource()).collect(toList()); ListMultimap<LocalDate, RatesCurveGroup> map = parse( d -> marketDataDate.equals(d), groupsResource.getCharSource(), settingsResource.getCharSource(), curveCharSources); return ImmutableList.copyOf(map.get(marketDataDate)); }
public void test_writeCurveGroup() { List<RatesCurveGroup> curveGroups = RatesCurvesCsvLoader.load( CURVE_DATE, ResourceLocator.of(GROUPS_1), ResourceLocator.of(SETTINGS_1), ImmutableList.of(ResourceLocator.of(CURVES_1), ResourceLocator.of(CURVES_2))); Appendable underlying = new StringBuilder(); RatesCurveGroupDefinitionCsvLoader.writeCurveGroup(underlying, curveGroups.get(0)); String created = underlying.toString(); String expected = "Group Name,Curve Type,Reference,Curve Name" + System.lineSeparator() + "Default,discount,USD,USD-Disc" + System.lineSeparator() + "Default,forward,USD-LIBOR-3M,USD-3ML" + System.lineSeparator(); assertEquals(created, expected); }
private void testSettings(String settingsResource) { RatesCurvesCsvLoader.load( CURVE_DATE, ResourceLocator.of(GROUPS_1), ResourceLocator.of(settingsResource), ImmutableList.of(ResourceLocator.of(CURVES_1))); }
private void testGroups(String groupsResource) { RatesCurvesCsvLoader.load( CURVE_DATE, ResourceLocator.of(groupsResource), ResourceLocator.of(SETTINGS_1), ImmutableList.of(ResourceLocator.of(CURVES_1))); }
@Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Rates curve loader found multiple curves with the same name: .*") public void test_single_curve_multiple_Files() { RatesCurvesCsvLoader.load( CURVE_DATE, ResourceLocator.of(GROUPS_1), ResourceLocator.of(SETTINGS_1), ImmutableList.of(ResourceLocator.of(CURVES_1), ResourceLocator.of(CURVES_1))); }
public void test_multiple_curves_single_file() { List<RatesCurveGroup> curveGroups = RatesCurvesCsvLoader.load( CURVE_DATE, ResourceLocator.of(GROUPS_1), ResourceLocator.of(SETTINGS_1), ImmutableList.of(ResourceLocator.of(CURVES_1_AND_2))); assertCurves(curveGroups); }