@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 boolean canApplyTo( final FunctionCompilationContext context, final ComputationTarget target) { if (!(target.getPosition().getSecurity() instanceof FinancialSecurity)) { return false; } final FinancialSecurity security = (FinancialSecurity) target.getPosition().getSecurity(); if (!(security instanceof FXDigitalOptionSecurity)) { return false; } final Currency putCurrency = security.accept(ForexVisitors.getPutCurrencyVisitor()); final Currency callCurrency = security.accept(ForexVisitors.getCallCurrencyVisitor()); return callCurrency.getCode().equals(_callCurrency) && putCurrency.getCode().equals(_putCurrency); }
// ------------------------------------------------------------------------- @Override public synchronized YieldCurveDefinitionDocument add(YieldCurveDefinitionDocument document) { ArgumentChecker.notNull(document, "document"); ArgumentChecker.notNull(document.getYieldCurveDefinition(), "document.yieldCurveDefinition"); final Currency currency = document.getYieldCurveDefinition().getCurrency(); final String name = document.getYieldCurveDefinition().getName(); final Pair<Currency, String> key = Pair.of(currency, name); if (_definitions.containsKey(key)) { throw new IllegalArgumentException("Duplicate definition"); } final TreeMap<Instant, YieldCurveDefinition> value = new TreeMap<Instant, YieldCurveDefinition>(); Instant now = Instant.now(); value.put(now, document.getYieldCurveDefinition()); _definitions.put(key, value); final UniqueId uid = UniqueId.of(getUniqueIdScheme(), name + "_" + currency.getCode()); document.setUniqueId(uid); changeManager() .entityChanged( ChangeType.ADDED, document.getObjectId(), document.getVersionFromInstant(), document.getVersionToInstant(), now); return document; }
@Override public synchronized YieldCurveDefinitionDocument update(YieldCurveDefinitionDocument document) { ArgumentChecker.notNull(document, "document"); ArgumentChecker.notNull(document.getYieldCurveDefinition(), "document.yieldCurveDefinition"); final Currency currency = document.getYieldCurveDefinition().getCurrency(); final String name = document.getYieldCurveDefinition().getName(); final UniqueId uid = UniqueId.of(getUniqueIdScheme(), name + "_" + currency.getCode()); if (!uid.equals(document.getUniqueId())) { throw new IllegalArgumentException("Invalid unique identifier"); } final Pair<Currency, String> key = Pair.of(currency, name); final TreeMap<Instant, YieldCurveDefinition> value = _definitions.get(key); if (value == null) { throw new DataNotFoundException("UID '" + uid + "' not found"); } if (_sourceVersionCorrection.getVersionAsOf() != null) { // Don't need to keep the old values before the one needed by "versionAsOfInstant" final Instant oldestNeeded = value.floorKey(_sourceVersionCorrection.getVersionAsOf()); value.headMap(oldestNeeded).clear(); } else { // Don't need any old values value.clear(); } Instant now = Instant.now(); value.put(now, document.getYieldCurveDefinition()); document.setUniqueId(uid); changeManager().entityChanged(ChangeType.CHANGED, uid.getObjectId(), null, null, now); return document; }
@Override protected ValueProperties.Builder createValueProperties(final Currency currency) { return createValueProperties() .with(ValuePropertyNames.CURRENCY, currency.getCode()) .with(ValuePropertyNames.CURVE_CURRENCY, currency.getCode()) .withAny(ValuePropertyNames.CURVE_CALCULATION_CONFIG) .withAny(ValuePropertyNames.CURVE) .withAny(SurfaceAndCubePropertyNames.PROPERTY_CUBE_DEFINITION) .withAny(SurfaceAndCubePropertyNames.PROPERTY_CUBE_SPECIFICATION) .withAny(SurfaceAndCubePropertyNames.PROPERTY_SURFACE_DEFINITION) .withAny(SurfaceAndCubePropertyNames.PROPERTY_SURFACE_SPECIFICATION) .withAny(SABRRightExtrapolationFunction.PROPERTY_CUTOFF_STRIKE) .withAny(SABRRightExtrapolationFunction.PROPERTY_TAIL_THICKNESS_PARAMETER) .withAny(SmileFittingPropertyNamesAndValues.PROPERTY_FITTING_METHOD) .with( SmileFittingPropertyNamesAndValues.PROPERTY_VOLATILITY_MODEL, SmileFittingPropertyNamesAndValues.SABR) .with(ValuePropertyNames.CALCULATION_METHOD, SABRFunction.SABR_RIGHT_EXTRAPOLATION); }
@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())); }
private ValueProperties.Builder createCurrencyValueProperties(final ComputationTarget target) { final Security security = target.getPosition().getSecurity(); if (security instanceof FXOptionSecurity || security instanceof FXBarrierOptionSecurity || security instanceof FXDigitalOptionSecurity || security instanceof FXForwardSecurity) { return createValueProperties(); // TODO what to do in this case? } final Currency ccy = FinancialSecurityUtils.getCurrency(security); final ValueProperties.Builder properties = createValueProperties(); properties.with(ValuePropertyNames.CURRENCY, ccy.getCode()); return properties; }
@Override public List<UniqueId> replaceAllVersions( ObjectIdentifiable objectIdentifiable, List<YieldCurveDefinitionDocument> replacementDocuments) { ArgumentChecker.notNull(replacementDocuments, "replacementDocuments"); ArgumentChecker.notNull(objectIdentifiable, "objectIdentifiable"); final Instant now = Instant.now(); for (YieldCurveDefinitionDocument replacementDocument : replacementDocuments) { ArgumentChecker.notNull(replacementDocument, "document"); ArgumentChecker.notNull( replacementDocument.getYieldCurveDefinition(), "document.yieldCurveDefinition"); final Currency currency = replacementDocument.getYieldCurveDefinition().getCurrency(); final String name = replacementDocument.getYieldCurveDefinition().getName(); final UniqueId id = UniqueId.of(getUniqueIdScheme(), name + "_" + currency.getCode()); ArgumentChecker.isTrue(id.equals(objectIdentifiable), "Invalid object identifier"); } YieldCurveDefinitionDocument storedDocument = get(objectIdentifiable, null); if (storedDocument == null) { throw new DataNotFoundException("Document not found: " + objectIdentifiable); } final Currency currency = storedDocument.getYieldCurveDefinition().getCurrency(); final String name = storedDocument.getYieldCurveDefinition().getName(); Pair<Currency, String> key = Pair.of(currency, name); final TreeMap<Instant, YieldCurveDefinition> value = _definitions.get(key); if (value == null) { throw new DataNotFoundException("OID '" + objectIdentifiable + "' not found"); } value.clear(); List<YieldCurveDefinitionDocument> orderedReplacementDocuments = MasterUtils.adjustVersionInstants(now, null, null, replacementDocuments); final Instant lowestVersionFrom = orderedReplacementDocuments.get(0).getVersionFromInstant(); ArgumentChecker.notNull( lowestVersionFrom, "You must define version from of the first document"); for (YieldCurveDefinitionDocument replacementDocument : orderedReplacementDocuments) { value.put( replacementDocument.getVersionFromInstant(), replacementDocument.getYieldCurveDefinition()); changeManager() .entityChanged(ChangeType.CHANGED, replacementDocument.getObjectId(), null, null, now); } return MasterUtils.mapToUniqueIDs(orderedReplacementDocuments); }
protected String createName( final Currency currency, final int optionLength, final int swapLength, final double notional, final double rate) { final StringBuilder sb = new StringBuilder(); sb.append("Vanilla swaption, ") .append(lengthString(optionLength)) .append(" x ") .append(lengthString(swapLength)) .append(", "); sb.append(currency.getCode()) .append(" ") .append(NOTIONAL_FORMATTER.format(notional)) .append(" @ ") .append(RATE_FORMATTER.format(rate)); return sb.toString(); }
@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()); }
public static String getResultCurrency( final ComputationTarget target, final CurrencyPair baseQuotePair) { final FinancialSecurity security = (FinancialSecurity) target.getSecurity(); if (security instanceof FXDigitalOptionSecurity) { return ((FXDigitalOptionSecurity) target.getSecurity()).getPaymentCurrency().getCode(); } if (security instanceof NonDeliverableFXDigitalOptionSecurity) { return ((NonDeliverableFXDigitalOptionSecurity) target.getSecurity()) .getPaymentCurrency() .getCode(); } final Currency putCurrency = security.accept(ForexVisitors.getPutCurrencyVisitor()); final Currency callCurrency = security.accept(ForexVisitors.getCallCurrencyVisitor()); Currency ccy; if (baseQuotePair.getBase().equals(putCurrency)) { ccy = callCurrency; } else { ccy = putCurrency; } return ccy.getCode(); }
@Override public synchronized YieldCurveDefinitionDocument addOrUpdate( YieldCurveDefinitionDocument document) { ArgumentChecker.notNull(document, "document"); ArgumentChecker.notNull(document.getYieldCurveDefinition(), "document.yieldCurveDefinition"); final Currency currency = document.getYieldCurveDefinition().getCurrency(); final String name = document.getYieldCurveDefinition().getName(); final Pair<Currency, String> key = Pair.of(currency, name); TreeMap<Instant, YieldCurveDefinition> value = _definitions.get(key); final UniqueId uid = UniqueId.of(getUniqueIdScheme(), name + "_" + currency.getCode()); Instant now = Instant.now(); if (value != null) { if (_sourceVersionCorrection.getVersionAsOf() != null) { // Don't need to keep the old values before the one needed by "versionAsOfInstant" final Instant oldestNeeded = value.floorKey(_sourceVersionCorrection.getVersionAsOf()); if (oldestNeeded != null) { value.headMap(oldestNeeded).clear(); } } else { // Don't need any old values value.clear(); } value.put(now, document.getYieldCurveDefinition()); changeManager().entityChanged(ChangeType.CHANGED, uid.getObjectId(), null, null, now); } else { value = new TreeMap<Instant, YieldCurveDefinition>(); value.put(now, document.getYieldCurveDefinition()); _definitions.put(key, value); changeManager() .entityChanged( ChangeType.ADDED, uid.getObjectId(), document.getVersionFromInstant(), document.getVersionToInstant(), now); } document.setUniqueId(uid); return document; }
/** * Creates an ISO alpha 3 currency code. * * <p>Examples might be {@code GBP} or {@code USD}. * * @param currency the currency, not null * @return the region identifier, not null */ public static ExternalId currencyRegionId(Currency currency) { ArgumentChecker.notNull(currency, "currency"); return ExternalId.of(ISO_CURRENCY_ALPHA3, currency.getCode()); }
@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 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); }
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 = 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 List<UniqueId> replaceVersions( ObjectIdentifiable objectIdentifiable, List<YieldCurveDefinitionDocument> replacementDocuments) { ArgumentChecker.notNull(replacementDocuments, "replacementDocuments"); ArgumentChecker.notNull(objectIdentifiable, "objectIdentifiable"); final Instant now = Instant.now(); for (YieldCurveDefinitionDocument replacementDocument : replacementDocuments) { ArgumentChecker.notNull(replacementDocument, "document"); ArgumentChecker.notNull( replacementDocument.getYieldCurveDefinition(), "document.yieldCurveDefinition"); final Currency currency = replacementDocument.getYieldCurveDefinition().getCurrency(); final String name = replacementDocument.getYieldCurveDefinition().getName(); final UniqueId id = UniqueId.of(getUniqueIdScheme(), name + "_" + currency.getCode()); ArgumentChecker.isTrue(id.equals(objectIdentifiable), "Invalid object identifier"); } YieldCurveDefinitionDocument storedDocument = get(objectIdentifiable, null); if (storedDocument == null) { throw new DataNotFoundException("Document not found: " + objectIdentifiable); } final Currency currency = storedDocument.getYieldCurveDefinition().getCurrency(); final String name = storedDocument.getYieldCurveDefinition().getName(); Pair<Currency, String> key = Pair.of(currency, name); final TreeMap<Instant, YieldCurveDefinition> value = _definitions.get(key); if (value == null) { throw new DataNotFoundException("OID '" + objectIdentifiable + "' not found"); } if (_sourceVersionCorrection.getVersionAsOf() != null) { // Don't need to keep the old values before the one needed by "versionAsOfInstant" final Instant oldestNeeded = value.floorKey(_sourceVersionCorrection.getVersionAsOf()); value.headMap(oldestNeeded).clear(); } else { // Don't need any old values value.clear(); } Instant lowestCurrentVersionFrom = value.firstKey(); List<YieldCurveDefinitionDocument> orderedReplacementDocuments = MasterUtils.adjustVersionInstants( now, lowestCurrentVersionFrom, null, replacementDocuments); final Instant lowestVersionFrom = orderedReplacementDocuments.get(0).getVersionFromInstant(); final Instant highestVersionTo = orderedReplacementDocuments .get(orderedReplacementDocuments.size() - 1) .getVersionToInstant(); if (orderedReplacementDocuments.size() > 0) { value.subMap(lowestVersionFrom, true, highestVersionTo, false).clear(); } for (YieldCurveDefinitionDocument replacementDocument : orderedReplacementDocuments) { value.put( replacementDocument.getVersionFromInstant(), replacementDocument.getYieldCurveDefinition()); changeManager() .entityChanged(ChangeType.CHANGED, replacementDocument.getObjectId(), null, null, now); } return MasterUtils.mapToUniqueIDs(orderedReplacementDocuments); }
@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 CompiledFunctionDefinition compile( final FunctionCompilationContext context, final Instant atInstant) { final MultiCurveCalculationConfig impliedConfiguration = _multiCurveCalculationConfig.get(_curveCalculationConfig); if (impliedConfiguration == null) { throw new OpenGammaRuntimeException( "Multi-curve calculation called " + _curveCalculationConfig + " was null"); } ComputationTarget target = context.getComputationTargetResolver().resolve(impliedConfiguration.getTarget()); if (!(target.getValue() instanceof Currency)) { throw new OpenGammaRuntimeException( "Target of curve calculation configuration was not a currency"); } final Currency impliedCurrency = (Currency) target.getValue(); if (!IMPLIED_DEPOSIT.equals(impliedConfiguration.getCalculationMethod())) { throw new OpenGammaRuntimeException( "Curve calculation method was not " + IMPLIED_DEPOSIT + " for configuration called " + _curveCalculationConfig); } final String[] impliedCurveNames = impliedConfiguration.getYieldCurveNames(); if (impliedCurveNames.length != 1) { throw new OpenGammaRuntimeException( "Can only handle configurations with a single implied curve"); } final LinkedHashMap<String, String[]> originalConfigurationName = impliedConfiguration.getExogenousConfigData(); if (originalConfigurationName == null || originalConfigurationName.size() != 1) { throw new OpenGammaRuntimeException("Need a configuration with one exogenous configuration"); } final Map.Entry<String, String[]> entry = Iterables.getOnlyElement(originalConfigurationName.entrySet()); final String[] originalCurveNames = entry.getValue(); if (originalCurveNames.length != 1) { s_logger.warn("Found more than one exogenous configuration name; using only the first"); } final MultiCurveCalculationConfig originalConfiguration = _multiCurveCalculationConfig.get(entry.getKey()); if (originalConfiguration == null) { throw new OpenGammaRuntimeException( "Multi-curve calculation called " + entry.getKey() + " was null"); } target = context.getComputationTargetResolver().resolve(originalConfiguration.getTarget()); if (!(target.getValue() instanceof Currency)) { throw new OpenGammaRuntimeException( "Target of curve calculation configuration was not a currency"); } final Currency originalCurrency = (Currency) target.getValue(); if (!originalCurrency.equals(impliedCurrency)) { throw new OpenGammaRuntimeException( "Currency targets for configurations " + _curveCalculationConfig + " and " + entry.getKey() + " did not match"); } final YieldCurveDefinition impliedDefinition = _yieldCurveDefinition.get(impliedCurveNames[0] + "_" + impliedCurrency.getCode()); if (impliedDefinition == null) { throw new OpenGammaRuntimeException( "Could not get implied definition called " + impliedCurveNames[0] + "_" + impliedCurrency.getCode()); } final Set<FixedIncomeStrip> strips = impliedDefinition.getStrips(); for (final FixedIncomeStrip strip : strips) { if (strip.getInstrumentType() != StripInstrumentType.CASH) { throw new OpenGammaRuntimeException( "Can only handle yield curve definitions with CASH strips"); } } final ZonedDateTime atZDT = ZonedDateTime.ofInstant(atInstant, ZoneOffset.UTC); return new MyCompiledFunction( atZDT.with(LocalTime.MIDNIGHT), atZDT.plusDays(1).with(LocalTime.MIDNIGHT).minusNanos(1000000), impliedConfiguration, impliedDefinition, originalConfiguration, originalCurveNames[0]); };
@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<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; }