/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.sesame.function.scenarios.curvedata; import java.util.HashMap; import java.util.Map; import java.util.Set; import com.opengamma.financial.analytics.curve.CurveSpecification; import com.opengamma.financial.analytics.ircurve.strips.CurveNode; import com.opengamma.financial.analytics.ircurve.strips.CurveNodeWithIdentifier; import com.opengamma.financial.analytics.ircurve.strips.RateFutureNode; import com.opengamma.id.ExternalId; import com.opengamma.id.ExternalIdBundle; import com.opengamma.sesame.function.scenarios.ScenarioArgument; import com.opengamma.util.ArgumentChecker; /** * Performs a parallel shift on a set of curve data if the curve matches the {@link CurveSpecificationMatcher matcher}. * * @deprecated use the new scenario framework */ @Deprecated public abstract class CurveDataShift implements ScenarioArgument<CurveDataShift, CurveDataShiftDecorator> { /** Curves are only shifted if they match this matcher. */ private final CurveSpecificationMatcher _matcher; /** The amount to add to each point on the curve. */ private final double _shiftAmount; @Override public Class<CurveDataShiftDecorator> getFunctionType() { return CurveDataShiftDecorator.class; } /** * Creates a shift that adds an absolute amount to each market data point in the curve. * * @param shiftAmount the amount to add to each point * @param matcher for deciding whether a curve should be shifted */ protected CurveDataShift(double shiftAmount, CurveSpecificationMatcher matcher) { _shiftAmount = shiftAmount; _matcher = ArgumentChecker.notNull(matcher, "matcher"); } /** * Returns a new map of values containing the data in the input map with shifts applied. * Shifts are only applied if the curve specification matches the matcher. * * @param curveSpec specification of the curve * @param values market data of the curve's points, keyed by identifier * @return the shifted values */ public Map<ExternalIdBundle, Double> apply(CurveSpecification curveSpec, Map<ExternalIdBundle, Double> values) { if (!_matcher.matches(curveSpec)) { return values; } Map<ExternalIdBundle, Double> results = new HashMap<>(values.size()); Map<ExternalId, CurveNode> nodeMap = createNodeMap(curveSpec); for (Map.Entry<ExternalIdBundle, Double> entry : values.entrySet()) { ExternalIdBundle idBundle = entry.getKey(); Double value = entry.getValue(); CurveNode node = getNode(idBundle, nodeMap); double shiftedValue; // futures are quoted the other way round, i.e. (1 - value) if (node instanceof RateFutureNode) { shiftedValue = 1 - shift(1 - value); } else { shiftedValue = shift(value); } results.put(idBundle, shiftedValue); } return results; } private static Map<ExternalId, CurveNode> createNodeMap(CurveSpecification curveSpec) { Set<CurveNodeWithIdentifier> nodes = curveSpec.getNodes(); Map<ExternalId, CurveNode> nodeMap = new HashMap<>(nodes.size()); for (CurveNodeWithIdentifier node : nodes) { nodeMap.put(node.getIdentifier(), node.getCurveNode()); } return nodeMap; } private static CurveNode getNode(ExternalIdBundle idBundle, Map<ExternalId, CurveNode> nodeMap) { for (ExternalId id : idBundle) { CurveNode node = nodeMap.get(id); if (node != null) { return node; } } // this should never happen throw new IllegalArgumentException("No curve node found for ID bundle " + idBundle + " in map " + nodeMap); } /** * @return the shift amount to apply to the curve data. */ protected double getShiftAmount() { return _shiftAmount; } /** * Shifts a single value. Only invoked if the curve matches the matcher. If the curve data is quoted the other * way up (e.g. for futures) it is inverted before calling this method. * * @param normalizedValue the value * @return the shifted value */ protected abstract double shift(double normalizedValue); }