// Create output specification. Check for trivial cases
final ValueSpecification valueSpecification = new ValueSpecification(getValueRequirementName(), target.toSpecification(), desiredValue.getConstraints());
if (isNewTrade && tradeType.equalsIgnoreCase(PnLFunctionUtils.PNL_TRADE_TYPE_OPEN) ||
(!isNewTrade) && tradeType.equalsIgnoreCase(PnLFunctionUtils.PNL_TRADE_TYPE_NEW)) {
return Sets.newHashSet(new ComputedValue(valueSpecification, 0.0));
}
// 2. Get inputs
// For all TradeTypes, we'll require the live Price
Double livePrice = calculateLivePrice(inputs, target);
// For PNL, we need a reference price. We have two cases:
// Open: will need the closing price and any carry
// New: will need the trade price
Double referencePrice;
Double costOfCarry = 0.0;
if (isNewTrade) {
referencePrice = trade.getPremium();
if (referencePrice == null) {
throw new NullPointerException("New Trades require a premium to compute PNL on trade date. Premium was null for " + trade.getUniqueId());
}
if ((security instanceof InterestRateFutureSecurity || security instanceof IRFutureOptionSecurity) && (trade.getPremium() > 1.0)) {
referencePrice /= 100.0;
}
} else {
referencePrice = calculateReferencePrice(inputs, target);
if (referencePrice == null) {
final ComputedValue result = new ComputedValue(valueSpecification, MissingInput.MISSING_MARKET_DATA);
return Sets.newHashSet(result);
}
Object carryValue = inputs.getValue(_costOfCarryField);
if (carryValue != null) {
costOfCarry = (Double) carryValue;
}
}
// 3. Compute the PNL
// Move in the marked prices: Live - Previous Close
final Double dailyPriceMove = livePrice - referencePrice;
// Total move := Value
Double dailyValueMove = dailyPriceMove - costOfCarry;
// 4. Scale by Trade Notionals and Quantity
// Some SecurityType's have Notional values built-in. Scale by these if required.
if (security instanceof FutureSecurity) {
final FutureSecurity futureSecurity = (FutureSecurity) security;
dailyValueMove *= futureSecurity.getUnitAmount();
} else if (security instanceof EquityOptionSecurity) {
final EquityOptionSecurity optionSecurity = (EquityOptionSecurity) security;
dailyValueMove *= optionSecurity.getPointValue();
} else if (security instanceof EquityIndexOptionSecurity) {
final EquityIndexOptionSecurity optionSecurity = (EquityIndexOptionSecurity) security;
dailyValueMove *= optionSecurity.getPointValue();
} else if (security instanceof EquityIndexFutureOptionSecurity) {
final EquityIndexFutureOptionSecurity optionSecurity = (EquityIndexFutureOptionSecurity) security;
dailyValueMove *= optionSecurity.getPointValue();
} else if (security instanceof IRFutureOptionSecurity) {
final IRFutureOptionSecurity optionSecurity = (IRFutureOptionSecurity) security;
dailyValueMove *= optionSecurity.getPointValue();
}
// Multiply by the Trade's Quantity
final Double dailyPnL = target.getTrade().getQuantity().doubleValue() * dailyValueMove;
// 5. Return
final ComputedValue result = new ComputedValue(valueSpecification, dailyPnL);
return Sets.newHashSet(result);
}