Package com.opengamma.financial.analytics.model.curve.interestrate

Source Code of com.opengamma.financial.analytics.model.curve.interestrate.ImpliedDepositCurveSeriesFunction

/**
* Copyright (C) 2013 - 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.engine.value.ValuePropertyNames.CURVE;
import static com.opengamma.engine.value.ValuePropertyNames.CURVE_CALCULATION_CONFIG;
import static com.opengamma.engine.value.ValuePropertyNames.CURVE_CALCULATION_METHOD;
import static com.opengamma.engine.value.ValueRequirementNames.YIELD_CURVE_HISTORICAL_TIME_SERIES;
import static com.opengamma.engine.value.ValueRequirementNames.YIELD_CURVE_SERIES;
import static com.opengamma.engine.value.ValueRequirementNames.YIELD_CURVE_SPEC;
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 static com.opengamma.financial.analytics.timeseries.HistoricalTimeSeriesFunctionUtils.DATA_FIELD_PROPERTY;
import static com.opengamma.financial.analytics.timeseries.HistoricalTimeSeriesFunctionUtils.END_DATE_PROPERTY;
import static com.opengamma.financial.analytics.timeseries.HistoricalTimeSeriesFunctionUtils.INCLUDE_START_PROPERTY;
import static com.opengamma.financial.analytics.timeseries.HistoricalTimeSeriesFunctionUtils.RESOLUTION_KEY_PROPERTY;
import static com.opengamma.financial.analytics.timeseries.HistoricalTimeSeriesFunctionUtils.START_DATE_PROPERTY;
import static com.opengamma.financial.analytics.timeseries.HistoricalTimeSeriesFunctionUtils.YES_VALUE;
import static com.opengamma.financial.convention.percurrency.PerCurrencyConventionHelper.DEPOSIT;
import static com.opengamma.financial.convention.percurrency.PerCurrencyConventionHelper.SCHEME_NAME;
import static com.opengamma.financial.convention.percurrency.PerCurrencyConventionHelper.getConventionName;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.Instant;
import org.threeten.bp.LocalDate;
import org.threeten.bp.LocalTime;
import org.threeten.bp.ZoneOffset;
import org.threeten.bp.ZonedDateTime;

import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.analytics.financial.forex.method.FXMatrix;
import com.opengamma.analytics.financial.interestrate.InstrumentDerivative;
import com.opengamma.analytics.financial.interestrate.MultipleYieldCurveFinderDataBundle;
import com.opengamma.analytics.financial.interestrate.MultipleYieldCurveFinderFunction;
import com.opengamma.analytics.financial.interestrate.MultipleYieldCurveFinderJacobian;
import com.opengamma.analytics.financial.interestrate.ParRateCalculator;
import com.opengamma.analytics.financial.interestrate.ParRateCurveSensitivityCalculator;
import com.opengamma.analytics.financial.interestrate.YieldCurveBundle;
import com.opengamma.analytics.financial.interestrate.cash.derivative.Cash;
import com.opengamma.analytics.financial.interestrate.cash.method.CashDiscountingMethod;
import com.opengamma.analytics.financial.model.interestrate.curve.YieldAndDiscountCurve;
import com.opengamma.analytics.financial.model.interestrate.curve.YieldCurve;
import com.opengamma.analytics.math.curve.InterpolatedDoublesCurve;
import com.opengamma.analytics.math.function.Function1D;
import com.opengamma.analytics.math.interpolation.CombinedInterpolatorExtrapolator;
import com.opengamma.analytics.math.interpolation.CombinedInterpolatorExtrapolatorFactory;
import com.opengamma.analytics.math.interpolation.Interpolator1D;
import com.opengamma.analytics.math.linearalgebra.Decomposition;
import com.opengamma.analytics.math.linearalgebra.DecompositionFactory;
import com.opengamma.analytics.math.matrix.DoubleMatrix1D;
import com.opengamma.analytics.math.matrix.DoubleMatrix2D;
import com.opengamma.analytics.math.rootfinding.newton.BroydenVectorRootFinder;
import com.opengamma.analytics.math.rootfinding.newton.NewtonVectorRootFinder;
import com.opengamma.core.config.ConfigSource;
import com.opengamma.core.historicaltimeseries.HistoricalTimeSeries;
import com.opengamma.core.historicaltimeseries.impl.SimpleHistoricalTimeSeries;
import com.opengamma.core.holiday.HolidaySource;
import com.opengamma.core.value.MarketDataRequirementNames;
import com.opengamma.engine.ComputationTarget;
import com.opengamma.engine.ComputationTargetSpecification;
import com.opengamma.engine.function.AbstractFunction;
import com.opengamma.engine.function.CompiledFunctionDefinition;
import com.opengamma.engine.function.FunctionCompilationContext;
import com.opengamma.engine.function.FunctionExecutionContext;
import com.opengamma.engine.function.FunctionInputs;
import com.opengamma.engine.target.ComputationTargetType;
import com.opengamma.engine.value.ComputedValue;
import com.opengamma.engine.value.ValueProperties;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.engine.value.ValueRequirementNames;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.financial.OpenGammaCompilationContext;
import com.opengamma.financial.OpenGammaExecutionContext;
import com.opengamma.financial.analytics.conversion.CalendarUtils;
import com.opengamma.financial.analytics.ircurve.FixedIncomeStrip;
import com.opengamma.financial.analytics.ircurve.FixedIncomeStripWithSecurity;
import com.opengamma.financial.analytics.ircurve.InterpolatedYieldCurveSpecificationWithSecurities;
import com.opengamma.financial.analytics.ircurve.StripInstrumentType;
import com.opengamma.financial.analytics.ircurve.YieldCurveDefinition;
import com.opengamma.financial.analytics.ircurve.calcconfig.MultiCurveCalculationConfig;
import com.opengamma.financial.analytics.timeseries.HistoricalTimeSeriesBundle;
import com.opengamma.financial.analytics.timeseries.HistoricalTimeSeriesFunctionUtils;
import com.opengamma.financial.convention.ConventionSource;
import com.opengamma.financial.convention.DepositConvention;
import com.opengamma.financial.convention.businessday.BusinessDayConvention;
import com.opengamma.financial.convention.businessday.BusinessDayConventionFactory;
import com.opengamma.financial.convention.calendar.Calendar;
import com.opengamma.financial.convention.daycount.DayCount;
import com.opengamma.financial.convention.daycount.DayCountFactory;
import com.opengamma.financial.view.ConfigDocumentWatchSetProvider;
import com.opengamma.id.ExternalId;
import com.opengamma.id.ExternalIdBundle;
import com.opengamma.id.UniqueId;
import com.opengamma.timeseries.date.localdate.ImmutableLocalDateDoubleTimeSeries;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.async.AsynchronousExecution;
import com.opengamma.util.money.Currency;
import com.opengamma.util.time.Tenor;

/**
* Constructs a single yield curve and its Jacobian from an FX-implied yield curve calculation configuration
* and a yield curve definition that contains <b>only</b> {@link StripInstrumentType#CASH} strips. The transformation
* of the yield curve allows risk to be displayed with respect to implied deposit rates, not FX forwards.
*/
public class ImpliedDepositCurveSeriesFunction extends AbstractFunction {
  /** The calculation method property value */
  public static final String IMPLIED_DEPOSIT = "ImpliedDeposit";
  /** The Cash instrument method */
  private static final CashDiscountingMethod METHOD_CASH = CashDiscountingMethod.getInstance();
  /** Calculates the par rate */
  private static final ParRateCalculator PAR_RATE_CALCULATOR = ParRateCalculator.getInstance();
  /** Calculates the sensitivity of the par rate to the curves */
  private static final ParRateCurveSensitivityCalculator PAR_RATE_SENSITIVITY_CALCULATOR = ParRateCurveSensitivityCalculator.getInstance();
  /** The business day convention used for FX forward dates computation **/
  private static final BusinessDayConvention MOD_FOL = BusinessDayConventionFactory.INSTANCE.getBusinessDayConvention("Modified Following");
  /** The logger */
  private static final Logger s_logger = LoggerFactory.getLogger(ImpliedDepositCurveSeriesFunction.class);
  /** The curve name */
  private final String _impliedCurveCalculationConfig;

