/**
* 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);
}
}