blackSurface,
flatVolTS,
int main(int argc, char* argv[]){    try {        QL_IO_INIT        // our option        double underlying = 8;        double strike = 8;        Spread dividendYield = 0.05;        Rate riskFreeRate = 0.05;        Date todaysDate(15, May, 1998);        Date settlementDate(17, May, 1998);        Date exerciseDate(17, May, 1999);        DayCounter rateDayCounter = DayCounters::Actual365();        Time maturity = rateDayCounter.yearFraction(settlementDate,            exerciseDate);        double volatility = 0.10;        std::cout << "Time to maturity = "        << maturity                  << std::endl;        std::cout << "Underlying price = "        << underlying                  << std::endl;        std::cout << "Strike = "                  << strike                  << std::endl;        std::cout << "Risk-free interest rate = " << riskFreeRate                  << std::endl;        std::cout << "dividend yield = " << dividendYield                  << std::endl;        std::cout << "Volatility = "              << volatility                  << std::endl;        std::cout << std::endl;        std::string method;        double value, discrepancy, rightValue, relativeDiscrepancy;        std::cout << std::endl << std::endl ;        // write column headings        std::cout << "Method\t\tValue\tEstimatedError\tDiscrepancy"            "\tRel. Discr." << std::endl;        // first method: Black Scholes analytic solution        method ="Black Scholes";        value = EuropeanOption(Option::Call, underlying, strike,            dividendYield, riskFreeRate, maturity, volatility).value();        double estimatedError = 0.0;        discrepancy = 0.0;        relativeDiscrepancy = 0.0;        std::cout << method << "\t"             << DoubleFormatter::toString(value, 4) << "\t"             << DoubleFormatter::toString(estimatedError, 4) << "\t\t"             << DoubleFormatter::toString(discrepancy, 6) << "\t"             << DoubleFormatter::toString(relativeDiscrepancy, 6)             << std::endl;        // store the Black Scholes value as the correct one        rightValue = value;        // second method: Call-Put parity        method ="Call-Put parity";        value = EuropeanOption(Option::Put, underlying, strike,            dividendYield, riskFreeRate, maturity, volatility).value()            + underlying*QL_EXP(-dividendYield*maturity)            - strike*QL_EXP(- riskFreeRate*maturity);        discrepancy = QL_FABS(value-rightValue);        relativeDiscrepancy = discrepancy/rightValue;        std::cout << method << "\t"             << DoubleFormatter::toString(value, 4) << "\t"             << "N/A\t\t"             << discrepancy << "\t"             << DoubleFormatter::toString(relativeDiscrepancy, 6)             << std::endl;        // third method: Integral        method ="Integral";        using QuantLib::Math::SegmentIntegral;        Payoff po(maturity, strike, underlying, volatility, riskFreeRate,            dividendYield);        SegmentIntegral integrator(5000);        double nuT = (riskFreeRate - dividendYield                      + 0.5*volatility*volatility)*maturity;        double infinity = 10.0*volatility*QL_SQRT(maturity);        value = integrator(po, nuT-infinity, nuT+infinity);        discrepancy = QL_FABS(value-rightValue);        relativeDiscrepancy = discrepancy/rightValue;        std::cout << method << "\t"             << DoubleFormatter::toString(value, 4) << "\t"             << "N/A\t\t"             << DoubleFormatter::toString(discrepancy, 6) << "\t"             << DoubleFormatter::toString(relativeDiscrepancy, 6)             << std::endl;        // fourth method: Finite Differences        method ="Finite Diff.";        Size grid = 100;        value = FdEuropean(Option::Call, underlying, strike,            dividendYield, riskFreeRate, maturity, volatility, grid).value();        discrepancy = QL_FABS(value-rightValue);        relativeDiscrepancy = discrepancy/rightValue;        std::cout << method << "\t"             << DoubleFormatter::toString(value, 4) << "\t"             << "N/A\t\t"             << DoubleFormatter::toString(discrepancy, 6) << "\t"             << DoubleFormatter::toString(relativeDiscrepancy, 6)             << std::endl;        // fifth method: Monte Carlo (crude)        method ="MC (crude)";        bool antitheticVariance = false;        McEuropean mcEur(Option::Call, underlying, strike, dividendYield,            riskFreeRate, maturity, volatility, antitheticVariance, 123456);        // let's require a tolerance of 0.002%        value = mcEur.value(0.02);        estimatedError = mcEur.errorEstimate();        discrepancy = QL_FABS(value-rightValue);        relativeDiscrepancy = discrepancy/rightValue;        std::cout << method << "\t"             << DoubleFormatter::toString(value, 4) << "\t"             << DoubleFormatter::toString(estimatedError, 4) << "\t\t"             << DoubleFormatter::toString(discrepancy, 6) << "\t"             << DoubleFormatter::toString(relativeDiscrepancy, 6)             << std::endl;        // sixth method: Monte Carlo with antithetic variance reduction        method ="MC (antithetic)";        // let's use the same number of samples as in the crude Monte Carlo        Size nSamples = mcEur.sampleAccumulator().samples();        antitheticVariance = true;        McEuropean mcEur2(Option::Call, underlying, strike, dividendYield,            riskFreeRate, maturity, volatility, antitheticVariance);        value = mcEur2.valueWithSamples(nSamples);        estimatedError = mcEur2.errorEstimate();        discrepancy = QL_FABS(value-rightValue);        relativeDiscrepancy = discrepancy/rightValue;        std::cout << method << "\t"             << DoubleFormatter::toString(value, 4) << "\t"             << DoubleFormatter::toString(estimatedError, 4) << "\t\t"             << DoubleFormatter::toString(discrepancy, 6) << "\t"             << DoubleFormatter::toString(relativeDiscrepancy, 6)             << std::endl;/************************************/        // New option pricing framework        std::cout << "\nNew Pricing engine framework" << std::endl;        Date midlifeDate(19, November, 1998);        std::vector<Date> exDates(2);        exDates[0]=midlifeDate;        exDates[1]=exerciseDate;        EuropeanExercise exercise(exerciseDate);        AmericanExercise amExercise(settlementDate, exerciseDate);        BermudanExercise berExercise(exDates);        RelinkableHandle<MarketElement> underlyingH(            Handle<MarketElement>(new SimpleMarketElement(underlying)));        // bootstrap the yield/dividend/vol curves        RelinkableHandle<TermStructure> flatTermStructure(            Handle<TermStructure>(                new FlatForward(todaysDate, settlementDate,                                riskFreeRate, rateDayCounter)));        RelinkableHandle<TermStructure> flatDividendTS(            Handle<TermStructure>(                new FlatForward(todaysDate, settlementDate,                                dividendYield, rateDayCounter)));        RelinkableHandle<BlackVolTermStructure> flatVolTS(            Handle<BlackVolTermStructure>(                new BlackConstantVol(settlementDate, volatility)));        std::vector<Date> dates(4);        dates[0] = settlementDate.plusMonths(1);        dates[1] = exerciseDate;        dates[2] = exerciseDate.plusMonths(6);        dates[3] = exerciseDate.plusMonths(12);        std::vector<double> strikes(4);        strikes[0] = underlying*0.9;        strikes[1] = underlying;        strikes[2] = underlying*1.1;        strikes[3] = underlying*1.2;        Matrix vols(4,4);        vols[0][0] = volatility*1.1; vols[0][1] = volatility; vols[0][2] = volatility*0.9; vols[0][3] = volatility*0.8;        vols[1][0] = volatility*1.1; vols[1][1] = volatility; vols[1][2] = volatility*0.9; vols[1][3] = volatility*0.8;        vols[2][0] = volatility*1.1; vols[2][1] = volatility; vols[2][2] = volatility*0.9; vols[2][3] = volatility*0.8;        vols[3][0] = volatility*1.1; vols[3][1] = volatility; vols[3][2] = volatility*0.9; vols[3][3] = volatility*0.8;        RelinkableHandle<BlackVolTermStructure> blackSurface(            Handle<BlackVolTermStructure> (new            VolTermStructures::BlackVarianceSurface<            Math::BicubicSplineInterpolation<            std::vector<double>::const_iterator,			std::vector<double>::const_iterator,            Math::Matrix> >(settlementDate, dates, strikes, vols)));        Instruments::VanillaOption option(            Option::Call,            underlyingH,            strike,            flatDividendTS,            flatTermStructure,            exercise,//            flatVolTS,            blackSurface,            Handle<PricingEngine>(new AnalyticEuropeanEngine()));        // method: Black Scholes Engine        method = "Black Scholes";        option.setPricingEngine(Handle<PricingEngine>(            new AnalyticEuropeanEngine()));        value = option.NPV();        discrepancy = QL_FABS(value-rightValue);        relativeDiscrepancy = discrepancy/rightValue;        std::cout << method << "\t"             << DoubleFormatter::toString(value, 4) << "\t"             << "N/A\t\t"             << DoubleFormatter::toString(discrepancy, 6) << "\t"             << DoubleFormatter::toString(relativeDiscrepancy, 6)             << std::endl;        Size timeSteps=800;        // Binomial Method (JR)        method = "Binomial (JR)";        option.setPricingEngine(Handle<PricingEngine>(            new BinomialVanillaEngine(                BinomialVanillaEngine::JarrowRudd, timeSteps)));        value = option.NPV();        discrepancy = QL_FABS(value-rightValue);        relativeDiscrepancy = discrepancy/rightValue;        std::cout << method << "\t"             << DoubleFormatter::toString(value, 4) << "\t"             << "N/A\t\t"             << DoubleFormatter::toString(discrepancy, 6) << "\t"             << DoubleFormatter::toString(relativeDiscrepancy, 6)             << std::endl;        // Binomial Method (CRR)        method = "Binomial (CRR)";        option.setPricingEngine(Handle<PricingEngine>(            new BinomialVanillaEngine(                BinomialVanillaEngine::CoxRossRubinstein, timeSteps)));        value = option.NPV();        discrepancy = QL_FABS(value-rightValue);        relativeDiscrepancy = discrepancy/rightValue;        std::cout << method << "\t"             << DoubleFormatter::toString(value, 4) << "\t"             << "N/A\t\t"             << DoubleFormatter::toString(discrepancy, 6) << "\t"             << DoubleFormatter::toString(relativeDiscrepancy, 6)             << std::endl;        // Equal Probability Additive Binomial Tree (EQP)        method = "Additive (EQP)";        option.setPricingEngine(Handle<PricingEngine>(            new BinomialVanillaEngine(                BinomialVanillaEngine::EQP, timeSteps)));        value = option.NPV();        discrepancy = QL_FABS(value-rightValue);        relativeDiscrepancy = discrepancy/rightValue;        std::cout << method << "\t"             << DoubleFormatter::toString(value, 4) << "\t"             << "N/A\t\t"             << DoubleFormatter::toString(discrepancy, 6) << "\t"             << DoubleFormatter::toString(relativeDiscrepancy, 6)             << std::endl;        // Equal Jumps Additive Binomial Tree (Trigeorgis)        method = "Bin. Trigeorgis";        option.setPricingEngine(Handle<PricingEngine>(            new BinomialVanillaEngine(                BinomialVanillaEngine::Trigeorgis, timeSteps)));        value = option.NPV();        discrepancy = QL_FABS(value-rightValue);        relativeDiscrepancy = discrepancy/rightValue;        std::cout << method << "\t"             << DoubleFormatter::toString(value, 4) << "\t"             << "N/A\t\t"             << DoubleFormatter::toString(discrepancy, 6) << "\t"             << DoubleFormatter::toString(relativeDiscrepancy, 6)             << std::endl;        // Tian Binomial Tree (third moment matching)        method = "Binomial Tian";        option.setPricingEngine(Handle<PricingEngine>(            new BinomialVanillaEngine(                BinomialVanillaEngine::Tian, timeSteps)));        value = option.NPV();        discrepancy = QL_FABS(value-rightValue);        relativeDiscrepancy = discrepancy/rightValue;        std::cout << method << "\t"             << DoubleFormatter::toString(value, 4) << "\t"             << "N/A\t\t"             << DoubleFormatter::toString(discrepancy, 6) << "\t"             << DoubleFormatter::toString(relativeDiscrepancy, 6)             << std::endl;        // Finite Differences Method        method = "Finite Diff.";        option.setPricingEngine(Handle<PricingEngine>(            new FDVanillaEngine()));        value = option.NPV();        discrepancy = QL_FABS(value-rightValue);        relativeDiscrepancy = discrepancy/rightValue;        std::cout << method << "\t"             << DoubleFormatter::toString(value, 4) << "\t"             << "N/A\t\t"             << DoubleFormatter::toString(discrepancy, 6) << "\t"             << DoubleFormatter::toString(relativeDiscrepancy, 6)             << std::endl;        // Monte Carlo Method        timeSteps = 365;        Handle<TimeGrid> timeGrid(new TimeGrid(maturity, timeSteps));        method = "MC (crude)";        UniformRandomGenerator rng(123456);        UniformRandomSequenceGenerator rsg(timeSteps, rng);        UniformLowDiscrepancySequenceGenerator ldsg(timeSteps);        GaussianRandomSequenceGenerator grsg(rsg);        GaussianLowDiscrepancySequenceGenerator gldsg(ldsg);        option.setPricingEngine(Handle<PricingEngine>(            new MCEuropeanVanillaEngine<                Statistics,                GaussianRandomSequenceGenerator,                GaussianPathGenerator2,                PathPricer<Path> >(false, false, timeGrid, grsg)));        value = option.NPV();        double errorEstimate = option.errorEstimate();        discrepancy = QL_FABS(value-rightValue);        relativeDiscrepancy = discrepancy/rightValue;        std::cout << method << "\t"             << DoubleFormatter::toString(value, 4) << "\t"             << DoubleFormatter::toString(errorEstimate, 4) << "\t"             << DoubleFormatter::toString(discrepancy, 6) << "\t"             << DoubleFormatter::toString(relativeDiscrepancy, 6)             << std::endl;        Handle<AnalyticEuropeanEngine> baseEngine(new            AnalyticEuropeanEngine);        Handle<QuantoEngine<VanillaOptionArguments,                            VanillaOptionResults> >            quantoEngine(new QuantoEngine<VanillaOptionArguments,                                          VanillaOptionResults>(baseEngine));        double correlation = 0.0;        Instruments::QuantoVanillaOption quantoOption(            Option::Call,            underlyingH,            strike,            flatDividendTS,            flatTermStructure,            exercise,            flatVolTS,            quantoEngine,            flatTermStructure,            flatVolTS,            RelinkableHandle<MarketElement>(                Handle<MarketElement>(new SimpleMarketElement(correlation))));        value = quantoOption.NPV();        double delta = quantoOption.delta();        double gamma = quantoOption.gamma();        double theta = quantoOption.theta();        double vega = quantoOption.vega();        double rho = quantoOption.rho();        double divRho = quantoOption.dividendRho();        double qvega = quantoOption.qvega();        double qrho = quantoOption.qrho();        double qlambda = quantoOption.qlambda();        std::cout << std::endl << std::endl << "quanto: "             << DoubleFormatter::toString(value, 4)             << std::endl;        std::cout << "quanto delta: "             << DoubleFormatter::toString(delta, 4)             << std::endl;        std::cout << "quanto gamma: "             << DoubleFormatter::toString(gamma, 4)             << std::endl;        std::cout << "quanto theta: "             << DoubleFormatter::toString(theta, 4)             << std::endl;        std::cout << "quanto vega: "             << DoubleFormatter::toString(vega, 4)             << std::endl;        std::cout << "quanto rho: "             << DoubleFormatter::toString(rho, 4)             << std::endl;        std::cout << "quanto divRho: "             << DoubleFormatter::toString(divRho, 4)             << std::endl;        std::cout << "quanto qvega: "             << DoubleFormatter::toString(qvega, 4)             << std::endl;        std::cout << "quanto qrho: "             << DoubleFormatter::toString(qrho, 4)             << std::endl;        std::cout << "quanto qlambda: "             << DoubleFormatter::toString(qlambda, 4)             << std::endl;        Handle<ForwardEngine<VanillaOptionArguments,                             VanillaOptionResults> >            forwardEngine(new ForwardEngine<VanillaOptionArguments,                                            VanillaOptionResults>(baseEngine));        Instruments::ForwardVanillaOption forwardOption(            Option::Call,            underlyingH,            flatDividendTS,            flatTermStructure,            exercise,            flatVolTS,            forwardEngine,            1.1, // moneyness            settlementDate.plusMonths(1) // reset Date            );        value   = forwardOption.NPV();        delta   = forwardOption.delta();        gamma   = forwardOption.gamma();        theta   = forwardOption.theta();        vega    = forwardOption.vega();        rho     = forwardOption.rho();        divRho  = forwardOption.dividendRho();        std::cout << std::endl << std::endl << "forward: "             << DoubleFormatter::toString(value, 4)             << std::endl;        std::cout << "forward delta: "             << DoubleFormatter::toString(delta, 4)             << std::endl;        std::cout << "forward gamma: "             << DoubleFormatter::toString(gamma, 4)             << std::endl;        std::cout << "forward theta: "             << DoubleFormatter::toString(theta, 4)             << std::endl;        std::cout << "forward vega: "             << DoubleFormatter::toString(vega, 4)             << std::endl;        std::cout << "forward rho: "             << DoubleFormatter::toString(rho, 4)             << std::endl;        std::cout << "forward divRho: "             << DoubleFormatter::toString(divRho, 4)             << std::endl;        Handle<ForwardPerformanceEngine<VanillaOptionArguments,                                        VanillaOptionResults> >            forwardPerformanceEngine(                new ForwardPerformanceEngine<VanillaOptionArguments,                                             VanillaOptionResults>(                    baseEngine));        forwardOption.setPricingEngine(forwardPerformanceEngine);        value   = forwardOption.NPV();        delta   = forwardOption.delta();        gamma   = forwardOption.gamma();        theta   = forwardOption.theta();        vega    = forwardOption.vega();        rho     = forwardOption.rho();        divRho  = forwardOption.dividendRho();        std::cout << std::endl << std::endl << "forward performance: "             << DoubleFormatter::toString(value, 4)             << std::endl;        std::cout << "forward performance delta: "             << DoubleFormatter::toString(delta, 4)             << std::endl;        std::cout << "forward performance gamma: "             << DoubleFormatter::toString(gamma, 4)             << std::endl;        std::cout << "forward performance theta: "             << DoubleFormatter::toString(theta, 4)             << std::endl;        std::cout << "forward performance vega: "             << DoubleFormatter::toString(vega, 4)             << std::endl;        std::cout << "forward performance rho: "             << DoubleFormatter::toString(rho, 4)             << std::endl;        std::cout << "forward performance divRho: "             << DoubleFormatter::toString(divRho, 4)             << std::endl;        Handle<QuantoEngine<ForwardOptionArguments<VanillaOptionArguments>,                            VanillaOptionResults> >            quantoForwardEngine(               new QuantoEngine<ForwardOptionArguments<VanillaOptionArguments>,                                VanillaOptionResults>(forwardEngine));        Instruments::QuantoForwardVanillaOption quantoForwardOption(            Option::Call,            underlyingH,            strike,            flatDividendTS,            flatTermStructure,            exercise,            flatVolTS,            quantoForwardEngine,            flatTermStructure,            flatVolTS,            RelinkableHandle<MarketElement>(                Handle<MarketElement>(new SimpleMarketElement(correlation))),            1.1, // moneyness            settlementDate.plusMonths(1) // reset Date        );        value   = quantoForwardOption.NPV();        delta   = quantoForwardOption.delta();        gamma   = quantoForwardOption.gamma();        theta   = quantoForwardOption.theta();        vega    = quantoForwardOption.vega();        rho     = quantoForwardOption.rho();        divRho  = quantoForwardOption.dividendRho();        qvega   = quantoForwardOption.qvega();        qrho    = quantoForwardOption.qrho();        qlambda = quantoForwardOption.qlambda();        std::cout << std::endl << std::endl << "quanto forward: "             << DoubleFormatter::toString(value, 4)             << std::endl;        std::cout << "quanto forward delta: "             << DoubleFormatter::toString(delta, 4)             << std::endl;        std::cout << "quanto forward gamma: "             << DoubleFormatter::toString(gamma, 4)             << std::endl;        std::cout << "quanto forward theta: "             << DoubleFormatter::toString(theta, 4)             << std::endl;        std::cout << "quanto forward vega: "             << DoubleFormatter::toString(vega, 4)             << std::endl;        std::cout << "quanto forward rho: "             << DoubleFormatter::toString(rho, 4)             << std::endl;        std::cout << "quanto forward divRho: "             << DoubleFormatter::toString(divRho, 4)             << std::endl;        std::cout << "quanto forward qvega: "             << DoubleFormatter::toString(qvega, 4)             << std::endl;        std::cout << "quanto forward qrho: "             << DoubleFormatter::toString(qrho, 4)             << std::endl;        std::cout << "quanto forward qlambda: "             << DoubleFormatter::toString(qlambda, 4)             << std::endl;        Handle<QuantoEngine<ForwardOptionArguments<VanillaOptionArguments>,                            VanillaOptionResults> >            quantoForwardPerformanceEngine(               new QuantoEngine<ForwardOptionArguments<VanillaOptionArguments>,                                VanillaOptionResults>(                   forwardPerformanceEngine));        quantoForwardOption.setPricingEngine(quantoForwardPerformanceEngine);        value   = quantoForwardOption.NPV();        delta   = quantoForwardOption.delta();        gamma   = quantoForwardOption.gamma();        theta   = quantoForwardOption.theta();        vega    = quantoForwardOption.vega();        rho     = quantoForwardOption.rho();        divRho  = quantoForwardOption.dividendRho();        qvega   = quantoForwardOption.qvega();        qrho    = quantoForwardOption.qrho();        qlambda = quantoForwardOption.qlambda();        std::cout << std::endl << std::endl << "quanto forward performance: "             << DoubleFormatter::toString(value, 4)             << std::endl;        std::cout << "quanto forward performance delta: "             << DoubleFormatter::toString(delta, 4)             << std::endl;        std::cout << "quanto forward performance gamma: "             << DoubleFormatter::toString(gamma, 4)             << std::endl;        std::cout << "quanto forward performance theta: "             << DoubleFormatter::toString(theta, 4)             << std::endl;        std::cout << "quanto forward performance vega: "             << DoubleFormatter::toString(vega, 4)             << std::endl;        std::cout << "quanto forward performance rho: "             << DoubleFormatter::toString(rho, 4)             << std::endl;        std::cout << "quanto forward performance divRho: "             << DoubleFormatter::toString(divRho, 4)             << std::endl;        std::cout << "quanto forward performance qvega: "             << DoubleFormatter::toString(qvega, 4)             << std::endl;        std::cout << "quanto forward performance qrho: "             << DoubleFormatter::toString(qrho, 4)             << std::endl;        std::cout << "quanto forward performance qlambda: "             << DoubleFormatter::toString(qlambda, 4)             << std::endl;        return 0;    } catch (std::exception& e) {        std::cout << e.what() << std::endl;        return 1;    } catch (...) {        std::cout << "unknown error" << std::endl;        return 1;    }}