Package com.opengamma.financial.analytics.model.future

Source Code of com.opengamma.financial.analytics.model.future.FuturesFunction

/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.analytics.model.future;

import java.util.Collections;
import java.util.NoSuchElementException;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.Period;
import org.threeten.bp.ZonedDateTime;

import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.analytics.financial.instrument.InstrumentDefinitionWithData;
import com.opengamma.analytics.financial.interestrate.InstrumentDerivative;
import com.opengamma.analytics.financial.interestrate.InstrumentDerivativeVisitor;
import com.opengamma.analytics.financial.simpleinstruments.pricing.SimpleFutureDataBundle;
import com.opengamma.core.holiday.HolidaySource;
import com.opengamma.core.position.Trade;
import com.opengamma.core.region.RegionSource;
import com.opengamma.core.security.Security;
import com.opengamma.core.security.SecuritySource;
import com.opengamma.core.value.MarketDataRequirementNames;
import com.opengamma.engine.ComputationTarget;
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.target.ComputationTargetType;
import com.opengamma.engine.value.ComputedValue;
import com.opengamma.engine.value.ValueProperties;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.financial.OpenGammaCompilationContext;
import com.opengamma.financial.analytics.conversion.FutureTradeConverterDeprecated;
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.convention.ConventionBundleSource;
import com.opengamma.financial.security.FinancialSecurityUtils;
import com.opengamma.financial.security.future.FutureSecurity;
import com.opengamma.id.ExternalId;
import com.opengamma.id.ExternalIdBundle;
import com.opengamma.master.historicaltimeseries.HistoricalTimeSeriesResolutionResult;
import com.opengamma.master.historicaltimeseries.HistoricalTimeSeriesResolver;
import com.opengamma.util.ArgumentChecker;

/**
* Base class for FuturesSecurity ValueRequirements.
* FuturesFunctions, as the securities are exchange traded, closely resemble MarkToMarketPnLFunction.
* @param <T> The type of the data returned from the calculator
*/
public abstract class FuturesFunction<T> extends AbstractFunction.NonCompiledInvoker {

  /** The logger */
  private static final Logger s_logger = LoggerFactory.getLogger(FuturesFunction.class);

  /** The value requirement name */
  private final String _valueRequirementName;
  /** The calculator */
  private final InstrumentDerivativeVisitor<SimpleFutureDataBundle, T> _calculator;
  /** The trade converter */
  private FutureTradeConverterDeprecated _tradeConverter;
  /** The field name of the historical time series for price, e.g. "PX_LAST", "Close" */
  private final String _closingPriceField;
  /** The field name of the historical time series for cost of carry e.g. "COST_OF_CARRY" */
  private final String _costOfCarryField;
  /** key defining how the time series resolution is to occur e.g. "DEFAULT_TSS_CONFIG"*/
  private final String _resolutionKey;

  /**
   * @param valueRequirementName String describes the value requested
   * @param calculator The calculator
   * @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 FuturesFunction(final String valueRequirementName, final InstrumentDerivativeVisitor<SimpleFutureDataBundle, T> calculator,
      final String closingPriceField, final String costOfCarryField, final String resolutionKey) {
    ArgumentChecker.notNull(valueRequirementName, "value requirement name");
    ArgumentChecker.notNull(calculator, "calculator");
    ArgumentChecker.notNull(closingPriceField, "closingPriceField");
    ArgumentChecker.notNull(costOfCarryField, "costOfCarryField");
    ArgumentChecker.notNull(resolutionKey, "resolutionKey");
    _valueRequirementName = valueRequirementName;
    _calculator = calculator;
    _closingPriceField = closingPriceField;
    _costOfCarryField = costOfCarryField;
    _resolutionKey = resolutionKey;
  }

  @Override
  public void init(final FunctionCompilationContext 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);
    _tradeConverter = new FutureTradeConverterDeprecated(securitySource, holidaySource, conventionSource, regionSource);
  }

  @Override
  public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target) {
    return Collections.singleton(new ValueSpecification(_valueRequirementName, target.toSpecification(), createValueProperties(target).get()));
  }

  @Override
  public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target, final Set<ValueRequirement> desiredValues) {
    final Trade trade = target.getTrade();
    final FutureSecurity security = (FutureSecurity) trade.getSecurity();
    // Get reference price
    final HistoricalTimeSeriesBundle timeSeriesBundle = HistoricalTimeSeriesFunctionUtils.getHistoricalTimeSeriesInputs(executionContext, inputs);
    if (timeSeriesBundle == null) {
      throw new OpenGammaRuntimeException("Could not get time series bundle for " + trade);
    }
    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");
    }
    // Build the analytic's version of the security - the derivative
    final ZonedDateTime valuationTime = ZonedDateTime.now(executionContext.getValuationClock());
    final InstrumentDefinitionWithData<?, Double> tradeDefinition = _tradeConverter.convert(trade);
    double referencePrice = lastMarginPrice; // TODO: Decide if this logic should be here or in toDerivative.
    if (trade.getTradeDate() != null) {
      if (trade.getTradeDate().isEqual(valuationTime.toLocalDate())) { // Transaction is on pricing date.if (trade.getPremium() != null) {
        if (trade.getPremium() != null) {
          referencePrice = trade.getPremium(); // TODO: The trade price is stored in the trade premium. This has to be corrected.
        }
      }
    }
    final InstrumentDerivative derivative = tradeDefinition.toDerivative(valuationTime, referencePrice);
    // Build the DataBundle it requires
    final ValueRequirement desiredValue = desiredValues.iterator().next();
    final SimpleFutureDataBundle dataBundle = getFutureDataBundle(security, inputs, timeSeriesBundle, desiredValue);
    // Call OG-Analytics
    final T value = derivative.accept(_calculator, dataBundle);
    final ValueSpecification specification = new ValueSpecification(_valueRequirementName, target.toSpecification(), createValueProperties(target, desiredValue).get());
    return Collections.singleton(new ComputedValue(specification, value));
  }

  @Override
  public ComputationTargetType getTargetType() {
    return ComputationTargetType.TRADE;
  }

  @Override
  public boolean canApplyTo(final FunctionCompilationContext context, final ComputationTarget target) {
    final Security security = target.getTrade().getSecurity();
    return security instanceof FutureSecurity;
  }

  /**
   * Creates general value properties
   * @param target The target
   * @return The value properties
   */
  protected abstract ValueProperties.Builder createValueProperties(final ComputationTarget target);

