@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)); }
private static List<RequirementBasedColumnKey> getRequirements( ViewDefinition viewDefinition, EnumSet<ComputationTargetType> targetTypes) { List<RequirementBasedColumnKey> result = new ArrayList<RequirementBasedColumnKey>(); for (ViewCalculationConfiguration calcConfig : viewDefinition.getAllCalculationConfigurations()) { String calcConfigName = calcConfig.getName(); if (targetTypes.contains(ComputationTargetType.POSITION) || targetTypes.contains(ComputationTargetType.PORTFOLIO_NODE)) { for (Pair<String, ValueProperties> portfolioOutput : calcConfig.getAllPortfolioRequirements()) { String valueName = portfolioOutput.getFirst(); ValueProperties constraints = portfolioOutput.getSecond(); RequirementBasedColumnKey columnKey = new RequirementBasedColumnKey(calcConfigName, valueName, constraints); result.add(columnKey); } } for (ValueRequirement specificRequirement : calcConfig.getSpecificRequirements()) { if (!targetTypes.contains(specificRequirement.getTargetSpecification().getType())) { continue; } String valueName = specificRequirement.getValueName(); ValueProperties constraints = specificRequirement.getConstraints(); RequirementBasedColumnKey columnKey = new RequirementBasedColumnKey(calcConfigName, valueName, constraints); result.add(columnKey); } } return result; }
@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())); }
/** * Simplifies the type based on the associated {@link ComputationTargetResolver}. * * @param valueReq the requirement to process, not null * @return the possibly simplified requirement, not null */ public ValueRequirement simplifyType(final ValueRequirement valueReq) { final ComputationTargetReference oldTargetRef = valueReq.getTargetReference(); final ComputationTargetReference newTargetRef = ComputationTargetResolverUtils.simplifyType( oldTargetRef, getCompilationContext().getComputationTargetResolver()); if (newTargetRef == oldTargetRef) { return valueReq; } else { return MemoryUtils.instance( new ValueRequirement(valueReq.getValueName(), newTargetRef, valueReq.getConstraints())); } }
/** * Creates a new specification to satisfy the given requirement. * * <p>The properties must include the function identifier and be able to satisfy the constraints * of the original requirement. * * @param requirementSpecification a requirement, not null * @param properties the value properties, not null and must include the function identifier */ public ValueSpecification( final ValueRequirement requirementSpecification, final ValueProperties properties) { ArgumentChecker.notNull(requirementSpecification, "requirementSpecification"); ArgumentChecker.notNull(properties, "properties"); ArgumentChecker.notNull( properties.getValues(ValuePropertyNames.FUNCTION), "properties.FUNCTION"); assert requirementSpecification.getConstraints().isSatisfiedBy(properties); // requirement specification interns its valueName _valueName = requirementSpecification.getValueName(); _targetSpecification = requirementSpecification.getTargetSpecification(); _properties = properties; }
/** * Creates a new specification to satisfy the the given requirement. * * <p>The properties of the new specification are the constraints from the requirement with the * function identifier added. * * @param requirementSpecification a value requirement, not null * @param functionIdentifier the unique identifier of the function producing this value, not null */ public ValueSpecification( final ValueRequirement requirementSpecification, final String functionIdentifier) { ArgumentChecker.notNull(requirementSpecification, "requirementSpecification"); ArgumentChecker.notNull(functionIdentifier, "functionIdentifier"); // requirement specification interns its valueName _valueName = requirementSpecification.getValueName(); _targetSpecification = requirementSpecification.getTargetSpecification(); _properties = requirementSpecification .getConstraints() .copy() .with(ValuePropertyNames.FUNCTION, functionIdentifier) .get(); }
@Override public ComputedValue getComputedValue(final ValueRequirement requirement) { final Pair<String, Object> key = Pair.of( requirement.getValueName(), targetSpecKey(_resolver.getTargetSpecification(requirement.getTargetReference()))); final ComputedValue[] values = _valuesByRequirement.get(key); if (values != null) { for (final ComputedValue value : values) { // Shortcut to check the properties as we already know the name and target match if (requirement.getConstraints().isSatisfiedBy(value.getSpecification().getProperties())) { return value; } } } return null; }
@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<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)); }