Package com.opengamma.financial.analytics.volatility.surface

Source Code of com.opengamma.financial.analytics.volatility.surface.RawVolatilitySurfaceDataFunction

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

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.Instant;
import org.threeten.bp.LocalDate;
import org.threeten.bp.LocalTime;
import org.threeten.bp.ZoneOffset;
import org.threeten.bp.ZonedDateTime;

import com.google.common.collect.Iterables;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.core.config.ConfigSource;
import com.opengamma.core.marketdatasnapshot.VolatilitySurfaceData;
import com.opengamma.engine.ComputationTarget;
import com.opengamma.engine.function.AbstractFunction;
import com.opengamma.engine.function.CompiledFunctionDefinition;
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.SurfaceAndCubePropertyNames;
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.model.InstrumentTypeProperties;
import com.opengamma.id.ExternalId;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.tuple.Pair;

import it.unimi.dsi.fastutil.objects.ObjectArrayList;

/**
* Gets volatility surface data from definitions and specifications. No financial modelling is done and the data points can be any type of data (e.g. price, implied lognormal volatility).
*/
public abstract class RawVolatilitySurfaceDataFunction extends AbstractFunction {
  /** The logger */
  private static final Logger s_logger = LoggerFactory.getLogger(RawVolatilitySurfaceDataFunction.class);
  /**
   * Value specification property for the surface result. This allows surface to be distinguished by instrument type (e.g. an FX volatility
   * surface, swaption ATM volatility surface).
   */
  private final String _instrumentType;

  /**
   * @param instrumentType The instrument type, not null
   */
  public RawVolatilitySurfaceDataFunction(final String instrumentType) {
    ArgumentChecker.notNull(instrumentType, "Instrument Type");
    _instrumentType = instrumentType;
  }

  /**
   * Gets the target type for the surface
   * @return The target type
   */
  protected abstract ComputationTargetType getTargetType();

  /**
   * Determines whether this function applies to the target
   * @param context The compilation context
   * @param target The computation target
   * @return true if this function applies to the target
   */
  protected boolean canApplyTo(final FunctionCompilationContext context, final ComputationTarget target) {
    return true;
  }

  /**
   * Gets a volatility surface definition from a name, target and instrument type. The full name of the surface is constructed as<p>
   * [SURFACE NAME]_[TARGET NAME]_[INSTRUMENT TYPE]<p>
   * @param definitionSource The surface definition source
   * @param target The computation target
   * @param definitionName The definition name
   * @return The volatility surface definition
   * @throws OpenGammaRuntimeException if a volatility surface definition with the full name is not found
   */
  protected abstract VolatilitySurfaceDefinition<?, ?> getDefinition(VolatilitySurfaceDefinitionSource definitionSource, ComputationTarget target, String definitionName);


  /**
   * Gets a volatility surface specification from a name, target and instrument type. The full name of the surface is constructed as<p>
   * [SURFACE NAME]_[TRIMMED TARGET]_[INSTRUMENT TYPE]<p>
   * @param specificationSource The surface specification source
   * @param target The computation target
   * @param specificationName The specification name
   * @return The volatility surface specification
   * @throws OpenGammaRuntimeException if a volatility surface specification with the full name is not found
   */
  protected abstract VolatilitySurfaceSpecification getSpecification(VolatilitySurfaceSpecificationSource specificationSource, ComputationTarget target, String specificationName);

  /**
   * @return The instrument type of the surface
   */
  protected String getInstrumentType() {
    return _instrumentType;
  }

