/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.financial.analytics.model.equity.futures; import java.util.NoSuchElementException; import java.util.Set; import org.threeten.bp.ZonedDateTime; import com.opengamma.OpenGammaRuntimeException; import com.opengamma.analytics.financial.equity.future.pricing.DividendYieldFuturesCalculator; import com.opengamma.analytics.financial.future.FuturesRatesSensitivityCalculator; import com.opengamma.analytics.financial.instrument.InstrumentDefinitionWithData; import com.opengamma.analytics.financial.interestrate.InstrumentDerivative; import com.opengamma.analytics.financial.interestrate.YieldCurveBundle; import com.opengamma.analytics.financial.simpleinstruments.pricing.SimpleFutureDataBundle; import com.opengamma.analytics.math.matrix.DoubleMatrix1D; import com.opengamma.core.holiday.HolidaySource; import com.opengamma.core.position.Trade; import com.opengamma.core.region.RegionSource; import com.opengamma.core.security.SecuritySource; import com.opengamma.core.value.MarketDataRequirementNames; import com.opengamma.engine.ComputationTarget; import com.opengamma.engine.ComputationTargetSpecification; import com.opengamma.engine.function.FunctionCompilationContext; import com.opengamma.engine.function.FunctionExecutionContext; import com.opengamma.engine.function.FunctionInputs; import com.opengamma.engine.value.ComputedValue; import com.opengamma.engine.value.ValueProperties; import com.opengamma.engine.value.ValuePropertyNames; import com.opengamma.engine.value.ValueRequirement; import com.opengamma.engine.value.ValueRequirementNames; import com.opengamma.engine.value.ValueSpecification; import com.opengamma.financial.OpenGammaCompilationContext; import com.opengamma.financial.analytics.conversion.BondFutureSecurityConverter; import com.opengamma.financial.analytics.conversion.BondSecurityConverter; import com.opengamma.financial.analytics.conversion.FutureSecurityConverterDeprecated; import com.opengamma.financial.analytics.conversion.InterestRateFutureSecurityConverterDeprecated; import com.opengamma.financial.analytics.ircurve.InterpolatedYieldCurveSpecificationWithSecurities; import com.opengamma.financial.analytics.model.YieldCurveNodeSensitivitiesHelper; import com.opengamma.financial.analytics.timeseries.HistoricalTimeSeriesBundle; import com.opengamma.financial.analytics.timeseries.HistoricalTimeSeriesFunctionUtils; import com.opengamma.financial.convention.ConventionBundleSource; import com.opengamma.financial.security.FinancialSecurityUtils; import com.opengamma.financial.security.future.FutureSecurity; import com.opengamma.util.money.Currency; /** * */ public class EquityDividendYieldFuturesYCNSFunction extends EquityDividendYieldFuturesFunction<DoubleMatrix1D> { private FutureSecurityConverterDeprecated _converter; /** * @param closingPriceField The field name of the historical time series for price, e.g. "PX_LAST", "Close". Set in *FunctionConfiguration * @param costOfCarryField The field name of the historical time series for cost of carry e.g. "COST_OF_CARRY". Set in *FunctionConfiguration * @param resolutionKey The key defining how the time series resolution is to occur e.g. "DEFAULT_TSS_CONFIG" */ public EquityDividendYieldFuturesYCNSFunction(String closingPriceField, String costOfCarryField, String resolutionKey) { super(ValueRequirementNames.YIELD_CURVE_NODE_SENSITIVITIES, FuturesRatesSensitivityCalculator.getInstance(DividendYieldFuturesCalculator.PresentValueCalculator.getInstance()), closingPriceField, costOfCarryField, resolutionKey); } @Override public void init(final FunctionCompilationContext context) { super.init(context); final HolidaySource holidaySource = OpenGammaCompilationContext.getHolidaySource(context); final RegionSource regionSource = OpenGammaCompilationContext.getRegionSource(context); final ConventionBundleSource conventionSource = OpenGammaCompilationContext.getConventionBundleSource(context); final SecuritySource securitySource = OpenGammaCompilationContext.getSecuritySource(context); final InterestRateFutureSecurityConverterDeprecated irFutureConverter = new InterestRateFutureSecurityConverterDeprecated(holidaySource, conventionSource, regionSource); final BondSecurityConverter bondConverter = new BondSecurityConverter(holidaySource, conventionSource, regionSource); final BondFutureSecurityConverter bondFutureConverter = new BondFutureSecurityConverter(securitySource, bondConverter); _converter = new FutureSecurityConverterDeprecated(bondFutureConverter); } // Need to do this to get labels for the output private ValueRequirement getCurveSpecRequirement(final Currency currency, final String curveName) { final ValueProperties properties = ValueProperties.builder().with(ValuePropertyNames.CURVE, curveName).get(); return new ValueRequirement(ValueRequirementNames.YIELD_CURVE_SPEC, ComputationTargetSpecification.of(currency), properties); } @Override public Set<ValueRequirement> getRequirements(final FunctionCompilationContext context, final ComputationTarget target, final ValueRequirement desiredValue) { final Set<ValueRequirement> requirements = super.getRequirements(context, target, desiredValue); if (requirements == null) { return null; } // Get Funding Curve Name and Configuration final String fundingCurveName = desiredValue.getConstraint(ValuePropertyNames.CURVE); final FutureSecurity security = (FutureSecurity) target.getTrade().getSecurity(); // Add Funding Curve Spec, to get labels correct in result requirements.add(getCurveSpecRequirement(FinancialSecurityUtils.getCurrency(security), fundingCurveName)); return requirements; } @Override public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target, final Set<ValueRequirement> desiredValues) { // 1. Build the analytic derivative to be priced final Trade trade = target.getTrade(); final FutureSecurity security = (FutureSecurity) trade.getSecurity(); final HistoricalTimeSeriesBundle timeSeriesBundle = HistoricalTimeSeriesFunctionUtils.getHistoricalTimeSeriesInputs(executionContext, inputs); Double lastMarginPrice = null; try { lastMarginPrice = timeSeriesBundle.get(MarketDataRequirementNames.MARKET_VALUE, security.getExternalIdBundle()).getTimeSeries().getLatestValue(); } catch (final NoSuchElementException e) { throw new OpenGammaRuntimeException("Time series for " + security.getExternalIdBundle() + " was empty"); } final ZonedDateTime valuationTime = ZonedDateTime.now(executionContext.getValuationClock()); final InstrumentDefinitionWithData<?, Double> definition = security.accept(_converter); final InstrumentDerivative derivative = definition.toDerivative(valuationTime, lastMarginPrice); // 2. Build up the market data bundle final SimpleFutureDataBundle market = getFutureDataBundle(security, inputs, timeSeriesBundle, desiredValues.iterator().next()); final ValueRequirement desiredValue = desiredValues.iterator().next(); final YieldCurveBundle curveBundle = new YieldCurveBundle(); final String fundingCurveName = desiredValue.getConstraint(ValuePropertyNames.CURVE); curveBundle.setCurve(fundingCurveName, market.getFundingCurve()); // 3. Create specification that matches the properties promised in getResults // Build up InstrumentLabelledSensitivities for the Curve final Object curveSpecObject = inputs.getValue(ValueRequirementNames.YIELD_CURVE_SPEC); if (curveSpecObject == null) { throw new OpenGammaRuntimeException("Curve specification was null"); } final InterpolatedYieldCurveSpecificationWithSecurities curveSpec = (InterpolatedYieldCurveSpecificationWithSecurities) curveSpecObject; final ValueSpecification resultSpec = new ValueSpecification(ValueRequirementNames.YIELD_CURVE_NODE_SENSITIVITIES, target.toSpecification(), createValueProperties(target, desiredValue) .get()); // 4. Compute sensitivity to the discount rate, then use chain rule to distribute sensitivity across the curve final DoubleMatrix1D sensVector = derivative.accept(getCalculator(), getFutureDataBundle(security, inputs, timeSeriesBundle, desiredValue)); return YieldCurveNodeSensitivitiesHelper.getInstrumentLabelledSensitivitiesForCurve(fundingCurveName, curveBundle, sensVector, curveSpec, resultSpec); } }