private static void testJQuantLib() throws Exception {
   System.out.println(
       VolatilityDifference.impliedVolatility(
           "call", 4887.45, 4900, Date.todaysDate(), new Date(27, 10, 2011), 0.0925, 0, 124.2));
   System.out.println(
       VolatilityDifference.impliedVolatility(
           "call", 4887.45, 4900, Date.todaysDate(), new Date(24, 11, 2011), 0.0925, 0, 213.9));
 }
  private List<org.jquantlib.time.Date> generateCouponDates(DBObject stream1)
      throws ParseException, UnknownHostException {
    org.jquantlib.time.Date effectiveDate = getDate(stream1, "effectiveDate.unadjustedDate.$");
    org.jquantlib.time.Date terminationDate = getDate(stream1, "terminationDate.unadjustedDate.$");
    TimeUnit timeUnit = getTimeUnit(stream1, "calculationPeriodFrequency.period.$");
    int freq = (Integer) get(stream1, "calculationPeriodFrequency.periodMultiplier.$");

    Object roll = get(stream1, "calculationPeriodFrequency.rollConvention.$");

    String businessDayConvention =
        get(stream1, "calculationPeriodDatesAdjustments.businessDayConvention.$");
    String businessCentersHref =
        get(stream1, "calculationPeriodDatesAdjustments.businessCentersReference.@href");
    Calendar c =
        getCalendar(stream1, "terminationDate.dateAdjustments.businessCenters.businessCenter");
    Period period = new Period(freq, timeUnit);

    final Calendar nullCalendar = new NullCalendar();

    MakeSchedule mSchedule =
        new MakeSchedule(
            effectiveDate, terminationDate, period, c, BusinessDayConvention.ModifiedFollowing);
    mSchedule.forwards();

    if (roll instanceof Integer) {
      org.jquantlib.time.Date firstDate =
          nullCalendar.advance(effectiveDate, period, BusinessDayConvention.Unadjusted, false);
      if (firstDate.dayOfMonth() != (Integer) roll) {
        Date tmp = firstDate.longDate();
        tmp.setDate((Integer) roll);
        firstDate = new org.jquantlib.time.Date(tmp);
        mSchedule.withFirstDate(firstDate);
      }
    }

    List<org.jquantlib.time.Date> dates = mSchedule.schedule().dates();
    return dates;
  }
  @Test
  public void testHaugValues() {

    QL.info("Testing barrier options against Haug's values...");

    final NewBarrierOptionData values[] = {
      //
      // The data below are from "Option pricing formulas", E.G. Haug, McGraw-Hill 1998 pag. 72
      //
      //     barrierType, barrier, rebate,         type, strike,     s,    q,    r,    t,    v,
      // result, tol
      new NewBarrierOptionData(
          BarrierType.DownOut,
          95.0,
          3.0,
          Option.Type.Call,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          9.0246,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          95.0,
          3.0,
          Option.Type.Call,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          6.7924,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          95.0,
          3.0,
          Option.Type.Call,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          4.8759,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          100.0,
          3.0,
          Option.Type.Call,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          3.0000,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          100.0,
          3.0,
          Option.Type.Call,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          3.0000,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          100.0,
          3.0,
          Option.Type.Call,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          3.0000,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpOut,
          105.0,
          3.0,
          Option.Type.Call,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          2.6789,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpOut,
          105.0,
          3.0,
          Option.Type.Call,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          2.3580,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpOut,
          105.0,
          3.0,
          Option.Type.Call,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          2.3453,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          95.0,
          3.0,
          Option.Type.Call,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          7.7627,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          95.0,
          3.0,
          Option.Type.Call,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          4.0109,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          95.0,
          3.0,
          Option.Type.Call,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          2.0576,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          100.0,
          3.0,
          Option.Type.Call,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          13.8333,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          100.0,
          3.0,
          Option.Type.Call,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          7.8494,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          100.0,
          3.0,
          Option.Type.Call,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          3.9795,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpIn,
          105.0,
          3.0,
          Option.Type.Call,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          14.1112,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpIn,
          105.0,
          3.0,
          Option.Type.Call,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          8.4482,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpIn,
          105.0,
          3.0,
          Option.Type.Call,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          4.5910,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          95.0,
          3.0,
          Option.Type.Call,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          8.8334,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          95.0,
          3.0,
          Option.Type.Call,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          7.0285,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          95.0,
          3.0,
          Option.Type.Call,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          5.4137,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          100.0,
          3.0,
          Option.Type.Call,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          3.0000,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          100.0,
          3.0,
          Option.Type.Call,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          3.0000,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          100.0,
          3.0,
          Option.Type.Call,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          3.0000,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpOut,
          105.0,
          3.0,
          Option.Type.Call,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          2.6341,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpOut,
          105.0,
          3.0,
          Option.Type.Call,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          2.4389,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpOut,
          105.0,
          3.0,
          Option.Type.Call,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          2.4315,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          95.0,
          3.0,
          Option.Type.Call,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          9.0093,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          95.0,
          3.0,
          Option.Type.Call,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          5.1370,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          95.0,
          3.0,
          Option.Type.Call,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          2.8517,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          100.0,
          3.0,
          Option.Type.Call,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          14.8816,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          100.0,
          3.0,
          Option.Type.Call,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          9.2045,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          100.0,
          3.0,
          Option.Type.Call,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          5.3043,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpIn,
          105.0,
          3.0,
          Option.Type.Call,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          15.2098,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpIn,
          105.0,
          3.0,
          Option.Type.Call,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          9.7278,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpIn,
          105.0,
          3.0,
          Option.Type.Call,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          5.8350,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          95.0,
          3.0,
          Option.Type.Put,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          2.2798,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          95.0,
          3.0,
          Option.Type.Put,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          2.2947,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          95.0,
          3.0,
          Option.Type.Put,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          2.6252,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          100.0,
          3.0,
          Option.Type.Put,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          3.0000,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          100.0,
          3.0,
          Option.Type.Put,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          3.0000,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          100.0,
          3.0,
          Option.Type.Put,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          3.0000,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpOut,
          105.0,
          3.0,
          Option.Type.Put,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          3.7760,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpOut,
          105.0,
          3.0,
          Option.Type.Put,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          5.4932,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpOut,
          105.0,
          3.0,
          Option.Type.Put,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          7.5187,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          95.0,
          3.0,
          Option.Type.Put,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          2.9586,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          95.0,
          3.0,
          Option.Type.Put,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          6.5677,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          95.0,
          3.0,
          Option.Type.Put,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          11.9752,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          100.0,
          3.0,
          Option.Type.Put,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          2.2845,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          100.0,
          3.0,
          Option.Type.Put,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          5.9085,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          100.0,
          3.0,
          Option.Type.Put,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          11.6465,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpIn,
          105.0,
          3.0,
          Option.Type.Put,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          1.4653,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpIn,
          105.0,
          3.0,
          Option.Type.Put,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          3.3721,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpIn,
          105.0,
          3.0,
          Option.Type.Put,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.25,
          7.0846,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          95.0,
          3.0,
          Option.Type.Put,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          2.4170,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          95.0,
          3.0,
          Option.Type.Put,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          2.4258,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          95.0,
          3.0,
          Option.Type.Put,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          2.6246,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          100.0,
          3.0,
          Option.Type.Put,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          3.0000,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          100.0,
          3.0,
          Option.Type.Put,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          3.0000,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownOut,
          100.0,
          3.0,
          Option.Type.Put,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          3.0000,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpOut,
          105.0,
          3.0,
          Option.Type.Put,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          4.2293,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpOut,
          105.0,
          3.0,
          Option.Type.Put,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          5.8032,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpOut,
          105.0,
          3.0,
          Option.Type.Put,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          7.5649,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          95.0,
          3.0,
          Option.Type.Put,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          3.8769,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          95.0,
          3.0,
          Option.Type.Put,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          7.7989,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          95.0,
          3.0,
          Option.Type.Put,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          13.3078,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          100.0,
          3.0,
          Option.Type.Put,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          3.3328,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          100.0,
          3.0,
          Option.Type.Put,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          7.2636,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.DownIn,
          100.0,
          3.0,
          Option.Type.Put,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          12.9713,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpIn,
          105.0,
          3.0,
          Option.Type.Put,
          90,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          2.0658,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpIn,
          105.0,
          3.0,
          Option.Type.Put,
          100,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          4.4226,
          1.0e-4),
      new NewBarrierOptionData(
          BarrierType.UpIn,
          105.0,
          3.0,
          Option.Type.Put,
          110,
          100.0,
          0.04,
          0.08,
          0.50,
          0.30,
          8.3686,
          1.0e-4),

      //
      //  Data from "Going to Extreme: Correcting Simulation Bias in Exotic Option Valuation"
      //  D.R. Beaglehole, P.H. Dybvig and G. Zhou
      //  Financial Analysts Journal; Jan / Feb 1997; 53, 1
      //
      //    barrierType, barrier, rebate,         type, strike,     s,    q,    r,    t,    v,
      // result, tol
      // ---- new NewBarrierOptionData( BarrierType.DownOut,    45.0,    0.0,  Option.Type.PUT,
      // 50,  50.0,-0.05, 0.10, 0.25, 0.50,   4.032, 1.0e-3 ),
      // ---- new NewBarrierOptionData( BarrierType.DownOut,    45.0,    0.0,  Option.Type.PUT,
      // 50,  50.0,-0.05, 0.10, 1.00, 0.50,   5.477, 1.0e-3 )
    };

    final DayCounter dc = new Actual360();
    final Date today = Date.todaysDate();
    new Settings().setEvaluationDate(today);

    final SimpleQuote spot = new SimpleQuote(0.0);
    final SimpleQuote qRate = new SimpleQuote(0.0);
    final YieldTermStructure qTS = Utilities.flatRate(today, qRate, dc);
    final SimpleQuote rRate = new SimpleQuote(0.0);
    final YieldTermStructure rTS = Utilities.flatRate(today, rRate, dc);
    final SimpleQuote vol = new SimpleQuote(0.0);
    final BlackVolTermStructure volTS = Utilities.flatVol(today, vol, dc);

    for (final NewBarrierOptionData value : values) {
      final Date exDate = today.add(timeToDays(value.t));
      final Exercise exercise = new EuropeanExercise(exDate);

      spot.setValue(value.s);
      qRate.setValue(value.q);
      rRate.setValue(value.r);
      vol.setValue(value.v);

      final StrikedTypePayoff payoff = new PlainVanillaPayoff(value.type, value.strike);

      final BlackScholesMertonProcess stochProcess =
          new BlackScholesMertonProcess(
              new Handle<Quote>(spot),
              new Handle<YieldTermStructure>(qTS),
              new Handle<YieldTermStructure>(rTS),
              new Handle<BlackVolTermStructure>(volTS));
      final PricingEngine engine = new AnalyticBarrierEngine(stochProcess);

      final BarrierOption barrierOption =
          new BarrierOption(value.barrierType, value.barrier, value.rebate, payoff, exercise);
      barrierOption.setPricingEngine(engine);

      final double calculated = barrierOption.NPV();
      final double expected = value.result;
      final double error = Math.abs(calculated - expected);
      if (error > value.tol) {
        REPORT_FAILURE(
            "value",
            value.barrierType,
            value.barrier,
            value.rebate,
            payoff,
            exercise,
            value.s,
            value.q,
            value.r,
            today,
            value.v,
            expected,
            calculated,
            error,
            value.tol);
      }
    }
  }
  @Test
  public void testBeagleholeValues() {

    QL.info("Testing barrier options against Beaglehole's values...");

    /**
     * Data from "Going to Extreme: Correcting Simulation Bias in Exotic Option Valuation" - D.R.
     * Beaglehole, P.H. Dybvig and G. Zhou Financial Analysts Journal; Jan / Feb 1997; 53, 1
     */
    final BarrierOptionData values[] = {
      new BarrierOptionData(BarrierType.DownOut, 0.50, 50, 45, 5.477, 0.0)
    };

    final double underlyingPrice = 50.0;
    final double rebate = 0.0;
    final double r = Math.log(1.1);
    final double q = 0.00;

    final DayCounter dc = new Actual360();
    final Date today = Date.todaysDate();
    new Settings().setEvaluationDate(today);

    final Quote underlying = new SimpleQuote(underlyingPrice);
    final Quote qH_SME = new SimpleQuote(q);
    final YieldTermStructure qTS = Utilities.flatRate(today, qH_SME, dc);
    final Quote rH_SME = new SimpleQuote(r);
    final YieldTermStructure rTS = Utilities.flatRate(today, rH_SME, dc);
    final SimpleQuote volatility = new SimpleQuote(0.10);
    final BlackVolTermStructure volTS = Utilities.flatVol(today, volatility, dc);

    final Date exDate = today.add(360);

    final Exercise exercise = new EuropeanExercise(exDate);

    for (final BarrierOptionData value : values) {
      volatility.setValue(value.volatility);
      final StrikedTypePayoff callPayoff = new PlainVanillaPayoff(Option.Type.Call, value.strike);

      final BlackScholesMertonProcess stochProcess =
          new BlackScholesMertonProcess(
              new Handle<Quote>(underlying),
              new Handle<YieldTermStructure>(qTS),
              new Handle<YieldTermStructure>(rTS),
              new Handle<BlackVolTermStructure>(volTS));
      final PricingEngine engine = new AnalyticBarrierEngine(stochProcess);

      final BarrierOption barrierCallOption =
          new BarrierOption(value.barrierType, value.barrier, rebate, callPayoff, exercise);
      barrierCallOption.setPricingEngine(engine);

      final double calculated = barrierCallOption.NPV();
      final double expected = value.callValue;
      final double error = Math.abs(calculated - expected);
      final double maxErrorAllowed = 1.0e-3;

      if (error > maxErrorAllowed) {
        REPORT_FAILURE(
            "value",
            value.barrierType,
            value.barrier,
            rebate,
            callPayoff,
            exercise,
            underlyingPrice,
            q,
            r,
            today,
            value.volatility,
            expected,
            calculated,
            error,
            maxErrorAllowed);
      }
    }

    // TODO: MC Barrier engine not implemented yet.
    /*

    final double maxMcRelativeErrorAllowed = 0.01;
    final int timeSteps = 1;
    final boolean brownianBridge = true;
    final boolean antitheticVariate = false;
    final boolean controlVariate = false;
    final int requiredSamples = 131071; //2^17-1
    final double requiredTolerance;
    final int maxSamples = 1048575; // 2^20-1
    final boolean isBiased = false;
    final double seed = 10;

    boost::shared_ptr<PricingEngine> mcEngine(
            new MCBarrierEngine<LowDiscrepancy>(timeSteps, brownianBridge,
                                            antitheticVariate, controlVariate,
                                            requiredSamples, requiredTolerance,
                                            maxSamples, isBiased, seed));

        barrierCallOption.setPricingEngine(mcEngine);
        calculated = barrierCallOption.NPV();
        error = std::fabs(calculated-expected)/expected;
        if (error>maxMcRelativeErrorAllowed) {
            REPORT_FAILURE("value", values[i].type, values[i].barrier,
                           rebate, callPayoff, exercise, underlyingPrice,
                           q, r, today, values[i].volatility,
                           expected, calculated, error,
                           maxMcRelativeErrorAllowed);
        }
     */
  }
  @Test
  public void testBabsiriValues() {
    QL.info("Testing barrier options against Babsiri's values...");

    /**
     * Data from "Simulating Path-Dependent Options: A New Approach" - M. El Babsiri and G. Noel
     * Journal of Derivatives; Winter 1998; 6, 2
     */
    final BarrierOptionData values[] = {
      new BarrierOptionData(BarrierType.DownIn, 0.10, 100, 90, 0.07187, 0.0),
      new BarrierOptionData(BarrierType.DownIn, 0.15, 100, 90, 0.60638, 0.0),
      new BarrierOptionData(BarrierType.DownIn, 0.20, 100, 90, 1.64005, 0.0),
      new BarrierOptionData(BarrierType.DownIn, 0.25, 100, 90, 2.98495, 0.0),
      new BarrierOptionData(BarrierType.DownIn, 0.30, 100, 90, 4.50952, 0.0),
      new BarrierOptionData(BarrierType.UpIn, 0.10, 100, 110, 4.79148, 0.0),
      new BarrierOptionData(BarrierType.UpIn, 0.15, 100, 110, 7.08268, 0.0),
      new BarrierOptionData(BarrierType.UpIn, 0.20, 100, 110, 9.11008, 0.0),
      new BarrierOptionData(BarrierType.UpIn, 0.25, 100, 110, 11.06148, 0.0),
      new BarrierOptionData(BarrierType.UpIn, 0.30, 100, 110, 12.98351, 0.0)
    };

    final double underlyingPrice = 100.0;
    final double rebate = 0.0;
    final double r = 0.05;
    final double q = 0.02;

    final DayCounter dc = new Actual360();
    final Date today = Date.todaysDate();
    new Settings().setEvaluationDate(today);

    final Quote underlying = new SimpleQuote(underlyingPrice);
    final Quote qH_SME = new SimpleQuote(q);
    final YieldTermStructure qTS = Utilities.flatRate(today, qH_SME, dc);
    final Quote rH_SME = new SimpleQuote(r);
    final YieldTermStructure rTS = Utilities.flatRate(today, rH_SME, dc);
    final SimpleQuote volatility = new SimpleQuote(0.10);
    final BlackVolTermStructure volTS = Utilities.flatVol(today, volatility, dc);

    final Date exDate = today.add(360);
    final Exercise exercise = new EuropeanExercise(exDate);

    for (final BarrierOptionData value : values) {
      volatility.setValue(value.volatility);
      final StrikedTypePayoff callPayoff = new PlainVanillaPayoff(Option.Type.Call, value.strike);

      final BlackScholesMertonProcess stochProcess =
          new BlackScholesMertonProcess(
              new Handle<Quote>(underlying),
              new Handle<YieldTermStructure>(qTS),
              new Handle<YieldTermStructure>(rTS),
              new Handle<BlackVolTermStructure>(volTS));

      final PricingEngine engine = new AnalyticBarrierEngine(stochProcess);

      final BarrierOption barrierCallOption =
          new BarrierOption(value.barrierType, value.barrier, rebate, callPayoff, exercise);
      barrierCallOption.setPricingEngine(engine);

      final double calculated = barrierCallOption.NPV();
      final double expected = value.callValue;
      final double error = Math.abs(calculated - expected);
      final double maxErrorAllowed = 1.0e-3;

      if (error > maxErrorAllowed) {
        REPORT_FAILURE(
            "value",
            value.barrierType,
            value.barrier,
            rebate,
            callPayoff,
            exercise,
            underlyingPrice,
            q,
            r,
            today,
            value.volatility,
            expected,
            calculated,
            error,
            maxErrorAllowed);
      }
    }
  }
  @Override
  public void run() {

    QL.validateExperimentalMode();

    QL.info("::::: " + this.getClass().getSimpleName() + " :::::");

    final String fmt = "%-45s %-15s %-15s\n";

    try {
      final StopClock clock = new StopClock();
      clock.startClock();

      final Date today = new Date(29, Month.May, 2006);
      new Settings().setEvaluationDate(today);

      // the option to replicate
      final BarrierType barrierType = BarrierType.DownOut;
      final double barrier = 70.0;
      final double rebate = 0.0;
      final Option.Type type = Option.Type.Put;
      final double underlyingValue = 100;
      final Handle<SimpleQuote> underlying =
          new Handle<SimpleQuote>(new SimpleQuote(underlyingValue));

      final double strike = 100.0;
      final Handle<SimpleQuote> riskFreeRate = new Handle<SimpleQuote>(new SimpleQuote(0.04));
      final Handle<SimpleQuote> volatility = new Handle<SimpleQuote>(new SimpleQuote(0.20));
      final Date maturity = today.add(Period.ONE_YEAR_FORWARD);

      System.out.println("\n");

      // write column headings - we don't need these values ...
      final int widths[] = {45, 15, 15};
      final int totalWidth = widths[0] + widths[1] + widths[2];

      System.out.println("Initial Market conditions");
      System.out.printf(fmt, "Option", "NPV", "Error");
      /*
      Size widths[] = { 45, 15, 15 };
      Size totalWidth = widths[0]+widths[1]+widths[2];
      std::string rule(totalWidth, '-'), dblrule(totalWidth, '=');

      std::cout << dblrule << std::endl;
      std::cout << "Initial market conditions" << std::endl;
      std::cout << dblrule << std::endl;
      std::cout << std::setw(widths[0]) << std::left << "Option"
            << std::setw(widths[1]) << std::left << "NPV"
            << std::setw(widths[2]) << std::left << "Error"
            << std::endl;
      std::cout << rule << std::endl;
       */

      // bootstrap the yield/vol curves
      final DayCounter dayCounter = new Actual365Fixed();
      final Handle<Quote> h1 = new Handle<Quote>(riskFreeRate.currentLink());
      final Handle<Quote> h2 = new Handle<Quote>(volatility.currentLink());
      final Handle<YieldTermStructure> flatRate =
          new Handle<YieldTermStructure>(new FlatForward(0, new NullCalendar(), h1, dayCounter));
      final Handle<BlackConstantVol> flatVol =
          new Handle<BlackConstantVol>(new BlackConstantVol(0, new NullCalendar(), h2, dayCounter));

      // instantiate the option
      final Exercise exercise = new EuropeanExercise(maturity);
      final Payoff payoff = new PlainVanillaPayoff(type, strike);

      // FIXME:Review BlackScholes, GeneralizedBlackScholesStochasticProcess
      // Handle<StochasticProcess> stochasticProcess = new Handle<StochasticProcess>(new
      // GeneralizedBlackScholesProcess(underlying, flatRate, flatVol));

    } catch (final Exception ex) {
      ex.printStackTrace();
    } finally {

    }
  }