  /**
   * @param curveCalculationConfig The curve name, not null
   */
  public ImpliedDepositCurveSeriesFunction(final String curveCalculationConfig) {
    ArgumentChecker.notNull(curveCalculationConfig, "curve name");
    _impliedCurveCalculationConfig = curveCalculationConfig;
  }

  @Override
  public void init(final FunctionCompilationContext context) {
    ConfigDocumentWatchSetProvider.reinitOnChanges(context, this, MultiCurveCalculationConfig.class);
    ConfigDocumentWatchSetProvider.reinitOnChanges(context, this, YieldCurveDefinition.class);
  }

  @Override
  public CompiledFunctionDefinition compile(final FunctionCompilationContext context, final Instant atInstant) {
    final ConfigSource configurationSource = OpenGammaCompilationContext.getConfigSource(context);
    final MultiCurveCalculationConfig impliedConfiguration = configurationSource.getLatestByName(MultiCurveCalculationConfig.class, _impliedCurveCalculationConfig);
    if (impliedConfiguration == null) {
      throw new OpenGammaRuntimeException("Multi-curve calculation called " + _impliedCurveCalculationConfig + " was null");
    }
    ComputationTarget target = context.getComputationTargetResolver().resolve(impliedConfiguration.getTarget());
    if (!(target.getValue() instanceof Currency)) {
      throw new OpenGammaRuntimeException("Target of curve calculation configuration was not a currency");
    }
    final Currency impliedCurrency = (Currency) target.getValue();
    if (!IMPLIED_DEPOSIT.equals(impliedConfiguration.getCalculationMethod())) {
      throw new OpenGammaRuntimeException("Curve calculation method was not " + IMPLIED_DEPOSIT + " for configuration called " + _impliedCurveCalculationConfig);
    }
    final String[] impliedCurveNames = impliedConfiguration.getYieldCurveNames();
    if (impliedCurveNames.length != 1) {
      throw new OpenGammaRuntimeException("Can only handle configurations with a single implied curve");
    }
    final LinkedHashMap<String, String[]> originalConfigurationName = impliedConfiguration.getExogenousConfigData();
    if (originalConfigurationName == null || originalConfigurationName.size() != 1) {
      throw new OpenGammaRuntimeException("Need a configuration with one exogenous configuration");
    }
    final Map.Entry<String, String[]> entry = Iterables.getOnlyElement(originalConfigurationName.entrySet());
    final String[] originalCurveNames = entry.getValue();
    if (originalCurveNames.length != 1) {
      s_logger.warn("Found more than one exogenous configuration name; using only the first");
    }
    final MultiCurveCalculationConfig originalConfiguration = configurationSource.getLatestByName(MultiCurveCalculationConfig.class, entry.getKey());
    if (originalConfiguration == null) {
      throw new OpenGammaRuntimeException("Multi-curve calculation called " + entry.getKey() + " was null");
    }
    target = context.getComputationTargetResolver().resolve(originalConfiguration.getTarget());
    if (!(target.getValue() instanceof Currency)) {
      throw new OpenGammaRuntimeException("Target of curve calculation configuration was not a currency");
    }
    final Currency originalCurrency = (Currency) target.getValue();
    if (!originalCurrency.equals(impliedCurrency)) {
      throw new OpenGammaRuntimeException("Currency targets for configurations " + _impliedCurveCalculationConfig + " and " + entry.getKey() + " did not match");
    }
    final YieldCurveDefinition impliedDefinition = configurationSource.getLatestByName(YieldCurveDefinition.class, impliedCurveNames[0] + "_" + impliedCurrency.getCode());
    if (impliedDefinition == null) {
      throw new OpenGammaRuntimeException("Could not get implied definition called " + impliedCurveNames[0] + "_" + impliedCurrency.getCode());
    }
    final Set<FixedIncomeStrip> strips = impliedDefinition.getStrips();
    for (final FixedIncomeStrip strip : strips) {
      if (strip.getInstrumentType() != StripInstrumentType.CASH) {
        throw new OpenGammaRuntimeException("Can only handle yield curve definitions with CASH strips");
      }
    }
    final ZonedDateTime atZDT = ZonedDateTime.ofInstant(atInstant, ZoneOffset.UTC);
    return new MyCompiledFunction(atZDT.with(LocalTime.MIDNIGHT), atZDT.plusDays(1).with(LocalTime.MIDNIGHT).minusNanos(1000000),
        impliedConfiguration, impliedDefinition, originalConfiguration, originalCurveNames[0]);
  };