  /**
   * Uses the volatility surface definition and specification to work out which market data requirements are needed to construct
   * the surface with the given name and type.
   * @param <X> The type of the x-axis data
   * @param <Y> The type of the y-axis data
   * @param specification The volatility specification
   * @param definition The volatility definition
   * @param atInstant The time stamp of the surface
   * @param surfaceName The surface name
   * @param instrumentType The instrument type
   * @return A set of market data value requirements, or null if the volatility surface specification or definition is null
   */
  public static <X, Y> Set<ValueRequirement> buildDataRequirements(final VolatilitySurfaceSpecification specification, final VolatilitySurfaceDefinition<X, Y> definition,
      final ZonedDateTime atInstant, final String surfaceName, final String instrumentType) {
    if (specification == null) {
      s_logger.error("Volatility surface specification called {} for instrument type {} was null", surfaceName, instrumentType);
      return null;
    }
    if (definition == null) {
      s_logger.error("Volatility surface definition called {} for instrument type {} was null", surfaceName, instrumentType);
      return null;
    }
    final Set<ValueRequirement> result = new HashSet<>();
    final SurfaceInstrumentProvider<X, Y> provider = (SurfaceInstrumentProvider<X, Y>) specification.getSurfaceInstrumentProvider();
    for (final X x : definition.getXs()) {
      for (final Y y : definition.getYs()) {
        final ExternalId identifier = provider.getInstrument(x, y, atInstant.toLocalDate());
        result.add(new ValueRequirement(provider.getDataFieldName(), ComputationTargetType.PRIMITIVE, identifier));
      }
    }
    return result;
  }

  @Override
  public CompiledFunctionDefinition compile(final FunctionCompilationContext myContext, final Instant atInstant) {
    final ConfigSource configSource = OpenGammaCompilationContext.getConfigSource(myContext);
    final ConfigDBVolatilitySurfaceDefinitionSource definitionSource = new ConfigDBVolatilitySurfaceDefinitionSource(configSource);
    final ConfigDBVolatilitySurfaceSpecificationSource specificationSource = new ConfigDBVolatilitySurfaceSpecificationSource(configSource);
    final ZonedDateTime atZDT = ZonedDateTime.ofInstant(atInstant, ZoneOffset.UTC);
    return new CompiledFunction(atZDT.with(LocalTime.MIDNIGHT), atZDT.plusDays(1).with(LocalTime.MIDNIGHT).minusNanos(1000000), atZDT, definitionSource, specificationSource);
  }

  /**
   * Implementation of the compiled function
   */
  protected class CompiledFunction extends AbstractInvokingCompiledFunction {
    /** The valuation time */
    private final ZonedDateTime _now;
    /** Source for volatility surface definitions */
    private final ConfigDBVolatilitySurfaceDefinitionSource _definitionSource;
    /** Source for volatility surface specifications */
    private final ConfigDBVolatilitySurfaceSpecificationSource _specificationSource;

    /**
     * @param from Earliest time that the invoker is valid
     * @param to Latest time that the invoker is valid
     * @param now The valuation time
     * @param definitionSource The volatility surface definition source
     * @param specificationSource The volatility surface specification source
     */
    public CompiledFunction(final ZonedDateTime from, final ZonedDateTime to, final ZonedDateTime now, final ConfigDBVolatilitySurfaceDefinitionSource definitionSource,
        final ConfigDBVolatilitySurfaceSpecificationSource specificationSource) {
      super(from.toInstant(), to.toInstant());
      _now = now;
      _definitionSource = definitionSource;
      _specificationSource = specificationSource;
    }

    @SuppressWarnings("synthetic-access")
    @Override
    public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target) {
      return Collections.singleton(new ValueSpecification(ValueRequirementNames.VOLATILITY_SURFACE_DATA, target.toSpecification(),
          createValueProperties()
          .withAny(ValuePropertyNames.SURFACE)
          .with(InstrumentTypeProperties.PROPERTY_SURFACE_INSTRUMENT_TYPE, _instrumentType)
          .withAny(SurfaceAndCubePropertyNames.PROPERTY_SURFACE_QUOTE_TYPE)
          .withAny(SurfaceAndCubePropertyNames.PROPERTY_SURFACE_UNITS).get()));
    }

