@Override public Set<ComputedValue> execute( final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target, final Set<ValueRequirement> desiredValues) { final FXFutureSecurity security = (FXFutureSecurity) target.getSecurity(); final Clock snapshotClock = executionContext.getValuationClock(); final ZonedDateTime now = ZonedDateTime.now(snapshotClock); final Currency payCurrency = security.getNumerator(); final Object payCurveObject = inputs.getValue( YieldCurveFunction.getCurveRequirement(payCurrency, _payCurveName, null, null)); if (payCurveObject == null) { throw new OpenGammaRuntimeException("Could not get " + _payCurveName + " curve"); } final Currency receiveCurrency = security.getDenominator(); final Object receiveCurveObject = inputs.getValue( YieldCurveFunction.getCurveRequirement(receiveCurrency, _receiveCurveName, null, null)); if (receiveCurveObject == null) { throw new OpenGammaRuntimeException("Could not get " + _receiveCurveName + " curve"); } // TODO: The convention is only looked up here so that we can convert the spot rate; would be // better to request the spot rate using the correct currency pair in the first place final CurrencyPairs currencyPairs = OpenGammaExecutionContext.getCurrencyPairsSource(executionContext) .getCurrencyPairs(CurrencyPairs.DEFAULT_CURRENCY_PAIRS); final CurrencyPair currencyPair = currencyPairs.getCurrencyPair(payCurrency, receiveCurrency); final Currency currencyBase = currencyPair.getBase(); final Object spotObject = inputs.getValue(ValueRequirementNames.SPOT_RATE); if (spotObject == null) { throw new OpenGammaRuntimeException("Could not get market data for spot rate"); } double spot = (Double) spotObject; if (!receiveCurrency.equals(currencyBase) && receiveCurrency.equals(security.getCurrency())) { spot = 1. / spot; } final YieldAndDiscountCurve payCurve = (YieldAndDiscountCurve) payCurveObject; final YieldAndDiscountCurve receiveCurve = (YieldAndDiscountCurve) receiveCurveObject; final SimpleFXFutureDataBundle data = new SimpleFXFutureDataBundle(payCurve, receiveCurve, spot); final SimpleInstrument instrument = security.accept(CONVERTER).toDerivative(now); final CurrencyAmount pv = instrument.accept(CALCULATOR, data); final ValueProperties properties = createValueProperties() .with(ValuePropertyNames.PAY_CURVE, _payCurveName) .with(ValuePropertyNames.RECEIVE_CURVE, _receiveCurveName) .with(ValuePropertyNames.CURRENCY, pv.getCurrency().getCode()) .get(); final ValueSpecification spec = new ValueSpecification( ValueRequirementNames.PRESENT_VALUE, target.toSpecification(), properties); return Collections.singleton(new ComputedValue(spec, pv.getAmount())); }
@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 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<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) { 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))); }
@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)); }
@Override public Set<ValueRequirement> getRequirements( final FunctionCompilationContext context, final ComputationTarget target, final ValueRequirement desiredValue) { final ValueProperties constraints = desiredValue.getConstraints(); final Set<String> payCurveNames = constraints.getValues(ValuePropertyNames.PAY_CURVE); if (payCurveNames == null || payCurveNames.size() != 1) { return null; } final Set<String> payCurveCalculationConfigs = constraints.getValues(ValuePropertyNames.PAY_CURVE_CALCULATION_CONFIG); if (payCurveCalculationConfigs == null || payCurveCalculationConfigs.size() != 1) { return null; } final Set<String> receiveCurveNames = constraints.getValues(ValuePropertyNames.RECEIVE_CURVE); if (receiveCurveNames == null || receiveCurveNames.size() != 1) { return null; } final Set<String> receiveCurveCalculationConfigs = constraints.getValues(ValuePropertyNames.RECEIVE_CURVE_CALCULATION_CONFIG); if (receiveCurveCalculationConfigs == null || receiveCurveCalculationConfigs.size() != 1) { return null; } final Set<String> calculationMethods = constraints.getValues(ValuePropertyNames.CALCULATION_METHOD); if (calculationMethods == null || calculationMethods.size() != 1) { final ValueProperties newConstraints = constraints .copy() .withoutAny(ValuePropertyNames.CALCULATION_METHOD) .with( ValuePropertyNames.CALCULATION_METHOD, CalculationPropertyNamesAndValues.DISCOUNTING) .get(); return Collections.singleton( new ValueRequirement( ValueRequirementNames.PNL_SERIES, target.toSpecification(), newConstraints)); } final Set<ValueRequirement> requirements = new HashSet<>(); final String calculationMethod = Iterables.getOnlyElement(calculationMethods); final FinancialSecurity security = (FinancialSecurity) target.getPosition().getSecurity(); if (CalculationPropertyNamesAndValues.DISCOUNTING.equals(calculationMethod)) { requirements.add( new ValueRequirement( ValueRequirementNames.FX_CURRENCY_EXPOSURE, ComputationTargetSpecification.of(target.getPosition().getSecurity()), ValueProperties.builder() .with( ValuePropertyNames.CALCULATION_METHOD, CalculationPropertyNamesAndValues.DISCOUNTING) .with(ValuePropertyNames.PAY_CURVE, payCurveNames.iterator().next()) .with( ValuePropertyNames.PAY_CURVE_CALCULATION_CONFIG, payCurveCalculationConfigs.iterator().next()) .with(ValuePropertyNames.RECEIVE_CURVE, receiveCurveNames.iterator().next()) .with( ValuePropertyNames.RECEIVE_CURVE_CALCULATION_CONFIG, receiveCurveCalculationConfigs.iterator().next()) .get())); } else if (CalculationPropertyNamesAndValues.FORWARD_POINTS.equals(calculationMethod)) { final Set<String> forwardCurveNames = constraints.getValues(ValuePropertyNames.FORWARD_CURVE_NAME); if (forwardCurveNames == null || forwardCurveNames.size() != 1) { return null; } final String forwardCurveName = Iterables.getOnlyElement(forwardCurveNames); requirements.add( new ValueRequirement( ValueRequirementNames.FX_CURRENCY_EXPOSURE, ComputationTargetSpecification.of(target.getPosition().getSecurity()), ValueProperties.builder() .with( ValuePropertyNames.CALCULATION_METHOD, CalculationPropertyNamesAndValues.FORWARD_POINTS) .with(ValuePropertyNames.PAY_CURVE, payCurveNames.iterator().next()) .with( ValuePropertyNames.PAY_CURVE_CALCULATION_CONFIG, payCurveCalculationConfigs.iterator().next()) .with(ValuePropertyNames.RECEIVE_CURVE, receiveCurveNames.iterator().next()) .with( ValuePropertyNames.RECEIVE_CURVE_CALCULATION_CONFIG, receiveCurveCalculationConfigs.iterator().next()) .with(ValuePropertyNames.FORWARD_CURVE_NAME, forwardCurveName) .get())); } else { return null; } final Set<String> resultCurrencies = constraints.getValues(CURRENCY); final Currency payCurrency = security.accept(ForexVisitors.getPayCurrencyVisitor()); final Currency receiveCurrency = security.accept(ForexVisitors.getReceiveCurrencyVisitor()); final String resultCurrency; final CurrencyPair baseQuotePair = _currencyPairs.getCurrencyPair(payCurrency, receiveCurrency); final Currency baseCurrency = baseQuotePair.getBase(); final Currency nonBaseCurrency = baseQuotePair.getCounter(); if (resultCurrencies != null && resultCurrencies.size() == 1) { final Currency ccy = Currency.of(Iterables.getOnlyElement(resultCurrencies)); if (!(ccy.equals(payCurrency) || ccy.equals(receiveCurrency))) { requirements.add( ConventionBasedFXRateFunction.getHistoricalTimeSeriesRequirement( UnorderedCurrencyPair.of(baseCurrency, ccy))); resultCurrency = ccy.getCode(); } else if (ccy.equals(nonBaseCurrency)) { requirements.add( ConventionBasedFXRateFunction.getHistoricalTimeSeriesRequirement( UnorderedCurrencyPair.of(nonBaseCurrency, baseCurrency))); resultCurrency = nonBaseCurrency.getCode(); } else { requirements.add( ConventionBasedFXRateFunction.getHistoricalTimeSeriesRequirement( UnorderedCurrencyPair.of(baseCurrency, nonBaseCurrency))); resultCurrency = baseCurrency.getCode(); } } else { resultCurrency = baseCurrency.getCode(); } final ValueProperties fxSpotConstraints = desiredValue .getConstraints() .copy() .withoutAny(ValuePropertyNames.PAY_CURVE) .withoutAny(ValuePropertyNames.PAY_CURVE_CALCULATION_CONFIG) .withoutAny(ValuePropertyNames.RECEIVE_CURVE) .withoutAny(ValuePropertyNames.RECEIVE_CURVE_CALCULATION_CONFIG) .withoutAny(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS) .withoutAny(ValuePropertyNames.CURVE_CURRENCY) .withoutAny(ValuePropertyNames.CALCULATION_METHOD) .withoutAny(ValuePropertyNames.FORWARD_CURVE_NAME) .with(CURRENCY, resultCurrency) .withOptional(CURRENCY) .get(); final ComputationTargetSpecification fxSpotReturnSeriesSpec = ComputationTargetType.UNORDERED_CURRENCY_PAIR.specification( UnorderedCurrencyPair.of(payCurrency, receiveCurrency)); requirements.add( new ValueRequirement( ValueRequirementNames.RETURN_SERIES, fxSpotReturnSeriesSpec, fxSpotConstraints)); return requirements; }
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; }