private static final TimeSeriesDifferenceOperator DIFFERENCE = new TimeSeriesDifferenceOperator();
@Override
public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target,
final Set<ValueRequirement> desiredValues) throws AsynchronousExecution {
final Position position = target.getPosition();
final ValueRequirement desiredValue = Iterables.getOnlyElement(desiredValues);
final DoubleLabelledMatrix1D sensitivities = ((DoubleLabelledMatrix1D) inputs.getValue(FX_FORWARD_POINTS_NODE_SENSITIVITIES));
final String currency = inputs.getComputedValue(FX_FORWARD_POINTS_NODE_SENSITIVITIES).getSpecification().getProperty(CURRENCY);
final double[] fcns = sensitivities.getValues();
final Object[] labels = sensitivities.getLabels();
final CurveSpecification curveSpec = (CurveSpecification) inputs.getValue(CURVE_SPECIFICATION);
final int n = fcns.length;
if (n != curveSpec.getNodes().size()) {
throw new OpenGammaRuntimeException("Do not have a sensitivity for each node");
}
final Tenor[] tenors = new Tenor[n];
final LocalDateDoubleTimeSeries[] returnSeries = new LocalDateDoubleTimeSeries[n];
final HistoricalTimeSeriesBundle tsBundle = (HistoricalTimeSeriesBundle) inputs.getValue(CURVE_HISTORICAL_TIME_SERIES);
final Iterator<CurveNodeWithIdentifier> iterator = curveSpec.getNodes().iterator();
for (int i = 0; i < n; i++) {
final double sensitivity = fcns[i];
final CurveNodeWithIdentifier curveNode = iterator.next();
final HistoricalTimeSeries ts = tsBundle.get(curveNode.getDataField(), curveNode.getIdentifier());
if (ts == null) {
throw new OpenGammaRuntimeException("Could not get time series for id " + curveNode.getIdentifier() + " and data field " + curveNode.getDataField());
}
LocalDateDoubleTimeSeries pnlSeries;
if (curveNode instanceof PointsCurveNodeWithIdentifier) {
final PointsCurveNodeWithIdentifier pointsCurveNode = (PointsCurveNodeWithIdentifier) curveNode;
final HistoricalTimeSeries underlyingSeries = tsBundle.get(pointsCurveNode.getUnderlyingDataField(), pointsCurveNode.getUnderlyingIdentifier());
if (underlyingSeries == null) {
throw new OpenGammaRuntimeException("Could not get time series for id " + pointsCurveNode.getUnderlyingIdentifier() + " and data field " + pointsCurveNode.getUnderlyingDataField());
}
pnlSeries = getReturnSeries(ts.getTimeSeries().add(underlyingSeries.getTimeSeries()), desiredValue, executionContext);
} else {
pnlSeries = getReturnSeries(ts.getTimeSeries(), desiredValue, executionContext);
}
tenors[i] = curveNode.getCurveNode().getResolvedMaturity();
returnSeries[i] = pnlSeries.multiply(sensitivity * position.getQuantity().doubleValue());
}
final TenorLabelledLocalDateDoubleTimeSeriesMatrix1D matrix = new TenorLabelledLocalDateDoubleTimeSeriesMatrix1D(tenors, labels, returnSeries);
final ValueProperties properties = desiredValue.getConstraints().copy()
.withoutAny(CURRENCY)
.with(CURRENCY, currency)