/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.analytics.model.pnl;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Sets;
import com.opengamma.core.position.PortfolioNode;
import com.opengamma.core.position.Position;
import com.opengamma.core.position.impl.PositionAccumulator;
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.analytics.SumUtils;
import com.opengamma.util.money.MoneyCalculationUtils;
/**
*
*/
public abstract class AbstractPortfolioDailyPnLFunction extends AbstractFunction.NonCompiledInvoker {
@SuppressWarnings("unused")
private static final Logger s_logger = LoggerFactory.getLogger(AbstractPortfolioDailyPnLFunction.class);
@Override
public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target, final Set<ValueRequirement> desiredValues) {
BigDecimal currentSum = BigDecimal.ZERO;
ValueProperties currentProperties = null;
for (final ComputedValue value : inputs.getAllValues()) {
currentSum = MoneyCalculationUtils.add(currentSum, new BigDecimal(String.valueOf(value.getValue())));
currentProperties = SumUtils.addProperties(currentProperties, value.getSpecification().getProperties());
}
if (currentProperties == null) {
return Collections.emptySet();
}
for (final ValueSpecification valueSpec : inputs.getMissingValues()) {
currentProperties = SumUtils.addProperties(currentProperties, valueSpec.getProperties());
}
currentProperties = currentProperties.copy().withoutAny(ValuePropertyNames.FUNCTION).with(ValuePropertyNames.FUNCTION, getUniqueId()).get();
final ValueSpecification valueSpecification = new ValueSpecification(ValueRequirementNames.DAILY_PNL, target.toSpecification(), currentProperties);
final ComputedValue result = new ComputedValue(valueSpecification, currentSum.doubleValue());
return Sets.newHashSet(result);
}
@Override
public Set<ValueRequirement> getRequirements(final FunctionCompilationContext context, final ComputationTarget target, final ValueRequirement desiredValue) {
final String currency = desiredValue.getConstraint(ValuePropertyNames.CURRENCY);
if (currency == null) {
return null;
}
final PortfolioNode node = target.getPortfolioNode();
// TODO: We don't need the accumulated positions - the object identifiers only would suffice (don't need to go to both databases!)
final Set<Position> allPositions = PositionAccumulator.getAccumulatedPositions(node);
final ValueProperties constraints = ValueProperties.with(ValuePropertyNames.CURRENCY, currency).get();
final Set<ValueRequirement> requirements = new HashSet<ValueRequirement>();
for (final Position position : allPositions) {
requirements.add(new ValueRequirement(ValueRequirementNames.DAILY_PNL, ComputationTargetType.POSITION, position.getUniqueId().toLatest(), constraints));
}
return requirements;
}
@Override
protected ValueProperties.Builder createValueProperties() {
final ValueProperties.Builder properties = super.createValueProperties();
properties.withAny(ValuePropertyNames.CURRENCY);
return properties;
}
@Override
public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target) {
return Collections.singleton(new ValueSpecification(ValueRequirementNames.DAILY_PNL, target.toSpecification(), createValueProperties().get()));
}
@Override
public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target, final Map<ValueSpecification, ValueRequirement> inputs) {
ValueProperties currentProperties = null;
for (final ValueSpecification input : inputs.keySet()) {
currentProperties = SumUtils.addProperties(currentProperties, input.getProperties());
}
if (currentProperties == null) {
return null;
}
currentProperties = currentProperties.copy().withoutAny(ValuePropertyNames.FUNCTION).with(ValuePropertyNames.FUNCTION, getUniqueId()).get();
return Collections.singleton(new ValueSpecification(ValueRequirementNames.DAILY_PNL, target.toSpecification(), currentProperties));
}
@Override
public ComputationTargetType getTargetType() {
return ComputationTargetType.PORTFOLIO_NODE;
}
}