
/*
 Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl

 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 ferdinando@ametrano.net
 The license is also available online at http://quantlib.org/html/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 bsmfdoption.hpp
    \brief common code for numerical option evaluation

    \fullpath
    ql/Pricers/%bsmfdoption.hpp
*/

// $Id: fdbsmoption.hpp,v 1.7.8.1 2002/12/31 18:40:41 nando Exp $

#ifndef BSM_numerical_option_pricer_h
#define BSM_numerical_option_pricer_h

#include <ql/Pricers/singleassetoption.hpp>
#include <ql/FiniteDifferences/bsmoperator.hpp>
#include <ql/FiniteDifferences/boundarycondition.hpp>
#include <ql/FiniteDifferences/tridiagonaloperator.hpp>
#include <vector>

namespace QuantLib {

    namespace Pricers {

        //! Black-Scholes-Merton option priced numerically
        class FdBsmOption : public SingleAssetOption {
          public:
            FdBsmOption(Option::Type type, double underlying,
                double strike, Spread dividendYield, Rate riskFreeRate,
                Time residualTime, double volatility, Size gridPoints);
            // accessors
            virtual void calculate() const = 0;
            double value() const;
            double delta() const;
            double gamma() const;
            Array getGrid() const{return grid_;}

          protected:
            // methods
            virtual void setGridLimits(double center,
                                       double timeDelay) const;
            virtual void initializeGrid() const;
            virtual void initializeInitialCondition() const;
            virtual void initializeOperator() const;
            // input data
            Size gridPoints_;
            // results
            mutable double value_, delta_, gamma_;

            mutable Array grid_;
            mutable FiniteDifferences::BSMOperator finiteDifferenceOperator_;
            mutable Array initialPrices_;
            typedef FiniteDifferences::BoundaryCondition<
                        FiniteDifferences::TridiagonalOperator>
                            BoundaryCondition;
            mutable std::vector<Handle<BoundaryCondition> > BCs_;
            // temporaries
            mutable double sMin_, center_, sMax_;
          private:
            // temporaries
            mutable double gridLogSpacing_;
            Size safeGridPoints(Size gridPoints,
                                Time residualTime);
        };

        //! This is a safety check to be sure we have enough grid points.
        #define QL_NUM_OPT_MIN_GRID_POINTS            10
        //! This is a safety check to be sure we have enough grid points.
        #define QL_NUM_OPT_GRID_POINTS_PER_YEAR        2

        // The following is a safety check to be sure we have enough grid
        // points.
        inline Size FdBsmOption::safeGridPoints(
            Size gridPoints, Time residualTime) {
            return QL_MAX(gridPoints, residualTime>1.0 ?
                static_cast<Size>(
                    (QL_NUM_OPT_MIN_GRID_POINTS +
                    (residualTime-1.0) *
                    QL_NUM_OPT_GRID_POINTS_PER_YEAR))
                : QL_NUM_OPT_MIN_GRID_POINTS);
        }

    }

}


#endif
