Java tutorial
/** * Copyright (C) 2011 - 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.Collections; import java.util.Set; import javax.time.calendar.Period; import javax.time.calendar.ZonedDateTime; import org.apache.commons.lang.Validate; import com.google.common.collect.Sets; import com.opengamma.OpenGammaRuntimeException; import com.opengamma.analytics.financial.equity.future.EquityFutureDataBundle; import com.opengamma.analytics.financial.equity.future.EquityFuturesRatesSensitivityCalculator; import com.opengamma.analytics.financial.equity.future.definition.EquityFutureDefinition; import com.opengamma.analytics.financial.equity.future.derivative.EquityFuture; import com.opengamma.analytics.financial.model.interestrate.curve.YieldAndDiscountCurve; import com.opengamma.analytics.math.matrix.DoubleMatrix1D; import com.opengamma.core.position.Trade; import com.opengamma.core.value.MarketDataRequirementNames; import com.opengamma.engine.ComputationTarget; import com.opengamma.engine.ComputationTargetType; import com.opengamma.engine.function.AbstractFunction; 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.EquityFutureConverter; import com.opengamma.financial.analytics.ircurve.InterpolatedYieldCurveSpecificationWithSecurities; import com.opengamma.financial.analytics.model.YieldCurveNodeSensitivitiesHelper; import com.opengamma.financial.analytics.timeseries.DateConstraint; import com.opengamma.financial.analytics.timeseries.HistoricalTimeSeriesBundle; import com.opengamma.financial.analytics.timeseries.HistoricalTimeSeriesFunctionUtils; import com.opengamma.financial.security.future.EquityFutureSecurity; import com.opengamma.id.ExternalIdBundle; import com.opengamma.master.historicaltimeseries.HistoricalTimeSeriesResolutionResult; import com.opengamma.master.historicaltimeseries.HistoricalTimeSeriesResolver; import com.opengamma.util.money.Currency; /** * */ public class EquityFutureYieldCurveNodeSensitivityFunction extends AbstractFunction.NonCompiledInvoker { private static final String DIVIDEND_YIELD_FIELD = "EQY_DVD_YLD_EST"; private static final EquityFuturesRatesSensitivityCalculator CALCULATOR = EquityFuturesRatesSensitivityCalculator .getInstance(); private final String _fundingCurveName; private EquityFutureConverter _converter; public EquityFutureYieldCurveNodeSensitivityFunction(final String fundingCurveName) { Validate.notNull(fundingCurveName); _fundingCurveName = fundingCurveName; } @Override public void init(final FunctionCompilationContext context) { _converter = new EquityFutureConverter(); } @Override public Set<ComputedValue> execute(FunctionExecutionContext executionContext, FunctionInputs inputs, ComputationTarget target, Set<ValueRequirement> desiredValues) { final HistoricalTimeSeriesBundle timeSeries = HistoricalTimeSeriesFunctionUtils .getHistoricalTimeSeriesInputs(executionContext, inputs); final Trade trade = target.getTrade(); final EquityFutureSecurity security = (EquityFutureSecurity) trade.getSecurity(); final ZonedDateTime valuationTime = executionContext.getValuationClock().zonedDateTime(); final Double lastMarginPrice = timeSeries .get(MarketDataRequirementNames.MARKET_VALUE, security.getExternalIdBundle()).getTimeSeries() .getLatestValue(); final EquityFutureDefinition definition = _converter.visitEquityFutureTrade(trade, lastMarginPrice); final EquityFuture derivative = definition.toDerivative(valuationTime); final YieldAndDiscountCurve fundingCurve = getYieldCurve(security, inputs); final Double spot = getSpot(security, inputs); final Double marketPrice = getMarketPrice(security, inputs); double dividendYield = timeSeries.get(DIVIDEND_YIELD_FIELD, security.getUnderlyingId()).getTimeSeries() .getLatestValue(); dividendYield /= 100.0; final DoubleMatrix1D sensitivities = CALCULATOR.calcDeltaBucketed(derivative, new EquityFutureDataBundle(fundingCurve, marketPrice, spot, dividendYield, null)); final Object curveSpecObject = inputs.getValue(getCurveSpecRequirement(security.getCurrency())); if (curveSpecObject == null) { throw new OpenGammaRuntimeException("Curve specification was null"); } final InterpolatedYieldCurveSpecificationWithSecurities curveSpec = (InterpolatedYieldCurveSpecificationWithSecurities) curveSpecObject; final ValueSpecification resultSpec = getValueSpecification(target); return YieldCurveNodeSensitivitiesHelper.getSensitivitiesForCurve(fundingCurve, sensitivities, curveSpec, resultSpec); } @Override public ComputationTargetType getTargetType() { return ComputationTargetType.TRADE; } @Override public boolean canApplyTo(FunctionCompilationContext context, ComputationTarget target) { if (target.getType() != ComputationTargetType.TRADE) { return false; } return target.getTrade() .getSecurity() instanceof com.opengamma.financial.security.future.EquityFutureSecurity; } @Override public Set<ValueRequirement> getRequirements(FunctionCompilationContext context, ComputationTarget target, ValueRequirement desiredValue) { final Trade trade = target.getTrade(); final EquityFutureSecurity security = (EquityFutureSecurity) trade.getSecurity(); final Set<ValueRequirement> requirements = Sets.newHashSetWithExpectedSize(6); requirements.add(getSpotAssetRequirement(security)); requirements.add(getDiscountCurveRequirement(security)); requirements.add(getMarketPriceRequirement(security)); requirements.add(getCurveSpecRequirement(security.getCurrency())); ValueRequirement requirement = getMarketValueRequirement(context, security); if (requirement == null) { return null; } requirements.add(requirement); requirement = getDividendYieldRequirement(context, security); if (requirement == null) { return null; } requirements.add(requirement); return requirements; } @Override public Set<ValueSpecification> getResults(FunctionCompilationContext context, ComputationTarget target) { return Collections.singleton(getValueSpecification(target)); } private ValueRequirement getSpotAssetRequirement(EquityFutureSecurity security) { ValueRequirement req = new ValueRequirement(MarketDataRequirementNames.MARKET_VALUE, security.getUnderlyingId()); return req; } private ValueRequirement getMarketPriceRequirement(EquityFutureSecurity security) { return new ValueRequirement(MarketDataRequirementNames.MARKET_VALUE, ComputationTargetType.SECURITY, security.getUniqueId()); } private ValueRequirement getCurveSpecRequirement(final Currency currency) { ValueProperties properties = ValueProperties.builder().with(ValuePropertyNames.CURVE, _fundingCurveName) .get(); return new ValueRequirement(ValueRequirementNames.YIELD_CURVE_SPEC, ComputationTargetType.PRIMITIVE, currency.getUniqueId(), properties); } private ValueRequirement getMarketValueRequirement(final FunctionCompilationContext context, final EquityFutureSecurity security) { final HistoricalTimeSeriesResolver resolver = OpenGammaCompilationContext .getHistoricalTimeSeriesResolver(context); final HistoricalTimeSeriesResolutionResult timeSeries = resolver.resolve(security.getExternalIdBundle(), null, null, null, MarketDataRequirementNames.MARKET_VALUE, null); if (timeSeries == null) { return null; } return HistoricalTimeSeriesFunctionUtils.createHTSRequirement(timeSeries, MarketDataRequirementNames.MARKET_VALUE, DateConstraint.VALUATION_TIME.minus(Period.ofDays(7)), true, DateConstraint.VALUATION_TIME, true); } private ValueRequirement getDividendYieldRequirement(final FunctionCompilationContext context, final EquityFutureSecurity security) { final HistoricalTimeSeriesResolver resolver = OpenGammaCompilationContext .getHistoricalTimeSeriesResolver(context); final HistoricalTimeSeriesResolutionResult timeSeries = resolver.resolve( ExternalIdBundle.of(security.getUnderlyingId()), null, null, null, DIVIDEND_YIELD_FIELD, null); if (timeSeries == null) { return null; } return HistoricalTimeSeriesFunctionUtils.createHTSRequirement(timeSeries, DIVIDEND_YIELD_FIELD, DateConstraint.VALUATION_TIME.minus(Period.ofDays(7)), true, DateConstraint.VALUATION_TIME, true); } private Double getSpot(EquityFutureSecurity security, FunctionInputs inputs) { ValueRequirement spotRequirement = getSpotAssetRequirement(security); final Object spotObject = inputs.getValue(spotRequirement); if (spotObject == null) { throw new OpenGammaRuntimeException("Could not get " + spotRequirement); } return (Double) spotObject; } private Double getMarketPrice(EquityFutureSecurity security, FunctionInputs inputs) { ValueRequirement marketPriceRequirement = getMarketPriceRequirement(security); final Object marketPriceObject = inputs.getValue(marketPriceRequirement); if (marketPriceObject == null) { throw new OpenGammaRuntimeException("Could not get " + marketPriceRequirement); } return (Double) marketPriceObject; } private YieldAndDiscountCurve getYieldCurve(EquityFutureSecurity security, FunctionInputs inputs) { final ValueRequirement curveRequirement = getDiscountCurveRequirement(security); final Object curveObject = inputs.getValue(curveRequirement); if (curveObject == null) { throw new OpenGammaRuntimeException("Could not get " + curveRequirement); } return (YieldAndDiscountCurve) curveObject; } private ValueRequirement getDiscountCurveRequirement(EquityFutureSecurity security) { ValueProperties properties = ValueProperties.builder().with(ValuePropertyNames.CURVE, _fundingCurveName) .get(); return new ValueRequirement(ValueRequirementNames.YIELD_CURVE, ComputationTargetType.PRIMITIVE, security.getCurrency().getUniqueId(), properties); } private ValueSpecification getValueSpecification(final ComputationTarget target) { final EquityFutureSecurity security = (EquityFutureSecurity) target.getTrade().getSecurity(); final ValueProperties properties = createValueProperties().with(ValuePropertyNames.CURVE, _fundingCurveName) .with(ValuePropertyNames.CURVE_CURRENCY, security.getCurrency().getCode()) .with(ValuePropertyNames.CURRENCY, security.getCurrency().getCode()).get(); return new ValueSpecification(ValueRequirementNames.YIELD_CURVE_NODE_SENSITIVITIES, target.toSpecification(), properties); } }