@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 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 Position position = target.getPosition(); final ValueRequirement desiredValue = desiredValues.iterator().next(); final ValueProperties constraints = desiredValue.getConstraints(); final Set<String> resultCurrencies = constraints.getValues(CURRENCY); final FXForwardSecurity security = (FXForwardSecurity) position.getSecurity(); final MultipleCurrencyAmount mca = (MultipleCurrencyAmount) inputs.getValue(ValueRequirementNames.FX_CURRENCY_EXPOSURE); final Currency payCurrency = security.getPayCurrency(); final Currency receiveCurrency = security.getReceiveCurrency(); final CurrencyPair currencyPair = _currencyPairs.getCurrencyPair(payCurrency, receiveCurrency); final Currency baseCurrency = currencyPair.getBase(); final Currency currencyNonBase = currencyPair.getCounter(); // The non-base currency final double exposure = mca.getAmount(currencyNonBase); final ValueSpecification spec = new ValueSpecification( ValueRequirementNames.PNL_SERIES, target.toSpecification(), desiredValue.getConstraints()); if (resultCurrencies == null || resultCurrencies.size() != 1) { s_logger.warn("No Currency property - returning result in base currency"); final LocalDateDoubleTimeSeries fxSpotReturnSeries = (LocalDateDoubleTimeSeries) inputs.getValue(ValueRequirementNames.RETURN_SERIES); final LocalDateDoubleTimeSeries pnlSeries = fxSpotReturnSeries.multiply( position.getQuantity().doubleValue() * exposure); // The P/L time series is in the base currency return Collections.singleton(new ComputedValue(spec, pnlSeries)); } final Currency resultCurrency = Currency.of(Iterables.getOnlyElement(resultCurrencies)); final LocalDateDoubleTimeSeries conversionTS = (LocalDateDoubleTimeSeries) inputs.getValue(HISTORICAL_FX_TIME_SERIES); if (conversionTS == null) { throw new OpenGammaRuntimeException( "Asked for result in " + resultCurrency + " but could not get " + baseCurrency + "/" + resultCurrency + " conversion series"); } if (resultCurrency.equals(baseCurrency)) { final LocalDateDoubleTimeSeries fxSpotReturnSeries = (LocalDateDoubleTimeSeries) inputs.getValue(ValueRequirementNames.RETURN_SERIES); final LocalDateDoubleTimeSeries convertedSeries = conversionTS .reciprocal() .multiply( position.getQuantity().doubleValue() * exposure); // The P/L time series is in the base currency final LocalDateDoubleTimeSeries pnlSeries = fxSpotReturnSeries.multiply( convertedSeries); // The P/L time series is in the base currency return Collections.singleton(new ComputedValue(spec, pnlSeries)); } final LocalDateDoubleTimeSeries fxSpotReturnSeries = (LocalDateDoubleTimeSeries) inputs.getValue(ValueRequirementNames.RETURN_SERIES); final LocalDateDoubleTimeSeries convertedSeries = conversionTS.multiply( position.getQuantity().doubleValue() * exposure); // The P/L time series is in the base currency final LocalDateDoubleTimeSeries pnlSeries = convertedSeries.multiply(fxSpotReturnSeries); return Collections.singleton(new ComputedValue(spec, pnlSeries)); }