  private class MyCompiledFunction extends AbstractInvokingCompiledFunction {
    /** The definition of the implied curve */
    private final YieldCurveDefinition _impliedDefinition;
    /** The implied curve calculation configuration */
    private final MultiCurveCalculationConfig _impliedConfiguration;
    /** The original curve calculation configuration */
    private final MultiCurveCalculationConfig _originalConfiguration;
    /** The implied curve name */
    private final String _impliedCurveName;
    /** The original curve name */
    private final String _originalCurveName;
    /** The currency */
    private final Currency _currency;
    /** The interpolator */
    private final String _interpolatorName;
    /** The left extrapolator */
    private final String _leftExtrapolatorName;
    /** The right extrapolator */
    private final String _rightExtrapolatorName;

    public MyCompiledFunction(final ZonedDateTime earliestInvokation, final ZonedDateTime latestInvokation, final MultiCurveCalculationConfig impliedConfiguration,
        final YieldCurveDefinition impliedDefinition, final MultiCurveCalculationConfig originalConfiguration, final String originalCurveName) {
      super(earliestInvokation, latestInvokation);
      _impliedConfiguration = impliedConfiguration;
      _impliedDefinition = impliedDefinition;
      _originalConfiguration = originalConfiguration;
      _impliedCurveName = impliedDefinition.getName();
      _originalCurveName = originalCurveName;
      _currency = impliedDefinition.getCurrency();
      _interpolatorName = impliedDefinition.getInterpolatorName();
      _leftExtrapolatorName = impliedDefinition.getLeftExtrapolatorName();
      _rightExtrapolatorName = impliedDefinition.getRightExtrapolatorName();
    }

