Example #1
0
void StatisticsTest::testIncrementalStatistics() {

    BOOST_TEST_MESSAGE("Testing incremental statistics...");

    // With QuantLib 1.7 IncrementalStatistics was changed to
    // a wrapper to the boost accumulator library. This is
    // a test of the new implementation against results from
    // the old one.

    MersenneTwisterUniformRng mt(42);

    IncrementalStatistics stat;

    for (Size i = 0; i < 500000; ++i) {
        Real x = 2.0 * (mt.nextReal() - 0.5) * 1234.0;
        Real w = mt.nextReal();
        stat.add(x, w);
    }

    TEST_INC_STAT(stat.samples(), 500000);
    TEST_INC_STAT(stat.weightSum(), 2.5003623600676749e+05);
    TEST_INC_STAT(stat.mean(), 4.9122325964293845e-01);
    TEST_INC_STAT(stat.variance(),  5.0706503959683329e+05);
    TEST_INC_STAT(stat.standardDeviation(),  7.1208499464378076e+02);
    TEST_INC_STAT(stat.errorEstimate(), 1.0070402569876076e+00);
    TEST_INC_STAT(stat.skewness(), -1.7360169326720038e-03);
    TEST_INC_STAT(stat.kurtosis(), -1.1990742562085395e+00);
    TEST_INC_STAT(stat.min(), -1.2339945045639761e+03);
    TEST_INC_STAT(stat.max(),  1.2339958308008499e+03);
    TEST_INC_STAT(stat.downsideVariance(), 5.0786776146975247e+05);
    TEST_INC_STAT(stat.downsideDeviation(),  7.1264841364431061e+02);

    // This is a test for numerical stability,
    // where the old implementation fails

    InverseCumulativeRng<MersenneTwisterUniformRng,InverseCumulativeNormal> normal_gen(mt);

    IncrementalStatistics stat2;

    for (Size i = 0; i < 500000; ++i) {
        Real x = normal_gen.next().value * 1E-1 + 1E8;
        Real w = 1.0;
        stat2.add(x, w);
    }

    Real tol = 1E-5;

    if(std::fabs( stat2.variance() - 1E-2 ) > tol)
        BOOST_ERROR("variance (" << stat2.variance()
                                 << ") out of expected range " << 1E-2 << " +- "
                                 << tol);
}
Example #2
0
// evaluate fitting error on benchmark with parameter set
Real HestonPriceBenchmark(Handle<Quote> &s0, std::vector<CALIB> &c, std::vector<RD> &rd,
                          std::vector<double> p, double sdCutOff) {

    Date settlementDate(24, January, 2011);
    SavedSettings backup;
    Settings::instance().evaluationDate() = settlementDate;

    Real theta = p[0];
    Real kappa = p[1];
    Real sigma = p[2];
    Real rho = p[3];
    Real v0 = p[4];

    std::cout << "Theta: " << theta <<
    "\nKappa: " << kappa <<
    "\nsigma: " << sigma <<
    "\nrho: " << rho <<
    "\nv0: " << v0 << std::endl;

    DayCounter dayCounter = Actual365Fixed();
    Calendar calendar = TARGET();

    std::vector<Date> dates;
    std::vector<Rate> rates;
    std::vector<Rate> div;

    // this is indispensable: expiry in Heston helper is computed from YC settlement date

    dates.push_back(settlementDate);
    rates.push_back(rd[0].R);
    div.push_back(rd[0].D);
    for (Size i = 0; i < rd.size(); ++i) {
        Integer days = 365*rd[i].T;
        dates.push_back(settlementDate + days);

        rates.push_back(rd[i].R);
        div.push_back(rd[i].D);
    }

    Date dtLast = settlementDate + ((int) 365*rd[rd.size()-1].T);

    std::cout << "Last curve date: " << dtLast << std::endl;

    Integer days = (rd[rd.size()-1].T+1)*365;
    dates.push_back(settlementDate + days);
    rates.push_back(rd[rd.size()-1].R);
    div.push_back(rd[rd.size()-1].D);


    std::cout << "Heston model Benchmark Pricing: TS..." << std::endl;

    Handle<YieldTermStructure> riskFreeTS(
        boost::shared_ptr<YieldTermStructure>(
            new ZeroCurve(dates, rates, dayCounter)));

    Handle<YieldTermStructure> dividendTS(
        boost::shared_ptr<YieldTermStructure>(
            new ZeroCurve(dates, div, dayCounter)));

    Volatility vol = 2.0;

    Handle<BlackVolTermStructure> volTS(
        boost::shared_ptr<BlackVolTermStructure>(
            new BlackConstantVol(settlementDate, calendar, vol,
                                 dayCounter)));


    boost::shared_ptr<BlackScholesMertonProcess> BSprocess(
        new BlackScholesMertonProcess(s0, dividendTS, riskFreeTS, volTS));
//    boost::shared_ptr<PricingEngine> BSengine(
//        new AnalyticEuropeanEngine(BSprocess));

    boost::shared_ptr<HestonProcess> process(new HestonProcess(
                riskFreeTS, dividendTS, s0, v0, kappa, theta, sigma, rho));

    boost::shared_ptr<PricingEngine> engine(new AnalyticHestonEngine(
                                                boost::shared_ptr<HestonModel>(new HestonModel(process)), 64));

    std::cout << "Heston model Benchmark Pricing: engine set ..." << std::endl;

    IncrementalStatistics errorStat;
    vector<Real> error;

    ofstream myfile;
    Volatility ivol;

    Real errorBid;
    Real errorAsk;


//        myfile.open ("dump.csv", ios::out|ios::trunc); // this is the default
//        myfile << "T, dm, y, CP, PB, Calc, PA, Vega, iVol, ErrorBid, ErrorAsk" << std::endl;

    for (Size i = 0; i < c.size(); ++i) {
        Integer days = 365*c[i].T;
        //std::cout << "Expiry dates: " << dtExpiry << std::endl;
        Period maturity((int)((days+3)/7.), Weeks); // round to weeks
        Date dtExpiry = calendar.advance(riskFreeTS->referenceDate(),
                                         maturity);

        if (i==0)
            std::cout << dtExpiry << std::endl;

        // Time tau = riskFreeTS->dayCounter().yearFraction(
        //                       riskFreeTS->referenceDate(), dtExpiry);

        boost::shared_ptr<StrikedTypePayoff> payoff(
            new PlainVanillaPayoff(Option::Call, c[i].K));

        boost::shared_ptr<Exercise> exercise(new EuropeanExercise(dtExpiry));

        VanillaOption option(payoff, exercise);
        option.setPricingEngine(engine);
        Real calculated = option.NPV();

        // option.setPricingEngine(BSengine);

        if (calculated >0) {
            try {
                ivol = option.impliedVolatility(calculated, BSprocess, 1.e-6, 1000, .1, 10);
                errorBid  = std::max((c[i].VB-ivol), 0.0)*100;
                errorAsk =  std::max((ivol-c[i].VA), 0.0)*100;
            } catch (...) {
                errorBid  = 0.0;
                errorAsk =  0.0;
            };
        } else {
            vol = 0.0;
            errorAsk = 0.0;
            errorBid = 0.0;
        };

        error.push_back(errorBid+errorAsk);
//            myfile << c[i].T << "," << dtExpiry << "," << c[i].CP << "," << c[i].PB << "," << calculated << "," << c[i].PA << "," << c[i].Vega << "," << ivol << "," << errorBid << "," << errorAsk << std::endl;
    }

    // remove outliers and calculate sse

    errorStat.addSequence(error.begin(), error.end());
    Real sse = errorStat.standardDeviation();

    for (Size i=0; i<error.size(); ++i)
        if (abs(error[i]) > sdCutOff*sse) error[i] = 0.0;

    errorStat.reset();
    errorStat.addSequence(error.begin(), error.end());
    sse = errorStat.standardDeviation();
    return sse;
}