/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.interestrate; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map.Entry; import org.apache.commons.lang.ObjectUtils; import com.opengamma.analytics.financial.forex.method.FXMatrix; import com.opengamma.analytics.math.interpolation.Interpolator1D; import com.opengamma.util.ArgumentChecker; /** * @deprecated {@link YieldCurveBundle} is deprecated */ @Deprecated public class MultipleYieldCurveFinderDataBundle { private final List<InstrumentDerivative> _derivatives; private final double[] _marketValues; private final YieldCurveBundle _knownCurves; private final LinkedHashMap<String, double[]> _unknownCurveNodePoints; private final LinkedHashMap<String, Interpolator1D> _unknownCurveInterpolators; private final int _totalNodes; private final List<String> _names; private final boolean _useFiniteDifferenceByDefault; private final FXMatrix _fxMatrix; /** * Private constructor from all the stored data. No check is performed; they are done in the public methods. * @param derivatives The list of instruments used in the calibration. * @param marketValues The market value of the instruments. * @param knownCurves The curves already calibrated. * @param unknownCurveNodePoints The node points of the new curves to calibrate. * @param unknownCurveInterpolators The interpolators of the new curves to calibrate. * @param useFiniteDifferenceByDefault Flag for using the finite difference computation of the Jacobian. * @param fxMatrix The FX Matrix with the required exchange rates. * @param totalNodes The total number of nodes. * @param names The names of the curves used for matrix evaluation. */ private MultipleYieldCurveFinderDataBundle(final List<InstrumentDerivative> derivatives, final double[] marketValues, final YieldCurveBundle knownCurves, final LinkedHashMap<String, double[]> unknownCurveNodePoints, final LinkedHashMap<String, Interpolator1D> unknownCurveInterpolators, final boolean useFiniteDifferenceByDefault, final FXMatrix fxMatrix, final int totalNodes, final List<String> names) { _derivatives = derivatives; _marketValues = marketValues; _knownCurves = knownCurves; _unknownCurveNodePoints = unknownCurveNodePoints; _unknownCurveInterpolators = unknownCurveInterpolators; _useFiniteDifferenceByDefault = useFiniteDifferenceByDefault; _fxMatrix = fxMatrix; _totalNodes = totalNodes; _names = names; } public MultipleYieldCurveFinderDataBundle(final List<InstrumentDerivative> derivatives, final double[] marketValues, final YieldCurveBundle knownCurves, final LinkedHashMap<String, double[]> unknownCurveNodePoints, final LinkedHashMap<String, Interpolator1D> unknownCurveInterpolators, final boolean useFiniteDifferenceByDefault, final FXMatrix fxMatrix) { ArgumentChecker.notNull(derivatives, "derivatives"); ArgumentChecker.noNulls(derivatives, "derivatives"); ArgumentChecker.notNull(marketValues, "market values null"); ArgumentChecker.notNull(unknownCurveNodePoints, "unknown curve node points"); ArgumentChecker.notNull(unknownCurveInterpolators, "unknown curve interpolators"); ArgumentChecker.notEmpty(unknownCurveNodePoints, "unknown curve node points"); ArgumentChecker.notEmpty(unknownCurveInterpolators, "unknown curve interpolators"); ArgumentChecker.isTrue(derivatives.size() == marketValues.length, "marketValues wrong length; must be one par rate per derivative (have {} values for {} derivatives", marketValues.length, derivatives.size()); ArgumentChecker.notNull(fxMatrix, "FX matrix"); if (knownCurves != null) { for (final String name : knownCurves.getAllNames()) { if (unknownCurveInterpolators.containsKey(name)) { throw new IllegalArgumentException("Curve name in known set matches one to be solved for"); } } _knownCurves = knownCurves; } else { _knownCurves = null; } _derivatives = derivatives; _marketValues = marketValues; if (unknownCurveNodePoints.size() != unknownCurveInterpolators.size()) { throw new IllegalArgumentException("Number of unknown curves not the same as curve interpolators"); } final Iterator<Entry<String, double[]>> nodePointsIterator = unknownCurveNodePoints.entrySet().iterator(); final Iterator<Entry<String, Interpolator1D>> unknownCurvesIterator = unknownCurveInterpolators.entrySet().iterator(); _names = new ArrayList<>(); while (nodePointsIterator.hasNext()) { final Entry<String, double[]> entry1 = nodePointsIterator.next(); final Entry<String, Interpolator1D> entry2 = unknownCurvesIterator.next(); final String name1 = entry1.getKey(); if (!name1.equals(entry2.getKey())) { throw new IllegalArgumentException("Names must be the same"); } ArgumentChecker.notNull(entry1.getValue(), "curve node points for " + name1); ArgumentChecker.notNull(entry2.getValue(), "interpolator for " + name1); _names.add(name1); } int nNodes = 0; for (final double[] nodes : unknownCurveNodePoints.values()) { nNodes += nodes.length; } if (nNodes > derivatives.size()) { throw new IllegalArgumentException("Total number of nodes (" + nNodes + ") is greater than the number of instruments (" + derivatives.size() + ")"); } _totalNodes = nNodes; _unknownCurveNodePoints = unknownCurveNodePoints; _unknownCurveInterpolators = unknownCurveInterpolators; _useFiniteDifferenceByDefault = useFiniteDifferenceByDefault; _fxMatrix = fxMatrix; } /** * Create a MultipleYieldCurveFinderDataBundle where the number of nodes and the list of curve names correspond to all the curves (known curves and curves still to be calibrated). * This constructor is used to compute the extended Jacobian matrix when curves are calibrated in several blocks. * @param derivatives The list of instruments used in the calibration. * @param marketValues The market value of the instruments. * @param knownCurves The curves already calibrated. * @param unknownCurveNodePoints The node points of the new curves to calibrate. * @param unknownCurveInterpolators The interpolators of the new curves to calibrate. * @param useFiniteDifferenceByDefault Flag for using the finite difference computation of the Jacobian. * @param fxMatrix The FX Matrix with the required exchange rates. * @return The data bundle. */ public static MultipleYieldCurveFinderDataBundle withAllCurves(final List<InstrumentDerivative> derivatives, final double[] marketValues, final YieldCurveBundle knownCurves, final LinkedHashMap<String, double[]> unknownCurveNodePoints, final LinkedHashMap<String, Interpolator1D> unknownCurveInterpolators, final boolean useFiniteDifferenceByDefault, final FXMatrix fxMatrix) { // Argument checker: start ArgumentChecker.notNull(derivatives, "derivatives"); ArgumentChecker.noNulls(derivatives, "derivatives"); ArgumentChecker.notNull(marketValues, "market values null"); ArgumentChecker.notNull(unknownCurveNodePoints, "unknown curve node points"); ArgumentChecker.notNull(unknownCurveInterpolators, "unknown curve interpolators"); ArgumentChecker.notEmpty(unknownCurveNodePoints, "unknown curve node points"); ArgumentChecker.notEmpty(unknownCurveInterpolators, "unknown curve interpolators"); ArgumentChecker.isTrue(derivatives.size() == marketValues.length, "marketValues wrong length; must be one par rate per derivative (have {} values for {} derivatives", marketValues.length, derivatives.size()); ArgumentChecker.notNull(fxMatrix, "FX matrix"); if (knownCurves != null) { for (final String name : knownCurves.getAllNames()) { if (unknownCurveInterpolators.containsKey(name)) { throw new IllegalArgumentException("Curve name in known set matches one to be solved for"); } } } if (unknownCurveNodePoints.size() != unknownCurveInterpolators.size()) { throw new IllegalArgumentException("Number of unknown curves not the same as curve interpolators"); } // Argument checker: end int nbNodes = 0; if (knownCurves != null) { for (final String name : knownCurves.getAllNames()) { nbNodes += knownCurves.getCurve(name).getNumberOfParameters(); } } for (final double[] nodes : unknownCurveNodePoints.values()) { // Nodes from new curves nbNodes += nodes.length; } final List<String> names = new ArrayList<>(); if (knownCurves != null) { names.addAll(knownCurves.getAllNames()); // Names from existing curves } final Iterator<Entry<String, double[]>> nodePointsIterator = unknownCurveNodePoints.entrySet().iterator(); final Iterator<Entry<String, Interpolator1D>> unknownCurvesIterator = unknownCurveInterpolators.entrySet().iterator(); while (nodePointsIterator.hasNext()) { // Names from new curves final Entry<String, double[]> entry1 = nodePointsIterator.next(); final Entry<String, Interpolator1D> entry2 = unknownCurvesIterator.next(); final String name1 = entry1.getKey(); if (!name1.equals(entry2.getKey())) { throw new IllegalArgumentException("Names must be the same"); } ArgumentChecker.notNull(entry1.getValue(), "curve node points for " + name1); ArgumentChecker.notNull(entry2.getValue(), "interpolator for " + name1); names.add(name1); } return new MultipleYieldCurveFinderDataBundle(derivatives, marketValues, knownCurves, unknownCurveNodePoints, unknownCurveInterpolators, useFiniteDifferenceByDefault, fxMatrix, nbNodes, names); } public List<InstrumentDerivative> getDerivatives() { return _derivatives; } public YieldCurveBundle getKnownCurves() { return _knownCurves; } public LinkedHashMap<String, double[]> getUnknownCurveNodePoints() { return _unknownCurveNodePoints; } public LinkedHashMap<String, Interpolator1D> getUnknownCurveInterpolators() { return _unknownCurveInterpolators; } public int getNumInstruments() { return _derivatives.size(); } public int getTotalNodes() { return _totalNodes; } public InstrumentDerivative getDerivative(final int i) { return _derivatives.get(i); } public double getMarketValue(final int i) { return _marketValues[i]; } public boolean useFiniteDifferenceForNodeSensitivities() { return _useFiniteDifferenceByDefault; } public FXMatrix getFXMatrix() { return _fxMatrix; } public double[] getCurveNodePointsForCurve(final String name) { ArgumentChecker.notNull(name, "name"); final double[] result = _unknownCurveNodePoints.get(name); if (result == null) { throw new IllegalArgumentException("Data for name " + name + " not found"); } return result; } public int getNumberOfPointsForCurve(final String name) { ArgumentChecker.notNull(name, "name"); if (_unknownCurveNodePoints.containsKey(name)) { return _unknownCurveNodePoints.get(name).length; } if (_knownCurves != null) { if (_knownCurves.containsName(name)) { return _knownCurves.getCurve(name).getNumberOfParameters(); } } throw new IllegalArgumentException("Data for name " + name + " not found"); } public Interpolator1D getInterpolatorForCurve(final String name) { ArgumentChecker.notNull(name, "name"); final Interpolator1D result = _unknownCurveInterpolators.get(name); if (result == null) { throw new IllegalArgumentException("Data for name " + name + " not found"); } return result; } public List<String> getCurveNames() { return _names; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + _derivatives.hashCode(); result = prime * result + ((_knownCurves == null) ? 0 : _knownCurves.hashCode()); result = prime * result + Arrays.hashCode(_marketValues); result = prime * result + _unknownCurveInterpolators.hashCode(); result = prime * result + _unknownCurveNodePoints.hashCode(); result = prime * result + (_useFiniteDifferenceByDefault ? 1231 : 1237); result = prime * result + _fxMatrix.hashCode(); return result; } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final MultipleYieldCurveFinderDataBundle other = (MultipleYieldCurveFinderDataBundle) obj; if (!Arrays.equals(_marketValues, other._marketValues)) { return false; } if (!ObjectUtils.equals(_derivatives, other._derivatives)) { return false; } if (!ObjectUtils.equals(_knownCurves, other._knownCurves)) { return false; } if (!ObjectUtils.equals(_unknownCurveInterpolators, other._unknownCurveInterpolators)) { return false; } if (!ObjectUtils.equals(_unknownCurveNodePoints, other._unknownCurveNodePoints)) { return false; } if (_useFiniteDifferenceByDefault != other._useFiniteDifferenceByDefault) { return false; } if (!ObjectUtils.equals(_fxMatrix, other._fxMatrix)) { return false; } return true; } }