if (specification == null) {
throw new OpenGammaRuntimeException("Couldn't find FX forward curve specification called " + domesticCurveName + " for target " + currencyPair);
}
final FXForwardCurveInstrumentProvider provider = specification.getCurveInstrumentProvider();
final HistoricalTimeSeriesBundle timeSeriesBundle = getTimeSeriesBundle(inputs, ComputationTargetType.UNORDERED_CURRENCY_PAIR.specification(currencyPair), domesticCurveName);
final HistoricalTimeSeries spotTimeSeries = timeSeriesBundle.get(provider.getMarketDataField(), provider.getSpotInstrument());
if (spotTimeSeries == null) {
throw new OpenGammaRuntimeException("Could not get spot FX time series");
}
final LocalDateDoubleTimeSeries spotTS = spotTimeSeries.getTimeSeries();
final Map<LocalDate, YieldAndDiscountCurve> foreignCurves = (Map<LocalDate, YieldAndDiscountCurve>) foreignCurveObject;
final Map<LocalDate, YieldAndDiscountCurve> domesticCurves = new LinkedHashMap<>();
final Calendar calendar = CalendarUtils.getCalendar(holidaySource, domesticCurrency, foreignCurrency);
final ConventionSource conventionSource = OpenGammaExecutionContext.getConventionSource(executionContext);
final FXSpotConvention fxSpotConvention = (FXSpotConvention) conventionSource.getConvention(ExternalId.of("CONVENTION", "FX Spot"));
final int spotLag = fxSpotConvention.getSettlementDays();
final boolean isRegular = specification.isMarketQuoteConvention();
final ExternalId conventionSettlementRegion = fxSpotConvention.getSettlementRegion();
for (final Map.Entry<LocalDate, YieldAndDiscountCurve> entry : foreignCurves.entrySet()) {
final LocalDate valuationDate = entry.getKey();
final ZonedDateTime valuationDateTime = ZonedDateTime.of(valuationDate, now.toLocalTime(), now.getZone());
final Double spotValue = spotTS.getValue(valuationDate);
if (spotValue == null) {
continue;
}
final double spotFX = invertFXQuotes ? 1 / spotValue : spotValue;
final YieldAndDiscountCurve foreignCurve = entry.getValue();
final DoubleArrayList marketValues = new DoubleArrayList();
final DoubleArrayList nodeTimes = new DoubleArrayList();
final DoubleArrayList initialRatesGuess = new DoubleArrayList();
final String fullDomesticCurveName = domesticCurveName + "_" + domesticCurrency.getCode();
final String fullForeignCurveName = foreignCurveName + "_" + foreignCurrency.getCode();
final List<InstrumentDerivative> derivatives = new ArrayList<>();
int nInstruments = 0;
ZonedDateTime spotDate;
if (spotLag == 0 && conventionSettlementRegion == null) {
spotDate = valuationDateTime;
} else {
spotDate = ScheduleCalculator.getAdjustedDate(valuationDateTime, spotLag, calendar);
}
for (final Tenor tenor : definition.getTenors()) {
final ExternalId identifier = provider.getInstrument(valuationDate, tenor);
final HistoricalTimeSeries forwardFXTS = timeSeriesBundle.get(provider.getMarketDataField(), identifier);
if (forwardFXTS == null) {
throw new OpenGammaRuntimeException("Could not get time series for " + identifier);
}
final LocalDateDoubleTimeSeries forwardTS = forwardFXTS.getTimeSeries();
final ZonedDateTime paymentDate;
if (spotLag == 0 && conventionSettlementRegion == null) {
paymentDate = now.plus(tenor.getPeriod()); //This preserves the old behaviour that ignored holidays and settlement days.
} else {