  /**
   * Creates value properties with the property values set
   * @param target The target
   * @param desiredValue The desired value
   * @return The value properties
   */
  protected ValueProperties.Builder createValueProperties(final ComputationTarget target, final ValueRequirement desiredValue) {
    return createValueProperties(target);
  }

  /**
   * Creates the data bundle used in futures pricing
   * @param security The security
   * @param inputs The market data inputs
   * @param timeSeriesBundle A bundle containing time series
   * @param desiredValue The desired value
   * @return The data bundle used for pricing futures
   */
  protected abstract SimpleFutureDataBundle getFutureDataBundle(final FutureSecurity security, final FunctionInputs inputs,
      final HistoricalTimeSeriesBundle timeSeriesBundle, final ValueRequirement desiredValue);

  /**
   * @return The calculator
   */
  protected InstrumentDerivativeVisitor<SimpleFutureDataBundle, T> getCalculator() {
    return _calculator;
  }

  /**
   * Gets the spot value requirement
   * @param security The security
   * @return The spot asset value requirement if the future has a spot asset id, null otherwise
   */
  protected ValueRequirement getSpotAssetRequirement(final FutureSecurity security) {
    try {
      final ExternalId spotAssetId = getSpotAssetId(security);
      if (spotAssetId == null) {
        return null;
      }
      final ValueRequirement req = new ValueRequirement(MarketDataRequirementNames.MARKET_VALUE, ComputationTargetType.PRIMITIVE, spotAssetId);
      return req;
    } catch (final UnsupportedOperationException e) {
      s_logger.info(e.getMessage());
      return null;
    }
  }

  /**
   * Gets the spot asset id from a security
   * @param sec The security
   * @return The spot asset id, null if not available
   */
  protected ExternalId getSpotAssetId(final FutureSecurity sec) {
    final ExternalId spotAssetId = FinancialSecurityUtils.getUnderlyingId(sec);
    if (spotAssetId == null) {
      s_logger.info("Failed to find spot asset id (category = {}) for future with id bundle {}", sec.getContractCategory(), sec.getExternalIdBundle());
      return null;
    }
    return spotAssetId;
  }

  /**
   * Gets the spot value
   * @param inputs The market data inputs
   * @return The spot value
   * @throws OpenGammaRuntimeException If the spot value is null
   */
  protected Double getSpot(final FunctionInputs inputs) {
    final Object spotObject = inputs.getValue(MarketDataRequirementNames.MARKET_VALUE);
    if (spotObject == null) {
      throw new OpenGammaRuntimeException("Could not get the spot value");
    }
    return (Double) spotObject;
  }

  /**
   * Gets the historical time series of the future price
   * @param context The compilation context
   * @param security The security
   * @return The value requirement for the time series of future price
   */
  protected ValueRequirement getReferencePriceRequirement(final FunctionCompilationContext context, final FutureSecurity security) {
    final HistoricalTimeSeriesResolver resolver = OpenGammaCompilationContext.getHistoricalTimeSeriesResolver(context);
    final ExternalIdBundle idBundle = security.getExternalIdBundle();
    // TODO CASE: Test that you can change field to MARKET_VALUE because of the FieldAdjustment in ActivHistoricalTimeSeriesSourceComponentFactory.createResolver
    final HistoricalTimeSeriesResolutionResult timeSeries = resolver.resolve(security.getExternalIdBundle(), null, null, null, MarketDataRequirementNames.MARKET_VALUE, getResolutionKey());
    if (timeSeries == null) {
      s_logger.warn("Failed to find time series for: " + idBundle.toString());
      return null;
    }
    return HistoricalTimeSeriesFunctionUtils.createHTSRequirement(timeSeries, MarketDataRequirementNames.MARKET_VALUE,
        DateConstraint.VALUATION_TIME.minus(Period.ofDays(7)), true, DateConstraint.VALUATION_TIME, true);
  }

  protected String getClosingPriceField() {
    return _closingPriceField;
  }

  protected String getCostOfCarryField() {
    return _costOfCarryField;
  }

  protected String getResolutionKey() {
    return _resolutionKey;
  }

}
TOP

Related Classes of com.opengamma.financial.analytics.model.future.FuturesFunction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.