/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.analytics.model.volatility.local;
import static com.opengamma.financial.analytics.model.volatility.local.PDEPropertyNamesAndValues.PROPERTY_MAX_MONEYNESS;
import static com.opengamma.financial.analytics.model.volatility.local.PDEPropertyNamesAndValues.PROPERTY_NUMBER_SPACE_STEPS;
import static com.opengamma.financial.analytics.model.volatility.local.PDEPropertyNamesAndValues.PROPERTY_NUMBER_TIME_STEPS;
import static com.opengamma.financial.analytics.model.volatility.local.PDEPropertyNamesAndValues.PROPERTY_SPACE_DIRECTION_INTERPOLATOR;
import static com.opengamma.financial.analytics.model.volatility.local.PDEPropertyNamesAndValues.PROPERTY_SPACE_STEPS_BUNCHING;
import static com.opengamma.financial.analytics.model.volatility.local.PDEPropertyNamesAndValues.PROPERTY_THETA;
import static com.opengamma.financial.analytics.model.volatility.local.PDEPropertyNamesAndValues.PROPERTY_TIME_STEP_BUNCHING;
import java.util.Collections;
import java.util.Set;
import org.threeten.bp.Clock;
import org.threeten.bp.ZonedDateTime;
import com.google.common.collect.Sets;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.analytics.financial.model.interestrate.curve.ForwardCurve;
import com.opengamma.analytics.financial.model.interestrate.curve.YieldAndDiscountCurve;
import com.opengamma.analytics.financial.model.option.pricing.analytic.formula.EuropeanVanillaOption;
import com.opengamma.analytics.financial.model.volatility.local.LocalVolatilityBackwardPDECalculator;
import com.opengamma.analytics.financial.model.volatility.local.LocalVolatilitySurfaceMoneyness;
import com.opengamma.analytics.financial.model.volatility.local.PDELocalVolatilityCalculator;
import com.opengamma.analytics.math.interpolation.Interpolator1D;
import com.opengamma.analytics.math.interpolation.Interpolator1DFactory;
import com.opengamma.engine.ComputationTarget;
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.ValueSpecification;
import com.opengamma.financial.security.FinancialSecurity;
/**
*
*/
public abstract class LocalVolatilityBackwardPDEFunction extends LocalVolatilityPDEFunction {
public LocalVolatilityBackwardPDEFunction(final String blackSmileInterpolatorName) {
super(blackSmileInterpolatorName);
}
@Override
public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target, final Set<ValueRequirement> desiredValues) {
final Clock snapshotClock = executionContext.getValuationClock();
final ZonedDateTime now = ZonedDateTime.now(snapshotClock);
final FinancialSecurity security = (FinancialSecurity) target.getSecurity();
final ValueRequirement desiredValue = desiredValues.iterator().next();
final double theta = Double.parseDouble(desiredValue.getConstraint(PROPERTY_THETA));
final int nTimeSteps = Integer.parseInt(desiredValue.getConstraint(PROPERTY_NUMBER_TIME_STEPS));
final int nSpaceSteps = Integer.parseInt(desiredValue.getConstraint(PROPERTY_NUMBER_SPACE_STEPS));
final double timeStepBunching = Double.parseDouble(desiredValue.getConstraint(PROPERTY_TIME_STEP_BUNCHING));
final double spaceStepBunching = Double.parseDouble(desiredValue.getConstraint(PROPERTY_SPACE_STEPS_BUNCHING));
final double maxMoneyness = Double.parseDouble(desiredValue.getConstraint(PROPERTY_MAX_MONEYNESS));
final String interpolatorName = desiredValue.getConstraint(PROPERTY_SPACE_DIRECTION_INTERPOLATOR);
final Interpolator1D interpolator = Interpolator1DFactory.getInterpolator(interpolatorName);
final PDELocalVolatilityCalculator<?> pdeCalculator =
getPDECalculator(new LocalVolatilityBackwardPDECalculator(theta, nTimeSteps, nSpaceSteps, timeStepBunching, spaceStepBunching, maxMoneyness), interpolator);
final Object localVolatilityObject = inputs.getValue(getVolatilitySurfaceRequirement(target, desiredValue));
if (localVolatilityObject == null) {
throw new OpenGammaRuntimeException("Could not get local volatility surface");
}
final Object forwardCurveObject = inputs.getValue(getForwardCurveRequirement(target, desiredValue));
if (forwardCurveObject == null) {
throw new OpenGammaRuntimeException("Could not get forward curve");
}
final Object discountingCurveObject = inputs.getValue(getDiscountingCurveRequirement(target, desiredValue));
if (discountingCurveObject == null) {
throw new OpenGammaRuntimeException("Could not get discounting curve");
}
final LocalVolatilitySurfaceMoneyness localVolatility = (LocalVolatilitySurfaceMoneyness) localVolatilityObject;
final ForwardCurve forwardCurve = (ForwardCurve) forwardCurveObject;
final EuropeanVanillaOption option = getOption(security, now);
final YieldAndDiscountCurve discountingCurve = (YieldAndDiscountCurve) discountingCurveObject;
final Object result = getResult(pdeCalculator, localVolatility, forwardCurve, option, discountingCurve);
final ValueProperties properties = getResultProperties(desiredValue);
final ValueSpecification spec = new ValueSpecification(getRequirementName(), target.toSpecification(), properties);
return Collections.singleton(new ComputedValue(spec, result));
}
@Override
public Set<ValueRequirement> getRequirements(final FunctionCompilationContext context, final ComputationTarget target, final ValueRequirement desiredValue) {
final ValueProperties constraints = desiredValue.getConstraints();
final Set<ValueRequirement> requirements = PDEFunctionUtils.ensureBackwardPDEFunctionProperties(constraints);
if (requirements == null) {
return null;
}
final ValueRequirement volatilitySurfaceRequirement = getVolatilitySurfaceRequirement(target, desiredValue);
final ValueRequirement forwardCurveRequirement = getForwardCurveRequirement(target, desiredValue);
final ValueRequirement discountingCurveRequirement = getDiscountingCurveRequirement(target, desiredValue);
return Sets.newHashSet(volatilitySurfaceRequirement, forwardCurveRequirement, discountingCurveRequirement);
}
protected abstract PDELocalVolatilityCalculator<?> getPDECalculator(final LocalVolatilityBackwardPDECalculator calculator, final Interpolator1D interpolator);
@Override
protected ValueProperties getResultProperties() {
ValueProperties result = createValueProperties().get();
result = LocalVolatilitySurfaceUtils.addAllDupireLocalVolatilitySurfaceProperties(result, getInstrumentType(), getBlackSmileInterpolatorName(),
LocalVolatilitySurfacePropertyNamesAndValues.MONEYNESS).get();
result = PDEFunctionUtils.addBackwardPDEProperties(result)
.with(ValuePropertyNames.CALCULATION_METHOD, LocalVolatilityPDEFunction.CALCULATION_METHOD).get();
return result;
}
@Override
protected ValueProperties getResultProperties(final ValueRequirement desiredValue) {
ValueProperties result = createValueProperties().get();
result = LocalVolatilitySurfaceUtils.addAllDupireLocalVolatilitySurfaceProperties(result, getInstrumentType(), getBlackSmileInterpolatorName(),
LocalVolatilitySurfacePropertyNamesAndValues.MONEYNESS, desiredValue).get();
result = PDEFunctionUtils.addBackwardPDEProperties(result, desiredValue)
.with(ValuePropertyNames.CALCULATION_METHOD, LocalVolatilityPDEFunction.CALCULATION_METHOD).get();
return result;
}
}