BlackFormulaRepository { @ExternalFunction public static double price(final double forward, final double strike, final double timeToExpiry, final double lognormalVol, final boolean isCall) { ArgumentChecker.isTrue(forward >= 0.0, "negative/NaN forward; have {}", forward); ArgumentChecker.isTrue(strike >= 0.0, "negative/NaN strike; have {}", strike); ArgumentChecker.isTrue(timeToExpiry >= 0.0, "negative/NaN timeToExpiry; have {}", timeToExpiry); ArgumentChecker.isTrue(lognormalVol >= 0.0, "negative/NaN lognormalVol; have {}", lognormalVol); double sigmaRootT = lognormalVol * Math.sqrt(timeToExpiry); if (Double.isNaN(sigmaRootT)) { s_logger.info("lognormalVol * Math.sqrt(timeToExpiry) ambiguous"); sigmaRootT = 1.; } final int sign = isCall ? 1 : -1; final boolean bFwd = (forward > LARGE); final boolean bStr = (strike > LARGE); final boolean bSigRt = (sigmaRootT > LARGE); double d1 = 0.; double d2 = 0.; if (bFwd && bStr) { s_logger.info("(large value)/(large value) ambiguous"); return isCall ? (forward >= strike ? forward : 0.) : (strike >= forward ? strike : 0.); } if (sigmaRootT < SMALL) { return Math.max(sign * (forward - strike), 0.0); } if (Math.abs(forward - strike) < SMALL || bSigRt) { d1 = 0.5 * sigmaRootT; d2 = -0.5 * sigmaRootT; } else { d1 = Math.log(forward / strike) / sigmaRootT + 0.5 * sigmaRootT; d2 = d1 - sigmaRootT; } final double nF = NORMAL.getCDF(sign * d1); final double nS = NORMAL.getCDF(sign * d2); final double first = nF == 0. ? 0. : forward * nF; final double second = nS == 0. ? 0. : strike * nS; final double res = sign * (first - second); return Math.max(0., res); }  @ExternalFunction static double price(final double forward, final double strike, final double timeToExpiry,
      final double lognormalVol, final boolean isCall); static double price(final SimpleOptionData data, final double lognormalVol); static double price(final SimpleOptionData[] data, final double lognormalVol); @ExternalFunction static double delta(final double forward, final double strike, final double timeToExpiry,
      final double lognormalVol, final boolean isCall); static double strikeForDelta(final double forward, final double forwardDelta, final double timeToExpiry,
      final double lognormalVol, final boolean isCall); @ExternalFunction static double dualDelta(final double forward, final double strike, final double timeToExpiry,
      final double lognormalVol, final boolean isCall); @ExternalFunction static double simpleDelta(final double forward, final double strike, final double timeToExpiry,
      final double lognormalVol, final boolean isCall); @ExternalFunction static double gamma(final double forward, final double strike, final double timeToExpiry,
      final double lognormalVol); @ExternalFunction static double dualGamma(final double forward, final double strike, final double timeToExpiry,
      final double lognormalVol); @ExternalFunction static double crossGamma(final double forward, final double strike, final double timeToExpiry,
      final double lognormalVol); @ExternalFunction static double theta(final double forward, final double strike, final double timeToExpiry,
      final double lognormalVol, final boolean isCall, final double interestRate); @ExternalFunction static double thetaMod(final double forward, final double strike, final double timeToExpiry,
      final double lognormalVol, final boolean isCall, final double interestRate); @ExternalFunction static double driftlessTheta(final double forward, final double strike, final double timeToExpiry,
      final double lognormalVol); @ExternalFunction static double vega(final double forward, final double strike, final double timeToExpiry,
      final double lognormalVol); @ExternalFunction static double vega(final SimpleOptionData data, final double lognormalVol); @ExternalFunction static double vanna(final double forward, final double strike, final double timeToExpiry,
      final double lognormalVol); @ExternalFunction static double dualVanna(final double forward, final double strike, final double timeToExpiry,
      final double lognormalVol); @ExternalFunction static double vomma(final double forward, final double strike, final double timeToExpiry,
      final double lognormalVol); @ExternalFunction static double volga(final double forward, final double strike, final double timeToExpiry,
      final double lognormalVol); static double impliedVolatility(final double price, final double forward, final double strike,
      final double timeToExpiry, final boolean isCall); @ExternalFunction static double impliedVolatility(final double otmPrice, final double forward, final double strike,
      final double timeToExpiry, final double volGuess); static double impliedVolatility(final SimpleOptionData data, final double price); static double impliedVolatility(final SimpleOptionData[] data, final double price); @ExternalFunction static double impliedStrike(final double delta, final boolean isCall, final double forward, final double time,
      final double volatility); static double impliedStrike(final double delta, final boolean isCall, final double forward, final double time,
      final double volatility, final double[] derivatives);  }