    @SuppressWarnings("synthetic-access")
    @Override
    public Set<ValueRequirement> getRequirements(final FunctionCompilationContext context, final ComputationTarget target, final ValueRequirement desiredValue) {
      final Set<String> surfaceNames = desiredValue.getConstraints().getValues(ValuePropertyNames.SURFACE);
      if (surfaceNames == null || surfaceNames.size() != 1) {
        s_logger.info("Can only get a single surface; asked for " + surfaceNames);
        return null;
      }
      final Set<String> instrumentTypes = desiredValue.getConstraints().getValues(InstrumentTypeProperties.PROPERTY_SURFACE_INSTRUMENT_TYPE);
      if (instrumentTypes == null || instrumentTypes.size() != 1) {
        s_logger.info("Did not specify a single instrument type; asked for " + instrumentTypes);
        return null;
      }
      final String surfaceName = Iterables.getOnlyElement(surfaceNames);
      if (surfaceName == null) {
        s_logger.error("Surface name was null");
        return null;
      }
      final String instrumentType = Iterables.getOnlyElement(instrumentTypes);
      if (instrumentType == null) {
        s_logger.error("Instrument type was null");
        return null;
      }
      if (!_instrumentType.equals(instrumentType)) {
        s_logger.error("Instrument type {} did not match that required {}", instrumentType, _instrumentType);
        return null;
      }
      try {
        final VolatilitySurfaceDefinition<?, ?> definition = getDefinition(_definitionSource, target, surfaceName);
        if (definition == null) {
          s_logger.error("Could not get volatility surface definition for instrument type {} with target {} called {}", new Object[] {target, _instrumentType, surfaceName});
          return null;
        }
        final VolatilitySurfaceSpecification specification = getSpecification(_specificationSource, target, surfaceName);
        if (specification == null) {
          s_logger.error("Could not get volatility surface specification for instrument type {} with target {} called {}", new Object[] {target, _instrumentType, surfaceName});
          return null;
        }
        final Set<ValueRequirement> requirements = buildDataRequirements(specification, definition, _now, surfaceName, instrumentType);
        final ValueProperties definitionProperties = ValueProperties.builder()
            .with(ValuePropertyNames.SURFACE, surfaceName)
            .with(InstrumentTypeProperties.PROPERTY_SURFACE_INSTRUMENT_TYPE, instrumentType)
            .get();
        final ValueProperties specificationProperties = ValueProperties.builder()
            .with(ValuePropertyNames.SURFACE, surfaceName)
            .with(InstrumentTypeProperties.PROPERTY_SURFACE_INSTRUMENT_TYPE, instrumentType)
            .with(SurfaceAndCubePropertyNames.PROPERTY_SURFACE_QUOTE_TYPE, specification.getSurfaceQuoteType())
            .with(SurfaceAndCubePropertyNames.PROPERTY_SURFACE_UNITS, specification.getQuoteUnits())
            .get();
        requirements.add(new ValueRequirement(ValueRequirementNames.VOLATILITY_SURFACE_SPEC, target.toSpecification(), specificationProperties));
        requirements.add(new ValueRequirement(ValueRequirementNames.VOLATILITY_SURFACE_DEFINITION, target.toSpecification(), definitionProperties));
        return requirements;
      } catch (final Exception e) {
        s_logger.error(e.getMessage());
        return null;
      }
    }