    @Override
    public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target,
        final Set<ValueRequirement> desiredValues) throws AsynchronousExecution {
      try {
        final ZonedDateTime now = ZonedDateTime.now(executionContext.getValuationClock());
        final Object originalCurveObject = inputs.getValue(YIELD_CURVE_SERIES);
        if (originalCurveObject == null) {
          throw new OpenGammaRuntimeException("Could not get original curve");
        }
        ValueProperties resultCurveProperties = null;
        String absoluteToleranceName = null;
        String relativeToleranceName = null;
        String iterationsName = null;
        String decompositionName = null;
        String useFiniteDifferenceName = null;
        for (final ValueRequirement desiredValue : desiredValues) {
          if (desiredValue.getValueName().equals(YIELD_CURVE_HISTORICAL_TIME_SERIES)) {
            absoluteToleranceName = desiredValue.getConstraint(MultiYieldCurvePropertiesAndDefaults.PROPERTY_ROOT_FINDER_ABSOLUTE_TOLERANCE);
            relativeToleranceName = desiredValue.getConstraint(MultiYieldCurvePropertiesAndDefaults.PROPERTY_ROOT_FINDER_RELATIVE_TOLERANCE);
            iterationsName = desiredValue.getConstraint(MultiYieldCurvePropertiesAndDefaults.PROPERTY_ROOT_FINDER_MAX_ITERATIONS);
            decompositionName = desiredValue.getConstraint(MultiYieldCurvePropertiesAndDefaults.PROPERTY_DECOMPOSITION);
            useFiniteDifferenceName = desiredValue.getConstraint(MultiYieldCurvePropertiesAndDefaults.PROPERTY_USE_FINITE_DIFFERENCE);
            resultCurveProperties = desiredValue.getConstraints().copy().get();
            break;
          }
        }
        if (resultCurveProperties == null) {
          throw new OpenGammaRuntimeException("Could not get result curve properties");
        }
        final YieldCurveBundle knownCurve = new YieldCurveBundle();
        final Map<LocalDate, YieldAndDiscountCurve> originalCurveSeries = (Map<LocalDate, YieldAndDiscountCurve>) originalCurveObject;
        final Map<FixedIncomeStrip, List<Double>> results = new HashMap<>();
        List<LocalDate> impliedRateDates = new ArrayList<>();

        for (final Map.Entry<LocalDate, YieldAndDiscountCurve> entry : originalCurveSeries.entrySet()) {
          final LocalDate valuationDate = entry.getKey();
          final ZonedDateTime valuationDateTime = ZonedDateTime.of(valuationDate, now.toLocalTime(), now.getZone());
          final HolidaySource holidaySource = OpenGammaExecutionContext.getHolidaySource(executionContext);
          final ConventionSource conventionSource = OpenGammaExecutionContext.getConventionSource(executionContext);
          final Calendar calendar = CalendarUtils.getCalendar(holidaySource, _currency);
          final DepositConvention convention = conventionSource.getConvention(DepositConvention.class, ExternalId.of(SCHEME_NAME, getConventionName(_currency, DEPOSIT)));
          final int spotLag = 0;
          final ExternalId conventionSettlementRegion = convention.getRegionCalendar();
          ZonedDateTime spotDate;
          if (spotLag == 0 && conventionSettlementRegion == null) {
            spotDate = valuationDateTime;
          } else {
            spotDate = valuationDateTime;
          }
          final YieldCurveBundle curves = new YieldCurveBundle();
          final String fullYieldCurveName = _originalCurveName + "_" + _currency;
          curves.setCurve(fullYieldCurveName, entry.getValue());
          final int n = _impliedDefinition.getStrips().size();
          final double[] t = new double[n];
          final double[] r = new double[n];
          int i = 0;
          final DayCount dayCount = DayCountFactory.INSTANCE.getDayCount("Act/360"); //TODO
          final String impliedDepositCurveName = _impliedCurveCalculationConfig + "_" + _currency.getCode();
          final List<InstrumentDerivative> derivatives = new ArrayList<>();
          for (final FixedIncomeStrip strip : _impliedDefinition.getStrips()) {
            final Tenor tenor = strip.getCurveNodePointTime();
            final ZonedDateTime paymentDate = spotDate.plus(tenor.getPeriod()); // ScheduleCalculator.getAdjustedDate(spotDate, tenor.getPeriod(), MOD_FOL, calendar, true);
            final double startTime = 0.0; // TimeCalculator.getTimeBetween(valuationDateTime, spotDate);
            final double endTime = tenor.getPeriod().toTotalMonths() / 12.0d; // TimeCalculator.getTimeBetween(valuationDateTime, paymentDate);
            final double accrualFactor = dayCount.getDayCountFraction(valuationDateTime, valuationDateTime.plus(tenor.getPeriod()), calendar);
            final Cash cashFXCurve = new Cash(_currency, startTime, endTime, 1, 0, accrualFactor, fullYieldCurveName);
            final double parRate = METHOD_CASH.parRate(cashFXCurve, curves);
            final Cash cashDepositCurve = new Cash(_currency, startTime, endTime, 1, 0, accrualFactor, impliedDepositCurveName);
            derivatives.add(cashDepositCurve);
            t[i] = endTime;
            r[i++] = parRate;
          }
          final CombinedInterpolatorExtrapolator interpolator = CombinedInterpolatorExtrapolatorFactory.getInterpolator(_interpolatorName, _leftExtrapolatorName,
              _rightExtrapolatorName);
          final double absoluteTolerance = Double.parseDouble(absoluteToleranceName);
          final double relativeTolerance = Double.parseDouble(relativeToleranceName);
          final int iterations = Integer.parseInt(iterationsName);
          final Decomposition<?> decomposition = DecompositionFactory.getDecomposition(decompositionName);
          final boolean useFiniteDifference = Boolean.parseBoolean(useFiniteDifferenceName);
          final LinkedHashMap<String, double[]> curveNodes = new LinkedHashMap<>();
          final LinkedHashMap<String, Interpolator1D> interpolators = new LinkedHashMap<>();
          curveNodes.put(impliedDepositCurveName, t);
          interpolators.put(impliedDepositCurveName, interpolator);
          final FXMatrix fxMatrix = new FXMatrix();
          final MultipleYieldCurveFinderDataBundle data = new MultipleYieldCurveFinderDataBundle(derivatives, r, knownCurve, curveNodes, interpolators, useFiniteDifference, fxMatrix);
          final NewtonVectorRootFinder rootFinder = new BroydenVectorRootFinder(absoluteTolerance, relativeTolerance, iterations, decomposition);
          final Function1D<DoubleMatrix1D, DoubleMatrix1D> curveCalculator = new MultipleYieldCurveFinderFunction(data, PAR_RATE_CALCULATOR);
          final Function1D<DoubleMatrix1D, DoubleMatrix2D> jacobianCalculator = new MultipleYieldCurveFinderJacobian(data, PAR_RATE_SENSITIVITY_CALCULATOR);

          final double[] fittedYields;
          try {
            fittedYields = rootFinder.getRoot(curveCalculator, jacobianCalculator, new DoubleMatrix1D(r)).getData();
            YieldCurve impliedCurve = new YieldCurve("Name", InterpolatedDoublesCurve.from(t, fittedYields, interpolator));

            final DoubleMatrix2D jacobianMatrix = jacobianCalculator.evaluate(new DoubleMatrix1D(fittedYields));

            impliedRateDates.add(valuationDate);

            i = 0;
            for (final FixedIncomeStrip strip : _impliedDefinition.getStrips()) {
              if (results.containsKey(strip)) {
                results.get(strip).add(fittedYields[i++]);
              } else {
                final List<Double> value = new ArrayList<>();
                value.add(fittedYields[i++]);
                results.put(strip, value);
              }
            }
          } catch (Throwable t2) {
            t2.printStackTrace();
            continue;
          }
        }
        final HistoricalTimeSeriesBundle bundle = new HistoricalTimeSeriesBundle();
        final Set<LocalDate> dates = originalCurveSeries.keySet();
        final InterpolatedYieldCurveSpecificationWithSecurities yieldCurveSpec = (InterpolatedYieldCurveSpecificationWithSecurities) inputs.getValue(YIELD_CURVE_SPEC);
        for (final FixedIncomeStripWithSecurity strip : yieldCurveSpec.getStrips()) {
          try {
            final ExternalId securityIdentifier = strip.getSecurityIdentifier();
            final UniqueId uid = UniqueId.of(securityIdentifier.getScheme().getName(), securityIdentifier.getValue());
            final ExternalIdBundle id = ExternalIdBundle.of(securityIdentifier);

            final HistoricalTimeSeries ts = new SimpleHistoricalTimeSeries(uid,
                ImmutableLocalDateDoubleTimeSeries.of(impliedRateDates, results.get(strip.getStrip())));

            bundle.add(MarketDataRequirementNames.MARKET_VALUE, id, ts);
          } catch (Exception e) {
            e.printStackTrace();
            break;
          }
        }
        final ValueSpecification curveSpec = new ValueSpecification(YIELD_CURVE_HISTORICAL_TIME_SERIES, target.toSpecification(), resultCurveProperties);

        return Collections.singleton(new ComputedValue(curveSpec, bundle));

      } catch (Throwable t3) {
        t3.printStackTrace();
        throw t3;
      }

    }

