BjerksundStenslandModel { public double price(double s0, double k, double r, double b, double t, double sigma, boolean isCall) { double fwd = s0 * Math.exp(b * t); double df = Math.exp(-r * t); double bsPrice = df * BlackFormulaRepository.price(fwd, k, t, sigma, isCall); double immediateExPrice = isCall ? Math.max(s0 - k, 0.0) : Math.max(k - s0, 0.0); double lowBoundPrice = Math.max(immediateExPrice, bsPrice); if (sigma * Math.sqrt(t) < SMALL) { return lowBoundPrice; } if (isCall) { return Math.max(lowBoundPrice, getCallPrice(s0, k, r, b, t, sigma, bsPrice)); } double temp = (2 * b + sigma * sigma) / 2 / sigma; double minR = b - 0.5 * temp * temp; if (r < minR) { return lowBoundPrice; } return Math.max(lowBoundPrice, getCallPrice(k, s0, r - b, -b, t, sigma, bsPrice)); }  Function1D<StandardOptionDataBundle, Double> getPricingFunction(final AmericanVanillaOptionDefinition definition); double price(double s0, double k, double r, double b, double t, double sigma, boolean isCall); double[] getPriceAdjoint(double s0, double k, double r, double b, double t, double sigma, boolean isCall); double[] getPriceDeltaGamma(double s0, double k, double r, double b, double t, double sigma, boolean isCall); double[] getPriceAndVega(double s0, double k, double r, double b, double t, double sigma, boolean isCall); Function1D<Double, double[]> getPriceAndVegaFunction(final double s0, final double k, final double r, final double b, final double t, final boolean isCall); double impliedVolatility(double price, double s0, double k, double r, double b, double t, boolean isCall); double impliedVolatility(double price, double s0, double k, double r, double b, double t, boolean isCall, double guess);  }
@Test public void priceTest() { final double s0 = 120; final double r = 0.08; final double q = 0.12; final double b = r - q; final double k = 100.0; final double t = 0.25; final double sigma = 0.3; final BjerksundStenslandModel bs = new BjerksundStenslandModel(); final double eurPrice = Math.exp(-r * t) * BlackFormulaRepository.price(s0 * Math.exp(b * t), k, t, sigma, true); final double amPrice = bs.price(s0, k, r, b, t, sigma, true); assertTrue(amPrice > eurPrice); assertEquals(20.193913138412203, amPrice, 1e-15); }
@Test public void earlyExciseTest() { final double s0 = 10.0; final double r = 0.0; final double b = 0.05; final double k = 13.0; final double t = 0.25; final double sigma = 0.3; final boolean isCall = false; final BjerksundStenslandModel bs = new BjerksundStenslandModel(); final double amPrice = bs.price(s0, k, r, b, t, sigma, isCall); assertTrue(amPrice >= (k - s0)); }
@Test void zeroVolTest() { double spot = 100; double strike = 96; double r = 0.01; double q = 0.07; double b = r - q; double t = 2.0; boolean isCall = false; final BjerksundStenslandModel bs = new BjerksundStenslandModel(); double price = bs.price(spot, strike, r, b, t, 0.0, isCall); double expected = Math.exp(-r * t) * Math.max(strike - spot * Math.exp(b * t), 0.0); assertEquals(expected, price, 1e-14); }