@Override
  public Set<ComputedValue> execute(
      final FunctionExecutionContext executionContext,
      final FunctionInputs inputs,
      final ComputationTarget target,
      final Set<ValueRequirement> desiredValues) {
    final ValueRequirement desiredValue = desiredValues.iterator().next();
    final String curveName = desiredValue.getConstraint(ValuePropertyNames.CURVE);
    final String interpolatorName =
        desiredValue.getConstraint(
            ForwardCurveValuePropertyNames.PROPERTY_FORWARD_CURVE_INTERPOLATOR);
    final String leftExtrapolatorName =
        desiredValue.getConstraint(
            ForwardCurveValuePropertyNames.PROPERTY_FORWARD_CURVE_LEFT_EXTRAPOLATOR);
    final String rightExtrapolatorName =
        desiredValue.getConstraint(
            ForwardCurveValuePropertyNames.PROPERTY_FORWARD_CURVE_RIGHT_EXTRAPOLATOR);

    final Object objectFuturePriceData =
        inputs.getValue(ValueRequirementNames.FUTURE_PRICE_CURVE_DATA);
    if (objectFuturePriceData == null) {
      throw new OpenGammaRuntimeException("Could not get futures curve " + curveName);
    }
    final NodalDoublesCurve futurePriceData = (NodalDoublesCurve) objectFuturePriceData;

    final Interpolator1D interpolator =
        CombinedInterpolatorExtrapolatorFactory.getInterpolator(
            interpolatorName, leftExtrapolatorName, rightExtrapolatorName);

    final ForwardCurve curve =
        new ForwardCurve(
            InterpolatedDoublesCurve.from(
                futurePriceData.getXData(), futurePriceData.getYData(), interpolator));

    final ValueProperties properties =
        createValueProperties()
            .with(
                ForwardCurveValuePropertyNames.PROPERTY_FORWARD_CURVE_CALCULATION_METHOD,
                ForwardCurveValuePropertyNames.PROPERTY_FUTURE_PRICE_METHOD)
            .with(ValuePropertyNames.CURVE, curveName)
            .with(
                ForwardCurveValuePropertyNames.PROPERTY_FORWARD_CURVE_INTERPOLATOR,
                interpolatorName)
            .with(
                ForwardCurveValuePropertyNames.PROPERTY_FORWARD_CURVE_LEFT_EXTRAPOLATOR,
                leftExtrapolatorName)
            .with(
                ForwardCurveValuePropertyNames.PROPERTY_FORWARD_CURVE_RIGHT_EXTRAPOLATOR,
                rightExtrapolatorName)
            .with(
                InstrumentTypeProperties.PROPERTY_SURFACE_INSTRUMENT_TYPE,
                InstrumentTypeProperties.EQUITY_FUTURE_PRICE)
            .get();

    final ValueSpecification resultSpec =
        new ValueSpecification(
            ValueRequirementNames.FORWARD_CURVE, target.toSpecification(), properties);
    return Collections.singleton(new ComputedValue(resultSpec, curve));
  }
