// Test getDelta, getGamma and getVega public virtual void greeksTest() { double tol = 1.0e-12; double eps = 1.0e-5; EuropeanVanillaOption[] options = new EuropeanVanillaOption[] { ITM_CALL, ITM_PUT, OTM_CALL, OTM_PUT, ATM_CALL, ATM_PUT }; foreach (EuropeanVanillaOption option in options) { // consistency with getPriceFunction for first order derivatives ValueDerivatives price = FUNCTION.getPriceAdjoint(option, VOL_DATA); double delta = FUNCTION.getDelta(option, VOL_DATA); double vega = FUNCTION.getVega(option, VOL_DATA); assertEquals(price.getDerivative(0), delta, tol); assertEquals(price.getDerivative(1), vega, tol); // testing second order derivative against finite difference approximation NormalFunctionData dataUp = NormalFunctionData.of(F + eps, DF, SIGMA); NormalFunctionData dataDw = NormalFunctionData.of(F - eps, DF, SIGMA); double deltaUp = FUNCTION.getDelta(option, dataUp); double deltaDw = FUNCTION.getDelta(option, dataDw); double @ref = 0.5 * (deltaUp - deltaDw) / eps; double gamma = FUNCTION.getGamma(option, VOL_DATA); assertEquals(gamma, @ref, eps); EuropeanVanillaOption optionUp = EuropeanVanillaOption.of(option.Strike, T + eps, option.PutCall); EuropeanVanillaOption optionDw = EuropeanVanillaOption.of(option.Strike, T - eps, option.PutCall); double priceTimeUp = FUNCTION.getPriceFunction(optionUp).apply(VOL_DATA); double priceTimeDw = FUNCTION.getPriceFunction(optionDw).apply(VOL_DATA); @ref = -0.5 * (priceTimeUp - priceTimeDw) / eps; double theta = FUNCTION.getTheta(option, VOL_DATA); assertEquals(theta, @ref, eps); } }
public virtual void intrinsic_price() { NormalFunctionData data = NormalFunctionData.of(1.0, 1.0, 0.01); EuropeanVanillaOption option1 = EuropeanVanillaOption.of(0.5, 1.0, PutCall.CALL); assertThrowsIllegalArg(() => impliedVolatility(data, option1, 1e-6)); EuropeanVanillaOption option2 = EuropeanVanillaOption.of(1.5, 1.0, PutCall.PUT); assertThrowsIllegalArg(() => impliedVolatility(data, option2, 1e-6)); }
//----------------------------------------------------------------------- public override bool Equals(object obj) { if (obj == this) { return(true); } if (obj != null && obj.GetType() == this.GetType()) { NormalFunctionData other = (NormalFunctionData)obj; return(JodaBeanUtils.equal(forward, other.forward) && JodaBeanUtils.equal(numeraire, other.numeraire) && JodaBeanUtils.equal(normalVolatility, other.normalVolatility)); } return(false); }
static NormalFormulaRepositoryImpliedVolatilityTest() { PRICES = new double[N]; SIGMA = new double[N]; DATA = new NormalFunctionData[N]; for (int i = 0; i < N; i++) { STRIKES[i] = FORWARD + (-N / 2 + i) * 10; STRIKES_ATM[i] = FORWARD + (-0.5d * N + i) / 100.0d; SIGMA[i] = FORWARD * (0.05 + 4.0 * i / 100.0); SIGMA_BLACK[i] = 0.20 + i / 100.0d; DATA[i] = NormalFunctionData.of(FORWARD, DF, SIGMA[i]); OPTIONS[i] = EuropeanVanillaOption.of(STRIKES[i], T, PutCall.CALL); PRICES[i] = FUNCTION.getPriceFunction(OPTIONS[i]).apply(DATA[i]); } }
// Testing the branch for sigmaRootT < 1e-16 public virtual void smallParameterGreeksTest() { double eps = 1.0e-5; NormalFunctionData dataVolUp = NormalFunctionData.of(F, DF, eps); NormalFunctionData dataFwUp = NormalFunctionData.of(F + eps, DF, 0.0); NormalFunctionData dataFwDw = NormalFunctionData.of(F - eps, DF, 0.0); EuropeanVanillaOption[] options = new EuropeanVanillaOption[] { ITM_CALL, ITM_PUT, OTM_CALL, OTM_PUT, ATM_CALL, ATM_PUT }; foreach (EuropeanVanillaOption option in options) { double delta = FUNCTION.getDelta(option, ZERO_VOL_DATA); double priceUp = FUNCTION.getPriceFunction(option).apply(dataFwUp); double priceDw = FUNCTION.getPriceFunction(option).apply(dataFwDw); double refDelta = 0.5 * (priceUp - priceDw) / eps; assertEquals(delta, refDelta, eps); double vega = FUNCTION.getVega(option, ZERO_VOL_DATA); double priceVolUp = FUNCTION.getPriceFunction(option).apply(dataVolUp); double price = FUNCTION.getPriceFunction(option).apply(ZERO_VOL_DATA); double refVega = (priceVolUp - price) / eps; assertEquals(vega, refVega, eps); double gamma = FUNCTION.getGamma(option, ZERO_VOL_DATA); double deltaUp = FUNCTION.getDelta(option, dataFwUp); double deltaDw = FUNCTION.getDelta(option, dataFwDw); double refGamma = 0.5 * (deltaUp - deltaDw) / eps; if (Math.Abs(refGamma) > 0.1 / eps) { // infinity handled assertTrue(double.IsInfinity(gamma)); } else { assertEquals(gamma, refGamma, eps); } EuropeanVanillaOption optionUp = EuropeanVanillaOption.of(option.Strike, T + eps, option.PutCall); EuropeanVanillaOption optionDw = EuropeanVanillaOption.of(option.Strike, T - eps, option.PutCall); double priceTimeUp = FUNCTION.getPriceFunction(optionUp).apply(ZERO_VOL_DATA); double priceTimeDw = FUNCTION.getPriceFunction(optionDw).apply(ZERO_VOL_DATA); double refTheta = -0.5 * (priceTimeUp - priceTimeDw) / eps; double theta = FUNCTION.getTheta(option, ZERO_VOL_DATA); assertEquals(theta, refTheta, eps); } }
public virtual void testPriceAdjoint() { // Price double price = FUNCTION.getPriceFunction(ITM_CALL).apply(VOL_DATA); ValueDerivatives priceAdjoint = FUNCTION.getPriceAdjoint(ITM_CALL, VOL_DATA); assertEquals(priceAdjoint.Value, price, 1E-10); // Price with 0 volatility double price0 = FUNCTION.getPriceFunction(ITM_CALL).apply(ZERO_VOL_DATA); ValueDerivatives price0Adjoint = FUNCTION.getPriceAdjoint(ITM_CALL, ZERO_VOL_DATA); assertEquals(price0Adjoint.Value, price0, 1E-10); // Derivative forward. double deltaF = 0.01; NormalFunctionData dataFP = NormalFunctionData.of(F + deltaF, DF, SIGMA); NormalFunctionData dataFM = NormalFunctionData.of(F - deltaF, DF, SIGMA); double priceFP = FUNCTION.getPriceFunction(ITM_CALL).apply(dataFP); double priceFM = FUNCTION.getPriceFunction(ITM_CALL).apply(dataFM); double derivativeF_FD = (priceFP - priceFM) / (2 * deltaF); assertEquals(priceAdjoint.getDerivative(0), derivativeF_FD, 1E-7); // Derivative strike. double deltaK = 0.01; EuropeanVanillaOption optionKP = EuropeanVanillaOption.of(F - DELTA + deltaK, T, CALL); EuropeanVanillaOption optionKM = EuropeanVanillaOption.of(F - DELTA - deltaK, T, CALL); double priceKP = FUNCTION.getPriceFunction(optionKP).apply(VOL_DATA); double priceKM = FUNCTION.getPriceFunction(optionKM).apply(VOL_DATA); double derivativeK_FD = (priceKP - priceKM) / (2 * deltaK); assertEquals(priceAdjoint.getDerivative(2), derivativeK_FD, 1E-7); // Derivative volatility. double deltaV = 0.0001; NormalFunctionData dataVP = NormalFunctionData.of(F, DF, SIGMA + deltaV); NormalFunctionData dataVM = NormalFunctionData.of(F, DF, SIGMA - deltaV); double priceVP = FUNCTION.getPriceFunction(ITM_CALL).apply(dataVP); double priceVM = FUNCTION.getPriceFunction(ITM_CALL).apply(dataVM); double derivativeV_FD = (priceVP - priceVM) / (2 * deltaV); assertEquals(priceAdjoint.getDerivative(1), derivativeV_FD, 1E-6); }
/// <summary> /// Computes vega of an option in the normally distributed assets hypothesis (Bachelier model). /// </summary> /// <param name="option"> the option description </param> /// <param name="data"> the model data </param> /// <returns> vega </returns> public double getVega(EuropeanVanillaOption option, NormalFunctionData data) { ArgChecker.notNull(option, "option"); ArgChecker.notNull(data, "data"); return(data.Numeraire * NormalFormulaRepository.vega(data.Forward, option.Strike, option.TimeToExpiry, data.NormalVolatility, option.PutCall)); }
/// <summary> /// Computes the price of an option in the normally distributed assets hypothesis (Bachelier model). /// The first order price derivatives are also provided. /// </summary> /// <param name="option"> the option description </param> /// <param name="data"> the model data </param> /// <returns> a <seealso cref="ValueDerivatives"/> with the price in the value and the derivatives with /// respect to [0] the forward, [1] the volatility and [2] the strike </returns> public ValueDerivatives getPriceAdjoint(EuropeanVanillaOption option, NormalFunctionData data) { ArgChecker.notNull(option, "option"); ArgChecker.notNull(data, "data"); return(NormalFormulaRepository.priceAdjoint(data.Forward, option.Strike, option.TimeToExpiry, data.NormalVolatility, data.Numeraire, option.PutCall)); }
private double impliedVolatility(NormalFunctionData data, EuropeanVanillaOption option, double price) { return(NormalFormulaRepository.impliedVolatility(price, data.Forward, option.Strike, option.TimeToExpiry, data.NormalVolatility, data.Numeraire, option.PutCall)); }