EuropeanStandardBarrierOptionModel extends AnalyticOptionModel<EuropeanStandardBarrierOptionDefinition, StandardOptionDataBundle> { @Override public Function1D<StandardOptionDataBundle, Double> getPricingFunction(final EuropeanStandardBarrierOptionDefinition definition) { Validate.notNull(definition, "definition"); final Barrier barrier = definition.getBarrier(); final boolean isKnockIn = barrier.getKnockType() == KnockType.IN; final boolean isDown = barrier.getBarrierType() == BarrierType.DOWN; final double h = barrier.getBarrierLevel(); final int phi = definition.isCall() ? 1 : -1; final double eta = isDown ? 1 : -1; return new Function1D<StandardOptionDataBundle, Double>() { @SuppressWarnings("synthetic-access") @Override public Double evaluate(final StandardOptionDataBundle data) { Validate.notNull(data, "data"); final boolean isCall = definition.isCall(); final double s = data.getSpot(); final double b = data.getCostOfCarry(); final double t = definition.getTimeToExpiry(data.getDate()); final double rebate = definition.getRebate(); final double k = definition.getStrike(); final double r = data.getInterestRate(t); final double sigma = data.getVolatility(t, h); final double df1 = Math.exp(t * (b - r)); final double df2 = Math.exp(-r * t); if (CompareUtils.closeEquals(sigma, 0, 1e-16)) { return df1 * definition.getPayoffFunction().getPayoff(data, null); } final double sigmaSq = sigma * sigma; final double sigmaT = sigma * Math.sqrt(t); final double mu = (b - 0.5 * sigmaSq) / sigmaSq; final double lambda = Math.sqrt(mu * mu + 2 * r / sigmaSq); final double m1 = sigmaT * (1 + mu); final double x1 = Math.log(s / k) / sigmaT + m1; final double x2 = Math.log(s / h) / sigmaT + m1; final double y1 = Math.log(h * h / s / k) / sigmaT + m1; final double y2 = Math.log(h / s) / sigmaT + m1; final double z = Math.log(h / s) / sigmaT + lambda * sigmaT; final double xA = getA(s, k, df1, df2, x1, sigmaT, phi); final double xB = getA(s, k, df1, df2, x2, sigmaT, phi); final double xC = getC(s, k, df1, df2, y1, sigmaT, h, mu, phi, eta); final double xD = getC(s, k, df1, df2, y2, sigmaT, h, mu, phi, eta); final double xE = isKnockIn ? getE(s, rebate, df2, x2, y2, sigmaT, h, mu, eta) : getF(s, rebate, z, sigmaT, h, mu, lambda, eta); if (isKnockIn) { if (isDown) { if (isCall) { return k > h ? xC + xE : xA - xB + xD + xE; } return k > h ? xB - xC + xD + xE : xA + xE; } if (isCall) { return k > h ? xA + xE : xB - xC + xD + xE; } return k > h ? xA - xB + xD + xE : xC + xE; } if (isDown) { if (isCall) { return k > h ? xA - xC + xE : xB - xD + xE; } return k > h ? xA - xB + xC - xD + xE : xE; } if (isCall) { return k > h ? xE : xA - xB + xC - xD + xE; } return k > h ? xB - xD + xE : xA - xC + xE; } }; }  @Override Function1D<StandardOptionDataBundle, Double> getPricingFunction(final EuropeanStandardBarrierOptionDefinition definition);  }
@Test(expectedExceptions = IllegalArgumentException.class) public void testNullDefinition() { MODEL.getPricingFunction(null); }
@Test(expectedExceptions = IllegalArgumentException.class) public void testNullData() { MODEL.getPricingFunction(new EuropeanStandardBarrierOptionDefinition(SPOT, EXPIRY, true, new Barrier(KnockType.IN, BarrierType.DOWN, ObservationType.CONTINUOUS, SPOT))).evaluate( (StandardOptionDataBundle) null); }
@Test public void testZeroVol() { final double delta = 10; final StandardOptionDataBundle data = new StandardOptionDataBundle(YieldCurve.from(ConstantDoublesCurve.from(0.)), 0, new VolatilitySurface(ConstantDoublesSurface.from(0.)), SPOT, DATE); Barrier barrier = new Barrier(KnockType.OUT, BarrierType.DOWN, ObservationType.CONTINUOUS, 95); EuropeanStandardBarrierOptionDefinition option = new EuropeanStandardBarrierOptionDefinition(SPOT - delta, EXPIRY, true, barrier, REBATE); assertEquals(MODEL.getPricingFunction(option).evaluate(data), 10, 0); barrier = new Barrier(KnockType.IN, BarrierType.UP, ObservationType.CONTINUOUS, 105); option = new EuropeanStandardBarrierOptionDefinition(SPOT - delta, EXPIRY, true, barrier, REBATE); assertEquals(MODEL.getPricingFunction(option).evaluate(data), REBATE, 0); }
@Test public void test() { final StandardOptionDataBundle data = new StandardOptionDataBundle(R, B, new VolatilitySurface(ConstantDoublesSurface.from(0.25)), SPOT, DATE); Barrier barrier = new Barrier(KnockType.OUT, BarrierType.DOWN, ObservationType.CONTINUOUS, 95); EuropeanStandardBarrierOptionDefinition option = new EuropeanStandardBarrierOptionDefinition(90, EXPIRY, true, barrier, REBATE); assertEquals(MODEL.getPricingFunction(option).evaluate(data), 9.0246, EPS); barrier = new Barrier(KnockType.OUT, BarrierType.UP, ObservationType.CONTINUOUS, 105); option = new EuropeanStandardBarrierOptionDefinition(90, EXPIRY, true, barrier, REBATE); assertEquals(MODEL.getPricingFunction(option).evaluate(data), 2.6789, EPS); barrier = new Barrier(KnockType.OUT, BarrierType.DOWN, ObservationType.CONTINUOUS, 95); option = new EuropeanStandardBarrierOptionDefinition(90, EXPIRY, false, barrier, REBATE); assertEquals(MODEL.getPricingFunction(option).evaluate(data), 2.2798, EPS); barrier = new Barrier(KnockType.OUT, BarrierType.UP, ObservationType.CONTINUOUS, 105); option = new EuropeanStandardBarrierOptionDefinition(90, EXPIRY, false, barrier, REBATE); assertEquals(MODEL.getPricingFunction(option).evaluate(data), 3.7760, EPS); barrier = new Barrier(KnockType.IN, BarrierType.DOWN, ObservationType.CONTINUOUS, 95); option = new EuropeanStandardBarrierOptionDefinition(90, EXPIRY, true, barrier, REBATE); assertEquals(MODEL.getPricingFunction(option).evaluate(data), 7.7627, EPS); barrier = new Barrier(KnockType.IN, BarrierType.UP, ObservationType.CONTINUOUS, 105); option = new EuropeanStandardBarrierOptionDefinition(90, EXPIRY, true, barrier, REBATE); assertEquals(MODEL.getPricingFunction(option).evaluate(data), 14.1112, EPS); barrier = new Barrier(KnockType.IN, BarrierType.DOWN, ObservationType.CONTINUOUS, 95); option = new EuropeanStandardBarrierOptionDefinition(90, EXPIRY, false, barrier, REBATE); assertEquals(MODEL.getPricingFunction(option).evaluate(data), 2.9586, EPS); barrier = new Barrier(KnockType.IN, BarrierType.UP, ObservationType.CONTINUOUS, 105); option = new EuropeanStandardBarrierOptionDefinition(90, EXPIRY, false, barrier, REBATE); assertEquals(MODEL.getPricingFunction(option).evaluate(data), 1.4653, EPS); }