    @SuppressWarnings("synthetic-access")
    @Override
    public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target, final Map<ValueSpecification, ValueRequirement> inputs) {
      String surfaceQuoteType = null;
      String surfaceQuoteUnits = null;
      String surfaceName = null;
      for (final Map.Entry<ValueSpecification, ValueRequirement> entry : inputs.entrySet()) {
        final ValueSpecification key = entry.getKey();
        if (key.getValueName().equals(ValueRequirementNames.VOLATILITY_SURFACE_SPEC)) {
          surfaceQuoteType = key.getProperty(SurfaceAndCubePropertyNames.PROPERTY_SURFACE_QUOTE_TYPE);
          surfaceQuoteUnits = key.getProperty(SurfaceAndCubePropertyNames.PROPERTY_SURFACE_UNITS);
          surfaceName = key.getProperty(ValuePropertyNames.SURFACE);
          break;
        }
      }
      if (surfaceName == null) {
        return null;
      }
      assert surfaceQuoteType != null;
      assert surfaceQuoteUnits != null;
      return Collections.singleton(new ValueSpecification(ValueRequirementNames.VOLATILITY_SURFACE_DATA, target.toSpecification(),
          createValueProperties()
          .with(ValuePropertyNames.SURFACE, surfaceName)
          .with(InstrumentTypeProperties.PROPERTY_SURFACE_INSTRUMENT_TYPE, _instrumentType)
          .with(SurfaceAndCubePropertyNames.PROPERTY_SURFACE_QUOTE_TYPE, surfaceQuoteType)
          .with(SurfaceAndCubePropertyNames.PROPERTY_SURFACE_UNITS, surfaceQuoteUnits).get()));
    }

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

    @Override
    public boolean canApplyTo(final FunctionCompilationContext context, final ComputationTarget target) {
      return RawVolatilitySurfaceDataFunction.this.canApplyTo(context, target);
    }

    @SuppressWarnings({"synthetic-access" })
    @Override
    public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target,
        final Set<ValueRequirement> desiredValues) {
      final ValueRequirement desiredValue = Iterables.getOnlyElement(desiredValues);
      final String surfaceName = desiredValue.getConstraint(ValuePropertyNames.SURFACE);
      final String instrumentType = desiredValue.getConstraint(InstrumentTypeProperties.PROPERTY_SURFACE_INSTRUMENT_TYPE);
      final Object definitionObject = inputs.getValue(ValueRequirementNames.VOLATILITY_SURFACE_DEFINITION);
      if (definitionObject == null) {
        throw new OpenGammaRuntimeException("Could not get volatility surface definition");
      }
      final Object specificationObject = inputs.getValue(ValueRequirementNames.VOLATILITY_SURFACE_SPEC);
      if (specificationObject == null) {
        throw new OpenGammaRuntimeException("Could not get volatility surface specification");
      }
      @SuppressWarnings("unchecked")
      final VolatilitySurfaceDefinition<Object, Object> definition = (VolatilitySurfaceDefinition<Object, Object>) definitionObject;
      final VolatilitySurfaceSpecification specification = (VolatilitySurfaceSpecification) specificationObject;
      final LocalDate valuationDate = LocalDate.now(executionContext.getValuationClock());
      final SurfaceInstrumentProvider<Object, Object> provider = (SurfaceInstrumentProvider<Object, Object>) specification.getSurfaceInstrumentProvider();
      final Map<Pair<Object, Object>, Double> volatilityValues = new HashMap<>();
      final ObjectArrayList<Object> xList = new ObjectArrayList<>();
      final ObjectArrayList<Object> yList = new ObjectArrayList<>();
      for (final Object x : definition.getXs()) {
        for (final Object y : definition.getYs()) {
          final ExternalId identifier = provider.getInstrument(x, y, valuationDate);
          final ValueRequirement requirement = new ValueRequirement(provider.getDataFieldName(), ComputationTargetType.PRIMITIVE, identifier);
          final Double volatility = (Double) inputs.getValue(requirement);
          if (volatility != null) {
            xList.add(x);
            yList.add(y);
            volatilityValues.put(Pair.of(x, y), volatility);
          } else {
            s_logger.info("Missing value {}", identifier.toString());
          }
        }
      }
      final VolatilitySurfaceData<Object, Object> volSurfaceData = new VolatilitySurfaceData<>(definition.getName(), specification.getName(),
          definition.getTarget(), definition.getXs(), definition.getYs(), volatilityValues);
      final ValueSpecification result = new ValueSpecification(ValueRequirementNames.VOLATILITY_SURFACE_DATA, target.toSpecification(),
          createValueProperties()
          .with(ValuePropertyNames.SURFACE, surfaceName)
          .with(InstrumentTypeProperties.PROPERTY_SURFACE_INSTRUMENT_TYPE, instrumentType)
          .with(SurfaceAndCubePropertyNames.PROPERTY_SURFACE_QUOTE_TYPE, specification.getSurfaceQuoteType())
          .with(SurfaceAndCubePropertyNames.PROPERTY_SURFACE_UNITS, specification.getQuoteUnits()).get());
      return Collections.singleton(new ComputedValue(result, volSurfaceData));
    }

    @Override
    public boolean canHandleMissingInputs() {
      return true;
    }

    @Override
    public boolean canHandleMissingRequirements() {
      return true;
    }

    /**
     * Gets the definition source.
     * @return The definition source
     */
    protected ConfigDBVolatilitySurfaceDefinitionSource getDefinitionSource() {
      return _definitionSource;
    }

    /**
     * Gets the specification source.
     * @return The specification source
     */
    protected ConfigDBVolatilitySurfaceSpecificationSource getSpecificationSource() {
      return _specificationSource;
    }
  };
}
TOP

Related Classes of com.opengamma.financial.analytics.volatility.surface.RawVolatilitySurfaceDataFunction

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.