class FxOptionVolatilitiesMarketDataFunction implements MarketDataFunction<FxOptionVolatilities, FxOptionVolatilitiesId> {

  @Override
  public MarketDataBox<FxOptionVolatilities> build(
      FxOptionVolatilitiesId id,
      MarketDataConfig marketDataConfig,
      ScenarioMarketData marketData,
      ReferenceData refData) {

    FxOptionVolatilitiesDefinition volatilitiesDefinition =
        marketDataConfig.get(FxOptionVolatilitiesDefinition.class, id.getName().getName());
    ValuationZoneTimeDefinition zoneTimeDefinition = marketDataConfig.get(ValuationZoneTimeDefinition.class);
    int nScenarios = marketData.getScenarioCount();
    MarketDataBox<LocalDate> valuationDates = marketData.getValuationDate();
    MarketDataBox<ZonedDateTime> valuationDateTimes = zoneTimeDefinition.toZonedDateTime(valuationDates);

    int nParameters = volatilitiesDefinition.getParameterCount();
    ImmutableList<MarketDataBox<Double>> inputs = volatilitiesDefinition.volatilitiesInputs().stream()
        .map(q -> marketData.getValue(q))
        .collect(toImmutableList());
    ImmutableList<FxOptionVolatilities> vols = IntStream.range(0, nScenarios)
        .mapToObj(scenarioIndex -> volatilitiesDefinition.volatilities(
            valuationDateTimes.getValue(scenarioIndex),
            DoubleArray.of(nParameters, paramIndex -> inputs.get(paramIndex).getValue(scenarioIndex)),
            refData))
        .collect(toImmutableList());

    return nScenarios > 1 ? MarketDataBox.ofScenarioValues(vols) : MarketDataBox.ofSingleValue(vols.get(0));
  }

}