/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.sesame.bondfutureoption;
import org.threeten.bp.ZonedDateTime;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.analytics.financial.forex.method.FXMatrix;
import com.opengamma.analytics.financial.instrument.InstrumentDefinition;
import com.opengamma.analytics.financial.instrument.InstrumentDefinitionWithData;
import com.opengamma.analytics.financial.interestrate.InstrumentDerivative;
import com.opengamma.analytics.financial.interestrate.future.calculator.DeltaBlackBondFuturesCalculator;
import com.opengamma.analytics.financial.interestrate.future.calculator.FuturesPriceBlackBondFuturesCalculator;
import com.opengamma.analytics.financial.interestrate.future.calculator.GammaBlackBondFuturesCalculator;
import com.opengamma.analytics.financial.interestrate.future.calculator.ThetaBlackBondFuturesCalculator;
import com.opengamma.analytics.financial.interestrate.future.calculator.VegaBlackBondFuturesCalculator;
import com.opengamma.analytics.financial.provider.calculator.blackbondfutures.PresentValueBlackBondFuturesOptionCalculator;
import com.opengamma.analytics.financial.provider.calculator.blackbondfutures.PresentValueCurveSensitivityBlackBondFuturesOptionCalculator;
import com.opengamma.analytics.financial.provider.description.interestrate.BlackBondFuturesProviderInterface;
import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyMulticurveSensitivity;
import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyParameterSensitivity;
import com.opengamma.analytics.financial.provider.sensitivity.parameter.ParameterSensitivityParameterCalculator;
import com.opengamma.core.historicaltimeseries.HistoricalTimeSeries;
import com.opengamma.core.position.Trade;
import com.opengamma.core.security.Security;
import com.opengamma.core.value.MarketDataRequirementNames;
import com.opengamma.financial.analytics.conversion.BondFutureOptionTradeConverter;
import com.opengamma.financial.analytics.timeseries.HistoricalTimeSeriesBundle;
import com.opengamma.sesame.trade.BondFutureOptionTrade;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.money.Currency;
import com.opengamma.util.money.MultipleCurrencyAmount;
import com.opengamma.util.result.Result;
/**
* Bond future option calculator using black volatilities.
*/
public class BondFutureOptionBlackCalculator implements BondFutureOptionCalculator {
private static final PresentValueBlackBondFuturesOptionCalculator PV_CALC = PresentValueBlackBondFuturesOptionCalculator.getInstance();
private static final PresentValueCurveSensitivityBlackBondFuturesOptionCalculator PVCSBFC =
new PresentValueCurveSensitivityBlackBondFuturesOptionCalculator();
private static final ParameterSensitivityParameterCalculator<BlackBondFuturesProviderInterface> PSSFC =
new ParameterSensitivityParameterCalculator<>(PVCSBFC);
private static final FuturesPriceBlackBondFuturesCalculator PRICE_CALC = FuturesPriceBlackBondFuturesCalculator.getInstance();
private static final DeltaBlackBondFuturesCalculator DELTA_CALC = DeltaBlackBondFuturesCalculator.getInstance();
private static final GammaBlackBondFuturesCalculator GAMMA_CALC = GammaBlackBondFuturesCalculator.getInstance();
private static final VegaBlackBondFuturesCalculator VEGA_CALC = VegaBlackBondFuturesCalculator.getInstance();
private static final ThetaBlackBondFuturesCalculator THETA_CALC = ThetaBlackBondFuturesCalculator.getInstance();
private final InstrumentDerivative _derivative;
private final BlackBondFuturesProviderInterface _black;
private final Currency _currency;
public static final double BP = 0.0001;
/**
* Constructs a Black calculator for bond future options.
* @param trade the bond future option trade, not null.
* @param converter the bond future option converter, not null.
* @param black the Black volatility provider, not null.
* @param valTime the valuation time, not null.
* @param fixings the times series containing the last margin price, not null.
*/
public BondFutureOptionBlackCalculator(BondFutureOptionTrade trade,
BondFutureOptionTradeConverter converter,
BlackBondFuturesProviderInterface black,
ZonedDateTime valTime,
HistoricalTimeSeriesBundle fixings) {
_derivative = createInstrumentDerivative(ArgumentChecker.notNull(trade, "trade"),
ArgumentChecker.notNull(converter, "converter"),
ArgumentChecker.notNull(valTime, "valTime"),
ArgumentChecker.notNull(fixings, "fixings"));
_currency = trade.getSecurity().getCurrency();
_black = ArgumentChecker.notNull(black, "black");
}
@Override
public Result<MultipleCurrencyAmount> calculatePV() {
return Result.success(_derivative.accept(PV_CALC, _black));
}
@Override
public Result<Double> calculatePV01() {
return Result.success(PSSFC.calculateSensitivity(_derivative, _black).multipliedBy(BP)
.totalSensitivity(new FXMatrix(_currency), _currency));
}
@Override
public Result<Double> calculateModelPrice() {
return Result.success(_derivative.accept(PRICE_CALC, _black));
}
@Override
public Result<Double> calculateDelta() {
return Result.success(_derivative.accept(DELTA_CALC, _black));
}
@Override
public Result<Double> calculateGamma() {
return Result.success(_derivative.accept(GAMMA_CALC, _black));
}
@Override
public Result<Double> calculateVega() {
return Result.success(_derivative.accept(VEGA_CALC, _black));
}
@Override
public Result<Double> calculateTheta() {
return Result.success(_derivative.accept(THETA_CALC, _black));
}
@Override
public Result<MultipleCurrencyParameterSensitivity> calculateBucketedPV01() {
return Result.success(PSSFC.calculateSensitivity(_derivative, _black).multipliedBy(BP));
}
@SuppressWarnings("unchecked")
private InstrumentDerivative createInstrumentDerivative(BondFutureOptionTrade tradeWrapper,
BondFutureOptionTradeConverter converter,
ZonedDateTime valTime,
HistoricalTimeSeriesBundle timeSeries) {
Trade trade = tradeWrapper.getTrade();
InstrumentDefinition<?> definition = converter.convert(trade);
if (definition instanceof InstrumentDefinitionWithData) {
final Security security = tradeWrapper.getSecurity();
final HistoricalTimeSeries ts = timeSeries.get(MarketDataRequirementNames.MARKET_VALUE, security.getExternalIdBundle());
Double lastMarginPrice;
if (valTime.toLocalDate().equals(trade.getTradeDate())) {
lastMarginPrice = trade.getPremium();
} else {
if (ts == null) {
throw new OpenGammaRuntimeException("Could not get price time series for " + security);
}
final int length = ts.getTimeSeries().size();
if (length == 0) {
throw new OpenGammaRuntimeException("Price time series for " + security.getExternalIdBundle() + " was empty");
}
lastMarginPrice = ts.getTimeSeries().getLatestValue();
}
return ((InstrumentDefinitionWithData<?, Double>) definition).toDerivative(valTime, lastMarginPrice);
} else {
return definition.toDerivative(valTime);
}
}
}