/** * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.financial.analytics.model.futureoption; import java.util.Collections; import java.util.Set; import com.opengamma.OpenGammaRuntimeException; import com.opengamma.engine.ComputationTarget; import com.opengamma.engine.function.AbstractFunction.NonCompiledInvoker; 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.security.FinancialSecurity; import com.opengamma.util.async.AsynchronousExecution; /** * Function to compute barrier distance for equity options * * Defined as absolute difference (optionally expressed as a percentage) between barrier level and market price */ public abstract class BarrierOptionDistanceFunction extends NonCompiledInvoker { /** absolute difference */ public static final String BARRIER_ABS = "abs"; /** percentage difference from barrier level */ public static final String BARRIER_PERCENTAGE = "percentage"; /** * */ public BarrierOptionDistanceFunction() { super(); } protected abstract double getBarrierLevel(final FinancialSecurity security); protected abstract ValueRequirement getMarketDataRequirement(final FinancialSecurity security); protected abstract Double getSpot(FunctionInputs inputs); @Override public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target) { final ValueProperties properties = createValueProperties() .withAny(ValuePropertyNames.BARRIER_DISTANCE_OUTPUT_FORMAT) .get(); return Collections.singleton(new ValueSpecification(ValueRequirementNames.BARRIER_DISTANCE, target.toSpecification(), properties)); } @Override public Set<ValueRequirement> getRequirements(final FunctionCompilationContext context, final ComputationTarget target, final ValueRequirement desiredValue) { final ValueProperties constraints = desiredValue.getConstraints(); final FinancialSecurity security = (FinancialSecurity) target.getSecurity(); final Set<String> outputFormat = constraints.getValues(ValuePropertyNames.BARRIER_DISTANCE_OUTPUT_FORMAT); if (outputFormat == null || outputFormat.size() != 1) { return null; } final ValueRequirement marketRequirement = getMarketDataRequirement(security); return Collections.singleton(marketRequirement); } @Override public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target, final Set<ValueRequirement> desiredValues) throws AsynchronousExecution { final FinancialSecurity security = (FinancialSecurity) target.getSecurity(); final ValueRequirement desiredValue = desiredValues.iterator().next(); // Do we care whether the option has expired? final Double spot = getSpot(inputs); final String outputFormat = desiredValue.getConstraint(ValuePropertyNames.BARRIER_DISTANCE_OUTPUT_FORMAT); Double distance; final double barrier = getBarrierLevel(security); switch (outputFormat) { case BARRIER_ABS: distance = Double.valueOf(Math.abs(barrier - spot.doubleValue())); break; case BARRIER_PERCENTAGE: distance = Double.valueOf(100 * Math.abs(barrier - spot.doubleValue()) / barrier); break; default: throw new OpenGammaRuntimeException("Unknown barrier output display type " + outputFormat); } final ValueSpecification resultSpec = new ValueSpecification(ValueRequirementNames.BARRIER_DISTANCE, target.toSpecification(), desiredValue.getConstraints().copy().get()); return Collections.singleton(new ComputedValue(resultSpec, distance)); } }