/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.analytics.model.pnl;
import java.util.Collections;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.opengamma.OpenGammaRuntimeException;
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.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.security.FinancialSecurity;
import com.opengamma.financial.security.FinancialSecurityUtils;
import com.opengamma.financial.security.FinancialSecurityVisitorAdapter;
import com.opengamma.financial.security.fx.FXForwardSecurity;
import com.opengamma.financial.security.option.FXOptionSecurity;
import com.opengamma.timeseries.DoubleTimeSeries;
/**
*
*/
public class PositionPnLFunction extends AbstractFunction.NonCompiledInvoker {
private static final Logger s_logger = LoggerFactory.getLogger(PositionPnLFunction.class);
@Override
public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target, final Set<ValueRequirement> desiredValues) {
final ValueRequirement desiredValue = desiredValues.iterator().next();
final String currency = desiredValue.getConstraint(ValuePropertyNames.CURRENCY);
final String samplingPeriod = desiredValue.getConstraint(ValuePropertyNames.SAMPLING_PERIOD);
final String scheduleCalculator = desiredValue.getConstraint(ValuePropertyNames.SCHEDULE_CALCULATOR);
final String samplingFunction = desiredValue.getConstraint(ValuePropertyNames.SAMPLING_FUNCTION);
final ValueProperties properties = createValueProperties()
.with(ValuePropertyNames.CURRENCY, currency)
.with(ValuePropertyNames.SAMPLING_PERIOD, samplingPeriod)
.with(ValuePropertyNames.SCHEDULE_CALCULATOR, scheduleCalculator)
.with(ValuePropertyNames.SAMPLING_FUNCTION, samplingFunction)
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, "Delta").get();
final ValueSpecification spec = new ValueSpecification(ValueRequirementNames.PNL_SERIES, target.toSpecification(), properties);
DoubleTimeSeries<?> ts = null;
for (final ComputedValue input : inputs.getAllValues()) {
final Object value = input.getValue();
if (value == null) {
throw new OpenGammaRuntimeException("Could not get time series for " + input.getSpecification());
} else if (!(DoubleTimeSeries.class.isAssignableFrom(value.getClass()))) {
throw new OpenGammaRuntimeException("Value for " + input.getSpecification() + " was not a time series: " + value.getClass());
}
if (ts == null) {
ts = (DoubleTimeSeries<?>) value;
} else {
ts = ts.add((DoubleTimeSeries<?>) value);
}
}
return Collections.singleton(new ComputedValue(spec, ts));
}
@Override
public ComputationTargetType getTargetType() {
return ComputationTargetType.POSITION;
}
@Override
public boolean canApplyTo(final FunctionCompilationContext context, final ComputationTarget target) {
return target.getPosition().getSecurity() instanceof FinancialSecurity;
}
@Override
public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target) {
final ValueProperties properties = createValueProperties()
.withAny(ValuePropertyNames.CURRENCY)
.withAny(ValuePropertyNames.SAMPLING_PERIOD)
.withAny(ValuePropertyNames.SCHEDULE_CALCULATOR)
.withAny(ValuePropertyNames.SAMPLING_FUNCTION)
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, "Delta").get();
return Collections.singleton(new ValueSpecification(ValueRequirementNames.PNL_SERIES, target.toSpecification(), properties));
}
@Override
public Set<ValueRequirement> getRequirements(final FunctionCompilationContext context, final ComputationTarget target, final ValueRequirement desiredValue) {
final ValueProperties constraints = desiredValue.getConstraints();
final Set<String> currencies = constraints.getValues(ValuePropertyNames.CURRENCY);
if (currencies == null || currencies.size() != 1) {
return null;
}
final Set<String> samplingPeriods = constraints.getValues(ValuePropertyNames.SAMPLING_PERIOD);
if (samplingPeriods == null || samplingPeriods.size() != 1) {
return null;
}
final Set<String> scheduleCalculators = constraints.getValues(ValuePropertyNames.SCHEDULE_CALCULATOR);
if (scheduleCalculators == null || scheduleCalculators.size() != 1) {
return null;
}
final Set<String> samplingFunctions = constraints.getValues(ValuePropertyNames.SAMPLING_FUNCTION);
if (samplingFunctions == null || samplingFunctions.size() != 1) {
return null;
}
final String samplingPeriod = samplingPeriods.iterator().next();
final String scheduleCalculator = scheduleCalculators.iterator().next();
final String samplingFunction = samplingFunctions.iterator().next();
final FinancialSecurity security = (FinancialSecurity) target.getPosition().getSecurity();
final String currency = currencies.iterator().next();
try {
final Set<ValueRequirement> set = OpenGammaCompilationContext.getPnLRequirementsGatherer(context).getFirstOrderRequirements(security, samplingPeriod, scheduleCalculator, samplingFunction,
target.toSpecification(), currency);
return set;
} catch (final OpenGammaRuntimeException e) {
s_logger.error("Could not get delta requirements for {} {}; reason was {}", new Object[] {getCcyString(security), security.getClass(), e.getMessage() });
return null;
}
}
private String getCcyString(final FinancialSecurity financialSecurity) {
try {
return FinancialSecurityUtils.getCurrency(financialSecurity).getCode();
} catch (final UnsupportedOperationException e) {
return financialSecurity.accept(new FinancialSecurityVisitorAdapter<String>() {
@Override
public String visitFXForwardSecurity(final FXForwardSecurity security) {
return security.getPayCurrency().getCode() + "/" + security.getReceiveCurrency().getCode();
}
@Override
public String visitFXOptionSecurity(final FXOptionSecurity security) {
return security.getPutCurrency().getCode() + "/" + security.getCallCurrency().getCode();
}
});
}
}
}