@Test public void zeroVolTest() { final boolean isCall = true; final int n = STRIKES_INPUT.length; for (int i = 0; i < n; i++) { final double intrinic = Math.max(0, FORWARD - STRIKES_INPUT[i]); final double price = BlackFormulaRepository.price(FORWARD, STRIKES_INPUT[i], TIME_TO_EXPIRY, 0.0, isCall); assertEquals(intrinic, price, 1e-15); } }
@Test public void zeroExpiryTest() { final boolean isCall = false; final int n = STRIKES_INPUT.length; for (int i = 0; i < n; i++) { final double intrinic = Math.max(0, STRIKES_INPUT[i] - FORWARD); final double price = BlackFormulaRepository.price(FORWARD, STRIKES_INPUT[i], 0.0, 0.3, isCall); assertEquals(intrinic, price, 1e-15); } }
@Test public void tinyVolTest() { final double vol = 1e-4; final boolean isCall = true; final int n = STRIKES_INPUT.length; for (int i = 0; i < n; i++) { final double intrinic = Math.max(0, FORWARD - STRIKES_INPUT[i]); final double price = BlackFormulaRepository.price(FORWARD, STRIKES_INPUT[i], TIME_TO_EXPIRY, vol, isCall); assertEquals(intrinic, price, 1e-15); } }
@Test public void shortExpiryTest() { final double t = 1e-5; final double vol = 0.4; final boolean isCall = false; final int n = STRIKES_INPUT.length; for (int i = 0; i < n; i++) { final double intrinic = Math.max(0, STRIKES_INPUT[i] - FORWARD); final double price = BlackFormulaRepository.price(FORWARD, STRIKES_INPUT[i], t, vol, isCall); assertEquals(intrinic, price, 1e-15); } }
@Test public void massiveVolTest() { final double vol = 8.0; final boolean isCall = true; final int n = STRIKES_INPUT.length; for (int i = 0; i < n; i++) { final double price = BlackFormulaRepository.price(FORWARD, STRIKES_INPUT[i], TIME_TO_EXPIRY, vol, isCall); assertEquals(FORWARD, price, 1e-15); } }
@Test public void zeroStikeTest() { final boolean isCall = true; final int n = VOLS.length; for (int i = 0; i < n; i++) { final double price = BlackFormulaRepository.price(FORWARD, 0.0, TIME_TO_EXPIRY, VOLS[i], isCall); assertEquals(FORWARD, price, 1e-15); } }
@Test public void putCallParityTest() { final int n = VOLS.length; final int m = STRIKES_INPUT.length; for (int i = 0; i < m; i++) { final double fk = FORWARD - STRIKES_INPUT[i]; for (int j = 0; j < n; j++) { final double call = BlackFormulaRepository.price(FORWARD, STRIKES_INPUT[i], TIME_TO_EXPIRY, VOLS[j], true); final double put = BlackFormulaRepository.price(FORWARD, STRIKES_INPUT[i], TIME_TO_EXPIRY, VOLS[j], false); assertEquals(fk, call - put, 1e-13); } } }
@Test public void nonEdgeCaseTest() { final boolean print = false; if (print) { System.out.println("BlackFormulaRepositotyTest"); } final boolean isCall = true; final int n = VOLS.length; final int m = STRIKES_INPUT.length; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { final double price = BlackFormulaRepository.price(FORWARD, STRIKES_INPUT[i], TIME_TO_EXPIRY, VOLS[j], isCall); assertEquals(PRE_COMPUTER_PRICES[i][j], price, 1e-13 * price); if (print) { if (j == 0) { System.out.print(price); } else { System.out.print(", " + price); } } } if (print) { System.out.print("\n"); } } }
@Test public void exPriceTest() { final int nStrikes = STRIKES_INPUT.length; final int nVols = VOLS.length; final double inf = Double.POSITIVE_INFINITY; for (int i = 0; i < nStrikes; ++i) { for (int j = 0; j < nVols; ++j) { final double strike = STRIKES_INPUT[i]; final double vol = VOLS[j]; final double resC1 = BlackFormulaRepository.price(1.e-12 * strike, strike, TIME_TO_EXPIRY, vol, true); final double refC1 = BlackFormulaRepository.price(0., strike, TIME_TO_EXPIRY, vol, true); final double resC2 = BlackFormulaRepository.price(1.e12 * strike, strike, TIME_TO_EXPIRY, vol, true); final double refC2 = BlackFormulaRepository.price(inf, strike, TIME_TO_EXPIRY, vol, true); final double resP1 = BlackFormulaRepository.price(1.e-12 * strike, strike, TIME_TO_EXPIRY, vol, false); final double refP1 = BlackFormulaRepository.price(0., strike, TIME_TO_EXPIRY, vol, false); final double resP2 = BlackFormulaRepository.price(1.e12 * strike, strike, TIME_TO_EXPIRY, vol, false); final double refP2 = BlackFormulaRepository.price(inf, strike, TIME_TO_EXPIRY, vol, false); assertEquals(0., resC1, EPS); assertEquals(1.e12 * strike - strike, resC2, EPS * 1.e12 * strike); assertEquals(strike - 1.e-12 * strike, resP1, EPS * strike); assertEquals(0., resP2, EPS * strike); final double[] resVec = new double[] {resC1, resP1, resC2, resP2 }; final double[] refVec = new double[] {refC1, refP1, refC2, refP2 }; for (int k = 0; k < 4; ++k) { if (refVec[k] > 1.e10) { assertTrue(resVec[k] > 1.e12); } else { if (refVec[k] < -1.e10) { assertTrue(resVec[k] < -1.e12); } else { if (refVec[k] == 0.) { assertTrue(Math.abs(resVec[k]) < 1.e-11); } else { assertEquals(refVec[k], resVec[k], Math.abs(refVec[k]) * 1.e-11); } } } } } } for (int i = 0; i < nStrikes; ++i) { for (int j = 0; j < nVols; ++j) { final double forward = STRIKES_INPUT[i]; final double vol = VOLS[j]; final double resC1 = BlackFormulaRepository.price(forward, 1.e-12 * forward, TIME_TO_EXPIRY, vol, true); final double resC2 = BlackFormulaRepository.price(forward, 1.e12 * forward, TIME_TO_EXPIRY, vol, true); final double resP1 = BlackFormulaRepository.price(forward, 1.e-12 * forward, TIME_TO_EXPIRY, vol, false); final double resP2 = BlackFormulaRepository.price(forward, 1.e12 * forward, TIME_TO_EXPIRY, vol, false); final double refC1 = BlackFormulaRepository.price(forward, 0., TIME_TO_EXPIRY, vol, true); final double refC2 = BlackFormulaRepository.price(forward, inf, TIME_TO_EXPIRY, vol, true); final double refP1 = BlackFormulaRepository.price(forward, 0., TIME_TO_EXPIRY, vol, false); final double refP2 = BlackFormulaRepository.price(forward, inf, TIME_TO_EXPIRY, vol, false); assertEquals(forward, resC1, forward * EPS); assertEquals(0., resC2, EPS); assertEquals(1.e12 * forward, resP2, 1.e12 * forward * EPS); assertEquals(0., resP1, EPS); final double[] resVec = new double[] {resC1, resP1, resC2, resP2 }; final double[] refVec = new double[] {refC1, refP1, refC2, refP2 }; for (int k = 0; k < 4; ++k) { if (refVec[k] > 1.e10) { assertTrue(resVec[k] > 1.e12); } else { if (refVec[k] < -1.e10) { assertTrue(resVec[k] < -1.e12); } else { if (refVec[k] == 0.) { assertTrue(Math.abs(resVec[k]) < 1.e-12); } else { assertEquals(refVec[k], resVec[k], Math.abs(refVec[k]) * 1.e-10); } } } } } } for (int i = 0; i < nStrikes; ++i) { for (int j = 0; j < nVols; ++j) { final double strike = STRIKES_INPUT[i]; final double vol = VOLS[j]; final double resC1 = BlackFormulaRepository.price(FORWARD, strike, 1e-24, vol, true); final double resC2 = BlackFormulaRepository.price(FORWARD, strike, 1e24, vol, true); final double resP1 = BlackFormulaRepository.price(FORWARD, strike, 1e-24, vol, false); final double resP2 = BlackFormulaRepository.price(FORWARD, strike, 1e24, vol, false); final double refC1 = BlackFormulaRepository.price(FORWARD, strike, 0., vol, true); final double refC2 = BlackFormulaRepository.price(FORWARD, strike, inf, vol, true); final double refP1 = BlackFormulaRepository.price(FORWARD, strike, 0., vol, false); final double refP2 = BlackFormulaRepository.price(FORWARD, strike, inf, vol, false); assertEquals(FORWARD > strike ? FORWARD - strike : 0., resC1, EPS); assertEquals(FORWARD, resC2, FORWARD * EPS); assertEquals(strike, resP2, strike * EPS); assertEquals(FORWARD > strike ? 0. : -FORWARD + strike, resP1, EPS); final double[] resVec = new double[] {resC1, resP1, resC2, resP2 }; final double[] refVec = new double[] {refC1, refP1, refC2, refP2 }; for (int k = 0; k < 4; ++k) { if (refVec[k] > 1.e10) { assertTrue(resVec[k] > 1.e12); } else { if (refVec[k] < -1.e10) { assertTrue(resVec[k] < -1.e12); } else { if (refVec[k] == 0.) { assertTrue(Math.abs(resVec[k]) < 1.e-12); } else { assertEquals(refVec[k], resVec[k], Math.abs(refVec[k]) * 1.e-12); } } } } } } for (int i = 0; i < nStrikes; ++i) { final double strike = STRIKES_INPUT[i]; final double resC1 = BlackFormulaRepository.price(FORWARD, strike, TIME_TO_EXPIRY, 1.e-12, true); final double refC1 = BlackFormulaRepository.price(FORWARD, strike, TIME_TO_EXPIRY, 0., true); final double resC2 = BlackFormulaRepository.price(FORWARD, strike, TIME_TO_EXPIRY, 1.e12, true); final double refC2 = BlackFormulaRepository.price(FORWARD, strike, TIME_TO_EXPIRY, inf, true); final double resP1 = BlackFormulaRepository.price(FORWARD, strike, TIME_TO_EXPIRY, 1.e-12, false); final double refP1 = BlackFormulaRepository.price(FORWARD, strike, TIME_TO_EXPIRY, 0., false); final double resP2 = BlackFormulaRepository.price(FORWARD, strike, TIME_TO_EXPIRY, 1.e12, false); final double refP2 = BlackFormulaRepository.price(FORWARD, strike, TIME_TO_EXPIRY, inf, false); final double[] resVec = new double[] {resC1, resP1, resC2, resP2 }; final double[] refVec = new double[] {refC1, refP1, refC2, refP2 }; for (int k = 0; k < 4; ++k) { if (refVec[k] > 1.e10) { assertTrue(resVec[k] > 1.e12); } else { if (refVec[k] < -1.e10) { assertTrue(resVec[k] < -1.e12); } else { if (refVec[k] == 0.) { assertTrue(Math.abs(resVec[k]) < 1.e-12); } else { assertEquals(refVec[k], resVec[k], Math.abs(refVec[k]) * 1.e-12); } } } } } for (int j = 0; j < nVols; ++j) { final double vol = VOLS[j]; final double resC1 = BlackFormulaRepository.price(1.e-12, 1.e-12, TIME_TO_EXPIRY, vol, true); final double resC2 = BlackFormulaRepository.price(1.e-12, 1.e12, TIME_TO_EXPIRY, vol, true); final double resC3 = BlackFormulaRepository.price(1.e12, 1.e-12, TIME_TO_EXPIRY, vol, true); final double resP1 = BlackFormulaRepository.price(1.e-12, 1.e-12, TIME_TO_EXPIRY, vol, false); final double resP2 = BlackFormulaRepository.price(1.e-12, 1.e12, TIME_TO_EXPIRY, vol, false); final double resP3 = BlackFormulaRepository.price(1.e12, 1.e-12, TIME_TO_EXPIRY, vol, false); final double resC4 = BlackFormulaRepository.price(1.e12, 1.e12, TIME_TO_EXPIRY, vol, true); final double resP4 = BlackFormulaRepository.price(1.e12, 1.e12, TIME_TO_EXPIRY, vol, false); final double refC1 = BlackFormulaRepository.price(0., 0., TIME_TO_EXPIRY, vol, true); final double refC2 = BlackFormulaRepository.price(0., inf, TIME_TO_EXPIRY, vol, true); final double refC3 = BlackFormulaRepository.price(inf, 0., TIME_TO_EXPIRY, vol, true); final double refP1 = BlackFormulaRepository.price(0., 0., TIME_TO_EXPIRY, vol, false); final double refP2 = BlackFormulaRepository.price(0., inf, TIME_TO_EXPIRY, vol, false); final double refP3 = BlackFormulaRepository.price(inf, 0., TIME_TO_EXPIRY, vol, false); final double refC4 = BlackFormulaRepository.price(inf, inf, TIME_TO_EXPIRY, vol, true); final double refP4 = BlackFormulaRepository.price(inf, inf, TIME_TO_EXPIRY, vol, false); final double[] resVec = new double[] {resC1, resP1, resC2, resP2, resC3, resP3, resC4, resP4 }; final double[] refVec = new double[] {refC1, refP1, refC2, refP2, refC3, refP3, refC4, refP4 }; for (int k = 0; k < 8; ++k) { if (refVec[k] > 1.e10) { assertTrue(resVec[k] > 1.e10); } else { if (refVec[k] < -1.e10) { assertTrue(resVec[k] < -1.e10); } else { if (refVec[k] == 0.) { assertTrue(Math.abs(resVec[k]) < 1.e-10); } else { assertEquals(refVec[k], resVec[k], Math.abs(refVec[k]) * 1.e-10); } } } } } for (int i = 0; i < nStrikes; ++i) { for (int j = 0; j < nVols; ++j) { final double strike = STRIKES_INPUT[i]; final double vol = VOLS[j]; final double resC1 = BlackFormulaRepository.price(1.e-12, strike, 1.e-12, vol, true); final double resC2 = BlackFormulaRepository.price(1.e-12, strike, 1.e12, vol, true); final double resC3 = BlackFormulaRepository.price(1.e12, strike, 1.e-12, vol, true); final double resP1 = BlackFormulaRepository.price(1.e-12, strike, 1.e-12, vol, false); final double resP2 = BlackFormulaRepository.price(1.e-12, strike, 1.e12, vol, false); final double resP3 = BlackFormulaRepository.price(1.e12, strike, 1.e-12, vol, false); final double resC4 = BlackFormulaRepository.price(1.e12, strike, 1.e24, vol, true); final double resP4 = BlackFormulaRepository.price(1.e12, strike, 1.e24, vol, false); final double refC1 = BlackFormulaRepository.price(0., strike, 0., vol, true); final double refC2 = BlackFormulaRepository.price(0., strike, inf, vol, true); final double refC3 = BlackFormulaRepository.price(inf, strike, 0., vol, true); final double refP1 = BlackFormulaRepository.price(0., strike, 0., vol, false); final double refP2 = BlackFormulaRepository.price(0., strike, inf, vol, false); final double refP3 = BlackFormulaRepository.price(inf, strike, 0., vol, false); final double refC4 = BlackFormulaRepository.price(inf, strike, inf, vol, true); final double refP4 = BlackFormulaRepository.price(inf, strike, inf, vol, false); final double[] resVec = new double[] {resC1, resP1, resC2, resP2, resC3, resP3, resC4, resP4 }; final double[] refVec = new double[] {refC1, refP1, refC2, refP2, refC3, refP3, refC4, refP4 }; for (int k = 0; k < 8; ++k) { if (refVec[k] > 1.e10) { assertTrue(resVec[k] > 1.e10); } else { if (refVec[k] < -1.e10) { assertTrue(resVec[k] < -1.e10); } else { if (refVec[k] == 0.) { assertTrue(Math.abs(resVec[k]) < 1.e-10); } else { assertEquals(refVec[k], resVec[k], Math.abs(refVec[k]) * 1.e-10); } } } } } } for (int i = 0; i < nStrikes; ++i) { final double strike = STRIKES_INPUT[i]; final double resC1 = BlackFormulaRepository.price(1.e-12, strike, TIME_TO_EXPIRY, 1.e-12, true); final double resC2 = BlackFormulaRepository.price(1.e-12, strike, TIME_TO_EXPIRY, 1.e12, true); final double resC3 = BlackFormulaRepository.price(1.e12, strike, TIME_TO_EXPIRY, 1.e-12, true); final double resP1 = BlackFormulaRepository.price(1.e-12, strike, TIME_TO_EXPIRY, 1.e-12, false); final double resP2 = BlackFormulaRepository.price(1.e-12, strike, TIME_TO_EXPIRY, 1.e12, false); final double resP3 = BlackFormulaRepository.price(1.e12, strike, TIME_TO_EXPIRY, 1.e-12, false); final double resC4 = BlackFormulaRepository.price(1.e12, strike, TIME_TO_EXPIRY, 1.e12, true); final double resP4 = BlackFormulaRepository.price(1.e12, strike, TIME_TO_EXPIRY, 1.e12, false); final double refC1 = BlackFormulaRepository.price(0., strike, TIME_TO_EXPIRY, 0., true); final double refC2 = BlackFormulaRepository.price(0., strike, TIME_TO_EXPIRY, inf, true); final double refC3 = BlackFormulaRepository.price(inf, strike, TIME_TO_EXPIRY, 0., true); final double refP1 = BlackFormulaRepository.price(0., strike, TIME_TO_EXPIRY, 0., false); final double refP2 = BlackFormulaRepository.price(0., strike, TIME_TO_EXPIRY, inf, false); final double refP3 = BlackFormulaRepository.price(inf, strike, TIME_TO_EXPIRY, 0., false); final double refC4 = BlackFormulaRepository.price(inf, strike, TIME_TO_EXPIRY, inf, true); final double refP4 = BlackFormulaRepository.price(inf, strike, TIME_TO_EXPIRY, inf, false); final double[] resVec = new double[] {resC1, resP1, resC2, resP2, resC3, resP3, resC4, resP4 }; final double[] refVec = new double[] {refC1, refP1, refC2, refP2, refC3, refP3, refC4, refP4 }; for (int k = 0; k < 8; ++k) { if (refVec[k] > 1.e10) { assertTrue(resVec[k] > 1.e10); } else { if (refVec[k] < -1.e10) { assertTrue(resVec[k] < -1.e10); } else { if (refVec[k] == 0.) { assertTrue(Math.abs(resVec[k]) < 1.e-10); } else { assertEquals(refVec[k], resVec[k], Math.abs(refVec[k]) * 1.e-10); } } } } } for (int i = 0; i < nStrikes; ++i) { for (int j = 0; j < nVols; ++j) { final double forward = STRIKES_INPUT[i]; final double vol = VOLS[j]; final double resC1 = BlackFormulaRepository.price(forward, 1.e-12, 1.e-12, vol, true); final double resC2 = BlackFormulaRepository.price(forward, 1.e-12, 1.e12, vol, true); final double resC3 = BlackFormulaRepository.price(forward, 1.e12, 1.e-12, vol, true); final double resP1 = BlackFormulaRepository.price(forward, 1.e-12, 1.e-12, vol, false); final double resP2 = BlackFormulaRepository.price(forward, 1.e-12, 1.e12, vol, false); final double resP3 = BlackFormulaRepository.price(forward, 1.e12, 1.e-12, vol, false); final double resC4 = BlackFormulaRepository.price(forward, 1.e12, 1.e24, vol, true); final double resP4 = BlackFormulaRepository.price(forward, 1.e12, 1.e24, vol, false); final double refC1 = BlackFormulaRepository.price(forward, 0., 0., vol, true); final double refC2 = BlackFormulaRepository.price(forward, 0., inf, vol, true); final double refC3 = BlackFormulaRepository.price(forward, inf, 0., vol, true); final double refP1 = BlackFormulaRepository.price(forward, 0., 0., vol, false); final double refP2 = BlackFormulaRepository.price(forward, 0., inf, vol, false); final double refP3 = BlackFormulaRepository.price(forward, inf, 0., vol, false); final double refC4 = BlackFormulaRepository.price(forward, inf, inf, vol, true); final double refP4 = BlackFormulaRepository.price(forward, inf, inf, vol, false); final double[] resVec = new double[] {resC1, resP1, resC2, resP2, resC3, resP3, resC4, resP4 }; final double[] refVec = new double[] {refC1, refP1, refC2, refP2, refC3, refP3, refC4, refP4 }; for (int k = 0; k < 8; ++k) { if (refVec[k] > 1.e10) { assertTrue(resVec[k] > 1.e10); } else { if (refVec[k] < -1.e10) { assertTrue(resVec[k] < -1.e10); } else { if (refVec[k] == 0.) { assertTrue(Math.abs(resVec[k]) < 1.e-10); } else { assertEquals(refVec[k], resVec[k], Math.abs(refVec[k]) * 1.e-10); } } } } } } for (int i = 0; i < nStrikes; ++i) { final double forward = STRIKES_INPUT[i]; final double resC1 = BlackFormulaRepository.price(forward, 1.e-12, TIME_TO_EXPIRY, 1.e-12, true); final double resC2 = BlackFormulaRepository.price(forward, 1.e-12, TIME_TO_EXPIRY, 1.e12, true); final double resC3 = BlackFormulaRepository.price(forward, 1.e12, TIME_TO_EXPIRY, 1.e-12, true); final double resP1 = BlackFormulaRepository.price(forward, 1.e-12, TIME_TO_EXPIRY, 1.e-12, false); final double resP2 = BlackFormulaRepository.price(forward, 1.e-12, TIME_TO_EXPIRY, 1.e12, false); final double resP3 = BlackFormulaRepository.price(forward, 1.e12, TIME_TO_EXPIRY, 1.e-12, false); final double resC4 = BlackFormulaRepository.price(forward, 1.e12, TIME_TO_EXPIRY, 1.e12, true); final double resP4 = BlackFormulaRepository.price(forward, 1.e12, TIME_TO_EXPIRY, 1.e12, false); final double refC1 = BlackFormulaRepository.price(forward, 0., TIME_TO_EXPIRY, 0., true); final double refC2 = BlackFormulaRepository.price(forward, 0., TIME_TO_EXPIRY, inf, true); final double refC3 = BlackFormulaRepository.price(forward, inf, TIME_TO_EXPIRY, 0., true); final double refP1 = BlackFormulaRepository.price(forward, 0., TIME_TO_EXPIRY, 0., false); final double refP2 = BlackFormulaRepository.price(forward, 0., TIME_TO_EXPIRY, inf, false); final double refP3 = BlackFormulaRepository.price(forward, inf, TIME_TO_EXPIRY, 0., false); final double refC4 = BlackFormulaRepository.price(forward, inf, TIME_TO_EXPIRY, inf, true); final double refP4 = BlackFormulaRepository.price(forward, inf, TIME_TO_EXPIRY, inf, false); final double[] resVec = new double[] {resC1, resP1, resC2, resP2, resC3, resP3, resC4, resP4 }; final double[] refVec = new double[] {refC1, refP1, refC2, refP2, refC3, refP3, refC4, refP4 }; for (int k = 0; k < 8; ++k) { if (refVec[k] > 1.e10) { assertTrue(resVec[k] > 1.e10); } else { if (refVec[k] < -1.e10) { assertTrue(resVec[k] < -1.e10); } else { if (refVec[k] == 0.) { assertTrue(Math.abs(resVec[k]) < 1.e-10); } else { assertEquals(refVec[k], resVec[k], Math.abs(refVec[k]) * 1.e-10); } } } } } for (int j = 0; j < nVols; ++j) { final double vol = VOLS[j]; final double resC1 = BlackFormulaRepository.price(1.e-12, 1.e-12, 1.e-24, vol, true); final double resC2 = BlackFormulaRepository.price(1.e-12, 1.e-12, 1.e24, vol, true); final double resC3 = BlackFormulaRepository.price(1.e-12, 1.e12, 1.e-24, vol, true); final double resP1 = BlackFormulaRepository.price(1.e-12, 1.e-12, 1.e-24, vol, false); final double resP2 = BlackFormulaRepository.price(1.e-12, 1.e-12, 1.e24, vol, false); final double resP3 = BlackFormulaRepository.price(1.e-12, 1.e12, 1.e-24, vol, false); final double resC4 = BlackFormulaRepository.price(1.e12, 1.e-12, 1.e-24, vol, true); final double resP4 = BlackFormulaRepository.price(1.e12, 1.e-12, 1.e-24, vol, false); final double resC5 = BlackFormulaRepository.price(FORWARD, FORWARD * (1. + 1.e-12), 1.e-24, vol, true); final double resP5 = BlackFormulaRepository.price(FORWARD, FORWARD * (1. + 1.e-12), 1.e-24, vol, false); final double resC6 = BlackFormulaRepository.price(1.e12, 1.e12, 1.e24, vol, true); final double resP6 = BlackFormulaRepository.price(1.e12, 1.e12, 1.e24, vol, false); final double refC1 = BlackFormulaRepository.price(0., 0., 0., vol, true); final double refC2 = BlackFormulaRepository.price(0., 0., inf, vol, true); final double refC3 = BlackFormulaRepository.price(0., inf, 0., vol, true); final double refP1 = BlackFormulaRepository.price(0., 0., 0., vol, false); final double refP2 = BlackFormulaRepository.price(0., 0., inf, vol, false); final double refP3 = BlackFormulaRepository.price(0., inf, 0., vol, false); final double refC4 = BlackFormulaRepository.price(inf, 0., 0., vol, true); final double refP4 = BlackFormulaRepository.price(inf, 0., 0., vol, false); final double refC5 = BlackFormulaRepository.price(FORWARD, FORWARD, 0., vol, true); final double refP5 = BlackFormulaRepository.price(FORWARD, FORWARD, 0., vol, false); final double refC6 = BlackFormulaRepository.price(inf, inf, inf, vol, true); final double refP6 = BlackFormulaRepository.price(inf, inf, inf, vol, false); final double[] resVec = new double[] {resC1, resP1, resC2, resP2, resC3, resP3, resC4, resP4, resC5, resP5, resC6, resP6 }; final double[] refVec = new double[] {refC1, refP1, refC2, refP2, refC3, refP3, refC4, refP4, refC5, refP5, refC6, refP6 }; for (int k = 0; k < 12; ++k) { if (refVec[k] > 1.e10) { assertTrue(resVec[k] > 1.e10); } else { if (refVec[k] < -1.e10) { assertTrue(resVec[k] < -1.e10); } else { if (refVec[k] == 0.) { assertTrue(Math.abs(resVec[k]) < 1.e-9); } else { assertEquals(refVec[k], resVec[k], Math.abs(refVec[k]) * 1.e-10); } } } } } { final double resC1 = BlackFormulaRepository.price(1.e-12, 1.e-12, TIME_TO_EXPIRY, 1.e-12, true); final double resC2 = BlackFormulaRepository.price(1.e-12, 1.e-12, TIME_TO_EXPIRY, 1.e12, true); final double resC3 = BlackFormulaRepository.price(1.e-12, 1.e12, TIME_TO_EXPIRY, 1.e-12, true); final double resP1 = BlackFormulaRepository.price(1.e-12, 1.e-12, TIME_TO_EXPIRY, 1.e-12, false); final double resP2 = BlackFormulaRepository.price(1.e-12, 1.e-12, TIME_TO_EXPIRY, 1.e12, false); final double resP3 = BlackFormulaRepository.price(1.e-12, 1.e12, TIME_TO_EXPIRY, 1.e-12, false); final double resC4 = BlackFormulaRepository.price(1.e12, 1.e-12, TIME_TO_EXPIRY, 1.e-12, true); final double resP4 = BlackFormulaRepository.price(1.e12, 1.e-12, TIME_TO_EXPIRY, 1.e-12, false); final double resC5 = BlackFormulaRepository.price(FORWARD, FORWARD * (1. + 1.e-12), TIME_TO_EXPIRY, 1.e-12, true); final double resP5 = BlackFormulaRepository .price(FORWARD, FORWARD * (1. + 1.e-12), TIME_TO_EXPIRY, 1.e-12, false); final double refC1 = BlackFormulaRepository.price(0., 0., TIME_TO_EXPIRY, 0., true); final double refC2 = BlackFormulaRepository.price(0., 0., TIME_TO_EXPIRY, inf, true); final double refC3 = BlackFormulaRepository.price(0., inf, TIME_TO_EXPIRY, 0., true); final double refP1 = BlackFormulaRepository.price(0., 0., TIME_TO_EXPIRY, 0., false); final double refP2 = BlackFormulaRepository.price(0., 0., TIME_TO_EXPIRY, inf, false); final double refP3 = BlackFormulaRepository.price(0., inf, TIME_TO_EXPIRY, 0., false); final double refC4 = BlackFormulaRepository.price(inf, 0., TIME_TO_EXPIRY, 0., true); final double refP4 = BlackFormulaRepository.price(inf, 0., TIME_TO_EXPIRY, 0., false); final double refC5 = BlackFormulaRepository.price(FORWARD, FORWARD, TIME_TO_EXPIRY, 1.e-12, true); final double refP5 = BlackFormulaRepository.price(FORWARD, FORWARD, TIME_TO_EXPIRY, 1.e-12, false); final double[] resVec = new double[] {resC1, resP1, resC2, resP2, resC3, resP3, resC4, resP4, resC5, resP5 }; final double[] refVec = new double[] {refC1, refP1, refC2, refP2, refC3, refP3, refC4, refP4, refC5, refP5 }; for (int k = 0; k < 10; ++k) { if (refVec[k] > 1.e10) { assertTrue(resVec[k] > 1.e10); } else { if (refVec[k] < -1.e10) { assertTrue(resVec[k] < -1.e10); } else { if (refVec[k] == 0.) { assertTrue(Math.abs(resVec[k]) < 1.e-10); } else { assertEquals(refVec[k], resVec[k], Math.max(Math.abs(refVec[k]) * 1.e-10, 1.e-10)); } } } } } for (int i = 0; i < nStrikes; ++i) { final double strike = STRIKES_INPUT[i]; final double resC1 = BlackFormulaRepository.price(strike, strike, inf, 0., true); final double resP1 = BlackFormulaRepository.price(strike, strike, inf, 0., false); final double refC1 = strike * NORMAL.getCDF(0.5) - strike * NORMAL.getCDF(-0.5); final double refP1 = -strike * NORMAL.getCDF(-0.5) + strike * NORMAL.getCDF(0.5); final double[] resVec = new double[] {resC1, resP1 }; final double[] refVec = new double[] {refC1, refP1 }; for (int k = 0; k < 2; ++k) { if (refVec[k] > 1.e10) { assertTrue(resVec[k] > 1.e10); } else { if (refVec[k] < -1.e10) { assertTrue(resVec[k] < -1.e10); } else { if (refVec[k] == 0.) { assertTrue(Math.abs(resVec[k]) < 1.e-10); } else { assertEquals(refVec[k], resVec[k], Math.max(Math.abs(refVec[k]) * 1.e-10, 1.e-10)); } } } } } }
@Test(expectedExceptions = IllegalArgumentException.class) public void negativeVolErrorPriceTest() { BlackFormulaRepository.price(FORWARD, STRIKES_INPUT[1], TIME_TO_EXPIRY, -0.5, true); }
@Test(expectedExceptions = IllegalArgumentException.class) public void negativeFwdErrorPriceTest() { BlackFormulaRepository.price(-FORWARD, STRIKES_INPUT[1], TIME_TO_EXPIRY, VOLS[1], true); }
@Test(expectedExceptions = IllegalArgumentException.class) public void negativeStrikeErrorPriceTest() { BlackFormulaRepository.price(FORWARD, -STRIKES_INPUT[1], TIME_TO_EXPIRY, VOLS[1], true); }
@Test(expectedExceptions = IllegalArgumentException.class) public void negativeTimeErrorPriceTest() { BlackFormulaRepository.price(FORWARD, STRIKES_INPUT[1], -TIME_TO_EXPIRY, VOLS[1], true); }
@Test public void useSimpleOptionDataTest() { final int nStrikes = STRIKES_INPUT.length; final int nVols = VOLS.length; for (int i = 0; i < nStrikes; ++i) { for (int j = 0; j < nVols; ++j) { final double strike = STRIKES_INPUT[i]; final double vol = VOLS[j]; final SimpleOptionData dataC = new SimpleOptionData(FORWARD, strike, TIME_TO_EXPIRY, 1., true); final SimpleOptionData dataP = new SimpleOptionData(FORWARD, strike, TIME_TO_EXPIRY, 1., false); final SimpleOptionData[] dataV = new SimpleOptionData[] { new SimpleOptionData(FORWARD, strike, TIME_TO_EXPIRY, 1., true), new SimpleOptionData(FORWARD, strike, TIME_TO_EXPIRY, 1., true) }; final double resC1 = BlackFormulaRepository.price(FORWARD, strike, TIME_TO_EXPIRY, vol, true); final double resC2 = BlackFormulaRepository.price(dataC, vol); final double resC3 = BlackFormulaRepository.price(dataV, vol); final double resP1 = BlackFormulaRepository.price(FORWARD, strike, TIME_TO_EXPIRY, vol, false); final double resP2 = BlackFormulaRepository.price(dataP, vol); assertEquals(resC1, resC2, EPS); assertEquals(2. * resC1, resC3, EPS); assertEquals(resP1, resP2, EPS); } } }
@Test(expectedExceptions = IllegalArgumentException.class) public void nullSimpleOptionDataTest() { SimpleOptionData data = new SimpleOptionData(FORWARD, STRIKES_INPUT[1], TIME_TO_EXPIRY, 1., true); data = null; BlackFormulaRepository.price(data, VOLS[1]); }
@Test(expectedExceptions = IllegalArgumentException.class) public void nullSimpleOptionDataArrayTest() { SimpleOptionData[] data = new SimpleOptionData[] { new SimpleOptionData(FORWARD, STRIKES_INPUT[1], TIME_TO_EXPIRY, 1., true), new SimpleOptionData(FORWARD, STRIKES_INPUT[0], TIME_TO_EXPIRY, 1., true) }; data = null; BlackFormulaRepository.price(data, VOLS[0]); }
@Test(enabled = false) public void sample2Test() { final double inf = Double.POSITIVE_INFINITY; final double resC0 = BlackFormulaRepository.price(inf, FORWARD, 0.01, VOLS[2], true); final double resC00 = BlackFormulaRepository.price(1.e14, FORWARD, 0.01, VOLS[2], true); System.out.println(resC0 + "\t" + resC00); System.out.println("\n"); final double resP0 = BlackFormulaRepository.price(inf, FORWARD, 0.01, VOLS[2], false); final double resP00 = BlackFormulaRepository.price(1.e12, FORWARD, 0.01, VOLS[2], false); System.out.println(resP0 + "\t" + resP00); System.out.println("\n"); final double resC1 = BlackFormulaRepository.price(FORWARD * 0.9, inf, 0.001, VOLS[2], true); final double resC2 = BlackFormulaRepository.price(FORWARD * 0.9, 1.e12, 0.01, VOLS[2], true); System.out.println(resC1 + "\t" + resC2); System.out.println("\n"); final double resP1 = BlackFormulaRepository.price(FORWARD * 0.9, inf, 0.01, VOLS[2], false); final double resP2 = BlackFormulaRepository.price(FORWARD * 0.9, 1.e12, 0.01, VOLS[2], false); System.out.println(resP1 + "\t" + resP2); System.out.println("\n"); final double resC3 = BlackFormulaRepository.price(FORWARD * 0.9, FORWARD, inf, VOLS[2], true); final double resC4 = BlackFormulaRepository.price(FORWARD * 0.9, FORWARD, 1.e12, VOLS[2], true); System.out.println(resC3 + "\t" + resC4); System.out.println("\n"); final double resP3 = BlackFormulaRepository.price(FORWARD * 0.9, FORWARD, inf, VOLS[2], false); final double resP4 = BlackFormulaRepository.price(FORWARD * 0.9, FORWARD, 1.e12, VOLS[2], false); System.out.println(resP3 + "\t" + resP4); System.out.println("\n"); final double resC5 = BlackFormulaRepository.price(FORWARD * 0.9, FORWARD, 1.e-12, VOLS[2], true); final double resC6 = BlackFormulaRepository.price(FORWARD * 0.9, FORWARD, 1.e-11, VOLS[2], true); System.out.println(resC5 + "\t" + resC6); System.out.println("\n"); final double resP5 = BlackFormulaRepository.price(0., FORWARD, 0.01, VOLS[2], false); final double resP6 = BlackFormulaRepository.price(1.e-12, FORWARD, 0.01, VOLS[2], false); System.out.println(resP5 + "\t" + resP6); System.out.println("\n"); final double resC7 = BlackFormulaRepository.price(0., 0., 0.01, VOLS[2], true); final double resC8 = BlackFormulaRepository.price(1.e-12, 1.e-12, 0.01, VOLS[2], true); System.out.println(resC7 + "\t" + resC8); System.out.println("\n"); final double resP7 = BlackFormulaRepository.price(FORWARD, FORWARD, 0., VOLS[2], false); final double resP8 = BlackFormulaRepository.price(FORWARD, FORWARD, 1.e-60, VOLS[2], false); System.out.println(resP7 + "\t" + resP8); System.out.println("\n"); final double resP9 = BlackFormulaRepository.price(FORWARD, 0., 0.01, VOLS[2], true); final double resP10 = BlackFormulaRepository.price(FORWARD, 1.e-12, 0.01, VOLS[2], true); System.out.println(resP9 + "\t" + resP10); System.out.println("\n"); final double resC11 = BlackFormulaRepository.price(0., 0., 0., VOLS[2], false); final double resC12 = BlackFormulaRepository.price(1.e-12, 1.e-12, 1.e-20, VOLS[2], false); System.out.println(resC11 + "\t" + resC12); System.out.println("\n"); final double resC13 = BlackFormulaRepository.price(FORWARD, 0., 0., VOLS[2], true); final double resC14 = BlackFormulaRepository.price(FORWARD, 1.e-12, 1.e-20, VOLS[2], true); System.out.println(resC13 + "\t" + resC14); System.out.println("\n"); final double resC15 = BlackFormulaRepository.price(0., FORWARD, 0., VOLS[2], false); final double resC16 = BlackFormulaRepository.price(1.e-12, FORWARD, 1.e-20, VOLS[2], false); System.out.println(resC15 + "\t" + resC16); System.out.println("\n"); final double resP17 = BlackFormulaRepository.price(FORWARD, 0., 0.01, VOLS[2], false); final double resP18 = BlackFormulaRepository.price(FORWARD, 1.e-12, 0.01, VOLS[2], false); System.out.println(resP17 + "\t" + resP18); System.out.println("\n"); }