Logo Search packages:      
Sourcecode: quantlib version File versions

mclongstaffschwartzengine.hpp

/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/*
 Copyright (C) 2006 Klaus Spanderen

 This file is part of QuantLib, a free-software/open-source library
 for financial quantitative analysts and developers - http://quantlib.org/

 QuantLib is free software: you can redistribute it and/or modify it
 under the terms of the QuantLib license.  You should have received a
 copy of the license along with this program; if not, please email
 <quantlib-dev@lists.sf.net>. The license is also available online at
 <http://quantlib.org/reference/license.html>.

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the license for more details.
*/

/*! \file mclongstaffschwartzengine.hpp
    \brief Longstaff Schwartz Monte Carlo engine for early exercise options
*/

#ifndef quantlib_mc_longstaff_schwartz_engine_hpp
#define quantlib_mc_longstaff_schwartz_engine_hpp

#include <ql/PricingEngines/mcsimulation.hpp>
#include <ql/MonteCarlo/longstaffschwartzpathpricer.hpp>

namespace QuantLib {

    //! Longstaff Schwarz Monte Carlo engine for early exercise options
    /*! References:

        Francis Longstaff, Eduardo Schwartz, 2001. Valuing American Options
        by Simulation: A Simple Least-Squares Approach, The Review of
        Financial Studies, Volume 14, No. 1, 113-147

        \test the correctness of the returned value is tested by
              reproducing results available in web/literature
    */
    template <class GenericEngine, class MC, class S = Statistics>
00043     class MCLongstaffSchwartzEngine : public GenericEngine,
                                      public McSimulation<MC, S> {
      public:
        typedef typename MC::path_type path_type;
        typedef typename McSimulation<MC, S>::stats_type
            stats_type;
        typedef typename McSimulation<MC, S>::path_pricer_type
            path_pricer_type;
        typedef typename McSimulation<MC, S>::path_generator_type
            path_generator_type;

        MCLongstaffSchwartzEngine(
            Size timeSteps,
            Size timeStepsPerYear,
            bool brownianBridge,
            bool antitheticVariate,
            bool controlVariate,
            Size requiredSamples,
            Real requiredTolerance,
            Size maxSamples,
            BigNatural seed,
            Size nCalibrationSamples = Null<Size>());

        void calculate() const;

      protected:
        virtual boost::shared_ptr<LongstaffSchwartzPathPricer<path_type> >
                                                   lsmPathPricer() const = 0;

        TimeGrid timeGrid() const;
        boost::shared_ptr<path_pricer_type> pathPricer() const;
        boost::shared_ptr<path_generator_type> pathGenerator() const;

        const Size timeSteps_;
        const Size timeStepsPerYear_;
        const bool brownianBridge_;
        const Size requiredSamples_;
        const Real requiredTolerance_;
        const Size maxSamples_;
        const Size seed_;
        const Size nCalibrationSamples_;

        mutable boost::shared_ptr<LongstaffSchwartzPathPricer<path_type> >
            pathPricer_;
    };

    template <class GenericEngine, class MC, class S> inline
    MCLongstaffSchwartzEngine<GenericEngine,MC,S>::MCLongstaffSchwartzEngine(
            Size timeSteps,
            Size timeStepsPerYear,
            bool brownianBridge,
            bool antitheticVariate,
            bool controlVariate,
            Size requiredSamples,
            Real requiredTolerance,
            Size maxSamples,
            BigNatural seed,
            Size nCalibrationSamples)
    : McSimulation<MC, S> (antitheticVariate, controlVariate),
      timeSteps_          (timeSteps),
      timeStepsPerYear_   (timeStepsPerYear),
      brownianBridge_     (brownianBridge),
      requiredSamples_    (requiredSamples),
      requiredTolerance_  (requiredTolerance),
      maxSamples_         (maxSamples),
      seed_               (seed),
      nCalibrationSamples_( (nCalibrationSamples == Null<Size>())
                            ? 2048 : nCalibrationSamples) {
    }

    template <class GenericEngine, class MC, class S> inline
    boost::shared_ptr<typename
        MCLongstaffSchwartzEngine<GenericEngine, MC, S>::path_pricer_type>
        MCLongstaffSchwartzEngine<GenericEngine, MC, S>::pathPricer() const {

        QL_REQUIRE(pathPricer_, "path pricer unknown");
        return pathPricer_;
    }

    template <class GenericEngine, class MC, class S> inline
    void MCLongstaffSchwartzEngine<GenericEngine, MC, S>::calculate() const {
        pathPricer_ = this->lsmPathPricer();
        this->mcModel_ = boost::shared_ptr<MonteCarloModel<MC> >(
                          new MonteCarloModel<MC>
                              (pathGenerator(), pathPricer_,
                               stats_type(), this->antitheticVariate_));

        this->mcModel_->addSamples(nCalibrationSamples_);
        this->pathPricer_->calibrate();

        McSimulation<MC,S>::calculate(requiredTolerance_,
                                      requiredSamples_,
                                      maxSamples_);
        this->results_.value = this->mcModel_->sampleAccumulator().mean();
        if (MC::allowsErrorEstimate) {
            this->results_.errorEstimate =
                this->mcModel_->sampleAccumulator().errorEstimate();
        }
    }

    template <class GenericEngine, class MC, class S> inline
    TimeGrid MCLongstaffSchwartzEngine<GenericEngine, MC, S>::timeGrid()
        const {
        Date lastExerciseDate = this->arguments_.exercise->lastDate();
        Time t = this->arguments_.stochasticProcess->time(lastExerciseDate);
        if (this->timeSteps_ != Null<Size>()) {
            return TimeGrid(t, this->timeSteps_);
        } else if (this->timeStepsPerYear_ != Null<Size>()) {
            Size steps = static_cast<Size>(this->timeStepsPerYear_*t);
            return TimeGrid(t, std::max<Size>(steps, 1));
        } else {
            QL_FAIL("time steps not specified");
        }
    }

    template <class GenericEngine, class MC, class S> inline
    boost::shared_ptr<typename
        MCLongstaffSchwartzEngine<GenericEngine, MC, S>::path_generator_type>
    MCLongstaffSchwartzEngine<GenericEngine, MC, S>::pathGenerator() const {
        typedef typename MC::rng_traits RNG;

        Size dimensions = this->arguments_.stochasticProcess->factors();
        TimeGrid grid = this->timeGrid();
        typename RNG::rsg_type generator =
            RNG::make_sequence_generator(dimensions*(grid.size()-1),seed_);
        return boost::shared_ptr<path_generator_type>(
                   new path_generator_type(this->arguments_.stochasticProcess,
                                           grid, generator, brownianBridge_));
    }

}


#endif

Generated by  Doxygen 1.6.0   Back to index