/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.future; import com.opengamma.analytics.financial.commodity.derivative.AgricultureFuture; import com.opengamma.analytics.financial.commodity.derivative.EnergyFuture; import com.opengamma.analytics.financial.commodity.derivative.MetalFuture; import com.opengamma.analytics.financial.equity.future.derivative.CashSettledFuture; import com.opengamma.analytics.financial.equity.future.derivative.EquityFuture; import com.opengamma.analytics.financial.equity.future.derivative.EquityIndexDividendFuture; import com.opengamma.analytics.financial.equity.future.derivative.EquityIndexFuture; import com.opengamma.analytics.financial.equity.future.derivative.IndexFuture; import com.opengamma.analytics.financial.equity.future.derivative.VolatilityIndexFuture; import com.opengamma.analytics.financial.interestrate.InstrumentDerivativeVisitorAdapter; import com.opengamma.analytics.financial.interestrate.future.derivative.BondFuture; import com.opengamma.analytics.financial.interestrate.future.derivative.InterestRateFutureTransaction; import com.opengamma.analytics.financial.simpleinstruments.pricing.SimpleFutureDataBundle; import com.opengamma.util.ArgumentChecker; /** * */ public abstract class MarkToMarketFuturesCalculator extends InstrumentDerivativeVisitorAdapter<SimpleFutureDataBundle, Double> { /* package */MarkToMarketFuturesCalculator() { } @Override public Double visitAgricultureFuture(final AgricultureFuture future, final SimpleFutureDataBundle dataBundle) { ArgumentChecker.notNull(future, "future"); ArgumentChecker.notNull(dataBundle, "data bundle"); return Double.valueOf(getResult(dataBundle, future.getReferencePrice(), future.getUnitAmount(), future.getExpiry())); } @Override public Double visitEnergyFuture(final EnergyFuture future, final SimpleFutureDataBundle dataBundle) { ArgumentChecker.notNull(future, "future"); ArgumentChecker.notNull(dataBundle, "data bundle"); return Double.valueOf(getResult(dataBundle, future.getReferencePrice(), future.getUnitAmount(), future.getExpiry())); } @Override public Double visitEquityFuture(final EquityFuture future, final SimpleFutureDataBundle dataBundle) { ArgumentChecker.notNull(future, "future"); ArgumentChecker.notNull(dataBundle, "data bundle"); return Double.valueOf(getResult(dataBundle, future.getStrike(), future.getUnitAmount(), future.getTimeToSettlement())); } @Override public Double visitEquityIndexDividendFuture(final EquityIndexDividendFuture future, final SimpleFutureDataBundle dataBundle) { ArgumentChecker.notNull(future, "future"); ArgumentChecker.notNull(dataBundle, "data bundle"); return Double.valueOf(getResult(dataBundle, future.getStrike(), future.getUnitAmount(), future.getTimeToSettlement())); } @Override public Double visitMetalFuture(final MetalFuture future, final SimpleFutureDataBundle dataBundle) { ArgumentChecker.notNull(future, "future"); ArgumentChecker.notNull(dataBundle, "data bundle"); return Double.valueOf(getResult(dataBundle, future.getReferencePrice(), future.getUnitAmount(), future.getExpiry())); } @Override public Double visitInterestRateFutureTransaction(final InterestRateFutureTransaction future, final SimpleFutureDataBundle dataBundle) { ArgumentChecker.notNull(future, "future"); ArgumentChecker.notNull(dataBundle, "data bundle"); return Double.valueOf(getResult(dataBundle, future.getReferencePrice(), future.getUnderlyingSecurity().getNotional() * future.getUnderlyingSecurity().getPaymentAccrualFactor() * future.getQuantity(), future.getUnderlyingSecurity().getTradingLastTime())); } @Override public Double visitBondFuture(final BondFuture future, final SimpleFutureDataBundle dataBundle) { ArgumentChecker.notNull(future, "future"); ArgumentChecker.notNull(dataBundle, "data bundle"); return Double.valueOf(getResult(dataBundle, future.getReferencePrice(), future.getNotional(), future.getTradingLastTime())); } @Override public Double visitCashSettledFuture(final CashSettledFuture future, final SimpleFutureDataBundle dataBundle) { ArgumentChecker.notNull(future, "future"); ArgumentChecker.notNull(dataBundle, "data bundle"); return Double.valueOf(getResult(dataBundle, future.getStrike(), future.getUnitAmount(), future.getTimeToSettlement())); } @Override public Double visitIndexFuture(final IndexFuture future, final SimpleFutureDataBundle dataBundle) { ArgumentChecker.notNull(future, "future"); ArgumentChecker.notNull(dataBundle, "data bundle"); return Double.valueOf(getResult(dataBundle, future.getStrike(), future.getUnitAmount(), future.getTimeToSettlement())); } @Override public Double visitEquityIndexFuture(final EquityIndexFuture future, final SimpleFutureDataBundle dataBundle) { ArgumentChecker.notNull(future, "future"); ArgumentChecker.notNull(dataBundle, "data bundle"); return Double.valueOf(getResult(dataBundle, future.getStrike(), future.getUnitAmount(), future.getTimeToSettlement())); } @Override public Double visitVolatilityIndexFuture(final VolatilityIndexFuture future, final SimpleFutureDataBundle dataBundle) { ArgumentChecker.notNull(future, "future"); ArgumentChecker.notNull(dataBundle, "data bundle"); return Double.valueOf(getResult(dataBundle, future.getStrike(), future.getUnitAmount(), future.getTimeToSettlement())); } abstract double getResult(SimpleFutureDataBundle dataBundle, double strike, double unitAmount, double t); /** * Calculates the present value */ public static final class PresentValueCalculator extends MarkToMarketFuturesCalculator { private static final PresentValueCalculator INSTANCE = new PresentValueCalculator(); public static PresentValueCalculator getInstance() { return INSTANCE; } private PresentValueCalculator() { } @Override double getResult(final SimpleFutureDataBundle dataBundle, final double strike, final double unitAmount, final double t) { return (dataBundle.getMarketPrice().doubleValue() - strike) * unitAmount; } } /** * Calculates the spot delta. The 'Delta', dV/dS for a linear future is simply the unitAmount. */ public static final class SpotDeltaCalculator extends MarkToMarketFuturesCalculator { private static final SpotDeltaCalculator INSTANCE = new SpotDeltaCalculator(); public static SpotDeltaCalculator getInstance() { return INSTANCE; } private SpotDeltaCalculator() { } @Override double getResult(final SimpleFutureDataBundle dataBundle, final double strike, final double unitAmount, final double t) { return unitAmount; } } /** * Calculates the value delta of a Future.<p> * ValueDelta is defined as S(t) * dV/dS, hence it should be equal to unitAmount * market_price. <p> * ValueDelta represents the cash value of the position or, the value of money one would make if the underlying increased in price by 100%.<p> * Observe: PNL = dV/dS * (change in S) = S(t) * dV/dS * (S(T) - S(t)) / S(t), * thus S(t)* dV/dS (ValueDelta) would be the PNL if 1.0 = (S(T) - S(t)) / S(t) => S(T) = 2*S(t), * i.e. if the underlying doubled (increased by 100%). It thus gives a measure of the sensitivity as a relative measure. */ public static final class ValueDeltaCalculator extends MarkToMarketFuturesCalculator { private static final ValueDeltaCalculator INSTANCE = new ValueDeltaCalculator(); public static ValueDeltaCalculator getInstance() { return INSTANCE; } private ValueDeltaCalculator() { } @Override double getResult(final SimpleFutureDataBundle dataBundle, final double strike, final double unitAmount, final double t) { return unitAmount * dataBundle.getMarketPrice().doubleValue(); } } /** * Calculates the rates delta */ public static final class RatesDeltaCalculator extends MarkToMarketFuturesCalculator { private static final RatesDeltaCalculator INSTANCE = new RatesDeltaCalculator(); public static RatesDeltaCalculator getInstance() { return INSTANCE; } private RatesDeltaCalculator() { } @Override double getResult(final SimpleFutureDataBundle dataBundle, final double strike, final double unitAmount, final double t) { return t * dataBundle.getMarketPrice().doubleValue() * unitAmount; } } /** * Calculates the pv01 */ public static final class PV01Calculator extends MarkToMarketFuturesCalculator { private static final PV01Calculator INSTANCE = new PV01Calculator(); public static PV01Calculator getInstance() { return INSTANCE; } private PV01Calculator() { } @Override double getResult(final SimpleFutureDataBundle dataBundle, final double strike, final double unitAmount, final double t) { return RatesDeltaCalculator.getInstance().getResult(dataBundle, strike, unitAmount, t) / 10000; } } /** * Gets the spot price */ public static final class SpotPriceCalculator extends MarkToMarketFuturesCalculator { private static final SpotPriceCalculator INSTANCE = new SpotPriceCalculator(); public static SpotPriceCalculator getInstance() { return INSTANCE; } private SpotPriceCalculator() { } @Override double getResult(final SimpleFutureDataBundle dataBundle, final double strike, final double unitAmount, final double t) { if (dataBundle.getSpotValue() == null) { throw new UnsupportedOperationException("Spot value for future underlying was null"); } return dataBundle.getSpotValue().doubleValue(); } } /** * Gets the forward price */ public static final class ForwardPriceCalculator extends MarkToMarketFuturesCalculator { private static final ForwardPriceCalculator INSTANCE = new ForwardPriceCalculator(); public static ForwardPriceCalculator getInstance() { return INSTANCE; } private ForwardPriceCalculator() { } @Override double getResult(final SimpleFutureDataBundle dataBundle, final double strike, final double unitAmount, final double t) { return dataBundle.getMarketPrice().doubleValue(); } } }