    @Override
    public ComputationTargetType getTargetType() {
      return ComputationTargetType.CURRENCY;
    }

    @Override
    public Set<ValueSpecification> getResults(final FunctionCompilationContext compilationContext, final ComputationTarget target) {
      final ValueProperties properties = getCurveTSProperties(IMPLIED_DEPOSIT, _impliedCurveName, _impliedCurveCalculationConfig);
      return Collections.singleton(new ValueSpecification(ValueRequirementNames.YIELD_CURVE_HISTORICAL_TIME_SERIES, target.toSpecification(), properties));
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FunctionCompilationContext compilationContext, final ComputationTarget target, final ValueRequirement desiredValue) {
      final String valueName = desiredValue.getValueName();
      final ValueProperties constraints = desiredValue.getConstraints();
      ValueProperties.Builder seriesConstraints = null;
      Set<String> values = desiredValue.getConstraints().getValues(DATA_FIELD_PROPERTY);
      if ((values == null) || values.isEmpty()) {
        seriesConstraints = desiredValue.getConstraints().copy().with(DATA_FIELD_PROPERTY, MarketDataRequirementNames.MARKET_VALUE);
      } else if (values.size() > 1) {
        seriesConstraints = desiredValue.getConstraints().copy().withoutAny(DATA_FIELD_PROPERTY)
            .with(DATA_FIELD_PROPERTY, values.iterator().next());
      }
      values = desiredValue.getConstraints().getValues(RESOLUTION_KEY_PROPERTY);
      if ((values == null) || values.isEmpty()) {
        if (seriesConstraints == null) {
          seriesConstraints = desiredValue.getConstraints().copy();
        }
        seriesConstraints.with(RESOLUTION_KEY_PROPERTY, "");
      } else if (values.size() > 1) {
        if (seriesConstraints == null) {
          seriesConstraints = desiredValue.getConstraints().copy();
        }
        seriesConstraints.withoutAny(RESOLUTION_KEY_PROPERTY).with(RESOLUTION_KEY_PROPERTY, values.iterator().next());
      }
      values = desiredValue.getConstraints().getValues(START_DATE_PROPERTY);
      if ((values == null) || values.isEmpty()) {
        if (seriesConstraints == null) {
          seriesConstraints = desiredValue.getConstraints().copy();
        }
        seriesConstraints.with(START_DATE_PROPERTY, "Null");
      }
      values = desiredValue.getConstraints().getValues(INCLUDE_START_PROPERTY);
      if ((values == null) || (values.size() != 1)) {
        if (seriesConstraints == null) {
          seriesConstraints = desiredValue.getConstraints().copy();
        }
        seriesConstraints.with(INCLUDE_START_PROPERTY, YES_VALUE);
      }
      values = desiredValue.getConstraints().getValues(END_DATE_PROPERTY);
      if ((values == null) || values.isEmpty()) {
        if (seriesConstraints == null) {
          seriesConstraints = desiredValue.getConstraints().copy();
        }
        seriesConstraints.with(HistoricalTimeSeriesFunctionUtils.END_DATE_PROPERTY, "Now");
      }
      values = desiredValue.getConstraints().getValues(HistoricalTimeSeriesFunctionUtils.INCLUDE_END_PROPERTY);
      if ((values == null) || (values.size() != 1)) {
        if (seriesConstraints == null) {
          seriesConstraints = desiredValue.getConstraints().copy();
        }
        seriesConstraints.with(HistoricalTimeSeriesFunctionUtils.INCLUDE_END_PROPERTY, HistoricalTimeSeriesFunctionUtils.YES_VALUE);
      }
      if (seriesConstraints != null) {
        Set<String> propertyValue = constraints.getValues(PROPERTY_ROOT_FINDER_ABSOLUTE_TOLERANCE);
        if (propertyValue == null) {
          seriesConstraints.withAny(PROPERTY_ROOT_FINDER_ABSOLUTE_TOLERANCE);
        } else {
          seriesConstraints.with(PROPERTY_ROOT_FINDER_ABSOLUTE_TOLERANCE, propertyValue);
        }
        propertyValue = constraints.getValues(PROPERTY_ROOT_FINDER_RELATIVE_TOLERANCE);
        if (propertyValue == null) {
          seriesConstraints.withAny(PROPERTY_ROOT_FINDER_RELATIVE_TOLERANCE);
        } else {
          seriesConstraints.with(PROPERTY_ROOT_FINDER_RELATIVE_TOLERANCE, propertyValue);
        }
        propertyValue = constraints.getValues(PROPERTY_ROOT_FINDER_MAX_ITERATIONS);
        if (propertyValue == null) {
          seriesConstraints.withAny(PROPERTY_ROOT_FINDER_MAX_ITERATIONS);
        } else {
          seriesConstraints.with(PROPERTY_ROOT_FINDER_MAX_ITERATIONS, propertyValue);
        }
        propertyValue = constraints.getValues(PROPERTY_DECOMPOSITION);
        if (propertyValue == null) {
          seriesConstraints.withAny(PROPERTY_DECOMPOSITION);
        } else {
          seriesConstraints.with(PROPERTY_DECOMPOSITION, propertyValue);
        }
        propertyValue = constraints.getValues(PROPERTY_USE_FINITE_DIFFERENCE);
        if (propertyValue == null) {
          seriesConstraints.withAny(PROPERTY_USE_FINITE_DIFFERENCE);
        } else {
          seriesConstraints.with(PROPERTY_USE_FINITE_DIFFERENCE, propertyValue);
        }
        return Collections.singleton(new ValueRequirement(YIELD_CURVE_HISTORICAL_TIME_SERIES, target.toSpecification(), seriesConstraints.get()));
      }
      final Set<String> rootFinderAbsoluteTolerance = constraints.getValues(PROPERTY_ROOT_FINDER_ABSOLUTE_TOLERANCE);
      if (rootFinderAbsoluteTolerance == null || rootFinderAbsoluteTolerance.size() != 1) {
        return null;
      }
      final Set<String> rootFinderRelativeTolerance = constraints.getValues(PROPERTY_ROOT_FINDER_RELATIVE_TOLERANCE);
      if (rootFinderRelativeTolerance == null || rootFinderRelativeTolerance.size() != 1) {
        return null;
      }
      final Set<String> maxIterations = constraints.getValues(PROPERTY_ROOT_FINDER_MAX_ITERATIONS);
      if (maxIterations == null || maxIterations.size() != 1) {
        return null;
      }
      final Set<String> decomposition = constraints.getValues(PROPERTY_DECOMPOSITION);
      if (decomposition == null || decomposition.size() != 1) {
        return null;
      }
      final Set<String> useFiniteDifference = constraints.getValues(PROPERTY_USE_FINITE_DIFFERENCE);
      if (useFiniteDifference == null || useFiniteDifference.size() != 1) {
        return null;
      }
      if (!_originalConfiguration.getTarget().equals(target.toSpecification())) {
        s_logger.info("Invalid target, was {} - expected {}", target, _originalConfiguration.getTarget());
        return null;
      }
      final ValueProperties properties = constraints.copy()
          .withoutAny(CURVE_CALCULATION_METHOD)
          .with(CURVE_CALCULATION_METHOD, _originalConfiguration.getCalculationMethod())
          .withoutAny(CURVE_CALCULATION_CONFIG)
          .with(CURVE_CALCULATION_CONFIG, _originalConfiguration.getCalculationConfigName())
          .withoutAny(CURVE)
          .with(CURVE, _originalCurveName)
          .get();
      final ValueProperties curveProperties = ValueProperties.builder()
          .with(CURVE, _impliedCurveName)
          .get();
      final ComputationTargetSpecification targetSpec = ComputationTargetSpecification.of(_currency);
      final ValueRequirement curveSpec = new ValueRequirement(YIELD_CURVE_SPEC, targetSpec, curveProperties);
      final ValueRequirement curveSeries = new ValueRequirement(YIELD_CURVE_SERIES, targetSpec, properties);
      return Sets.newHashSet(curveSpec, curveSeries);
    }

