ConfigDBCurveCalculationConfigSource.reinitOnChanges(context, this);
}
@Override
public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target, final Set<ValueRequirement> desiredValues) {
final Position position = target.getPosition();
final ConfigSource configSource = OpenGammaExecutionContext.getConfigSource(executionContext);
final Clock snapshotClock = executionContext.getValuationClock();
final LocalDate now = ZonedDateTime.now(snapshotClock).toLocalDate();
final Currency currency = FinancialSecurityUtils.getCurrency(position.getSecurity());
final String currencyString = currency.getCode();
final ValueRequirement desiredValue = desiredValues.iterator().next();
final ValueProperties constraints = desiredValue.getConstraints();
final String desiredCurrency;
final Set<String> currencies = desiredValue.getConstraints().getValues(ValuePropertyNames.CURRENCY);
if (currencies != null && !currencies.isEmpty()) {
desiredCurrency = desiredValue.getConstraint(ValuePropertyNames.CURRENCY);
} else {
desiredCurrency = currencyString;
}
final String curveCalculationConfigName = desiredValue.getConstraint(ValuePropertyNames.CURVE_CALCULATION_CONFIG);
final Set<String> yieldCurveNames = constraints.getValues(ValuePropertyNames.CURVE);
final Period samplingPeriod = getSamplingPeriod(desiredValue.getConstraint(ValuePropertyNames.SAMPLING_PERIOD));
final LocalDate startDate = now.minus(samplingPeriod);
final Schedule scheduleCalculator = getScheduleCalculator(desiredValue.getConstraint(ValuePropertyNames.SCHEDULE_CALCULATOR));
final TimeSeriesSamplingFunction samplingFunction = getSamplingFunction(desiredValue.getConstraint(ValuePropertyNames.SAMPLING_FUNCTION));
final LocalDate[] schedule = HOLIDAY_REMOVER.getStrippedSchedule(scheduleCalculator.getSchedule(startDate, now, true, false), WEEKEND_CALENDAR); //REVIEW emcleod should "fromEnd" be hard-coded?
DoubleTimeSeries<?> result = null;
final ConfigDBCurveCalculationConfigSource curveCalculationConfigSource = new ConfigDBCurveCalculationConfigSource(configSource);
final MultiCurveCalculationConfig curveCalculationConfig = curveCalculationConfigSource.getConfig(curveCalculationConfigName);
DoubleTimeSeries<?> fxSeries = null;
boolean isInverse = true;
if (!desiredCurrency.equals(currencyString)) {
if (inputs.getValue(ValueRequirementNames.HISTORICAL_FX_TIME_SERIES) != null) {
final Map<UnorderedCurrencyPair, DoubleTimeSeries<?>> allFXSeries = (Map<UnorderedCurrencyPair, DoubleTimeSeries<?>>) inputs.getValue(ValueRequirementNames.HISTORICAL_FX_TIME_SERIES);
final CurrencyPairs currencyPairs = OpenGammaExecutionContext.getCurrencyPairsSource(executionContext).getCurrencyPairs(CurrencyPairs.DEFAULT_CURRENCY_PAIRS);
if (desiredCurrency.equals(currencyPairs.getCurrencyPair(Currency.of(desiredCurrency), currency).getCounter().getCode())) {
isInverse = false;
}
if (allFXSeries.size() != 1) {
throw new OpenGammaRuntimeException("Have more than one FX series; should not happen");
}
final Map.Entry<UnorderedCurrencyPair, DoubleTimeSeries<?>> entry = Iterables.getOnlyElement(allFXSeries.entrySet());
if (!UnorderedCurrencyPair.of(Currency.of(desiredCurrency), currency).equals(entry.getKey())) {
throw new OpenGammaRuntimeException("Could not get FX series for currency pair " + desiredCurrency + ", " + currencyString);
}
fxSeries = entry.getValue();
} else {
throw new OpenGammaRuntimeException("Could not get FX series for currency pair " + desiredCurrency + ", " + currencyString);
}
}
for (final String yieldCurveName : yieldCurveNames) {
final ValueRequirement ycnsRequirement = getYCNSRequirement(currencyString, curveCalculationConfigName, yieldCurveName, target, constraints);
final Object ycnsObject = inputs.getValue(ycnsRequirement);
if (ycnsObject == null) {
throw new OpenGammaRuntimeException("Could not get yield curve node sensitivities; " + ycnsRequirement);
}
final DoubleLabelledMatrix1D ycns = (DoubleLabelledMatrix1D) ycnsObject;
final ValueRequirement ychtsRequirement = getYCHTSRequirement(currency, yieldCurveName, samplingPeriod.toString());
final Object ychtsObject = inputs.getValue(ychtsRequirement);
if (ychtsObject == null) {
throw new OpenGammaRuntimeException("Could not get yield curve historical time series; " + ychtsRequirement);
}
final HistoricalTimeSeriesBundle ychts = (HistoricalTimeSeriesBundle) ychtsObject;
final DoubleTimeSeries<?> pnLSeries;
if (curveCalculationConfig.getCalculationMethod().equals(FXImpliedYieldCurveFunction.FX_IMPLIED)) {
pnLSeries = getPnLSeries(ycns, ychts, schedule, samplingFunction);
} else {
final ValueRequirement curveSpecRequirement = getCurveSpecRequirement(currency, yieldCurveName);
final Object curveSpecObject = inputs.getValue(curveSpecRequirement);
if (curveSpecObject == null) {
throw new OpenGammaRuntimeException("Could not get curve specification; " + curveSpecRequirement);
}
final InterpolatedYieldCurveSpecificationWithSecurities curveSpec = (InterpolatedYieldCurveSpecificationWithSecurities) curveSpecObject;
pnLSeries = getPnLSeries(curveSpec, ycns, ychts, schedule, samplingFunction, fxSeries, isInverse);
}
if (result == null) {
result = pnLSeries;
} else {
result = result.add(pnLSeries);
}
}
if (result == null) {
throw new OpenGammaRuntimeException("Could not get any values for security " + position.getSecurity());
}
result = result.multiply(position.getQuantity().doubleValue());
final ValueSpecification resultSpec = new ValueSpecification(ValueRequirementNames.PNL_SERIES, target.toSpecification(), desiredValue.getConstraints());
return Sets.newHashSet(new ComputedValue(resultSpec, result));
}