/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.analytics.model.carrlee;
import static com.opengamma.engine.value.ValuePropertyNames.SURFACE;
import static com.opengamma.engine.value.ValueRequirementNames.REALIZED_VARIANCE;
import static com.opengamma.engine.value.ValueRequirementNames.SPOT_RATE;
import static com.opengamma.engine.value.ValueRequirementNames.STANDARD_VOLATILITY_SURFACE_DATA;
import static com.opengamma.financial.analytics.model.CalculationPropertyNamesAndValues.HISTORICAL_REALIZED_VARIANCE;
import static com.opengamma.financial.analytics.model.CalculationPropertyNamesAndValues.HISTORICAL_VARIANCE_END;
import static com.opengamma.financial.analytics.model.CalculationPropertyNamesAndValues.HISTORICAL_VARIANCE_START;
import static com.opengamma.financial.analytics.model.CalculationPropertyNamesAndValues.MARKET_REALIZED_VARIANCE;
import static com.opengamma.financial.analytics.model.CalculationPropertyNamesAndValues.PROPERTY_REALIZED_VARIANCE_METHOD;
import static com.opengamma.financial.analytics.model.InstrumentTypeProperties.FOREX;
import static com.opengamma.financial.analytics.model.InstrumentTypeProperties.PROPERTY_SURFACE_INSTRUMENT_TYPE;
import static com.opengamma.financial.analytics.model.InterpolatedDataProperties.LEFT_X_EXTRAPOLATOR_NAME;
import static com.opengamma.financial.analytics.model.InterpolatedDataProperties.RIGHT_X_EXTRAPOLATOR_NAME;
import static com.opengamma.financial.analytics.model.InterpolatedDataProperties.X_INTERPOLATOR_NAME;
import org.threeten.bp.Clock;
import org.threeten.bp.LocalDate;
import org.threeten.bp.ZonedDateTime;
import com.google.common.collect.Iterables;
import com.opengamma.analytics.financial.forex.method.FXMatrix;
import com.opengamma.analytics.financial.model.volatility.surface.SmileDeltaTermStructureParametersStrikeInterpolation;
import com.opengamma.analytics.financial.provider.description.interestrate.MulticurveProviderInterface;
import com.opengamma.analytics.financial.provider.description.volatilityswap.CarrLeeFXData;
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.target.ComputationTargetType;
import com.opengamma.engine.value.ValueProperties;
import com.opengamma.engine.value.ValuePropertyNames;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.financial.analytics.conversion.FixedIncomeConverterDataProvider;
import com.opengamma.financial.analytics.conversion.DefaultTradeConverter;
import com.opengamma.financial.currency.CurrencyPair;
import com.opengamma.financial.security.fx.FXVolatilitySwapSecurity;
import com.opengamma.util.money.Currency;
import com.opengamma.util.money.UnorderedCurrencyPair;
import com.opengamma.util.tuple.Pair;
import com.opengamma.util.tuple.Pairs;
/**
* Base function for FX volatility swaps priced using the Carr-Lee method.
*/
public abstract class CarrLeeFXVolatilitySwapFunction extends CarrLeeVolatilitySwapFunction {
/**
* @param valueRequirementNames The value requirement names, not null
*/
public CarrLeeFXVolatilitySwapFunction(final String... valueRequirementNames) {
super(valueRequirementNames);
}
/**
* Base compiled function for FX volatility swaps priced using the Carr-Lee method.
*/
protected abstract class CarrLeeFXVolatilitySwapCompiledFunction extends CarrLeeVolatilitySwapCompiledFunction {
/**
* @param tradeToDefinitionConverter Converts targets to definitions, not null
* @param definitionToDerivativeConverter Converts definitions to derivatives, not null
* @param withCurrency True if the {@link ValuePropertyNames#CURRENCY} result property is set
*/
protected CarrLeeFXVolatilitySwapCompiledFunction(final DefaultTradeConverter tradeToDefinitionConverter,
final FixedIncomeConverterDataProvider definitionToDerivativeConverter, final boolean withCurrency) {
super(tradeToDefinitionConverter, definitionToDerivativeConverter, withCurrency);
}
@Override
public boolean canApplyTo(final FunctionCompilationContext context, final ComputationTarget target) {
return target.getTrade().getSecurity() instanceof FXVolatilitySwapSecurity;
}
@Override
protected ValueRequirement getVolatilitySurfaceRequirement(final ValueRequirement desiredValue, final ComputationTarget target) {
final ValueProperties constraints = desiredValue.getConstraints();
final String interpolatorName = Iterables.getOnlyElement(constraints.getValues(X_INTERPOLATOR_NAME));
final String leftExtrapolatorName = Iterables.getOnlyElement(constraints.getValues(LEFT_X_EXTRAPOLATOR_NAME));
final String rightExtrapolatorName = Iterables.getOnlyElement(constraints.getValues(RIGHT_X_EXTRAPOLATOR_NAME));
final String surface = Iterables.getOnlyElement(constraints.getValues(SURFACE));
final FXVolatilitySwapSecurity swap = (FXVolatilitySwapSecurity) target.getTrade().getSecurity();
final Currency counterCurrency = swap.getCounterCurrency();
final Currency baseCurrency = swap.getBaseCurrency();
final ValueProperties properties = ValueProperties.builder()
.with(SURFACE, surface)
.with(PROPERTY_SURFACE_INSTRUMENT_TYPE, FOREX)
.with(X_INTERPOLATOR_NAME, interpolatorName)
.with(LEFT_X_EXTRAPOLATOR_NAME, leftExtrapolatorName)
.with(RIGHT_X_EXTRAPOLATOR_NAME, rightExtrapolatorName)
.get();
final UnorderedCurrencyPair currencyPair = UnorderedCurrencyPair.of(counterCurrency, baseCurrency);
return new ValueRequirement(STANDARD_VOLATILITY_SURFACE_DATA, ComputationTargetType.UNORDERED_CURRENCY_PAIR.specification(currencyPair), properties);
}
@Override
protected ValueRequirement getSpotRequirement(final ComputationTarget target) {
final FXVolatilitySwapSecurity swap = (FXVolatilitySwapSecurity) target.getTrade().getSecurity();
final CurrencyPair currencyPair = CurrencyPair.of(swap.getBaseCurrency(), swap.getCounterCurrency());
return new ValueRequirement(SPOT_RATE, CurrencyPair.TYPE.specification(currencyPair));
}
@Override
protected ValueRequirement getRealizedVarianceRequirement(final ValueRequirement desiredValue, final ComputationTarget target) {
final ValueProperties constraints = desiredValue.getConstraints();
final ValueProperties.Builder properties = ValueProperties.builder();
final FXVolatilitySwapSecurity security = (FXVolatilitySwapSecurity) target.getTrade().getSecurity();
final LocalDate firstObservationDate = security.getFirstObservationDate().toLocalDate();
final LocalDate lastObservationDate = security.getLastObservationDate().toLocalDate();
final String varianceCalculationMethod = Iterables.getOnlyElement(constraints.getValues(PROPERTY_REALIZED_VARIANCE_METHOD));
if (MARKET_REALIZED_VARIANCE.equals(varianceCalculationMethod)) {
properties.with(PROPERTY_REALIZED_VARIANCE_METHOD, MARKET_REALIZED_VARIANCE);
} else if (HISTORICAL_REALIZED_VARIANCE.equals(varianceCalculationMethod)) {
properties.with(PROPERTY_REALIZED_VARIANCE_METHOD, HISTORICAL_REALIZED_VARIANCE)
.with(HISTORICAL_VARIANCE_START, firstObservationDate.toString())
.with(HISTORICAL_VARIANCE_END, lastObservationDate.toString());
}
final FXVolatilitySwapSecurity swap = (FXVolatilitySwapSecurity) target.getTrade().getSecurity();
final Currency counterCurrency = swap.getCounterCurrency();
final Currency baseCurrency = swap.getBaseCurrency();
final UnorderedCurrencyPair currencyPair = UnorderedCurrencyPair.of(counterCurrency, baseCurrency);
return new ValueRequirement(REALIZED_VARIANCE, ComputationTargetType.UNORDERED_CURRENCY_PAIR.specification(currencyPair), properties.get());
}
@Override
protected CarrLeeFXData getCarrLeeData(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target, final FXMatrix fxMatrix) {
final FXVolatilitySwapSecurity security = (FXVolatilitySwapSecurity) target.getTrade().getSecurity();
final MulticurveProviderInterface data = getMergedProviders(inputs, fxMatrix);
final SmileDeltaTermStructureParametersStrikeInterpolation volatilitySurface = (SmileDeltaTermStructureParametersStrikeInterpolation) inputs.getValue(STANDARD_VOLATILITY_SURFACE_DATA);
final Pair<Currency, Currency> currencyPair = Pairs.of(security.getBaseCurrency(), security.getCounterCurrency());
final Clock snapshotClock = executionContext.getValuationClock();
final ZonedDateTime now = ZonedDateTime.now(snapshotClock);
if (now.isBefore(security.getFirstObservationDate())) {
return new CarrLeeFXData(currencyPair, volatilitySurface, data);
}
final double realizedVariance = (Double) inputs.getValue(REALIZED_VARIANCE);
return new CarrLeeFXData(currencyPair, volatilitySurface, data, realizedVariance);
}
}
}