/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.integration.tool.portfolio.xml.v1_0.conversion;
import java.math.BigDecimal;
import java.math.RoundingMode;
import org.threeten.bp.ZoneOffset;
import org.threeten.bp.ZonedDateTime;
import com.opengamma.financial.currency.CurrencyPair;
import com.opengamma.financial.security.option.OptionType;
import com.opengamma.integration.tool.portfolio.xml.v1_0.jaxb.AbstractFxOptionTrade;
import com.opengamma.integration.tool.portfolio.xml.v1_0.jaxb.AdditionalCashflow;
import com.opengamma.integration.tool.portfolio.xml.v1_0.jaxb.BuySell;
import com.opengamma.util.money.Currency;
import com.opengamma.util.time.Expiry;
/**
* Calculator class allowing calculations performed for FxOptions to be defined once. Not
* intended for use outside of the TradeSecurityExtractors for FxOption.
*/
/* package */
class FxOptionCalculator {
private final Currency _callCurrency;
private final Currency _putCurrency;
private final double _callAmount;
private final double _putAmount;
private final Expiry _expiry;
private final ZonedDateTime _settlementDate;
private final boolean _long;
public FxOptionCalculator(AbstractFxOptionTrade trade, BigDecimal amount, Currency currency) {
CurrencyPair cp = CurrencyPair.parse(trade.getCurrencyPair());
Currency optionCurrency = trade.getOptionCurrency();
Currency notionalCurrency = currency;
if (!cp.contains(optionCurrency)) {
throw new PortfolioParsingException("Option currency must appear in the currency pair");
}
if (!cp.contains(notionalCurrency)) {
throw new PortfolioParsingException("Notional currency must appear in the currency pair");
}
boolean isCall = trade.getOptionType() == OptionType.CALL;
Currency other = cp.getComplement(optionCurrency);
_callCurrency = isCall ? optionCurrency : other;
_putCurrency = isCall ? other : optionCurrency;
BigDecimal strike = trade.getStrike();
// Depending on the currency, either call amount or put amount equals the supplied amount
// Then use the fact that Strike = (call amount / put amount) to calculate the other value
_callAmount = (_callCurrency.equals(notionalCurrency) ? amount : amount.multiply(strike)).doubleValue();
_putAmount = (_putCurrency.equals(notionalCurrency) ? amount : amount.divide(strike, RoundingMode.HALF_UP)).doubleValue();
_expiry = new Expiry(trade.getFxExpiry().getExpiryDate().atStartOfDay(ZoneOffset.UTC));
_settlementDate = extractSettlementDate(trade);
_long = trade.getBuySell() == BuySell.BUY;
}
/**
* Get a settlement date based on the premium paid for the option.
*
* @param trade
* @return
*/
private ZonedDateTime extractSettlementDate(AbstractFxOptionTrade trade) {
if (trade.getAdditionalCashflows() != null) {
for (AdditionalCashflow cashflow : trade.getAdditionalCashflows()) {
if (cashflow.getCashflowType() == AdditionalCashflow.CashflowType.PREMIUM) {
return cashflow.getCashflowDate().atStartOfDay(ZoneOffset.UTC);
}
}
}
return null;
}
public Currency getCallCurrency() {
return _callCurrency;
}
public Currency getPutCurrency() {
return _putCurrency;
}
public double getCallAmount() {
return _callAmount;
}
public double getPutAmount() {
return _putAmount;
}
public Expiry getExpiry() {
return _expiry;
}
public ZonedDateTime getSettlementDate() {
return _settlementDate;
}
public boolean isLong() {
return _long;
}
}