TwoStateMarkovChainPricer { PDEFullResults1D solve(final PDEGrid1D grid, final double theta) { Validate.notNull(grid, "null grid"); Validate.isTrue(0 <= theta && theta <= 1.0, "theta must be in range 0 to 1"); Validate.isTrue(grid.getSpaceNode(0) == 0.0, "space grid must start at zero"); final Function1D<Double, Double> strikeZeroPrice1 = new Function1D<Double, Double>() { @SuppressWarnings("synthetic-access") @Override public Double evaluate(final Double t) { return probState1(t) * _forward.getSpot(); } }; final Function1D<Double, Double> strikeZeroPrice2 = new Function1D<Double, Double>() { @SuppressWarnings("synthetic-access") @Override public Double evaluate(final Double t) { return (1 - probState1(t)) * _forward.getSpot(); } }; final BoundaryCondition lower1 = new DirichletBoundaryCondition(strikeZeroPrice1, 0.0); final BoundaryCondition lower2 = new DirichletBoundaryCondition(strikeZeroPrice2, 0.0); final double kMax = grid.getSpaceNode(grid.getNumSpaceNodes() - 1); final BoundaryCondition upper = new NeumannBoundaryCondition(0, kMax, false); final CoupledPDEDataBundle d1 = new CoupledPDEDataBundle(_data[0], _initalCond1, lower1, upper, grid); final CoupledPDEDataBundle d2 = new CoupledPDEDataBundle(_data[1], _initalCond2, lower2, upper, grid); final CoupledFiniteDifference solver = new CoupledFiniteDifference(theta, true); final PDEResults1D[] res = solver.solve(d1, d2); final PDEFullResults1D res1 = (PDEFullResults1D) res[0]; final PDEFullResults1D res2 = (PDEFullResults1D) res[1]; final double[][] prices = new double[grid.getNumTimeNodes()][grid.getNumSpaceNodes()]; for (int i = 0; i < grid.getNumTimeNodes(); i++) { for (int j = 0; j < grid.getNumSpaceNodes(); j++) { prices[i][j] = res1.getFunctionValue(j, i) + res2.getFunctionValue(j, i); } } return new PDEFullResults1D(grid, prices); } TwoStateMarkovChainPricer(final ForwardCurve forward, final TwoStateMarkovChainDataBundle chainDB);  TwoStateMarkovChainPricer(final ForwardCurve forward, final TwoStateMarkovChainDataBundle chainDB, final AbsoluteLocalVolatilitySurface localVolOverlay);   }
@Test public void test() { final double theta = 0.55; final int tNodes = 51; final int xNodes = 151; final MeshingFunction timeMesh = new ExponentialMeshing(0, T, tNodes, 7.5); final MeshingFunction spaceMesh = new HyperbolicMeshing(0, 10 * SPOT, SPOT, xNodes, 0.01); final PDEGrid1D grid = new PDEGrid1D(timeMesh, spaceMesh); final PDEFullResults1D res = PRICER.solve(grid, theta); final double[] expiries = timeMesh.getPoints(); final double[] strikes = spaceMesh.getPoints(); final double[] forwards = new double[tNodes]; for (int i = 0; i < tNodes; i++) { forwards[i] = FORWARD_CURVE.getForward(expiries[i]); } final double[] sims = CHAIN.simulate(T, 1000); for (int i = 0; i < xNodes; i++) { if (strikes[i] < 0.08) { final double mcPrice = CHAIN.priceCEV(FORWARD_CURVE.getForward(T), FORWARD_CURVE.getSpot() / FORWARD_CURVE.getForward(T), strikes[i], T, BETA, sims); final double price = res.getFunctionValue(i, tNodes - 1); assertEquals(mcPrice, price, 1e-2 * mcPrice); } } }