    @Override
    public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target, final Map<ValueSpecification, ValueRequirement> inputs) {
      final ValueSpecification input = inputs.keySet().iterator().next();
      if (ValueRequirementNames.YIELD_CURVE_HISTORICAL_TIME_SERIES.equals(input.getValueName())) {
        // Use the substituted result
        return Collections.singleton(input);
      }
      return getResults(context, target);
    }

    /**
     * Gets the properties of the implied yield curve.
     * @param curveName The implied curve name
     * @return The properties
     */
    private ValueProperties getCurveTSProperties(final String curveCalculationMethod, final String curveName, final String curveCalculationConfig) {
      return createValueProperties()
          .with(CURVE_CALCULATION_METHOD, curveCalculationMethod)
          .with(CURVE, curveName)
          .with(CURVE_CALCULATION_CONFIG, curveCalculationConfig)
          .withAny(PROPERTY_ROOT_FINDER_ABSOLUTE_TOLERANCE)
          .withAny(PROPERTY_ROOT_FINDER_RELATIVE_TOLERANCE)
          .withAny(PROPERTY_ROOT_FINDER_MAX_ITERATIONS)
          .withAny(PROPERTY_DECOMPOSITION)
          .withAny(PROPERTY_USE_FINITE_DIFFERENCE)
          .withAny(HistoricalTimeSeriesFunctionUtils.DATA_FIELD_PROPERTY)
          .withAny(HistoricalTimeSeriesFunctionUtils.RESOLUTION_KEY_PROPERTY)
          .withAny(HistoricalTimeSeriesFunctionUtils.START_DATE_PROPERTY)
          .with(HistoricalTimeSeriesFunctionUtils.INCLUDE_START_PROPERTY, HistoricalTimeSeriesFunctionUtils.YES_VALUE, HistoricalTimeSeriesFunctionUtils.NO_VALUE)
          .withAny(HistoricalTimeSeriesFunctionUtils.END_DATE_PROPERTY)
          .with(HistoricalTimeSeriesFunctionUtils.INCLUDE_END_PROPERTY, HistoricalTimeSeriesFunctionUtils.YES_VALUE, HistoricalTimeSeriesFunctionUtils.NO_VALUE)
          .get();
    }

  }
}
TOP

Related Classes of com.opengamma.financial.analytics.model.curve.interestrate.ImpliedDepositCurveSeriesFunction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.