Ejemplo n.º 2
0
 @Override
 public Set<ComputedValue> execute(
     final FunctionExecutionContext executionContext,
     final FunctionInputs inputs,
     final ComputationTarget target,
     final Set<ValueRequirement> desiredValues) {
   final Clock snapshotClock = executionContext.getValuationClock();
   final ZonedDateTime now = snapshotClock.zonedDateTime();
   final FinancialSecurity security = (FinancialSecurity) target.getSecurity();
   final Currency payCurrency, receiveCurrency;
   if (security instanceof FXForwardSecurity) {
     final FXForwardSecurity forward = (FXForwardSecurity) security;
     payCurrency = forward.getPayCurrency();
     receiveCurrency = forward.getReceiveCurrency();
   } else {
     final NonDeliverableFXForwardSecurity ndf = (NonDeliverableFXForwardSecurity) security;
     payCurrency = ndf.getPayCurrency();
     receiveCurrency = ndf.getReceiveCurrency();
   }
   final ForexDefinition definition = (ForexDefinition) security.accept(VISITOR);
   final ValueRequirement desiredValue = desiredValues.iterator().next();
   final String payCurveName = desiredValue.getConstraint(ValuePropertyNames.PAY_CURVE);
   final String receiveCurveName = desiredValue.getConstraint(ValuePropertyNames.RECEIVE_CURVE);
   final String payCurveConfig = desiredValue.getConstraint(PAY_CURVE_CALC_CONFIG);
   final String receiveCurveConfig = desiredValue.getConstraint(RECEIVE_CURVE_CALC_CONFIG);
   final String fullPutCurveName = payCurveName + "_" + payCurrency.getCode();
   final String fullCallCurveName = receiveCurveName + "_" + receiveCurrency.getCode();
   final YieldAndDiscountCurve payFundingCurve =
       getCurve(inputs, payCurrency, payCurveName, payCurveConfig);
   final YieldAndDiscountCurve receiveFundingCurve =
       getCurve(inputs, receiveCurrency, receiveCurveName, receiveCurveConfig);
   final YieldAndDiscountCurve[] curves;
   final Map<String, Currency> curveCurrency = new HashMap<String, Currency>();
   curveCurrency.put(fullPutCurveName, payCurrency);
   curveCurrency.put(fullCallCurveName, receiveCurrency);
   final String[] allCurveNames;
   if (FXUtils.isInBaseQuoteOrder(
       payCurrency, receiveCurrency)) { // To get Base/quote in market standard order.
     curves = new YieldAndDiscountCurve[] {payFundingCurve, receiveFundingCurve};
     allCurveNames = new String[] {fullPutCurveName, fullCallCurveName};
   } else {
     curves = new YieldAndDiscountCurve[] {receiveFundingCurve, payFundingCurve};
     allCurveNames = new String[] {fullCallCurveName, fullPutCurveName};
   }
   final YieldCurveBundle yieldCurves = new YieldCurveBundle(allCurveNames, curves);
   final ValueProperties.Builder properties =
       getResultProperties(
           payCurveName, receiveCurveName, payCurveConfig, receiveCurveConfig, target);
   final ValueSpecification spec =
       new ValueSpecification(
           ValueRequirementNames.VALUE_THETA, target.toSpecification(), properties.get());
   final ConstantSpreadHorizonThetaCalculator calculator =
       ConstantSpreadHorizonThetaCalculator.getInstance();
   final MultipleCurrencyAmount theta =
       calculator.getTheta(definition, now, allCurveNames, yieldCurves, DAYS_TO_MOVE_FORWARD);
   return Collections.singleton(new ComputedValue(spec, theta));
 }
 @Override
 protected PresentValueNodeSensitivityCalculator getNodeSensitivityCalculator(
     final ValueRequirement desiredValue) {
   final Double cutoff =
       Double.parseDouble(
           desiredValue.getConstraint(SABRRightExtrapolationFunction.PROPERTY_CUTOFF_STRIKE));
   final Double mu =
       Double.parseDouble(
           desiredValue.getConstraint(
               SABRRightExtrapolationFunction.PROPERTY_TAIL_THICKNESS_PARAMETER));
   return PresentValueNodeSensitivityCalculator.using(
       new PresentValueCurveSensitivitySABRExtrapolationCalculator(cutoff, mu));
 }
 private ValueProperties getResultProperties(final ValueRequirement desiredValue) {
   return createValueProperties()
       .with(
           ValuePropertyNames.SAMPLING_PERIOD,
           desiredValue.getConstraint(ValuePropertyNames.SAMPLING_PERIOD))
       .with(
           ValuePropertyNames.SCHEDULE_CALCULATOR,
           desiredValue.getConstraint(ValuePropertyNames.SCHEDULE_CALCULATOR))
       .with(
           ValuePropertyNames.SAMPLING_FUNCTION,
           desiredValue.getConstraint(ValuePropertyNames.SAMPLING_FUNCTION))
       .with(
           ValuePropertyNames.RETURN_CALCULATOR,
           desiredValue.getConstraint(ValuePropertyNames.RETURN_CALCULATOR))
       .with(
           ValuePropertyNames.STD_DEV_CALCULATOR,
           desiredValue.getConstraint(ValuePropertyNames.STD_DEV_CALCULATOR))
       .with(
           ValuePropertyNames.EXCESS_RETURN_CALCULATOR,
           desiredValue.getConstraint(ValuePropertyNames.EXCESS_RETURN_CALCULATOR))
       .with(
           ValuePropertyNames.COVARIANCE_CALCULATOR,
           desiredValue.getConstraint(ValuePropertyNames.COVARIANCE_CALCULATOR))
       .with(
           ValuePropertyNames.VARIANCE_CALCULATOR,
           desiredValue.getConstraint(ValuePropertyNames.VARIANCE_CALCULATOR))
       .get();
 }
 @Override
 protected LocalDateDoubleTimeSeries getReturnSeries(
     LocalDateDoubleTimeSeries ts, ValueRequirement desiredValue) {
   LocalDateDoubleTimeSeries differenceSeries = super.getReturnSeries(ts, desiredValue);
   double lambda =
       Double.parseDouble(
           desiredValue.getConstraint(
               VolatilityWeightingFunctionUtils.VOLATILITY_WEIGHTING_LAMBDA_PROPERTY));
   TimeSeriesWeightedVolatilityOperator weightedVol =
       new TimeSeriesWeightedVolatilityOperator(lambda);
   LocalDateDoubleTimeSeries weightedVolSeries =
       (LocalDateDoubleTimeSeries) weightedVol.evaluate(ts);
   int n = weightedVolSeries.size();
   double endDateWeightedVol = weightedVolSeries.getLatestValueFast();
   double[] volWeightedDifferences = new double[n];
   for (int i = 0; i < n; i++) {
     System.out.println(
         differenceSeries.getTimeAtIndex(i)
             + ","
             + differenceSeries.getValueAtIndexFast(i)
             + ","
             + weightedVolSeries.getValueAtIndexFast(i));
     volWeightedDifferences[i] =
         differenceSeries.getValueAtIndexFast(i)
             * endDateWeightedVol
             / weightedVolSeries.getValueAtIndexFast(i);
   }
   LocalDateDoubleTimeSeries volWeightedDifferenceSeries =
       ImmutableLocalDateDoubleTimeSeries.of(
           weightedVolSeries.timesArrayFast(), volWeightedDifferences);
   return volWeightedDifferenceSeries;
 }
 @Override
 protected Object getResult(
     final InstrumentDerivative derivative,
     final SABRInterestRateDataBundle data,
     final ValueRequirement desiredValue) {
   final Double cutoff =
       Double.parseDouble(
           desiredValue.getConstraint(SABRRightExtrapolationFunction.PROPERTY_CUTOFF_STRIKE));
   final Double mu =
       Double.parseDouble(
           desiredValue.getConstraint(
               SABRRightExtrapolationFunction.PROPERTY_TAIL_THICKNESS_PARAMETER));
   final PresentValueSABRSensitivitySABRRightExtrapolationCalculator calculator =
       new PresentValueSABRSensitivitySABRRightExtrapolationCalculator(cutoff, mu);
   return getResultAsMatrix(derivative.accept(calculator, data));
 }
 @SuppressWarnings("unchecked")
 @Override
 public Set<ComputedValue> execute(
     final FunctionExecutionContext executionContext,
     final FunctionInputs inputs,
     final ComputationTarget target,
     final Set<ValueRequirement> desiredValues) {
   final HistoricalTimeSeriesSource timeSeriesSource =
       OpenGammaExecutionContext.getHistoricalTimeSeriesSource(executionContext);
   final ValueRequirement desiredValue = desiredValues.iterator().next();
   Object value = timeSeriesSource.getLatestDataPoint(target.getUniqueId());
   if (value == null) {
     value = MissingMarketDataSentinel.getInstance();
   } else {
     final String adjusterString =
         desiredValue.getConstraint(HistoricalTimeSeriesFunctionUtils.ADJUST_PROPERTY);
     final HistoricalTimeSeriesAdjustment htsa =
         HistoricalTimeSeriesAdjustment.parse(adjusterString);
     value = htsa.adjust(((Pair<LocalDate, Double>) value).getValue());
   }
   return Collections.singleton(
       new ComputedValue(
           new ValueSpecification(
               desiredValue.getValueName(),
               desiredValue.getTargetSpecification(),
               desiredValue.getConstraints()),
           value));
 }
 @Override
 public Set<ComputedValue> execute(
     final FunctionExecutionContext executionContext,
     final FunctionInputs inputs,
     final ComputationTarget target,
     final Set<ValueRequirement> desiredValues) {
   final ValueRequirement desiredValue = desiredValues.iterator().next();
   final String surfaceName = desiredValue.getConstraint(SURFACE);
   final Object interpolatorObject =
       inputs.getValue(getInterpolatorRequirement(target, desiredValue));
   if (interpolatorObject == null) {
     throw new OpenGammaRuntimeException("Could not get volatility surface interpolator");
   }
   final VolatilitySurfaceInterpolator surfaceInterpolator =
       (VolatilitySurfaceInterpolator) interpolatorObject;
   final SmileSurfaceDataBundle data =
       getData(
           inputs,
           getVolatilityDataRequirement(
               target,
               surfaceName,
               getInstrumentType(),
               getSurfaceQuoteType(),
               getSurfaceQuoteUnits()),
           getForwardCurveRequirement(target, desiredValue));
   final BlackVolatilitySurfaceMoneyness impliedVolatilitySurface =
       surfaceInterpolator.getVolatilitySurface(data);
   final ValueProperties properties = getResultProperties(desiredValue);
   final ValueSpecification spec =
       new ValueSpecification(
           ValueRequirementNames.BLACK_VOLATILITY_SURFACE, target.toSpecification(), properties);
   return Collections.singleton(new ComputedValue(spec, impliedVolatilitySurface));
 }
 @Override
 protected ValueProperties.Builder getResultProperties(
     final ComputationTarget target, final ValueRequirement desiredValue) {
   final String daysForward = desiredValue.getConstraint(PROPERTY_DAYS_TO_MOVE_FORWARD);
   final ValueProperties.Builder properties =
       super.getResultProperties(target, desiredValue)
           .with(PROPERTY_THETA_CALCULATION_METHOD, THETA_CONSTANT_SPREAD)
           .with(PROPERTY_DAYS_TO_MOVE_FORWARD, daysForward);
   return properties;
 }
 @Override
 public Set<ValueSpecification> getResults(
     final FunctionCompilationContext context,
     final ComputationTarget target,
     final Map<ValueSpecification, ValueRequirement> inputs) {
   if (inputs.size() == 1) {
     final ValueSpecification input = Iterables.getOnlyElement(inputs.keySet());
     if (ValueRequirementNames.PNL_SERIES.equals(input.getValueName())) {
       return Collections.singleton(input);
     }
   }
   final FXForwardSecurity security = (FXForwardSecurity) target.getPosition().getSecurity();
   final CurrencyPair currencyPair =
       _currencyPairs.getCurrencyPair(security.getPayCurrency(), security.getReceiveCurrency());
   if (currencyPair == null) {
     return null;
   }
   final Currency currencyBase = currencyPair.getBase();
   String resultCurrency = null;
   final ValueProperties.Builder builder = createValueProperties();
   for (final Map.Entry<ValueSpecification, ValueRequirement> entry : inputs.entrySet()) {
     final ValueSpecification inputSpec = entry.getKey();
     final ValueRequirement inputReq = entry.getValue();
     if (inputReq.getValueName().equals(RETURN_SERIES)) {
       final Set<String> resultCurrencies = inputReq.getConstraints().getValues(CURRENCY);
       if (resultCurrencies != null && resultCurrencies.size() == 1) {
         resultCurrency = inputReq.getConstraint(CURRENCY);
       } else {
         resultCurrency = currencyBase.getCode();
       }
     }
     for (final String propertyName : inputSpec.getProperties().getProperties()) {
       if (ValuePropertyNames.FUNCTION.equals(propertyName)) {
         continue;
       }
       final Set<String> values = inputSpec.getProperties().getValues(propertyName);
       if (values == null || values.isEmpty()) {
         builder.withAny(propertyName);
       } else {
         builder.with(propertyName, values);
       }
     }
   }
   if (resultCurrency == null) {
     return null;
   }
   builder
       .with(ValuePropertyNames.CURRENCY, resultCurrency)
       .with(
           ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS,
           ValueRequirementNames.FX_CURRENCY_EXPOSURE);
   return ImmutableSet.of(
       new ValueSpecification(
           ValueRequirementNames.PNL_SERIES, target.toSpecification(), builder.get()));
 }
  @Override
  public Set<ComputedValue> execute(
      final FunctionExecutionContext executionContext,
      final FunctionInputs inputs,
      final ComputationTarget target,
      final Set<ValueRequirement> desiredValues) {
    final ValueRequirement desiredValue = Iterables.getOnlyElement(desiredValues);
    final String curveName = desiredValue.getConstraint(ValuePropertyNames.CURVE);
    final String curveCalculationConfig =
        desiredValue.getConstraint(ValuePropertyNames.CURVE_CALCULATION_CONFIG);
    // 1. Get the expiry _time_ from the trade
    final EquityVarianceSwapSecurity security = (EquityVarianceSwapSecurity) target.getSecurity();
    final double expiry =
        TimeCalculator.getTimeBetween(
            executionContext.getValuationClock().zonedDateTime(),
            security.getLastObservationDate());

    // 2. Get the discount curve and spot value
    final Object discountObject =
        inputs.getValue(getDiscountRequirement(security, curveName, curveCalculationConfig));
    if (discountObject == null) {
      throw new OpenGammaRuntimeException("Could not get Discount Curve");
    }
    final YieldAndDiscountCurve discountCurve = (YieldAndDiscountCurve) discountObject;

    final Object spotObject = inputs.getValue(getSpotRequirement(security));
    if (spotObject == null) {
      throw new OpenGammaRuntimeException("Could not get Underlying's Spot value");
    }
    final double spot = (Double) spotObject;

    // 3. Compute the forward
    final double discountFactor = discountCurve.getDiscountFactor(expiry);
    Validate.isTrue(
        discountFactor != 0,
        "The discount curve has returned a zero value for a discount bond. Check rates.");
    final double forward = spot / discountFactor;

    final ValueSpecification valueSpec = getValueSpecification(security);
    return Collections.singleton(new ComputedValue(valueSpec, forward));
  }
 @Override
 protected ValueProperties.Builder getResultProperties(
     final ComputationTarget target,
     final ValueRequirement desiredValue,
     final CurrencyPair baseQuotePair) {
   final String daysForward = desiredValue.getConstraint(PROPERTY_DAYS_TO_MOVE_FORWARD);
   final ValueProperties.Builder properties =
       super.getResultProperties(target, desiredValue, baseQuotePair);
   properties
       .with(PROPERTY_THETA_CALCULATION_METHOD, THETA_FORWARD_SLIDE_YIELD_CURVES)
       .with(PROPERTY_DAYS_TO_MOVE_FORWARD, daysForward);
   return properties;
 }
 @Override
 protected ValueProperties.Builder createValueProperties(
     final ComputationTarget target, final ValueRequirement desiredValue) {
   final String cubeDefinitionName =
       desiredValue.getConstraint(SurfaceAndCubePropertyNames.PROPERTY_CUBE_DEFINITION);
   final String cubeSpecificationName =
       desiredValue.getConstraint(SurfaceAndCubePropertyNames.PROPERTY_CUBE_SPECIFICATION);
   final String surfaceDefinitionName =
       desiredValue.getConstraint(SurfaceAndCubePropertyNames.PROPERTY_SURFACE_DEFINITION);
   final String surfaceSpecificationName =
       desiredValue.getConstraint(SurfaceAndCubePropertyNames.PROPERTY_SURFACE_SPECIFICATION);
   final String currency = FinancialSecurityUtils.getCurrency(target.getSecurity()).getCode();
   final String curveCalculationConfig =
       desiredValue.getConstraint(ValuePropertyNames.CURVE_CALCULATION_CONFIG);
   final String fittingMethod =
       desiredValue.getConstraint(SmileFittingPropertyNamesAndValues.PROPERTY_FITTING_METHOD);
   final String curveName = desiredValue.getConstraint(ValuePropertyNames.CURVE);
   final String cutoff =
       desiredValue.getConstraint(SABRRightExtrapolationFunction.PROPERTY_CUTOFF_STRIKE);
   final String mu =
       desiredValue.getConstraint(
           SABRRightExtrapolationFunction.PROPERTY_TAIL_THICKNESS_PARAMETER);
   return createValueProperties()
       .with(ValuePropertyNames.CURRENCY, currency)
       .with(ValuePropertyNames.CURVE_CURRENCY, currency)
       .with(ValuePropertyNames.CURVE_CALCULATION_CONFIG, curveCalculationConfig)
       .with(ValuePropertyNames.CURVE, curveName)
       .with(SurfaceAndCubePropertyNames.PROPERTY_CUBE_DEFINITION, cubeDefinitionName)
       .with(SurfaceAndCubePropertyNames.PROPERTY_CUBE_SPECIFICATION, cubeSpecificationName)
       .with(SurfaceAndCubePropertyNames.PROPERTY_SURFACE_DEFINITION, surfaceDefinitionName)
       .with(SurfaceAndCubePropertyNames.PROPERTY_SURFACE_SPECIFICATION, surfaceSpecificationName)
       .with(SABRRightExtrapolationFunction.PROPERTY_CUTOFF_STRIKE, cutoff)
       .with(SABRRightExtrapolationFunction.PROPERTY_TAIL_THICKNESS_PARAMETER, mu)
       .with(SmileFittingPropertyNamesAndValues.PROPERTY_FITTING_METHOD, fittingMethod)
       .with(
           SmileFittingPropertyNamesAndValues.PROPERTY_VOLATILITY_MODEL,
           SmileFittingPropertyNamesAndValues.SABR)
       .with(ValuePropertyNames.CALCULATION_METHOD, SABRFunction.SABR_RIGHT_EXTRAPOLATION);
 }
 @Override
 public Set<ComputedValue> execute(
     final FunctionExecutionContext executionContext,
     final FunctionInputs inputs,
     final ComputationTarget target,
     final Set<ValueRequirement> desiredValues) {
   final FinancialSecurity security = (FinancialSecurity) target.getSecurity();
   final Currency currency = FinancialSecurityUtils.getCurrency(security);
   final Clock snapshotClock = executionContext.getValuationClock();
   final ZonedDateTime now = snapshotClock.zonedDateTime();
   final HistoricalTimeSeriesBundle timeSeries =
       HistoricalTimeSeriesFunctionUtils.getHistoricalTimeSeriesInputs(executionContext, inputs);
   final ValueRequirement desiredValue = desiredValues.iterator().next();
   final String curveCalculationConfigName =
       desiredValue.getConstraint(ValuePropertyNames.CURVE_CALCULATION_CONFIG);
   final ConfigSource configSource = OpenGammaExecutionContext.getConfigSource(executionContext);
   final ConfigDBCurveCalculationConfigSource curveCalculationConfigSource =
       new ConfigDBCurveCalculationConfigSource(configSource);
   final MultiCurveCalculationConfig curveCalculationConfig =
       curveCalculationConfigSource.getConfig(curveCalculationConfigName);
   if (curveCalculationConfig == null) {
     throw new OpenGammaRuntimeException(
         "Could not find curve calculation configuration named " + curveCalculationConfigName);
   }
   final String[] curveNames = curveCalculationConfig.getYieldCurveNames();
   final String[] yieldCurveNames =
       curveNames.length == 1 ? new String[] {curveNames[0], curveNames[0]} : curveNames;
   final String[] curveNamesForSecurity =
       FixedIncomeInstrumentCurveExposureHelper.getCurveNamesForSecurity(
           security, yieldCurveNames[0], yieldCurveNames[1]);
   final YieldCurveBundle bundle =
       YieldCurveFunctionUtils.getAllYieldCurves(
           inputs, curveCalculationConfig, curveCalculationConfigSource);
   final InstrumentDefinition<?> definition = security.accept(_visitor);
   if (definition == null) {
     throw new OpenGammaRuntimeException("Definition for security " + security + " was null");
   }
   final InstrumentDerivative derivative =
       getDerivative(
           security, now, timeSeries, curveNamesForSecurity, definition, _definitionConverter);
   return getComputedValues(
       derivative, bundle, security, target, curveCalculationConfigName, currency.getCode());
 }
 @Override
 public Set<ComputedValue> execute(
     final FunctionExecutionContext context,
     final FunctionInputs inputs,
     final ComputationTarget target,
     final Set<ValueRequirement> desiredValues)
     throws AsynchronousExecution {
   final MultipleCurrencyParameterSensitivity sensitivities =
       (MultipleCurrencyParameterSensitivity) inputs.getValue(BLOCK_CURVE_SENSITIVITIES);
   final ValueRequirement desiredValue = desiredValues.iterator().next();
   final ValueProperties properties = desiredValue.getConstraints();
   final String desiredCurveName = desiredValue.getConstraint(CURVE);
   final Map<Pair<String, Currency>, DoubleMatrix1D> entries = sensitivities.getSensitivities();
   final Set<ComputedValue> results = new HashSet<>();
   for (final Map.Entry<Pair<String, Currency>, DoubleMatrix1D> entry : entries.entrySet()) {
     final String curveName = entry.getKey().getFirst();
     if (desiredCurveName.equals(curveName)) {
       final ValueProperties curveSpecificProperties =
           properties.copy().withoutAny(CURVE).with(CURVE, curveName).get();
       final CurveDefinition curveDefinition =
           (CurveDefinition)
               inputs.getValue(
                   new ValueRequirement(
                       CURVE_DEFINITION,
                       ComputationTargetSpecification.NULL,
                       ValueProperties.builder().with(CURVE, curveName).get()));
       final DoubleLabelledMatrix1D ycns =
           MultiCurveUtils.getLabelledMatrix(entry.getValue(), curveDefinition);
       final ValueSpecification spec =
           new ValueSpecification(
               YIELD_CURVE_NODE_SENSITIVITIES, target.toSpecification(), curveSpecificProperties);
       results.add(new ComputedValue(spec, ycns));
       return results;
     }
   }
   s_logger.info(
       "Could not get sensitivities to " + desiredCurveName + " for " + target.getName());
   return Collections.emptySet();
 }
