// -------------------------------------------------------------------------
  // loads a single fixing series CSV file
  private static ImmutableMap<ObservableId, LocalDateDoubleTimeSeries> parseSingle(
      CharSource resource) {
    Map<ObservableId, LocalDateDoubleTimeSeriesBuilder> 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);
        LocalDate date = LocalDate.parse(dateStr);
        double value = Double.parseDouble(valueStr);

        LocalDateDoubleTimeSeriesBuilder builder =
            builders.computeIfAbsent(id, k -> LocalDateDoubleTimeSeries.builder());
        builder.put(date, value);
      }
    } catch (RuntimeException ex) {
      throw new IllegalArgumentException(
          Messages.format("Error processing resource as CSV file: {}", resource), ex);
    }
    return MapStream.of(builders).mapValues(builder -> builder.build()).toMap();
  }
  /** Test parameter sensitivity with finite difference sensitivity calculator. No cutoff period. */
  public void rateChfNoCutOffParameterSensitivity() {
    LocalDate[] valuationDate = {date(2015, 1, 1), date(2015, 1, 8)};
    double[] time = new double[] {0.0, 0.5, 1.0, 2.0, 5.0, 10.0};
    double[] rate = new double[] {0.0100, 0.0110, 0.0115, 0.0130, 0.0135, 0.0135};

    for (int loopvaldate = 0; loopvaldate < 2; loopvaldate++) {
      Curve onCurve =
          InterpolatedNodalCurve.of(Curves.zeroRates("ON", ACT_ACT_ISDA), time, rate, INTERPOLATOR);
      ImmutableRatesProvider prov =
          ImmutableRatesProvider.builder()
              .valuationDate(valuationDate[loopvaldate])
              .indexCurves(ImmutableMap.of(CHF_TOIS, onCurve))
              .timeSeries(ImmutableMap.of(CHF_TOIS, TIME_SERIES_BUILDER.build()))
              .build();
      OvernightAveragedRateObservation ro =
          OvernightAveragedRateObservation.of(CHF_TOIS, FIXING_START_DATE, FIXING_END_DATE, 0);
      ForwardOvernightAveragedRateObservationFn obsFn =
          ForwardOvernightAveragedRateObservationFn.DEFAULT;

      PointSensitivityBuilder sensitivityBuilderComputed =
          obsFn.rateSensitivity(ro, DUMMY_ACCRUAL_START_DATE, DUMMY_ACCRUAL_END_DATE, prov);
      CurveCurrencyParameterSensitivities parameterSensitivityComputed =
          prov.curveParameterSensitivity(sensitivityBuilderComputed.build());

      CurveCurrencyParameterSensitivities parameterSensitivityExpected =
          CAL_FD.sensitivity(
              prov,
              (p) ->
                  CurrencyAmount.of(
                      CHF_TOIS.getCurrency(),
                      obsFn.rate(ro, DUMMY_ACCRUAL_START_DATE, DUMMY_ACCRUAL_END_DATE, (p))));
      assertTrue(
          parameterSensitivityComputed.equalWithTolerance(
              parameterSensitivityExpected, EPS_FD * 10.0));
    }
  }
 static {
   for (int i = 0; i < FIXING_DATES.length; i++) {
     TIME_SERIES_BUILDER.put(FIXING_DATES[i], FIXING_RATES[i]);
   }
 }