/** * 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.EquityFuture; import com.opengamma.analytics.financial.equity.future.derivative.EquityIndexDividendFuture; import com.opengamma.analytics.financial.interestrate.InstrumentDerivativeVisitorAdapter; import com.opengamma.analytics.financial.simpleinstruments.pricing.SimpleFutureDataBundle; import com.opengamma.util.ArgumentChecker; /** * */ public abstract class CostOfCarryFuturesCalculator extends InstrumentDerivativeVisitorAdapter<SimpleFutureDataBundle, Double> { /* package */CostOfCarryFuturesCalculator() { } @Override public Double visitAgricultureFuture(final AgricultureFuture future, final SimpleFutureDataBundle dataBundle) { ArgumentChecker.notNull(future, "future"); ArgumentChecker.notNull(dataBundle, "data bundle"); return 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 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 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 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 getResult(dataBundle, future.getReferencePrice(), future.getUnitAmount(), future.getExpiry()); } abstract double getResult(SimpleFutureDataBundle dataBundle, double strike, double unitAmount, double t); /** * Calculates the present value */ public static final class PresentValueCalculator extends CostOfCarryFuturesCalculator { 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) { final double fwdPrice = ForwardPriceCalculator.getInstance().getResult(dataBundle, strike, unitAmount, t); return (fwdPrice - strike) * unitAmount; } } /** * Calculates the spot delta */ public static final class SpotDeltaCalculator extends CostOfCarryFuturesCalculator { 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) { final double discountRate = dataBundle.getFundingCurve().getInterestRate(t); final double costOfCarry = Math.exp(t * (discountRate - dataBundle.getDividendYield())); return costOfCarry * unitAmount; } } /** * Calculates the rates delta */ public static final class RatesDeltaCalculator extends CostOfCarryFuturesCalculator { 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) { final double discountRate = dataBundle.getFundingCurve().getInterestRate(t); final double costOfCarry = Math.exp(t * (discountRate - dataBundle.getDividendYield())); final double fwdPrice = dataBundle.getSpotValue() * costOfCarry; return t * fwdPrice * unitAmount; } } /** * Calculates the pv01 */ public static final class PV01Calculator extends CostOfCarryFuturesCalculator { 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 CostOfCarryFuturesCalculator { 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) { return dataBundle.getSpotValue(); } } /** * Gets the forward price */ public static final class ForwardPriceCalculator extends CostOfCarryFuturesCalculator { 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) { final double discountRate = dataBundle.getFundingCurve().getInterestRate(t); final double costOfCarry = Math.exp(t * (discountRate - dataBundle.getDividendYield())); return dataBundle.getSpotValue() * costOfCarry; } } }