/**
* 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.util.money.MoneyCalculationUtils;
/**
*
*/
public abstract class AbstractPortfolioPnLFunction extends AbstractFunction.NonCompiledInvoker {
@SuppressWarnings("unused")
private static final Logger s_logger = LoggerFactory.getLogger(AbstractPortfolioPnLFunction.class);
@Override
public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target, final Set<ValueRequirement> desiredValues) {
BigDecimal currentSum = BigDecimal.ZERO;
for (ComputedValue input : inputs.getAllValues()) {
currentSum = MoneyCalculationUtils.add(currentSum, new BigDecimal(String.valueOf(input.getValue())));
}
final ValueRequirement desiredValue = desiredValues.iterator().next();
final ValueSpecification valueSpecification = new ValueSpecification(ValueRequirementNames.PNL, target.toSpecification(), desiredValue.getConstraints());
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 PortfolioNode node = target.getPortfolioNode();
final Set<Position> allPositions = PositionAccumulator.getAccumulatedPositions(node);
final Set<ValueRequirement> requirements = new HashSet<ValueRequirement>();
final Set<String> currencies = desiredValue.getConstraints().getValues(ValuePropertyNames.CURRENCY);
final ValueProperties constraints;
if ((currencies == null) || currencies.isEmpty()) {
constraints = ValueProperties.withAny(ValuePropertyNames.CURRENCY).get();
} else {
constraints = ValueProperties.with(ValuePropertyNames.CURRENCY, currencies).get();
}
for (final Position position : allPositions) {
requirements.add(new ValueRequirement(ValueRequirementNames.PNL, ComputationTargetType.POSITION, position.getUniqueId(), constraints));
}
return requirements;
}
@Override
public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target) {
return Collections.singleton(new ValueSpecification(ValueRequirementNames.PNL, target.toSpecification(), createValueProperties().withAny(ValuePropertyNames.CURRENCY).get()));
}
@Override
public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target, final Map<ValueSpecification, ValueRequirement> inputs) {
Set<String> currencies = null;
for (final ValueSpecification input : inputs.keySet()) {
final Set<String> inputCurrencies = input.getProperties().getValues(ValuePropertyNames.CURRENCY);
if ((inputCurrencies != null) && !inputCurrencies.isEmpty()) {
if (currencies == null) {
currencies = new HashSet<String>(inputCurrencies);
} else {
currencies.retainAll(inputCurrencies);
if (currencies.isEmpty()) {
// Inputs aren't in a common currency
return null;
}
}
}
}
if (currencies == null) {
return getResults(context, target);
} else {
return Collections.singleton(new ValueSpecification(ValueRequirementNames.PNL, target.toSpecification(), createValueProperties().with(ValuePropertyNames.CURRENCY, currencies).get()));
}
}
@Override
public ComputationTargetType getTargetType() {
return ComputationTargetType.PORTFOLIO_NODE;
}
}