BarrierOptionPricer { public double outBarrier(final double spot, final double barrierLevel, final double strike, final double expiry, final double rate, final double carry, final double vol, final boolean isCall, final double rebate) { final Function1D<Double, Double> intCon = ICP.getEuropeanPayoff(strike, isCall); final ConvectionDiffusionPDE1DStandardCoefficients pde = PDE.getBlackScholes(rate, rate - carry, vol); final boolean isUp = barrierLevel > spot; final double adj = 0.0; double sMin; double sMax; BoundaryCondition lower; BoundaryCondition upper; if (isUp) { sMin = 0.0; sMax = barrierLevel * Math.exp(-adj); if (isCall) { lower = new DirichletBoundaryCondition(0.0, sMin); } else { final Function1D<Double, Double> lowerValue = new Function1D<Double, Double>() { @Override public Double evaluate(final Double tau) { return Math.exp(-rate * tau) * strike; } }; lower = new DirichletBoundaryCondition(lowerValue, sMin); } upper = new DirichletBoundaryCondition(rebate, sMax); } else { sMin = barrierLevel * Math.exp(adj); sMax = spot * Math.exp(_z * Math.sqrt(expiry)); lower = new DirichletBoundaryCondition(rebate, sMin); if (isCall) { final Function1D<Double, Double> upperValue = new Function1D<Double, Double>() { @Override public Double evaluate(final Double tau) { return Math.exp(-rate * tau) * (spot * Math.exp(carry * tau) - strike); } }; upper = new DirichletBoundaryCondition(upperValue, sMax); } else { upper = new DirichletBoundaryCondition(0.0, sMax); } } final MeshingFunction tMesh = new ExponentialMeshing(0, expiry, _nTNodes, _lambda); final MeshingFunction xMesh = new HyperbolicMeshing(sMin, sMax, spot, _nXNodes, _bunching); final PDEGrid1D grid = new PDEGrid1D(tMesh, xMesh); final PDE1DDataBundle<ConvectionDiffusionPDE1DCoefficients> pdeData = new PDE1DDataBundle<ConvectionDiffusionPDE1DCoefficients>(pde, intCon, lower, upper, grid); final PDEResults1D res = SOLVER.solve(pdeData); final double[] xNodes = grid.getSpaceNodes(); final int index = SurfaceArrayUtils.getLowerBoundIndex(xNodes, spot); final double w = (xNodes[index + 1] - spot) / (xNodes[index + 1] - xNodes[index]); return w * res.getFunctionValue(index) + (1 - w) * res.getFunctionValue(index + 1); } BarrierOptionPricer();  BarrierOptionPricer(final int numXNodes, final int numTNodes, final double lambda, final double bunching); double getPrice(final EuropeanVanillaOption option, final Barrier barrier, final double rebate, final double spot, final double costOfCarry, final double rate, final double sigma); double outBarrier(final double spot, final double barrierLevel, final double strike, final double expiry, final double rate, final double carry,
      final double vol, final boolean isCall, final double rebate); double inBarrier(final double spot, final double barrierLevel, final double strike, final double expiry, final double rate, final double carry,
      final double vol, final boolean isCall, final double rebate);  }
@Test public void outBarrierTest() { if (PRINT) { System.out.println("BarrierOptionPricerTest"); } for (int i = 0; i < 5; i++) { final double strike = SPOT * (0.8 + i * 0.1); for (int j = 0; j < 5; j++) { final double h = SPOT * (0.9 + j * 0.05); for (int k = 0; k < 2; k++) { final boolean isCall = k == 0; final BarrierType bt = SPOT > h ? BarrierType.DOWN : BarrierType.UP; final double anPrice = ANAL_PRICER.getPrice(new EuropeanVanillaOption(strike, EXPIRY, isCall), new Barrier(KnockType.OUT, bt, ObservationType.CONTINUOUS, h), REBATE, SPOT, B, R, SIGMA); final double fdPrice = PRICER.outBarrier(SPOT, h, strike, EXPIRY, R, B, SIGMA, isCall, REBATE); if (PRINT) { final String call = isCall ? "call" : "put "; System.out.format(call + " x = %.0f h = %.0f\tprice = %.4f\tfdPrice = %.4f\n", strike, h, anPrice, fdPrice); } assertEquals(anPrice, fdPrice, 5e-2); } } } }