/**
* 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.Set;
import com.google.common.collect.Sets;
import com.opengamma.core.position.Position;
import com.opengamma.core.position.Trade;
import com.opengamma.core.security.Security;
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.model.forex.FXUtils;
import com.opengamma.financial.security.FinancialSecurityUtils;
import com.opengamma.util.money.Currency;
import com.opengamma.util.money.MoneyCalculationUtils;
/**
*
*/
public abstract class AbstractPositionPnLFunction extends AbstractFunction.NonCompiledInvoker {
@Override
public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target, final Set<ValueRequirement> desiredValues) {
final Position position = target.getPosition();
BigDecimal currentSum = BigDecimal.ZERO;
for (final Trade trade : position.getTrades()) {
final Object tradeValue = inputs.getValue(new ValueRequirement(ValueRequirementNames.PNL,
ComputationTargetType.TRADE, trade.getUniqueId()));
currentSum = MoneyCalculationUtils.add(currentSum, new BigDecimal(String.valueOf(tradeValue)));
}
return Sets.newHashSet(new ComputedValue(new ValueSpecification(ValueRequirementNames.PNL, target.toSpecification(), createValueProperties(position).get()), currentSum.doubleValue()));
}
@Override
public ComputationTargetType getTargetType() {
return ComputationTargetType.POSITION;
}
@Override
public boolean canApplyTo(final FunctionCompilationContext context, final ComputationTarget target) {
final Security security = target.getPosition().getSecurity();
if (FXUtils.isFXSecurity(security)) {
// Can't do FX securities with this because they don't have a single currency we can use
return false;
}
return true;
}
protected ValueProperties.Builder createValueProperties(final Position position) {
final ValueProperties.Builder properties = super.createValueProperties();
final Currency ccy = FinancialSecurityUtils.getCurrency(position.getSecurity());
if (ccy != null) {
properties.with(ValuePropertyNames.CURRENCY, ccy.getCode());
}
return properties;
}
@Override
public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target) {
return Collections.singleton(new ValueSpecification(ValueRequirementNames.PNL, target.toSpecification(), createValueProperties(target.getPosition()).get()));
}
@Override
public Set<ValueRequirement> getRequirements(final FunctionCompilationContext context, final ComputationTarget target, final ValueRequirement desiredValue) {
final Position position = target.getPosition();
final Currency currency = FinancialSecurityUtils.getCurrency(position.getSecurity());
final ValueProperties constraints;
if (currency != null) {
constraints = ValueProperties.with(ValuePropertyNames.CURRENCY, currency.getCode()).get();
} else {
constraints = ValueProperties.none();
}
final Set<ValueRequirement> requirements = new HashSet<ValueRequirement>();
for (final Trade trade : position.getTrades()) {
requirements.add(new ValueRequirement(ValueRequirementNames.PNL, ComputationTargetType.TRADE, trade.getUniqueId(), constraints));
}
return requirements;
}
}