public void theta() { double priceFutures = METHOD_FUTURE.price(CALL_JB_147.getUnderlyingFuture(), ISSUER_SPECIFIC_MULTICURVES); double expiry = CALL_JB_147.getExpirationTime(); double volatility = BLACK_SURFACE_EXP_STRIKE.getZValue(expiry, STRIKE_147); double rate = -Math.log( ISSUER_SPECIFIC_MULTICURVES .getMulticurveProvider() .getDiscountFactor(CALL_JB_147.getCurrency(), CALL_JB_147.getExpirationTime())) / CALL_JB_147.getExpirationTime(); double thetaCallExpected = BlackFormulaRepository.theta( priceFutures, STRIKE_147, CALL_JB_147.getExpirationTime(), volatility, CALL_JB_147.isCall(), rate); double thetaCallComputed = METHOD_OPT.theta(CALL_JB_147, BLACK_EXP_STRIKE_BNDFUT); assertEquals( "BondFuturesOptionMarginSecurityBlackFlatMethod: theta", thetaCallExpected, thetaCallComputed, TOLERANCE_DELTA); }
public void delta() { final double priceFutures = METHOD_FUTURE.price(CALL_JB_147.getUnderlyingFuture(), ISSUER_SPECIFIC_MULTICURVES); final EuropeanVanillaOption option = new EuropeanVanillaOption( STRIKE_147, CALL_JB_147.getExpirationTime(), CALL_JB_147.isCall()); final double expiry = CALL_JB_147.getExpirationTime(); final double volatility = BLACK_SURFACE_EXP_STRIKE.getZValue(expiry, STRIKE_147); double df = ISSUER_SPECIFIC_MULTICURVES .getMulticurveProvider() .getDiscountFactor(JBM5_DEFINITION.getCurrency(), CALL_JB_147.getExpirationTime()); final BlackFunctionData dataBlack = new BlackFunctionData(priceFutures, df, volatility); final double[] priceAD = BLACK_FUNCTION.getPriceAdjoint(option, dataBlack); final double deltaCallExpected = priceAD[1]; final double deltaCallComputed = METHOD_OPT.delta(CALL_JB_147, BLACK_EXP_STRIKE_BNDFUT); assertEquals( "BondFuturesOptionPremiumSecurityBlackBondFuturesMethod: delta", deltaCallExpected, deltaCallComputed, TOLERANCE_DELTA); final double deltaPutComputed = METHOD_OPT.delta(PUT_JB_147, BLACK_EXP_STRIKE_BNDFUT); assertEquals( "BondFuturesOptionPremiumSecurityBlackBondFuturesMethod: delta", deltaCallExpected - deltaPutComputed, df, TOLERANCE_DELTA); }
public void futurePrice() { final double priceExpected = METHOD_FUTURE.price(JBM5, ISSUER_SPECIFIC_MULTICURVES); final double priceComputed = METHOD_OPT.underlyingFuturePrice(CALL_JB_147, ISSUER_SPECIFIC_MULTICURVES); assertEquals( "BondFuturesOptionPremiumSecurityBlackBondFuturesMethod: underlying futures price", priceExpected, priceComputed, TOLERANCE_RATE); }
public void priceFromCurves() { final double priceFutures = METHOD_FUTURE.price(CALL_JB_147.getUnderlyingFuture(), ISSUER_SPECIFIC_MULTICURVES); final double priceExpected = METHOD_OPT.priceFromUnderlyingPrice(CALL_JB_147, BLACK_EXP_STRIKE_BNDFUT, priceFutures); final double priceComputed = METHOD_OPT.price(CALL_JB_147, BLACK_EXP_STRIKE_BNDFUT); assertEquals( "BondFuturesOptionPremiumSecurityBlackBondFuturesMethod: underlying futures price", priceExpected, priceComputed, TOLERANCE_RATE); }
public void putCallParity() { final double priceFutures = METHOD_FUTURE.price(CALL_JB_147.getUnderlyingFuture(), ISSUER_SPECIFIC_MULTICURVES); final double priceCallComputed = METHOD_OPT.price(CALL_JB_147, BLACK_EXP_STRIKE_BNDFUT); final double pricePutComputed = METHOD_OPT.price(PUT_JB_147, BLACK_EXP_STRIKE_BNDFUT); double df = ISSUER_SPECIFIC_MULTICURVES .getMulticurveProvider() .getDiscountFactor(JBM5_DEFINITION.getCurrency(), CALL_JB_147.getExpirationTime()); assertEquals( "BondFuturesOptionPremiumSecurityBlackBondFuturesMethod: put call parity price", priceCallComputed - pricePutComputed, (priceFutures - STRIKE_147) * df, TOLERANCE_RATE); }
/** Tests related to the pricing methods for bond future options with up-front premium payment. */ @Test(groups = TestGroup.UNIT) public class BondFuturesOptionPremiumSecurityBlackExpStrikeMethodTest { /** Bond future option: JGB */ private static final ZonedDateTime REFERENCE_DATE = DateUtils.getUTCDate(2015, 5, 12); private static final BondFuturesSecurityDefinition JBM5_DEFINITION = BondFuturesDataSets.JBM5_DEFINITION; private static final BondFuturesSecurity JBM5 = JBM5_DEFINITION.toDerivative(REFERENCE_DATE); private static final double STRIKE_147 = 1.47; // To be close to ATM for the data set used. private static final ZonedDateTime EXPIRY_DATE_OPT = DateUtils.getUTCDate(2015, 5, 31); private static final boolean IS_CALL = true; private static final BondFuturesOptionPremiumSecurityDefinition CALL_JB_147_DEFINITION = new BondFuturesOptionPremiumSecurityDefinition( JBM5_DEFINITION, EXPIRY_DATE_OPT, STRIKE_147, IS_CALL); private static final BondFuturesOptionPremiumSecurityDefinition PUT_JB_147_DEFINITION = new BondFuturesOptionPremiumSecurityDefinition( JBM5_DEFINITION, EXPIRY_DATE_OPT, STRIKE_147, !IS_CALL); private static final BondFuturesOptionPremiumSecurity CALL_JB_147 = CALL_JB_147_DEFINITION.toDerivative(REFERENCE_DATE); private static final BondFuturesOptionPremiumSecurity PUT_JB_147 = PUT_JB_147_DEFINITION.toDerivative(REFERENCE_DATE); /** Black surface expiry/log-moneyness */ private static final InterpolatedDoublesSurface BLACK_SURFACE_EXP_STRIKE = StandardDataSetsBlack.BLACK_SURFACE_BND_EXP_STRIKE; /** Curves for a specific issuer name */ private static final IssuerProviderDiscount ISSUER_SPECIFIC_MULTICURVES = IssuerProviderDiscountDataSets.ISSUER_SPECIFIC_MULTICURVE_JP; /** The legal entity */ private static final LegalEntity LEGAL_ENTITY_JAPAN = IssuerProviderDiscountDataSets.JP_GOVT; /** The Black bond futures provider * */ // TODO: Change to strike private static final BlackBondFuturesExpStrikeProvider BLACK_EXP_STRIKE_BNDFUT = new BlackBondFuturesExpStrikeProvider( ISSUER_SPECIFIC_MULTICURVES, BLACK_SURFACE_EXP_STRIKE, LEGAL_ENTITY_JAPAN); /** Methods and calculators */ private static final BondFuturesOptionPremiumSecurityBlackBondFuturesMethod METHOD_OPT = BondFuturesOptionPremiumSecurityBlackBondFuturesMethod.getInstance(); private static final BondFuturesSecurityDiscountingMethod METHOD_FUTURE = BondFuturesSecurityDiscountingMethod.getInstance(); private static final BlackPriceFunction BLACK_FUNCTION = new BlackPriceFunction(); /** Tolerances */ private static final double TOLERANCE_RATE = 1.0E-10; private static final double TOLERANCE_DELTA = 1.0E-8; public void impliedVolatility() { final double strike = STRIKE_147; final double expiry = CALL_JB_147.getExpirationTime(); final double ivExpected = BLACK_SURFACE_EXP_STRIKE.getZValue(expiry, strike); final double ivComputed = METHOD_OPT.impliedVolatility(CALL_JB_147, BLACK_EXP_STRIKE_BNDFUT); assertEquals( "BondFuturesOptionPremiumSecurityBlackSurfaceMethod: impliedVolatility", ivExpected, ivComputed, TOLERANCE_RATE); } public void futurePrice() { final double priceExpected = METHOD_FUTURE.price(JBM5, ISSUER_SPECIFIC_MULTICURVES); final double priceComputed = METHOD_OPT.underlyingFuturePrice(CALL_JB_147, ISSUER_SPECIFIC_MULTICURVES); assertEquals( "BondFuturesOptionPremiumSecurityBlackBondFuturesMethod: underlying futures price", priceExpected, priceComputed, TOLERANCE_RATE); } public void priceFromFuturesPrice() { final double price = 1.465; final EuropeanVanillaOption option = new EuropeanVanillaOption( STRIKE_147, CALL_JB_147.getExpirationTime(), CALL_JB_147.isCall()); final double logmoney = Math.log(STRIKE_147 / price); final double expiry = CALL_JB_147.getExpirationTime(); final double volatility = BLACK_SURFACE_EXP_STRIKE.getZValue(expiry, logmoney); double df = ISSUER_SPECIFIC_MULTICURVES .getMulticurveProvider() .getDiscountFactor(JBM5_DEFINITION.getCurrency(), expiry); final BlackFunctionData dataBlack = new BlackFunctionData(price, df, volatility); final double priceExpected = BLACK_FUNCTION.getPriceFunction(option).evaluate(dataBlack); final double priceComputed = METHOD_OPT.priceFromUnderlyingPrice(CALL_JB_147, BLACK_EXP_STRIKE_BNDFUT, price); assertEquals( "BondFuturesOptionPremiumSecurityBlackBondFuturesMethod: underlying futures price", priceExpected, priceComputed, TOLERANCE_RATE); } public void priceFromCurves() { final double priceFutures = METHOD_FUTURE.price(CALL_JB_147.getUnderlyingFuture(), ISSUER_SPECIFIC_MULTICURVES); final double priceExpected = METHOD_OPT.priceFromUnderlyingPrice(CALL_JB_147, BLACK_EXP_STRIKE_BNDFUT, priceFutures); final double priceComputed = METHOD_OPT.price(CALL_JB_147, BLACK_EXP_STRIKE_BNDFUT); assertEquals( "BondFuturesOptionPremiumSecurityBlackBondFuturesMethod: underlying futures price", priceExpected, priceComputed, TOLERANCE_RATE); } public void putCallParity() { final double priceFutures = METHOD_FUTURE.price(CALL_JB_147.getUnderlyingFuture(), ISSUER_SPECIFIC_MULTICURVES); final double priceCallComputed = METHOD_OPT.price(CALL_JB_147, BLACK_EXP_STRIKE_BNDFUT); final double pricePutComputed = METHOD_OPT.price(PUT_JB_147, BLACK_EXP_STRIKE_BNDFUT); double df = ISSUER_SPECIFIC_MULTICURVES .getMulticurveProvider() .getDiscountFactor(JBM5_DEFINITION.getCurrency(), CALL_JB_147.getExpirationTime()); assertEquals( "BondFuturesOptionPremiumSecurityBlackBondFuturesMethod: put call parity price", priceCallComputed - pricePutComputed, (priceFutures - STRIKE_147) * df, TOLERANCE_RATE); } public void vega() { final double priceFutures = METHOD_FUTURE.price(CALL_JB_147.getUnderlyingFuture(), ISSUER_SPECIFIC_MULTICURVES); final EuropeanVanillaOption option = new EuropeanVanillaOption( STRIKE_147, CALL_JB_147.getExpirationTime(), CALL_JB_147.isCall()); final double expiry = CALL_JB_147.getExpirationTime(); final double volatility = BLACK_SURFACE_EXP_STRIKE.getZValue(expiry, STRIKE_147); double df = ISSUER_SPECIFIC_MULTICURVES .getMulticurveProvider() .getDiscountFactor(JBM5_DEFINITION.getCurrency(), CALL_JB_147.getExpirationTime()); final BlackFunctionData dataBlack = new BlackFunctionData(priceFutures, df, volatility); final double[] priceAD = BLACK_FUNCTION.getPriceAdjoint(option, dataBlack); final double vegaExpected = priceAD[2]; final double vegaComputed = METHOD_OPT.vega(CALL_JB_147, BLACK_EXP_STRIKE_BNDFUT); assertEquals( "BondFuturesOptionPremiumSecurityBlackBondFuturesMethod: Black parameters sensitivity", vegaExpected, vegaComputed, TOLERANCE_RATE); } public void delta() { final double priceFutures = METHOD_FUTURE.price(CALL_JB_147.getUnderlyingFuture(), ISSUER_SPECIFIC_MULTICURVES); final EuropeanVanillaOption option = new EuropeanVanillaOption( STRIKE_147, CALL_JB_147.getExpirationTime(), CALL_JB_147.isCall()); final double expiry = CALL_JB_147.getExpirationTime(); final double volatility = BLACK_SURFACE_EXP_STRIKE.getZValue(expiry, STRIKE_147); double df = ISSUER_SPECIFIC_MULTICURVES .getMulticurveProvider() .getDiscountFactor(JBM5_DEFINITION.getCurrency(), CALL_JB_147.getExpirationTime()); final BlackFunctionData dataBlack = new BlackFunctionData(priceFutures, df, volatility); final double[] priceAD = BLACK_FUNCTION.getPriceAdjoint(option, dataBlack); final double deltaCallExpected = priceAD[1]; final double deltaCallComputed = METHOD_OPT.delta(CALL_JB_147, BLACK_EXP_STRIKE_BNDFUT); assertEquals( "BondFuturesOptionPremiumSecurityBlackBondFuturesMethod: delta", deltaCallExpected, deltaCallComputed, TOLERANCE_DELTA); final double deltaPutComputed = METHOD_OPT.delta(PUT_JB_147, BLACK_EXP_STRIKE_BNDFUT); assertEquals( "BondFuturesOptionPremiumSecurityBlackBondFuturesMethod: delta", deltaCallExpected - deltaPutComputed, df, TOLERANCE_DELTA); } public void gamma() { final double priceFutures = METHOD_FUTURE.price(CALL_JB_147.getUnderlyingFuture(), ISSUER_SPECIFIC_MULTICURVES); final EuropeanVanillaOption option = new EuropeanVanillaOption( STRIKE_147, CALL_JB_147.getExpirationTime(), CALL_JB_147.isCall()); final double expiry = CALL_JB_147.getExpirationTime(); final double volatility = BLACK_SURFACE_EXP_STRIKE.getZValue(expiry, STRIKE_147); double df = ISSUER_SPECIFIC_MULTICURVES .getMulticurveProvider() .getDiscountFactor(JBM5_DEFINITION.getCurrency(), CALL_JB_147.getExpirationTime()); final BlackFunctionData dataBlack = new BlackFunctionData(priceFutures, df, volatility); final double[] firstDerivs = new double[3]; final double[][] secondDerivs = new double[3][3]; BLACK_FUNCTION.getPriceAdjoint2(option, dataBlack, firstDerivs, secondDerivs); final double gammaCallExpected = secondDerivs[0][0]; final double gammaCallComputed = METHOD_OPT.gamma(CALL_JB_147, BLACK_EXP_STRIKE_BNDFUT); assertEquals( "BondFuturesOptionPremiumSecurityBlackBondFuturesMethod: gamma", gammaCallExpected, gammaCallComputed, TOLERANCE_DELTA); } public void theta() { double priceFutures = METHOD_FUTURE.price(CALL_JB_147.getUnderlyingFuture(), ISSUER_SPECIFIC_MULTICURVES); double expiry = CALL_JB_147.getExpirationTime(); double volatility = BLACK_SURFACE_EXP_STRIKE.getZValue(expiry, STRIKE_147); double rate = -Math.log( ISSUER_SPECIFIC_MULTICURVES .getMulticurveProvider() .getDiscountFactor(CALL_JB_147.getCurrency(), CALL_JB_147.getExpirationTime())) / CALL_JB_147.getExpirationTime(); double thetaCallExpected = BlackFormulaRepository.theta( priceFutures, STRIKE_147, CALL_JB_147.getExpirationTime(), volatility, CALL_JB_147.isCall(), rate); double thetaCallComputed = METHOD_OPT.theta(CALL_JB_147, BLACK_EXP_STRIKE_BNDFUT); assertEquals( "BondFuturesOptionMarginSecurityBlackFlatMethod: theta", thetaCallExpected, thetaCallComputed, TOLERANCE_DELTA); } }