/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.analytics.model.curve.interestrate;
import static com.opengamma.financial.analytics.model.curve.interestrate.MultiYieldCurvePropertiesAndDefaults.PROPERTY_DECOMPOSITION;
import static com.opengamma.financial.analytics.model.curve.interestrate.MultiYieldCurvePropertiesAndDefaults.PROPERTY_ROOT_FINDER_ABSOLUTE_TOLERANCE;
import static com.opengamma.financial.analytics.model.curve.interestrate.MultiYieldCurvePropertiesAndDefaults.PROPERTY_ROOT_FINDER_MAX_ITERATIONS;
import static com.opengamma.financial.analytics.model.curve.interestrate.MultiYieldCurvePropertiesAndDefaults.PROPERTY_ROOT_FINDER_RELATIVE_TOLERANCE;
import static com.opengamma.financial.analytics.model.curve.interestrate.MultiYieldCurvePropertiesAndDefaults.PROPERTY_USE_FINITE_DIFFERENCE;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Sets;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.analytics.financial.interestrate.YieldCurveBundle;
import com.opengamma.analytics.financial.model.interestrate.curve.YieldAndDiscountCurve;
import com.opengamma.engine.ComputationTarget;
import com.opengamma.engine.ComputationTargetSpecification;
import com.opengamma.engine.function.AbstractFunction;
import com.opengamma.engine.function.FunctionCompilationContext;
import com.opengamma.engine.function.FunctionInputs;
import com.opengamma.engine.target.ComputationTargetType;
import com.opengamma.engine.value.ValueProperties;
import com.opengamma.engine.value.ValuePropertyNames;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.engine.value.ValueRequirementNames;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.financial.analytics.ircurve.InterpolatedYieldCurveSpecificationWithSecurities;
import com.opengamma.financial.analytics.ircurve.YieldCurveData;
import com.opengamma.financial.analytics.ircurve.YieldCurveDefinition;
import com.opengamma.financial.analytics.ircurve.calcconfig.ConfigDBCurveCalculationConfigSource;
import com.opengamma.financial.analytics.ircurve.calcconfig.MultiCurveCalculationConfig;
import com.opengamma.financial.analytics.model.curve.MultiCurveFunction;
import com.opengamma.financial.analytics.timeseries.HistoricalTimeSeriesBundle;
/**
* Base class for functions that construct yield curves and the Jacobian from {@link YieldCurveDefinition} and {@link MultiCurveCalculationConfig}s using root-finding.
*
* @deprecated This function uses configuration objects that have been superseded. Use functions that descend from {@link MultiCurveFunction}
*/
@Deprecated
public abstract class MultiYieldCurveFunction extends AbstractFunction.NonCompiledInvoker {
/** The logger */
private static final Logger s_logger = LoggerFactory.getLogger(MultiYieldCurveFunction.class);
private ConfigDBCurveCalculationConfigSource _curveCalculationConfigSource;
@Override
public void init(final FunctionCompilationContext context) {
_curveCalculationConfigSource = ConfigDBCurveCalculationConfigSource.init(context, this);
}
@Override
public ComputationTargetType getTargetType() {
return ComputationTargetType.CURRENCY;
}
@Override
public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target) {
final ValueProperties curveProperties = getCurveProperties();
final ValueProperties properties = getJacobianProperties();
final ValueSpecification curve = new ValueSpecification(ValueRequirementNames.YIELD_CURVE, target.toSpecification(), curveProperties);
final ValueSpecification jacobian = new ValueSpecification(ValueRequirementNames.YIELD_CURVE_JACOBIAN, target.toSpecification(), properties);
return Sets.newHashSet(curve, jacobian);
}
@Override
public Set<ValueRequirement> getRequirements(final FunctionCompilationContext context, final ComputationTarget target, final ValueRequirement desiredValue) {
final ValueProperties constraints = desiredValue.getConstraints();
final String curveCalculationConfigName = constraints.getStrictValue(ValuePropertyNames.CURVE_CALCULATION_CONFIG);
if (curveCalculationConfigName == null) {
return null;
}
final MultiCurveCalculationConfig curveCalculationConfig = _curveCalculationConfigSource.getConfig(curveCalculationConfigName);
if (curveCalculationConfig == null) {
s_logger.error("Could not find curve calculation configuration named {}", curveCalculationConfigName);
return null;
}
if (!curveCalculationConfig.getCalculationMethod().equals(getCalculationMethod())) {
return null;
}
if (!curveCalculationConfig.getTarget().equals(target.toSpecification())) {
s_logger.warn("Invalid target for {}, was {} - expected {}", curveCalculationConfigName, target, curveCalculationConfig.getTarget());
return null;
}
final String absoluteTolerance = constraints.getStrictValue(PROPERTY_ROOT_FINDER_ABSOLUTE_TOLERANCE);
if (absoluteTolerance == null) {
return null;
}
final String relativeTolerance = constraints.getStrictValue(PROPERTY_ROOT_FINDER_RELATIVE_TOLERANCE);
if (relativeTolerance == null) {
return null;
}
final String maxIteration = constraints.getStrictValue(PROPERTY_ROOT_FINDER_MAX_ITERATIONS);
if (maxIteration == null) {
return null;
}
final String decomposition = constraints.getStrictValue(PROPERTY_DECOMPOSITION);
if (decomposition == null) {
return null;
}
final String finiteDifference = constraints.getStrictValue(PROPERTY_USE_FINITE_DIFFERENCE);
if (finiteDifference == null) {
return null;
}
final String[] curveNames = curveCalculationConfig.getYieldCurveNames();
final Set<ValueRequirement> requirements = new HashSet<>();
final ComputationTargetSpecification targetSpec = target.toSpecification();
for (final String curveName : curveNames) {
final ValueProperties properties = ValueProperties.builder().with(ValuePropertyNames.CURVE, curveName).with(ValuePropertyNames.CURVE_CALCULATION_CONFIG, curveCalculationConfigName)
.withOptional(ValuePropertyNames.CURVE_CALCULATION_CONFIG).get();
final ValueProperties curveTSProperties = ValueProperties.builder().with(ValuePropertyNames.CURVE_CALCULATION_CONFIG, curveCalculationConfigName).get();
requirements.add(new ValueRequirement(ValueRequirementNames.YIELD_CURVE_DATA, targetSpec, properties));
requirements.add(new ValueRequirement(ValueRequirementNames.YIELD_CURVE_SPEC, targetSpec, properties));
requirements.add(new ValueRequirement(ValueRequirementNames.YIELD_CURVE_INSTRUMENT_CONVERSION_HISTORICAL_TIME_SERIES, targetSpec, curveTSProperties));
}
if (curveCalculationConfig.getExogenousConfigData() != null) {
final LinkedHashMap<String, String[]> exogenousCurveConfigs = curveCalculationConfig.getExogenousConfigData();
for (final Map.Entry<String, String[]> entry : exogenousCurveConfigs.entrySet()) {
for (final String exogenousCurveName : entry.getValue()) {
final ValueProperties properties = ValueProperties.builder().with(ValuePropertyNames.CURVE_CALCULATION_CONFIG, entry.getKey()).with(ValuePropertyNames.CURVE, exogenousCurveName)
.with(PROPERTY_DECOMPOSITION, decomposition).with(PROPERTY_ROOT_FINDER_ABSOLUTE_TOLERANCE, absoluteTolerance).with(PROPERTY_ROOT_FINDER_MAX_ITERATIONS, maxIteration)
.with(PROPERTY_ROOT_FINDER_RELATIVE_TOLERANCE, relativeTolerance).with(PROPERTY_USE_FINITE_DIFFERENCE, finiteDifference).get();
requirements.add(new ValueRequirement(ValueRequirementNames.YIELD_CURVE, targetSpec, properties));
}
}
}
return requirements;
}
@Override
public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target, final Map<ValueSpecification, ValueRequirement> inputs) {
final Set<ValueSpecification> results = new HashSet<>();
final ComputationTargetSpecification targetSpec = target.toSpecification();
String curveCalculationConfigName = null;
for (final Map.Entry<ValueSpecification, ValueRequirement> entry : inputs.entrySet()) {
final ValueRequirement value = entry.getValue();
if (value.getValueName().equals(ValueRequirementNames.YIELD_CURVE_SPEC)) {
if (curveCalculationConfigName == null) {
curveCalculationConfigName = value.getConstraint(ValuePropertyNames.CURVE_CALCULATION_CONFIG);
} else {
if (!value.getConstraint(ValuePropertyNames.CURVE_CALCULATION_CONFIG).equals(curveCalculationConfigName)) {
throw new OpenGammaRuntimeException("Had different curve calculation configuration names; should never happen");
}
}
final String curveName = value.getConstraint(ValuePropertyNames.CURVE);
final ValueProperties curveProperties = getCurveProperties(curveCalculationConfigName, curveName);
final ValueSpecification spec = new ValueSpecification(ValueRequirementNames.YIELD_CURVE, targetSpec, curveProperties);
results.add(spec);
}
}
if (curveCalculationConfigName == null) {
return null;
}
final ValueProperties properties = getJacobianProperties(curveCalculationConfigName);
final ValueSpecification jacobian = new ValueSpecification(ValueRequirementNames.YIELD_CURVE_JACOBIAN, targetSpec, properties);
results.add(jacobian);
return results;
}
/**
* Gets the Jacobian properties with no values set.
*
* @return The properties for the Jacobian
*/
protected abstract ValueProperties getJacobianProperties();
/**
* Gets the yield curve properties with no values set.
*
* @return The properties for the curve
*/
protected abstract ValueProperties getCurveProperties();
/**
* Gets the Jacobian properties with the curve calculation configuration name set.
*
* @param curveCalculationConfigName The curve calculation configuration name
* @return The properties for the Jacobian
*/
protected abstract ValueProperties getJacobianProperties(final String curveCalculationConfigName);
/**
* Gets properties for a single yield curve with the curve calculation configuration name and curve. name set.
*
* @param curveCalculationConfigName The curve calculation configuration name
* @param curveName The curve name
* @return The properties for the curve
*/
protected abstract ValueProperties getCurveProperties(final String curveCalculationConfigName, final String curveName);
/**
* Gets the Jacobian properties with all values set.
*
* @param curveCalculationConfigName The curve calculation configuration name
* @param absoluteTolerance The absolute tolerance
* @param relativeTolerance The relative tolerance
* @param maxIterations The maximum number of iterations
* @param decomposition The decomposition
* @param useFiniteDifference True if finite difference was used to calculate the derivative
* @return The properties for the Jacobian
*/
protected abstract ValueProperties getJacobianProperties(final String curveCalculationConfigName, final String absoluteTolerance, final String relativeTolerance,
final String maxIterations, final String decomposition, final String useFiniteDifference);
/**
* Gets properties for a single yield curve all values set. name set.
*
* @param curveCalculationConfigName The curve calculation configuration name
* @param curveName The curve name
* @param absoluteTolerance The absolute tolerance
* @param relativeTolerance The relative tolerance
* @param maxIterations The maximum number of iterations
* @param decomposition The decomposition
* @param useFiniteDifference True if finite difference was used to calculate the derivative
* @return The properties for the curve
*/
protected abstract ValueProperties getCurveProperties(final String curveCalculationConfigName, final String curveName, final String absoluteTolerance, final String relativeTolerance,
final String maxIterations, final String decomposition, final String useFiniteDifference);
/**
* Gets the curve calculation method.
*
* @return The curve calculation method
*/
protected abstract String getCalculationMethod();
/**
* Gets the snapshot containing the market data from the function inputs.
*
* @param inputs The inputs
* @param targetSpec The specification of the market data
* @param curveName The curve name
* @return The market data snapshot
* @throws OpenGammaRuntimeException if the snapshot is not present in the inputs
*/
protected YieldCurveData getMarketData(final FunctionInputs inputs, final ComputationTargetSpecification targetSpec, final String curveName) {
ValueProperties constraints = ValueProperties.with(ValuePropertyNames.CURVE, curveName).get();
final ValueRequirement marketDataRequirement =
new ValueRequirement(ValueRequirementNames.YIELD_CURVE_DATA, targetSpec, constraints);
final Object marketDataObject = inputs.getValue(marketDataRequirement);
if (marketDataObject == null) {
throw new OpenGammaRuntimeException("Could not get a value for requirement " + marketDataRequirement);
}
return (YieldCurveData) marketDataObject;
}
/**
* Gets the bundle containing historical fixing from the function inputs.
*
* @param inputs The inputs
* @param targetSpec The specification of the historical data
* @param curveCalculationConfigName The curve calculation configuration name
* @return The bundle
* @throws OpenGammaRuntimeException if the bundle is not present in the inputs
*/
protected HistoricalTimeSeriesBundle getTimeSeriesBundle(final FunctionInputs inputs, final ComputationTargetSpecification targetSpec, final String curveCalculationConfigName) {
final ValueRequirement timeSeriesRequirement = new ValueRequirement(ValueRequirementNames.YIELD_CURVE_INSTRUMENT_CONVERSION_HISTORICAL_TIME_SERIES, targetSpec, ValueProperties.with(
ValuePropertyNames.CURVE_CALCULATION_CONFIG, curveCalculationConfigName).get());
final Object timeSeriesObject = inputs.getValue(timeSeriesRequirement);
if (timeSeriesObject == null) {
throw new OpenGammaRuntimeException("Could not get conversion time series for requirement " + timeSeriesRequirement);
}
return (HistoricalTimeSeriesBundle) timeSeriesObject;
}
/**
* Gets the interpolated yield curve specification from the function inputs
*
* @param inputs The inputs
* @param targetSpec The specification of the interpolated yield curve
* @param curveName The curve name
* @return The specification
* @throws OpenGammaRuntimeException if the specification is not present in the inputs
*/
protected InterpolatedYieldCurveSpecificationWithSecurities getYieldCurveSpecification(final FunctionInputs inputs, final ComputationTargetSpecification targetSpec, final String curveName) {
final ValueRequirement specRequirement = new ValueRequirement(ValueRequirementNames.YIELD_CURVE_SPEC, targetSpec, ValueProperties.with(ValuePropertyNames.CURVE, curveName).get());
final Object specObject = inputs.getValue(specRequirement);
if (specObject == null) {
return null;
}
final InterpolatedYieldCurveSpecificationWithSecurities spec = (InterpolatedYieldCurveSpecificationWithSecurities) specObject;
return spec;
}
/**
* Gets any known (i.e. exogenous) curves from the function inputs. These curves are held fixed during fitting.
*
* @param curveCalculationConfig The curve calculation configuration
* @param targetSpec The specification of the known curves
* @param inputs The inputs
* @return A yield curve bundle containing the curves or null if none of the curves are known before fitting
* @throws OpenGammaRuntimeException If an exogenous curve is required but is not present in the inputs
*/
protected YieldCurveBundle getKnownCurves(final MultiCurveCalculationConfig curveCalculationConfig, final ComputationTargetSpecification targetSpec, final FunctionInputs inputs) {
YieldCurveBundle knownCurves = null;
if (curveCalculationConfig.getExogenousConfigData() != null) {
knownCurves = new YieldCurveBundle();
final LinkedHashMap<String, String[]> exogenousCurveNames = curveCalculationConfig.getExogenousConfigData();
for (final Map.Entry<String, String[]> entry : exogenousCurveNames.entrySet()) {
for (final String exogenousCurveName : entry.getValue()) {
final ValueProperties properties = ValueProperties.builder().with(ValuePropertyNames.CURVE, exogenousCurveName).get();
final Object exogenousCurveObject = inputs.getValue(new ValueRequirement(ValueRequirementNames.YIELD_CURVE, targetSpec, properties));
if (exogenousCurveObject == null) {
throw new OpenGammaRuntimeException("Could not get exogenous curve named " + exogenousCurveName);
}
final YieldAndDiscountCurve exogenousCurve = (YieldAndDiscountCurve) exogenousCurveObject;
knownCurves.setCurve(exogenousCurveName, exogenousCurve);
}
}
}
return knownCurves;
}
protected ConfigDBCurveCalculationConfigSource getCurveCalculationConfigSource() {
return _curveCalculationConfigSource;
}
}