Ejemplo n.º 16
0
 public static ForexOptionDataBundle<?> buildMarketBundle(
     final ZonedDateTime now,
     final FunctionInputs inputs,
     final ComputationTarget target,
     final Set<ValueRequirement> desiredValues) {
   final FinancialSecurity security = (FinancialSecurity) target.getSecurity();
   final Currency putCurrency = security.accept(ForexVisitors.getPutCurrencyVisitor());
   final Currency callCurrency = security.accept(ForexVisitors.getCallCurrencyVisitor());
   if (now.isAfter(security.accept(ForexVisitors.getExpiryVisitor()))) {
     throw new OpenGammaRuntimeException(
         "FX option " + putCurrency.getCode() + "/" + callCurrency + " has expired");
   }
   final ValueRequirement desiredValue = desiredValues.iterator().next();
   final String putCurveName = desiredValue.getConstraint(PUT_CURVE);
   final String callCurveName = desiredValue.getConstraint(CALL_CURVE);
   final String putCurveConfig = desiredValue.getConstraint(PUT_CURVE_CALC_CONFIG);
   final String callCurveConfig = desiredValue.getConstraint(CALL_CURVE_CALC_CONFIG);
   final Object baseQuotePairsObject = inputs.getValue(ValueRequirementNames.CURRENCY_PAIRS);
   if (baseQuotePairsObject == null) {
     throw new OpenGammaRuntimeException("Could not get base/quote pair data");
   }
   final CurrencyPairs baseQuotePairs = (CurrencyPairs) baseQuotePairsObject;
   final String fullPutCurveName = putCurveName + "_" + putCurrency.getCode();
   final String fullCallCurveName = callCurveName + "_" + callCurrency.getCode();
   final YieldAndDiscountCurve putFundingCurve =
       getCurveForCurrency(inputs, putCurrency, putCurveName, putCurveConfig);
   final YieldAndDiscountCurve callFundingCurve =
       getCurveForCurrency(inputs, callCurrency, callCurveName, callCurveConfig);
   final YieldAndDiscountCurve[] curves;
   final Map<String, Currency> curveCurrency = new HashMap<>();
   curveCurrency.put(fullPutCurveName, putCurrency);
   curveCurrency.put(fullCallCurveName, callCurrency);
   final String[] allCurveNames;
   final Currency ccy1;
   final Currency ccy2;
   final Object spotObject = inputs.getValue(ValueRequirementNames.SPOT_RATE);
   if (spotObject == null) {
     throw new OpenGammaRuntimeException("Could not get spot requirement");
   }
   double spot = (Double) spotObject;
   final CurrencyPair baseQuotePair = baseQuotePairs.getCurrencyPair(putCurrency, callCurrency);
   if (baseQuotePair == null) {
     throw new OpenGammaRuntimeException(
         "Could not get base/quote pair for currency pair ("
             + putCurrency
             + ", "
             + callCurrency
             + ")");
   }
   if (baseQuotePair
       .getBase()
       .equals(putCurrency)) { // To get Base/quote in market standard order.
     ccy1 = putCurrency;
     ccy2 = callCurrency;
     curves = new YieldAndDiscountCurve[] {putFundingCurve, callFundingCurve};
     allCurveNames = new String[] {fullPutCurveName, fullCallCurveName};
   } else {
     curves = new YieldAndDiscountCurve[] {callFundingCurve, putFundingCurve};
     allCurveNames = new String[] {fullCallCurveName, fullPutCurveName};
     ccy1 = callCurrency;
     ccy2 = putCurrency;
     spot = 1. / spot;
   }
   final YieldCurveBundle yieldCurves = new YieldCurveBundle(allCurveNames, curves);
   final Object volatilitySurfaceObject =
       inputs.getValue(ValueRequirementNames.STANDARD_VOLATILITY_SURFACE_DATA);
   if (volatilitySurfaceObject == null) {
     throw new OpenGammaRuntimeException("Could not get volatility surface data");
   }
   final FXMatrix fxMatrix = new FXMatrix(ccy1, ccy2, spot);
   final YieldCurveBundle curvesWithFX =
       new YieldCurveBundle(fxMatrix, curveCurrency, yieldCurves.getCurvesMap());
   final Pair<Currency, Currency> currencyPair = Pair.of(ccy1, ccy2);
   if (volatilitySurfaceObject instanceof SmileDeltaTermStructureParametersStrikeInterpolation) {
     final SmileDeltaTermStructureParametersStrikeInterpolation smiles =
         (SmileDeltaTermStructureParametersStrikeInterpolation) volatilitySurfaceObject;
     final SmileDeltaTermStructureDataBundle smileBundle =
         new SmileDeltaTermStructureDataBundle(curvesWithFX, smiles, currencyPair);
     return smileBundle;
   }
   final BlackForexTermStructureParameters termStructure =
       (BlackForexTermStructureParameters) volatilitySurfaceObject;
   final YieldCurveWithBlackForexTermStructureBundle flatData =
       new YieldCurveWithBlackForexTermStructureBundle(curvesWithFX, termStructure, currencyPair);
   return flatData;
 }
 @Override
 public Set<ComputedValue> execute(
     final FunctionExecutionContext executionContext,
     final FunctionInputs inputs,
     final ComputationTarget target,
     final Set<ValueRequirement> desiredValues) {
   final Clock snapshotClock = executionContext.getValuationClock();
   final ZonedDateTime now = ZonedDateTime.now(snapshotClock);
   final SecuritySource securitySource =
       OpenGammaExecutionContext.getSecuritySource(executionContext);
   final SwaptionSecurity security = (SwaptionSecurity) target.getSecurity();
   final ValueRequirement desiredValue = desiredValues.iterator().next();
   final Currency currency = FinancialSecurityUtils.getCurrency(security);
   final String surfaceName = desiredValue.getConstraint(ValuePropertyNames.SURFACE);
   final String curveCalculationConfigName =
       desiredValue.getConstraint(ValuePropertyNames.CURVE_CALCULATION_CONFIG);
   final ConfigSource configSource = OpenGammaExecutionContext.getConfigSource(executionContext);
   final ConfigDBCurveCalculationConfigSource curveCalculationConfigSource =
       new ConfigDBCurveCalculationConfigSource(configSource);
   final MultiCurveCalculationConfig curveCalculationConfig =
       curveCalculationConfigSource.getConfig(curveCalculationConfigName);
   if (curveCalculationConfig == null) {
     throw new OpenGammaRuntimeException(
         "Could not find curve calculation configuration named " + curveCalculationConfigName);
   }
   String[] curveNames = curveCalculationConfig.getYieldCurveNames(); // TODO
   if (curveNames.length == 1) {
     curveNames = new String[] {curveNames[0], curveNames[0]};
   }
   final String[] fullCurveNames = new String[curveNames.length];
   for (int i = 0; i < curveNames.length; i++) {
     fullCurveNames[i] = curveNames[i] + "_" + currency.getCode();
   }
   final YieldCurveBundle curves =
       YieldCurveFunctionUtils.getYieldCurves(inputs, curveCalculationConfig);
   final Object volatilitySurfaceObject =
       inputs.getValue(getVolatilityRequirement(surfaceName, currency));
   if (volatilitySurfaceObject == null) {
     throw new OpenGammaRuntimeException("Could not get volatility surface");
   }
   final VolatilitySurface volatilitySurface = (VolatilitySurface) volatilitySurfaceObject;
   if (!(volatilitySurface.getSurface() instanceof InterpolatedDoublesSurface)) {
     throw new OpenGammaRuntimeException(
         "Expecting an InterpolatedDoublesSurface; got "
             + volatilitySurface.getSurface().getClass());
   }
   final InstrumentDefinition<?> definition = security.accept(_visitor);
   final HistoricalTimeSeriesBundle timeSeries =
       HistoricalTimeSeriesFunctionUtils.getHistoricalTimeSeriesInputs(executionContext, inputs);
   final InstrumentDerivative swaption =
       _definitionConverter.convert(security, definition, now, fullCurveNames, timeSeries);
   final ValueProperties properties =
       getResultProperties(currency.getCode(), curveCalculationConfigName, surfaceName);
   final ValueSpecification spec =
       new ValueSpecification(_valueRequirementName, target.toSpecification(), properties);
   final BlackFlatSwaptionParameters parameters =
       new BlackFlatSwaptionParameters(
           volatilitySurface.getSurface(),
           SwaptionUtils.getSwapGenerator(security, definition, securitySource));
   final YieldCurveWithBlackSwaptionBundle data =
       new YieldCurveWithBlackSwaptionBundle(parameters, curves);
   return getResult(swaption, data, spec);
 }
 @Override
 public Set<ComputedValue> execute(
     final FunctionExecutionContext executionContext,
     final FunctionInputs inputs,
     final ComputationTarget target,
     final Set<ValueRequirement> desiredValues) {
   final Clock snapshotClock = executionContext.getValuationClock();
   final ZonedDateTime now = ZonedDateTime.now(snapshotClock);
   final FinancialSecurity security = (FinancialSecurity) target.getSecurity();
   final Currency payCurrency = security.accept(ForexVisitors.getPayCurrencyVisitor());
   final Currency receiveCurrency = security.accept(ForexVisitors.getReceiveCurrencyVisitor());
   if (now.isAfter(security.accept(ForexVisitors.getExpiryVisitor()))) {
     throw new OpenGammaRuntimeException(
         "FX forward " + payCurrency.getCode() + "/" + receiveCurrency + " has expired");
   }
   final ValueRequirement desiredValue = desiredValues.iterator().next();
   final String payCurveName = desiredValue.getConstraint(ValuePropertyNames.PAY_CURVE);
   final String receiveCurveName = desiredValue.getConstraint(ValuePropertyNames.RECEIVE_CURVE);
   final String payCurveConfig =
       desiredValue.getConstraint(ValuePropertyNames.PAY_CURVE_CALCULATION_CONFIG);
   final String receiveCurveConfig =
       desiredValue.getConstraint(ValuePropertyNames.RECEIVE_CURVE_CALCULATION_CONFIG);
   final String daysForward = desiredValue.getConstraint(PROPERTY_DAYS_TO_MOVE_FORWARD);
   final String fullPayCurveName = payCurveName + "_" + payCurrency.getCode();
   final String fullReceiveCurveName = receiveCurveName + "_" + receiveCurrency.getCode();
   final YieldAndDiscountCurve payFundingCurve =
       getPayCurve(inputs, payCurrency, payCurveName, payCurveConfig);
   final YieldAndDiscountCurve receiveFundingCurve =
       getReceiveCurve(inputs, receiveCurrency, receiveCurveName, receiveCurveConfig);
   final YieldAndDiscountCurve[] curves;
   final Map<String, Currency> curveCurrency = new HashMap<>();
   curveCurrency.put(fullPayCurveName, payCurrency);
   curveCurrency.put(fullReceiveCurveName, receiveCurrency);
   final String[] allCurveNames;
   final Object baseQuotePairsObject = inputs.getValue(ValueRequirementNames.CURRENCY_PAIRS);
   if (baseQuotePairsObject == null) {
     throw new OpenGammaRuntimeException("Could not get base/quote pair data");
   }
   final CurrencyPairs baseQuotePairs = (CurrencyPairs) baseQuotePairsObject;
   final CurrencyPair baseQuotePair = baseQuotePairs.getCurrencyPair(payCurrency, receiveCurrency);
   if (baseQuotePair == null) {
     throw new OpenGammaRuntimeException(
         "Could not get base/quote pair for currency pair ("
             + payCurrency
             + ", "
             + receiveCurrency
             + ")");
   }
   if (baseQuotePair
       .getBase()
       .equals(payCurrency)) { // To get Base/quote in market standard order.
     curves = new YieldAndDiscountCurve[] {payFundingCurve, receiveFundingCurve};
     allCurveNames = new String[] {fullPayCurveName, fullReceiveCurveName};
   } else {
     curves = new YieldAndDiscountCurve[] {receiveFundingCurve, payFundingCurve};
     allCurveNames = new String[] {fullReceiveCurveName, fullPayCurveName};
   }
   final ForexSecurityConverter converter = new ForexSecurityConverter(baseQuotePairs);
   final ForexDefinition definition = (ForexDefinition) security.accept(converter);
   final YieldCurveBundle yieldCurves = new YieldCurveBundle(allCurveNames, curves);
   final ValueProperties.Builder properties = getResultProperties(target, desiredValue);
   final ValueSpecification spec =
       new ValueSpecification(
           getValueRequirementName(), target.toSpecification(), properties.get());
   final ConstantSpreadHorizonThetaCalculator calculator =
       ConstantSpreadHorizonThetaCalculator.getInstance();
   final MultipleCurrencyAmount theta =
       calculator.getTheta(
           definition, now, allCurveNames, yieldCurves, Integer.parseInt(daysForward));
   return Collections.singleton(new ComputedValue(spec, theta));
 }
 @Override
 public Set<ComputedValue> execute(
     final FunctionExecutionContext executionContext,
     final FunctionInputs inputs,
     final ComputationTarget target,
     final Set<ValueRequirement> desiredValues) {
   final Clock snapshotClock = executionContext.getValuationClock();
   final ZonedDateTime now = snapshotClock.zonedDateTime();
   final SecuritySource securitySource =
       OpenGammaExecutionContext.getSecuritySource(executionContext);
   final SwaptionSecurity security = (SwaptionSecurity) target.getSecurity();
   final ValueRequirement desiredValue = desiredValues.iterator().next();
   final Currency currency = FinancialSecurityUtils.getCurrency(security);
   final String forwardCurveName =
       desiredValue.getConstraint(YieldCurveFunction.PROPERTY_FORWARD_CURVE);
   final String fundingCurveName =
       desiredValue.getConstraint(YieldCurveFunction.PROPERTY_FUNDING_CURVE);
   final String curveCalculationMethod =
       desiredValue.getConstraint(ValuePropertyNames.CURVE_CALCULATION_METHOD);
   final String surfaceName = desiredValue.getConstraint(ValuePropertyNames.SURFACE);
   final Object forwardCurveObject =
       inputs.getValue(
           YieldCurveFunction.getCurveRequirement(
               currency,
               forwardCurveName,
               forwardCurveName,
               fundingCurveName,
               curveCalculationMethod));
   if (forwardCurveObject == null) {
     throw new OpenGammaRuntimeException("Could not get forward curve");
   }
   final Object fundingCurveObject =
       inputs.getValue(
           YieldCurveFunction.getCurveRequirement(
               currency,
               fundingCurveName,
               forwardCurveName,
               fundingCurveName,
               curveCalculationMethod));
   if (fundingCurveObject == null) {
     throw new OpenGammaRuntimeException("Could not get funding curve");
   }
   final Object volatilitySurfaceObject =
       inputs.getValue(getVolatilityRequirement(surfaceName, currency));
   if (volatilitySurfaceObject == null) {
     throw new OpenGammaRuntimeException("Could not get volatility surface");
   }
   final VolatilitySurface volatilitySurface = (VolatilitySurface) volatilitySurfaceObject;
   if (!(volatilitySurface.getSurface() instanceof InterpolatedDoublesSurface)) {
     throw new OpenGammaRuntimeException(
         "Expecting an InterpolatedDoublesSurface; got "
             + volatilitySurface.getSurface().getClass());
   }
   final YieldAndDiscountCurve forwardCurve = (YieldAndDiscountCurve) forwardCurveObject;
   final YieldAndDiscountCurve fundingCurve = (YieldAndDiscountCurve) fundingCurveObject;
   final InstrumentDefinition<?> definition = security.accept(_visitor);
   final InstrumentDerivative swaption =
       definition.toDerivative(now, new String[] {fundingCurveName, forwardCurveName});
   final ValueProperties properties =
       getResultProperties(
           currency.getCode(),
           forwardCurveName,
           fundingCurveName,
           curveCalculationMethod,
           surfaceName);
   final ValueSpecification spec =
       new ValueSpecification(_valueRequirementName, target.toSpecification(), properties);
   final YieldCurveBundle curves =
       new YieldCurveBundle(
           new String[] {fundingCurveName, forwardCurveName},
           new YieldAndDiscountCurve[] {fundingCurve, forwardCurve});
   final BlackSwaptionParameters parameters =
       new BlackSwaptionParameters(
           volatilitySurface.getSurface(),
           SwaptionUtils.getSwapGenerator(security, definition, securitySource));
   final YieldCurveWithBlackSwaptionBundle data =
       new YieldCurveWithBlackSwaptionBundle(parameters, curves);
   return getResult(swaption, data, spec);
 }
 @Override
 public Set<ValueSpecification> getResults(
     final FunctionCompilationContext context,
     final ComputationTarget target,
     final Map<ValueSpecification, ValueRequirement> inputs) {
   String currencyPairConfigName = null;
   String payCurveName = null;
   String payCurveCalculationConfig = null;
   String receiveCurveName = null;
   String receiveCurveCalculationConfig = null;
   String daysForward = null;
   for (final Map.Entry<ValueSpecification, ValueRequirement> entry : inputs.entrySet()) {
     final ValueSpecification specification = entry.getKey();
     final ValueRequirement requirement = entry.getValue();
     if (specification.getValueName().equals(ValueRequirementNames.CURRENCY_PAIRS)) {
       currencyPairConfigName =
           specification.getProperty(CurrencyPairsFunction.CURRENCY_PAIRS_NAME);
       daysForward = requirement.getConstraint(PROPERTY_DAYS_TO_MOVE_FORWARD);
     } else if (requirement.getValueName().equals(ValueRequirementNames.YIELD_CURVE)) {
       final ValueProperties constraints = requirement.getConstraints();
       if (constraints.getProperties().contains(ValuePropertyNames.PAY_CURVE)) {
         payCurveName = Iterables.getOnlyElement(constraints.getValues(ValuePropertyNames.CURVE));
         payCurveCalculationConfig =
             Iterables.getOnlyElement(
                 constraints.getValues(ValuePropertyNames.CURVE_CALCULATION_CONFIG));
       } else if (constraints.getProperties().contains(ValuePropertyNames.RECEIVE_CURVE)) {
         receiveCurveName =
             Iterables.getOnlyElement(constraints.getValues(ValuePropertyNames.CURVE));
         receiveCurveCalculationConfig =
             Iterables.getOnlyElement(
                 constraints.getValues(ValuePropertyNames.CURVE_CALCULATION_CONFIG));
       }
     }
   }
   assert currencyPairConfigName != null;
   final CurrencyPairs baseQuotePairs =
       OpenGammaCompilationContext.getCurrencyPairsSource(context)
           .getCurrencyPairs(currencyPairConfigName);
   final FinancialSecurity security = (FinancialSecurity) target.getSecurity();
   final Currency payCurrency = security.accept(ForexVisitors.getPayCurrencyVisitor());
   final Currency receiveCurrency = security.accept(ForexVisitors.getReceiveCurrencyVisitor());
   final CurrencyPair baseQuotePair = baseQuotePairs.getCurrencyPair(payCurrency, receiveCurrency);
   if (baseQuotePair == null) {
     s_logger.error(
         "Could not get base/quote pair for currency pair ("
             + payCurrency
             + ", "
             + receiveCurrency
             + ")");
     return null;
   }
   final ValueSpecification resultSpec =
       new ValueSpecification(
           getValueRequirementName(),
           target.toSpecification(),
           getResultProperties(
                   target,
                   payCurveName,
                   receiveCurveName,
                   payCurveCalculationConfig,
                   receiveCurveCalculationConfig,
                   baseQuotePair,
                   daysForward)
               .get());
   return Collections.singleton(resultSpec);
 }
  @Override
  public Set<ValueRequirement> getRequirements(
      final FunctionCompilationContext context,
      final ComputationTarget target,
      final ValueRequirement desiredValue) {
    final LegacyVanillaCDSSecurity cds = (LegacyVanillaCDSSecurity) target.getSecurity();
    final Currency ccy = cds.getNotional().getCurrency();
    final CreditCurveIdentifier isdaIdentifier = getISDACurveIdentifier(cds);
    final CreditCurveIdentifier spreadIdentifier = getSpreadCurveIdentifier(cds);

    final String isdaOffset = desiredValue.getConstraint(ISDAFunctionConstants.ISDA_CURVE_OFFSET);
    if (isdaOffset == null) {
      return null;
    }

    final String isdaCurveDate = desiredValue.getConstraint(ISDAFunctionConstants.ISDA_CURVE_DATE);
    if (isdaCurveDate == null) {
      return null;
    }

    final String isdaCurveMethod =
        desiredValue.getConstraint(ISDAFunctionConstants.ISDA_IMPLEMENTATION);
    if (isdaCurveMethod == null) {
      return null;
    }

    // isda curve
    final ValueProperties isdaProperties =
        ValueProperties.builder()
            .with(ValuePropertyNames.CURVE, isdaIdentifier.toString())
            .with(
                ValuePropertyNames.CURVE_CALCULATION_METHOD, ISDAFunctionConstants.ISDA_METHOD_NAME)
            .with(ISDAFunctionConstants.ISDA_CURVE_OFFSET, isdaOffset)
            .with(ISDAFunctionConstants.ISDA_CURVE_DATE, isdaCurveDate)
            .with(ISDAFunctionConstants.ISDA_IMPLEMENTATION, isdaCurveMethod)
            .get();
    final ValueRequirement isdaRequirment =
        new ValueRequirement(
            ValueRequirementNames.YIELD_CURVE,
            ComputationTargetType.CURRENCY,
            ccy.getUniqueId(),
            isdaProperties);

    final String quoteConvention =
        desiredValue.getConstraint(ISDAFunctionConstants.CDS_QUOTE_CONVENTION);
    if (quoteConvention == null) {
      return null;
    }

    final String bucketTenors =
        desiredValue.getConstraint(ISDAFunctionConstants.ISDA_BUCKET_TENORS);
    if (bucketTenors == null) {
      return null;
    }

    // market  spreads
    final ValueProperties spreadProperties =
        ValueProperties.builder()
            .with(ISDAFunctionConstants.CDS_QUOTE_CONVENTION, quoteConvention)
            .with(
                ValuePropertyNames.CURVE_CALCULATION_METHOD, ISDAFunctionConstants.ISDA_METHOD_NAME)
            .with(ISDAFunctionConstants.ISDA_CURVE_OFFSET, isdaOffset)
            .with(ISDAFunctionConstants.ISDA_CURVE_DATE, isdaCurveDate)
            .with(ISDAFunctionConstants.ISDA_IMPLEMENTATION, isdaCurveMethod)
            .with(ISDAFunctionConstants.ISDA_BUCKET_TENORS, bucketTenors)
            .get();
    final ValueRequirement spreadRequirment =
        new ValueRequirement(
            ValueRequirementNames.BUCKETED_SPREADS, target.toSpecification(), spreadProperties);
    final ValueRequirement pillarRequirment =
        new ValueRequirement(
            ValueRequirementNames.PILLAR_SPREADS, target.toSpecification(), spreadProperties);
    final ValueRequirement creditCurveRequirement =
        new ValueRequirement(
            ValueRequirementNames.HAZARD_RATE_CURVE, target.toSpecification(), spreadProperties);

    // get individual spread for this cds (ignore business day adjustment on either)
    final Period period =
        Period.between(
            cds.getStartDate().toLocalDate().withDayOfMonth(20),
            cds.getMaturityDate().toLocalDate().withDayOfMonth(20));
    final ValueRequirement cdsSpreadRequirement =
        new ValueRequirement(
            MarketDataRequirementNames.MARKET_VALUE,
            ComputationTargetType.PRIMITIVE,
            ExternalId.of("Tenor", period.toString()));

    final CdsRecoveryRateIdentifier recoveryRateIdentifier =
        cds.accept(new CreditSecurityToRecoveryRateVisitor(context.getSecuritySource()));
    final ValueRequirement recoveryRateRequirement =
        new ValueRequirement(
            "PX_LAST", ComputationTargetType.PRIMITIVE, recoveryRateIdentifier.getExternalId());

    return Sets.newHashSet(
        isdaRequirment,
        spreadRequirment,
        cdsSpreadRequirement,
        creditCurveRequirement,
        pillarRequirment,
        recoveryRateRequirement);
  }
  @Override
  public Set<ComputedValue> execute(
      final FunctionExecutionContext executionContext,
      final FunctionInputs inputs,
      final ComputationTarget target,
      final Set<ValueRequirement> desiredValues)
      throws AsynchronousExecution {
    final ZonedDateTime now = ZonedDateTime.now(executionContext.getValuationClock());
    final ValueRequirement requirement = desiredValues.iterator().next();
    final ValueProperties properties = requirement.getConstraints().copy().get();

    final LegacyVanillaCDSSecurity security = (LegacyVanillaCDSSecurity) target.getSecurity();
    // LegacyVanillaCreditDefaultSwapDefinition cds =
    // _converter.visitLegacyVanillaCDSSecurity(security);
    final ValueRequirement desiredValue = desiredValues.iterator().next(); // all same constraints

    final String quoteConventionString =
        desiredValue.getConstraint(ISDAFunctionConstants.CDS_QUOTE_CONVENTION);
    final StandardCDSQuotingConvention quoteConvention =
        StandardCDSQuotingConvention.parse(quoteConventionString);

    final CdsRecoveryRateIdentifier recoveryRateIdentifier =
        security.accept(
            new CreditSecurityToRecoveryRateVisitor(executionContext.getSecuritySource()));
    Object recoveryRateObject =
        inputs.getValue(
            new ValueRequirement(
                "PX_LAST",
                ComputationTargetType.PRIMITIVE,
                recoveryRateIdentifier.getExternalId()));
    if (recoveryRateObject == null) {
      throw new OpenGammaRuntimeException("Could not get recovery rate");
      // s_logger.warn("Could not get recovery rate, defaulting to 0.4: " + recoveryRateIdentifier);
      // recoveryRateObject = 0.4;
    }
    final double recoveryRate = (Double) recoveryRateObject;

    // get the isda curve
    final Object isdaObject = inputs.getValue(ValueRequirementNames.YIELD_CURVE);
    if (isdaObject == null) {
      throw new OpenGammaRuntimeException("Couldn't get isda curve");
    }
    final ISDACompliantYieldCurve yieldCurve = (ISDACompliantYieldCurve) isdaObject;

    // spreads
    NodalTenorDoubleCurve spreadObject =
        (NodalTenorDoubleCurve) inputs.getValue(ValueRequirementNames.BUCKETED_SPREADS);
    if (spreadObject == null) {
      throw new OpenGammaRuntimeException("Unable to get spreads");
    }
    final double[] spreads = ArrayUtils.toPrimitive(spreadObject.getYData());
    // final String pillarString = IMMDateGenerator.isIMMDate(security.getMaturityDate()) ?
    // requirement.getConstraint(ISDAFunctionConstants.ISDA_BUCKET_TENORS) :
    // ISDACompliantCreditCurveFunction.NON_IMM_PILLAR_TENORS;
    final ZonedDateTime[] bucketDates =
        SpreadCurveFunctions.getPillarDates(now, spreadObject.getXData());
    final CDSQuoteConvention[] quotes =
        SpreadCurveFunctions.getQuotes(
            security.getMaturityDate(), spreads, security.getParSpread(), quoteConvention, false);

    // spreads
    NodalTenorDoubleCurve pillarObject =
        (NodalTenorDoubleCurve) inputs.getValue(ValueRequirementNames.PILLAR_SPREADS);
    if (pillarObject == null) {
      throw new OpenGammaRuntimeException("Unable to get pillars");
    }

    // CDS analytics for credit curve (possible performance improvement if earlier result obtained)
    // final LegacyVanillaCreditDefaultSwapDefinition curveCDS = cds.withStartDate(now);
    // security.setStartDate(now); // needed for curve instruments
    final CDSAnalytic[] bucketCDSs = new CDSAnalytic[bucketDates.length];
    for (int i = 0; i < bucketCDSs.length; i++) {
      // security.setMaturityDate(bucketDates[i]);
      final CDSAnalyticVisitor visitor =
          new CDSAnalyticVisitor(
              now.toLocalDate(),
              _holidaySource,
              _regionSource,
              security.getStartDate().toLocalDate(),
              bucketDates[i].toLocalDate(),
              recoveryRate);
      bucketCDSs[i] = security.accept(visitor);
    }

    final ZonedDateTime[] pillarDates =
        SpreadCurveFunctions.getPillarDates(now, pillarObject.getXData());
    final CDSAnalytic[] pillarCDSs = new CDSAnalytic[pillarDates.length];
    for (int i = 0; i < pillarCDSs.length; i++) {
      // security.setMaturityDate(bucketDates[i]);
      final CDSAnalyticVisitor visitor =
          new CDSAnalyticVisitor(
              now.toLocalDate(),
              _holidaySource,
              _regionSource,
              security.getStartDate().toLocalDate(),
              pillarDates[i].toLocalDate(),
              recoveryRate);
      pillarCDSs[i] = security.accept(visitor);
    }

    final ISDACompliantCreditCurve creditCurve =
        (ISDACompliantCreditCurve) inputs.getValue(ValueRequirementNames.HAZARD_RATE_CURVE);
    if (creditCurve == null) {
      throw new OpenGammaRuntimeException("Couldnt get credit curve");
    }

    // final CDSAnalytic analytic = CDSAnalyticConverter.create(cds, now.toLocalDate());
    final CDSAnalyticVisitor visitor =
        new CDSAnalyticVisitor(now.toLocalDate(), _holidaySource, _regionSource, recoveryRate);
    final CDSAnalytic analytic = security.accept(visitor);
    final BuySellProtection buySellProtection =
        security.isBuy() ? BuySellProtection.BUY : BuySellProtection.SELL;
    //    final String term = new Tenor(Period.between(security.getStartDate().toLocalDate(),
    // security.getMaturityDate().toLocalDate())).getPeriod().toString();
    //    final Double cdsQuoteDouble = (Double) inputs.getValue(new
    // ValueRequirement(MarketDataRequirementNames.MARKET_VALUE,
    //        ComputationTargetType.PRIMITIVE, ExternalId.of("Tenor", term)));
    final Double cdsQuoteDouble = (Double) inputs.getValue(MarketDataRequirementNames.MARKET_VALUE);
    if (cdsQuoteDouble == null) {
      throw new OpenGammaRuntimeException("Couldn't get spread for " + security);
    }
    final CDSQuoteConvention quote =
        SpreadCurveFunctions.getQuotes(
            security.getMaturityDate(),
            new double[] {cdsQuoteDouble},
            security.getParSpread(),
            quoteConvention,
            true)[0];

    boolean isNonIMMFAndFromPUF =
        !IMMDateLogic.isIMMDate(security.getMaturityDate().toLocalDate())
            && quote instanceof PointsUpFront;
    boolean isNonIMMAndFromSpread =
        !IMMDateLogic.isIMMDate(security.getMaturityDate().toLocalDate())
            && (quote instanceof QuotedSpread || quote instanceof ParSpread);
    int buySellPremiumFactor = security.isBuy() ? -1 : 1;

    final double notional = security.getNotional().getAmount();
    final double coupon = security.getParSpread() * ONE_BPS;
    final PointsUpFront puf =
        getPointsUpfront(quote, buySellProtection, yieldCurve, analytic, creditCurve);
    final double accruedPremiumPrim =
        isNonIMMAndFromSpread || isNonIMMFAndFromPUF ? 0 : analytic.getAccruedPremium(coupon);
    //    final double accruedPremium = isNonIMMAndFromSpread || isNonIMMFAndFromPUF ? 0 :
    // analytic.getAccruedPremium(coupon) * notional * buySellPremiumFactor;
    final double accruedPremium =
        isNonIMMAndFromSpread || isNonIMMFAndFromPUF
            ? 0
            : accruedPremiumPrim * notional * buySellPremiumFactor;
    final int accruedDays =
        isNonIMMAndFromSpread || isNonIMMFAndFromPUF ? 0 : analytic.getAccuredDays();
    final double quotedSpread =
        getQuotedSpread(quote, puf, buySellProtection, yieldCurve, analytic).getQuotedSpread();
    final double upfrontAmount =
        isNonIMMAndFromSpread
            ? 0
            : getUpfrontAmount(analytic, puf, notional, accruedPremiumPrim, buySellProtection);
    final double cleanPV = puf.getPointsUpFront() * notional;
    final double principal = isNonIMMAndFromSpread ? 0 : cleanPV;
    final double cleanPrice = getCleanPrice(puf);
    final TenorLabelledMatrix1D bucketedCS01 =
        getBucketedCS01(
            analytic,
            bucketCDSs,
            spreadObject.getXData(),
            quote,
            notional,
            yieldCurve,
            creditCurve);
    final double parallelCS01 =
        getParallelCS01(
            quote,
            analytic,
            yieldCurve,
            notional,
            pillarCDSs,
            ArrayUtils.toPrimitive(pillarObject.getYData()));

    final Set<ComputedValue> results = Sets.newHashSetWithExpectedSize(_valueRequirements.length);
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.ACCRUED_PREMIUM, target.toSpecification(), properties),
            accruedPremium));
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.ACCRUED_DAYS, target.toSpecification(), properties),
            accruedDays));
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.QUOTED_SPREAD, target.toSpecification(), properties),
            quotedSpread / ONE_BPS));
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.UPFRONT_AMOUNT, target.toSpecification(), properties),
            upfrontAmount));
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.DIRTY_PRESENT_VALUE, target.toSpecification(), properties),
            upfrontAmount));
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.CLEAN_PRESENT_VALUE, target.toSpecification(), properties),
            cleanPV));
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.PRINCIPAL, target.toSpecification(), properties),
            principal));
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.CLEAN_PRICE, target.toSpecification(), properties),
            cleanPrice));
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.BUCKETED_CS01, target.toSpecification(), properties),
            bucketedCS01));
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.PARALLEL_CS01, target.toSpecification(), properties),
            parallelCS01));
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.POINTS_UPFRONT, target.toSpecification(), properties),
            puf.getPointsUpFront()));
    return results;
  }
    @Override
    public Set<ComputedValue> execute(
        final FunctionExecutionContext executionContext,
        final FunctionInputs inputs,
        final ComputationTarget target,
        final Set<ValueRequirement> desiredValues)
        throws AsynchronousExecution {
      final Object originalCurveObject = inputs.getValue(YIELD_CURVE);
      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)) {
          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 ValueProperties resultJacobianProperties = resultCurveProperties.withoutAny(CURVE);
      ZonedDateTime valuationDateTime =
          executionContext
              .getValuationTime()
              .atZone(executionContext.getValuationClock().getZone());
      final HolidaySource holidaySource =
          OpenGammaExecutionContext.getHolidaySource(executionContext);
      final ConventionSource conventionSource =
          OpenGammaExecutionContext.getConventionSource(executionContext);
      final Calendar calendar = CalendarUtils.getCalendar(holidaySource, _currency);
      final DepositConvention convention =
          conventionSource.getSingle(
              ExternalId.of(SCHEME_NAME, getConventionName(_currency, DEPOSIT)),
              DepositConvention.class);
      final int spotLag = convention.getSettlementDays();
      final ExternalId conventionSettlementRegion = convention.getRegionCalendar();
      ZonedDateTime spotDate;
      if (spotLag == 0 && conventionSettlementRegion == null) {
        spotDate = valuationDateTime;
      } else {
        spotDate = ScheduleCalculator.getAdjustedDate(valuationDateTime, spotLag, calendar);
        ;
      }
      final YieldCurveBundle curves = new YieldCurveBundle();
      final String fullYieldCurveName = _originalCurveName + "_" + _currency;
      curves.setCurve(fullYieldCurveName, (YieldAndDiscountCurve) originalCurveObject);
      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: Get the convention from the curve.

      final String impliedDepositCurveName = _curveCalculationConfig + "_" + _currency.getCode();
      final List<InstrumentDerivative> derivatives = new ArrayList<>();

      for (final FixedIncomeStrip strip : _impliedDefinition.getStrips()) {
        final Tenor tenor = strip.getCurveNodePointTime();
        final ZonedDateTime paymentDate =
            ScheduleCalculator.getAdjustedDate(
                spotDate, tenor.getPeriod(), MOD_FOL, calendar, true);
        final double startTime = TimeCalculator.getTimeBetween(valuationDateTime, spotDate);
        final double endTime = TimeCalculator.getTimeBetween(valuationDateTime, paymentDate);
        final double accrualFactor = dayCount.getDayCountFraction(spotDate, paymentDate, 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 YieldCurveBundle knownCurve = new YieldCurveBundle();
      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 =
          rootFinder.getRoot(curveCalculator, jacobianCalculator, new DoubleMatrix1D(r)).getData();
      final DoubleMatrix2D jacobianMatrix =
          jacobianCalculator.evaluate(new DoubleMatrix1D(fittedYields));
      final YieldCurve impliedDepositCurve =
          new YieldCurve(
              impliedDepositCurveName,
              InterpolatedDoublesCurve.from(t, fittedYields, interpolator));
      final ValueSpecification curveSpec =
          new ValueSpecification(YIELD_CURVE, target.toSpecification(), resultCurveProperties);
      final ValueSpecification jacobianSpec =
          new ValueSpecification(
              YIELD_CURVE_JACOBIAN, target.toSpecification(), resultJacobianProperties);
      return Sets.newHashSet(
          new ComputedValue(curveSpec, impliedDepositCurve),
          new ComputedValue(jacobianSpec, jacobianMatrix));
    }
 @Override
 public Set<ComputedValue> execute(
     final FunctionExecutionContext executionContext,
     final FunctionInputs inputs,
     final ComputationTarget target,
     final Set<ValueRequirement> desiredValues) {
   final Clock snapshotClock = executionContext.getValuationClock();
   final ZonedDateTime now = snapshotClock.zonedDateTime();
   final FinancialSecurity security = (FinancialSecurity) target.getSecurity();
   final InstrumentDefinition<InstrumentDerivative> definition =
       (InstrumentDefinition<InstrumentDerivative>) security.accept(VISITOR);
   final Currency putCurrency = security.accept(ForexVisitors.getPutCurrencyVisitor());
   final Currency callCurrency = security.accept(ForexVisitors.getCallCurrencyVisitor());
   final ValueRequirement desiredValue = desiredValues.iterator().next();
   final String putCurveName = desiredValue.getConstraint(PROPERTY_PUT_CURVE);
   final String callCurveName = desiredValue.getConstraint(PROPERTY_CALL_CURVE);
   final String surfaceName = desiredValue.getConstraint(ValuePropertyNames.SURFACE);
   final String putForwardCurveName = desiredValue.getConstraint(PROPERTY_PUT_FORWARD_CURVE);
   final String callForwardCurveName = desiredValue.getConstraint(PROPERTY_CALL_FORWARD_CURVE);
   final String putCurveCalculationMethod =
       desiredValue.getConstraint(PROPERTY_PUT_CURVE_CALCULATION_METHOD);
   final String callCurveCalculationMethod =
       desiredValue.getConstraint(PROPERTY_CALL_CURVE_CALCULATION_METHOD);
   final String interpolatorName =
       desiredValue.getConstraint(InterpolatedDataProperties.X_INTERPOLATOR_NAME);
   final String leftExtrapolatorName =
       desiredValue.getConstraint(InterpolatedDataProperties.LEFT_X_EXTRAPOLATOR_NAME);
   final String rightExtrapolatorName =
       desiredValue.getConstraint(InterpolatedDataProperties.RIGHT_X_EXTRAPOLATOR_NAME);
   final String spread = desiredValue.getConstraint(PROPERTY_CALL_SPREAD_VALUE);
   final double spreadValue = Double.parseDouble(spread);
   final String fullPutCurveName = putCurveName + "_" + putCurrency.getCode();
   final String fullCallCurveName = callCurveName + "_" + callCurrency.getCode();
   final String[] curveNames;
   if (FXUtils.isInBaseQuoteOrder(
       putCurrency, callCurrency)) { // To get Base/quote in market standard order.
     curveNames = new String[] {fullPutCurveName, fullCallCurveName};
   } else {
     curveNames = new String[] {fullCallCurveName, fullPutCurveName};
   }
   final YieldAndDiscountCurve putFundingCurve = getCurve(inputs, putCurrency, putCurveName);
   final YieldAndDiscountCurve callFundingCurve = getCurve(inputs, callCurrency, callCurveName);
   final YieldAndDiscountCurve[] curves;
   final Map<String, Currency> curveCurrency = new HashMap<String, Currency>();
   curveCurrency.put(fullPutCurveName, putCurrency);
   curveCurrency.put(fullCallCurveName, callCurrency);
   final String[] allCurveNames;
   final Currency ccy1;
   final Currency ccy2;
   if (FXUtils.isInBaseQuoteOrder(
       putCurrency, callCurrency)) { // To get Base/quote in market standard order.
     ccy1 = putCurrency;
     ccy2 = callCurrency;
     curves = new YieldAndDiscountCurve[] {putFundingCurve, callFundingCurve};
     allCurveNames = new String[] {fullPutCurveName, fullCallCurveName};
   } else {
     curves = new YieldAndDiscountCurve[] {callFundingCurve, putFundingCurve};
     allCurveNames = new String[] {fullCallCurveName, fullPutCurveName};
     ccy1 = callCurrency;
     ccy2 = putCurrency;
   }
   final InstrumentDerivative fxOption = definition.toDerivative(now, curveNames);
   final YieldCurveBundle yieldCurves = new YieldCurveBundle(allCurveNames, curves);
   final Object spotObject = inputs.getValue(ValueRequirementNames.SPOT_RATE);
   if (spotObject == null) {
     throw new OpenGammaRuntimeException("Could not get spot rate");
   }
   final double spot = (Double) spotObject;
   final ValueRequirement fxVolatilitySurfaceRequirement =
       getSurfaceRequirement(
           surfaceName,
           putCurrency,
           callCurrency,
           interpolatorName,
           leftExtrapolatorName,
           rightExtrapolatorName);
   final Object volatilitySurfaceObject = inputs.getValue(fxVolatilitySurfaceRequirement);
   if (volatilitySurfaceObject == null) {
     throw new OpenGammaRuntimeException("Could not get " + fxVolatilitySurfaceRequirement);
   }
   final SmileDeltaTermStructureParametersStrikeInterpolation smiles =
       (SmileDeltaTermStructureParametersStrikeInterpolation) volatilitySurfaceObject;
   final FXMatrix fxMatrix = new FXMatrix(ccy1, ccy2, spot);
   final ValueProperties.Builder properties =
       getResultProperties(
           putCurveName,
           putForwardCurveName,
           putCurveCalculationMethod,
           callCurveName,
           callForwardCurveName,
           callCurveCalculationMethod,
           surfaceName,
           spread,
           interpolatorName,
           leftExtrapolatorName,
           rightExtrapolatorName,
           target);
   final ValueSpecification spec =
       new ValueSpecification(_valueRequirementName, target.toSpecification(), properties.get());
   final YieldCurveBundle curvesWithFX =
       new YieldCurveBundle(fxMatrix, curveCurrency, yieldCurves.getCurvesMap());
   final SmileDeltaTermStructureDataBundle smileBundle =
       new SmileDeltaTermStructureDataBundle(curvesWithFX, smiles, Pair.of(ccy1, ccy2));
   return getResult(fxOption, spreadValue, smileBundle, spec);
 }
 @Override
 public Set<ComputedValue> execute(
     final FunctionExecutionContext executionContext,
     final FunctionInputs inputs,
     final ComputationTarget target,
     final Set<ValueRequirement> desiredValues) {
   final Clock snapshotClock = executionContext.getValuationClock();
   final ZonedDateTime now = snapshotClock.zonedDateTime();
   final FinancialSecurity security = (FinancialSecurity) target.getSecurity();
   final Currency putCurrency = security.accept(ForexVisitors.getPutCurrencyVisitor());
   final Currency callCurrency = security.accept(ForexVisitors.getCallCurrencyVisitor());
   final ValueRequirement desiredValue = desiredValues.iterator().next();
   final String putCurveName = desiredValue.getConstraint(PUT_CURVE);
   final String callCurveName = desiredValue.getConstraint(CALL_CURVE);
   final String surfaceName = desiredValue.getConstraint(ValuePropertyNames.SURFACE);
   final String putCurveConfig = desiredValue.getConstraint(PUT_CURVE_CALC_CONFIG);
   final String callCurveConfig = desiredValue.getConstraint(CALL_CURVE_CALC_CONFIG);
   final String interpolatorName =
       desiredValue.getConstraint(InterpolatedDataProperties.X_INTERPOLATOR_NAME);
   final String leftExtrapolatorName =
       desiredValue.getConstraint(InterpolatedDataProperties.LEFT_X_EXTRAPOLATOR_NAME);
   final String rightExtrapolatorName =
       desiredValue.getConstraint(InterpolatedDataProperties.RIGHT_X_EXTRAPOLATOR_NAME);
   final String daysForward = desiredValue.getConstraint(PROPERTY_DAYS_TO_MOVE_FORWARD);
   final String fullPutCurveName = putCurveName + "_" + putCurrency.getCode();
   final String fullCallCurveName = callCurveName + "_" + callCurrency.getCode();
   final YieldAndDiscountCurve putFundingCurve =
       FXOptionFunctionUtils.getCurveForCurrency(
           inputs, putCurrency, putCurveName, putCurveConfig);
   final YieldAndDiscountCurve callFundingCurve =
       FXOptionFunctionUtils.getCurveForCurrency(
           inputs, callCurrency, callCurveName, callCurveConfig);
   final YieldAndDiscountCurve[] curves;
   final Map<String, Currency> curveCurrency = new HashMap<String, Currency>();
   curveCurrency.put(fullPutCurveName, putCurrency);
   curveCurrency.put(fullCallCurveName, callCurrency);
   final Object baseQuotePairsObject = inputs.getValue(ValueRequirementNames.CURRENCY_PAIRS);
   if (baseQuotePairsObject == null) {
     throw new OpenGammaRuntimeException("Could not get base/quote pair data");
   }
   final CurrencyPairs baseQuotePairs = (CurrencyPairs) baseQuotePairsObject;
   final CurrencyPair baseQuotePair = baseQuotePairs.getCurrencyPair(putCurrency, callCurrency);
   if (baseQuotePair == null) {
     throw new OpenGammaRuntimeException(
         "Could not get base/quote pair for currency pair ("
             + putCurrency
             + ", "
             + callCurrency
             + ")");
   }
   final String[] allCurveNames;
   final Currency ccy1;
   final Currency ccy2;
   if (baseQuotePair
       .getBase()
       .equals(putCurrency)) { // To get Base/quote in market standard order.
     ccy1 = putCurrency;
     ccy2 = callCurrency;
     curves = new YieldAndDiscountCurve[] {putFundingCurve, callFundingCurve};
     allCurveNames = new String[] {fullPutCurveName, fullCallCurveName};
   } else {
     curves = new YieldAndDiscountCurve[] {callFundingCurve, putFundingCurve};
     allCurveNames = new String[] {fullCallCurveName, fullPutCurveName};
     ccy1 = callCurrency;
     ccy2 = putCurrency;
   }
   final YieldCurveBundle yieldCurves = new YieldCurveBundle(allCurveNames, curves);
   final Object spotObject = inputs.getValue(ValueRequirementNames.SPOT_RATE);
   if (spotObject == null) {
     throw new OpenGammaRuntimeException("Could not get spot requirement");
   }
   final double spot = (Double) spotObject;
   final ValueRequirement fxVolatilitySurfaceRequirement =
       getSurfaceRequirement(
           surfaceName,
           putCurrency,
           callCurrency,
           interpolatorName,
           leftExtrapolatorName,
           rightExtrapolatorName);
   final Object volatilitySurfaceObject = inputs.getValue(fxVolatilitySurfaceRequirement);
   if (volatilitySurfaceObject == null) {
     throw new OpenGammaRuntimeException("Could not get " + fxVolatilitySurfaceRequirement);
   }
   final SmileDeltaTermStructureParametersStrikeInterpolation smiles =
       (SmileDeltaTermStructureParametersStrikeInterpolation) volatilitySurfaceObject;
   final FXMatrix fxMatrix = new FXMatrix(ccy1, ccy2, spot);
   final ValueProperties.Builder properties =
       getResultProperties(target, desiredValue, baseQuotePair);
   final ValueSpecification spec =
       new ValueSpecification(
           ValueRequirementNames.VALUE_THETA, target.toSpecification(), properties.get());
   final YieldCurveBundle curvesWithFX =
       new YieldCurveBundle(fxMatrix, curveCurrency, yieldCurves.getCurvesMap());
   final SmileDeltaTermStructureDataBundle smileBundle =
       new SmileDeltaTermStructureDataBundle(curvesWithFX, smiles, Pair.of(ccy1, ccy2));
   final ForexSecurityConverter converter = new ForexSecurityConverter(baseQuotePairs);
   final ForexOptionVanillaDefinition definition =
       (ForexOptionVanillaDefinition) security.accept(converter);
   final MultipleCurrencyAmount theta =
       CALCULATOR.getTheta(
           definition, now, allCurveNames, smileBundle, Integer.parseInt(daysForward));
   return Collections.singleton(new ComputedValue(spec, HorizonUtils.getNonZeroValue(theta)));
 }