Binomial Tree Fever

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Binomial Tree Fever

John Maiden
Think I found two errors in the Binomial Tree class. The problems are in
LeisenReimer:: LeisenReimer and Joshi4::Joshi4. In both constructors the
variance should be

Real variance = process->variance(0.0, x0_, dt_);

Instead of

Real variance = process->variance(0.0, x0_, end);


-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: Binomial Tree Fever

Toyin Akin
Hi,
 
Perhaps not.
 
The variance looks like it is divided by the number of steps before it is being used.
 
Whereas in the other cases, the variance for a single dt step is taken and used directly.
 
Just an observation...
 
Toy out.

> To: [hidden email]
> From: [hidden email]
> Date: Mon, 27 Aug 2007 13:40:57 +0000
> Subject: [Quantlib-dev] Binomial Tree Fever
>
> Think I found two errors in the Binomial Tree class. The problems are in
> LeisenReimer:: LeisenReimer and Joshi4::Joshi4. In both constructors the
> variance should be
>
> Real variance = process->variance(0.0, x0_, dt_);
>
> Instead of
>
> Real variance = process->variance(0.0, x0_, end);
>
>
> -------------------------------------------------------------------------
> This SF.net email is sponsored by: Splunk Inc.
> Still grepping through log files to find problems? Stop.
> Now Search log events and configuration files using AJAX and a browser.
> Download your FREE copy of Splunk now >> http://get.splunk.com/
> _______________________________________________
> QuantLib-dev mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/quantlib-dev



Play Movie Mash-up and win BIG prizes!
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: Binomial Tree Fever

John Maiden
Yeah, I think you might be right. Thanks for noticing and replying so quickly.


-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: Binomial Tree Fever

John Maiden
Working on making extensions to the binomial tree classes.
The main change is that the tree now can use a time-dependent
stochastic process, i.e. a process that has risk-free rate and
volatility curves. I know that there are recombination issues
with a volatility curve, but as far as I know there isn't
anything wrong with incorporating a yield curve.

I've tested the trees with flat vol and different yield curves
(flat, treasury zero, and treasury strip), and half of the trees
(Jarrow-Rudd, Additive EQP, and Tian) produce normal results for
the flat and zero curve, but get very noisy for the strip curve.
The other trees are well-behaved for all the curves. Hoping
someone might be able to point out what's going wrong. I have
a spreadsheet of the results if anyone is interested in seeing
them.

Here's the code. I've renamed all the changed classes with the
extension "Extended":

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

/*
 Copyright (C) 2003 Ferdinando Ametrano
 Copyright (C) 2001, 2002, 2003 Sadruddin Rejeb
 Copyright (C) 2005 StatPro Italia 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
 <[hidden email]>. The license is also available online at
 <http://quantlib.org/license.shtml>.

 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 binomialtree.hpp
    \brief Binomial tree class
*/

#ifndef extended_binomial_tree_hpp
#define extended_binomial_tree_hpp

#include <ql/stochasticprocess.hpp>
#include <ql/methods/lattices/tree.hpp>
#include <ql/instruments/dividendschedule.hpp>
#include <ql/processes/blackscholesprocess.hpp>

#include <iostream>

namespace QuantLib {

    //! Binomial tree base class
    /*! \ingroup lattices */
    template <class T>
    class ExtendedBinomialTree : public Tree<T> {
      public:
        enum Branches { branches = 2 };
        ExtendedBinomialTree(const boost::shared_ptr<StochasticProcess1D>& process,
                     Time end,
                     Size steps)
        : Tree<T>(steps+1), treeProcess_(process) {
            x0_ = process->x0();
            dt_ = end/steps;
                        driftPerStep_ = process->drift(0.0, x0_) * dt_;
        }
        Size size(Size i) const {
            return i+1;
        }
        Size descendant(Size, Size index, Size branch) const {
            return index + branch;
        }

                const boost::shared_ptr<StochasticProcess1D> treeProcess() const {return
treeProcess_;}

                //the amount the stock price moves up in one step
                virtual Real upMove(Time stepTime) const = 0;
                //the amount the stock price moves down in one step
                virtual Real downMove(Time stepTime) const = 0;

      protected:
            //time dependent drift per step
                Real driftStep(Time driftTime) const {
                        return this->treeProcess_->drift(driftTime, x0_) * dt_;
                }

        Real x0_, driftPerStep_;
        Time dt_;

          protected:
                boost::shared_ptr<StochasticProcess1D> treeProcess_;
    };


    //! Base class for equal probabilities binomial tree
    /*! \ingroup lattices */
    template <class T>
    class ExtendedEqualProbabilitiesBinomialTree : public ExtendedBinomialTree<T> {
      public:
        ExtendedEqualProbabilitiesBinomialTree(
                        const boost::shared_ptr<StochasticProcess1D>& process,
                        Time end,
                        Size steps)
        : ExtendedBinomialTree<T>(process, end, steps) {}
        //Real underlying(Size i, Size index) const {
        //    BigInteger j = 2*BigInteger(index) - BigInteger(i);
        //    // exploiting the forward value tree centering
        //    return this->x0_*std::exp(i*this->driftPerStep_ + j*this->up_);
        //}
                Real underlying(Size i, Size index, Time stepTime) const {
                        BigInteger j = 2*BigInteger(index) - BigInteger(i);
                        // exploiting the forward value tree centering
                        return this->x0_*std::exp(i*this->driftStep(stepTime) +
j*this->upStep(stepTime));
                }

        Real probability(Size, Size, Size, Time) const { return 0.5; }

                Real upMove(Time stepTime) const {
                        return std::exp(this->driftStep(stepTime) + this->upStep(stepTime));
                }

                Real downMove(Time stepTime) const {
                        return std::exp(this->driftStep(stepTime) - this->upStep(stepTime));
                }

                //the tree dependent up move term at time stepTime
                virtual Real upStep(Time stepTime) const = 0;

      protected:
        Real up_;
    };


    //! Base class for equal jumps binomial tree
    /*! \ingroup lattices */
    template <class T>
    class ExtendedEqualJumpsBinomialTree : public ExtendedBinomialTree<T> {
      public:
        ExtendedEqualJumpsBinomialTree(
                        const boost::shared_ptr<StochasticProcess1D>& process,
                        Time end,
                        Size steps)
        : ExtendedBinomialTree<T>(process, end, steps) {}
        //Real underlying(Size i, Size index) const {
        //    BigInteger j = 2*BigInteger(index) - BigInteger(i);
        //    // exploiting equal jump and the x0_ tree centering
        //    return this->x0_*std::exp(j*this->dx_);
        //}
                Real underlying(Size i, Size index, Time stepTime) const {
                        BigInteger j = 2*BigInteger(index) - BigInteger(i);
                        // exploiting equal jump and the x0_ tree centering
                        return this->x0_*std::exp(j*this->dxStep(stepTime));
                }

       /* Real probability(Size, Size, Size branch) const {
            return (branch == 1 ? pu_ : pd_);
        }*/

                Real probability(Size, Size, Size branch, Time stepTime) const {
                        Real upProb = this->probUp(stepTime);
                        Real downProb = 1 - upProb;
                        return (branch == 1 ? upProb : downProb);
                }

                Real upMove(Time stepTime) const {
                        return std::exp(this->dxStep(stepTime));
                }

                Real downMove(Time stepTime) const {
                        return (1/upMove(stepTime));
                }

      protected:
                //probability of a up move
                virtual Real probUp(Time stepTime) const = 0;
                //time dependent term dx_
                virtual Real dxStep(Time stepTime) const = 0;

        Real dx_, pu_, pd_;
    };


    //! Jarrow-Rudd (multiplicative) equal probabilities binomial tree
    /*! \ingroup lattices */
    class ExtendedJarrowRudd : public
ExtendedEqualProbabilitiesBinomialTree<ExtendedJarrowRudd> {
      public:
        ExtendedJarrowRudd(const boost::shared_ptr<StochasticProcess1D>&,
                   Time end,
                   Size steps,
                   Real strike);
          protected:
                Real upStep(Time stepTime) const;
    };


    //! Cox-Ross-Rubinstein (multiplicative) equal jumps binomial tree
    /*! \ingroup lattices */
    class ExtendedCoxRossRubinstein
        : public ExtendedEqualJumpsBinomialTree<ExtendedCoxRossRubinstein> {
      public:
        ExtendedCoxRossRubinstein(const boost::shared_ptr<StochasticProcess1D>&,
                          Time end,
                          Size steps,
                          Real strike);

          protected:
                  Real dxStep(Time stepTime) const;
                  Real probUp(Time stepTime) const;
    };


    //! Additive equal probabilities binomial tree
    /*! \ingroup lattices */
    class ExtendedAdditiveEQPBinomialTree
        : public
ExtendedEqualProbabilitiesBinomialTree<ExtendedAdditiveEQPBinomialTree> {
      public:
        ExtendedAdditiveEQPBinomialTree(
                        const boost::shared_ptr<StochasticProcess1D>&,
                        Time end,
                        Size steps,
                        Real strike);

          protected:
                  Real upStep(Time stepTime) const;
    };


    //! %Trigeorgis (additive equal jumps) binomial tree
    /*! \ingroup lattices */
    class ExtendedTrigeorgis : public
ExtendedEqualJumpsBinomialTree<ExtendedTrigeorgis> {
      public:
        ExtendedTrigeorgis(const boost::shared_ptr<StochasticProcess1D>&,
                   Time end,
                   Size steps,
                   Real strike);
        protected:
                Real dxStep(Time stepTime) const;
                Real probUp(Time stepTime) const;
    };


    //! %Tian tree: third moment matching, multiplicative approach
    /*! \ingroup lattices */
    class ExtendedTian : public ExtendedBinomialTree<ExtendedTian> {
      public:
        ExtendedTian(const boost::shared_ptr<StochasticProcess1D>&,
             Time end,
             Size steps,
             Real strike);
        /*Real underlying(Size i, Size index) const {
            return x0_ * std::pow(down_, Real(BigInteger(i)-BigInteger(index)))
                       * std::pow(up_, Real(index));
        };
        Real probability(Size, Size, Size branch) const {
            return (branch == 1 ? pu_ : pd_);
        }*/

                Real underlying(Size i, Size index, Time stepTime) const;
                Real probability(Size, Size, Size branch, Time stepTime) const;

                Real upMove(Time stepTime) const;
                Real downMove(Time stepTime) const;

      protected:
        Real up_, down_, pu_, pd_;
    };

    //! Leisen & Reimer tree: multiplicative approach
    /*! \ingroup lattices */
    class ExtendedLeisenReimer : public ExtendedBinomialTree<ExtendedLeisenReimer> {
      public:
        ExtendedLeisenReimer(const boost::shared_ptr<StochasticProcess1D>&,
                     Time end,
                     Size steps,
                     Real strike);
        /*Real underlying(Size i, Size index) const {
            return x0_ * std::pow(down_, Real(BigInteger(i)-BigInteger(index)))
                       * std::pow(up_, Real(index));
        }
        Real probability(Size, Size, Size branch) const {
            return (branch == 1 ? pu_ : pd_);
        }*/

                Real underlying(Size i, Size index, Time stepTime) const;
                Real probability(Size, Size, Size branch, Time stepTime) const;

                Real upMove(Time stepTime) const;
                Real downMove(Time stepTime) const;

      protected:
        Real up_, down_, pu_, pd_, OddSteps_, Strike_, End_;
    };


         class ExtendedJoshi4 : public ExtendedBinomialTree<ExtendedJoshi4> {
      public:
        ExtendedJoshi4(const boost::shared_ptr<StochasticProcess1D>&,
               Time end,
               Size steps,
               Real strike);
        /*Real underlying(Size i, Size index) const {
            return x0_ * std::pow(down_, Real(BigInteger(i)-BigInteger(index)))
                       * std::pow(up_, Real(index));
        }
        Real probability(Size, Size, Size branch) const {
            return (branch == 1 ? pu_ : pd_);
        }*/

                Real underlying(Size i, Size index, Time stepTime) const;
                Real probability(Size, Size, Size branch, Time stepTime) const;

                Real upMove(Time stepTime) const;
                Real downMove(Time stepTime) const;

      protected:
        Real computeUpProb(Real k, Real dj) const;
        Real up_, down_, pu_, pd_, OddSteps_, Strike_, End_;
    };


}


#endif


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

/*
 Copyright (C) 2003 Ferdinando Ametrano
 Copyright (C) 2001, 2002, 2003 Sadruddin Rejeb
 Copyright (C) 2005 StatPro Italia 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
 <[hidden email]>. The license is also available online at
 <http://quantlib.org/license.shtml>.

 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.
*/

#include "extendedbinomialtree.hpp"
#include <ql/math/distributions/binomialdistribution.hpp>

namespace QuantLib {

    ExtendedJarrowRudd::ExtendedJarrowRudd(
                        const boost::shared_ptr<StochasticProcess1D>& process,
                        Time end, Size steps, Real)
    : ExtendedEqualProbabilitiesBinomialTree<ExtendedJarrowRudd>(process, end,
steps) {
        // drift removed
        up_ = process->stdDeviation(0.0, x0_, dt_);
    }

        Real ExtendedJarrowRudd::upStep(Time stepTime) const {
                return treeProcess_->stdDeviation(stepTime, x0_, dt_);
        }



    ExtendedCoxRossRubinstein::ExtendedCoxRossRubinstein(
                        const boost::shared_ptr<StochasticProcess1D>& process,
                        Time end, Size steps, Real)
    : ExtendedEqualJumpsBinomialTree<ExtendedCoxRossRubinstein>(process, end,
steps) {

                dx_ = process->stdDeviation(0.0, x0_, dt_);
                pu_ = 0.5 + 0.5*this->driftStep(0.0)/dx_;
        /*pu_ = 0.5 + 0.5*driftPerStep_/dx_;*/
        pd_ = 1.0 - pu_;

        QL_REQUIRE(pu_<=1.0, "negative probability");
        QL_REQUIRE(pu_>=0.0, "negative probability");
    }

        Real ExtendedCoxRossRubinstein::dxStep(Time stepTime) const {
                return this->treeProcess_->stdDeviation(stepTime, x0_, dt_);
        }

        Real ExtendedCoxRossRubinstein::probUp(Time stepTime) const {
                return 0.5 + 0.5*this->driftStep(stepTime)/dxStep(stepTime);
        }


        ExtendedAdditiveEQPBinomialTree::ExtendedAdditiveEQPBinomialTree(
                        const boost::shared_ptr<StochasticProcess1D>& process,
                        Time end, Size steps, Real)
    :
ExtendedEqualProbabilitiesBinomialTree<ExtendedAdditiveEQPBinomialTree>(process,
                                                              end, steps) {
        /*up_ = - 0.5 * driftPerStep_ + 0.5 *
            std::sqrt(4.0*process->variance(0.0, x0_, dt_)-
                      3.0*driftPerStep_*driftPerStep_);*/
              up_ = - 0.5 * this->driftStep(0.0) + 0.5 *
                    std::sqrt(4.0*process->variance(0.0, x0_, dt_)-
                              3.0*this->driftStep(0.0)*this->driftStep(0.0));
    }

        Real ExtendedAdditiveEQPBinomialTree::upStep(Time stepTime) const {
                return (- 0.5 * this->driftStep(stepTime) + 0.5 *
                        std::sqrt(4.0*this->treeProcess_->variance(stepTime, x0_, dt_)-
                        3.0*this->driftStep(stepTime)*this->driftStep(stepTime)));
        }




    ExtendedTrigeorgis::ExtendedTrigeorgis(
                        const boost::shared_ptr<StochasticProcess1D>& process,
                        Time end, Size steps, Real)
    : ExtendedEqualJumpsBinomialTree<ExtendedTrigeorgis>(process, end, steps) {

        /*dx_ = std::sqrt(process->variance(0.0, x0_, dt_)+
                        driftPerStep_*driftPerStep_);
        pu_ = 0.5 + 0.5*driftPerStep_/dx_;*/
                dx_ = std::sqrt(process->variance(0.0, x0_, dt_)+
                        this->driftStep(0.0)*this->driftStep(0.0));
                pu_ = 0.5 + 0.5*this->driftStep(0.0)/this->dxStep(0.0);
        pd_ = 1.0 - pu_;

        QL_REQUIRE(pu_<=1.0, "negative probability");
        QL_REQUIRE(pu_>=0.0, "negative probability");
    }

        Real ExtendedTrigeorgis::dxStep(Time stepTime) const {
                return std::sqrt(this->treeProcess_->variance(stepTime, x0_, dt_)+
                        this->driftStep(stepTime)*this->driftStep(stepTime));
        }

        Real ExtendedTrigeorgis::probUp(Time stepTime) const {
                return 0.5 + 0.5*this->driftStep(stepTime)/dxStep(stepTime);
        }


    ExtendedTian::ExtendedTian(const boost::shared_ptr<StochasticProcess1D>&
process,
               Time end, Size steps, Real)
    : ExtendedBinomialTree<ExtendedTian>(process, end, steps) {

        Real q = std::exp(process->variance(0.0, x0_, dt_));
        /*Real r = std::exp(driftPerStep_)*std::sqrt(q);*/

                Real r = std::exp(this->driftStep(0.0))*std::sqrt(q);

        up_ = 0.5 * r * q * (q + 1 + std::sqrt(q * q + 2 * q - 3));
        down_ = 0.5 * r * q * (q + 1 - std::sqrt(q * q + 2 * q - 3));

        pu_ = (r - down_) / (up_ - down_);
        pd_ = 1.0 - pu_;

        // doesn't work
        //     treeCentering_ = (up_+down_)/2.0;
        //     up_ = up_-treeCentering_;

        QL_REQUIRE(pu_<=1.0, "negative probability");
        QL_REQUIRE(pu_>=0.0, "negative probability");
    }

        Real ExtendedTian::underlying(Size i, Size index, Time stepTime) const {
                Real q = std::exp(this->treeProcess_->variance(stepTime, x0_, dt_));
                Real r = std::exp(this->driftStep(stepTime))*std::sqrt(q);

                Real up = 0.5 * r * q * (q + 1 + std::sqrt(q * q + 2 * q - 3));
                Real down = 0.5 * r * q * (q + 1 - std::sqrt(q * q + 2 * q - 3));

                return x0_ * std::pow(down, Real(BigInteger(i)-BigInteger(index)))
                        * std::pow(up, Real(index));
        }

        Real ExtendedTian::probability(Size, Size, Size branch, Time stepTime) const {
                Real q = std::exp(this->treeProcess_->variance(stepTime, x0_, dt_));
                Real r = std::exp(this->driftStep(stepTime))*std::sqrt(q);

                Real up = 0.5 * r * q * (q + 1 + std::sqrt(q * q + 2 * q - 3));
                Real down = 0.5 * r * q * (q + 1 - std::sqrt(q * q + 2 * q - 3));

                Real pu = (r - down) / (up - down);
                Real pd = 1.0 - pu;

                return (branch == 1 ? pu : pd);
        }


        Real ExtendedTian::upMove(Time stepTime) const {
                Real q = std::exp(this->treeProcess_->variance(stepTime, x0_, dt_));
                Real r = std::exp(this->driftStep(stepTime))*std::sqrt(q);

                return 0.5 * r * q * (q + 1 + std::sqrt(q * q + 2 * q - 3));
        }

        Real ExtendedTian::downMove(Time stepTime) const {
                Real q = std::exp(this->treeProcess_->variance(stepTime, x0_, dt_));
                Real r = std::exp(this->driftStep(stepTime))*std::sqrt(q);

                return 0.5 * r * q * (q + 1 - std::sqrt(q * q + 2 * q - 3));
        }




    ExtendedLeisenReimer::ExtendedLeisenReimer(
                        const boost::shared_ptr<StochasticProcess1D>& process,
                        Time end, Size steps, Real strike)
    : ExtendedBinomialTree<ExtendedLeisenReimer>(process, end, (steps%2 ? steps
: steps+1)),
        Strike_(strike), End_(end) {

        QL_REQUIRE(strike>0.0, "strike must be positive");
        Size oddSteps = (steps%2 ? steps : steps+1);
                OddSteps_ = oddSteps;
        Real variance = process->variance(0.0, x0_, end);
        /*Real ermqdt = std::exp(driftPerStep_ + 0.5*variance/oddSteps);
        Real d2 = (std::log(x0_/strike) + driftPerStep_*oddSteps ) /
                                                          std::sqrt(variance);*/
                Real ermqdt = std::exp(this->driftStep(0.0) + 0.5*variance/oddSteps);
                Real d2 = (std::log(x0_/strike) + this->driftStep(0.0)*oddSteps ) /
                        std::sqrt(variance);

        pu_ = PeizerPrattMethod2Inversion(d2, oddSteps);
        pd_ = 1.0 - pu_;
        Real pdash = PeizerPrattMethod2Inversion(d2+std::sqrt(variance),
                                                 oddSteps);
        up_ = ermqdt * pdash / pu_;
        down_ = (ermqdt - pu_ * up_) / (1.0 - pu_);

    }

        Real ExtendedLeisenReimer::underlying(Size i, Size index, Time stepTime) const {
                Real variance = this->treeProcess_->variance(stepTime, x0_, End_);
                Real ermqdt = std::exp(this->driftStep(stepTime) + 0.5*variance/OddSteps_);
                Real d2 = (std::log(x0_/Strike_) + this->driftStep(stepTime)*OddSteps_ ) /
                        std::sqrt(variance);

                Real pu = PeizerPrattMethod2Inversion(d2, OddSteps_);
                Real pd = 1.0 - pu;
                Real pdash = PeizerPrattMethod2Inversion(d2+std::sqrt(variance),
                        OddSteps_);
                Real up = ermqdt * pdash / pu;
                Real down = (ermqdt - pu * up) / (1.0 - pu);

                return x0_ * std::pow(down, Real(BigInteger(i)-BigInteger(index)))
                        * std::pow(up, Real(index));
        }
        Real ExtendedLeisenReimer::probability(Size, Size, Size branch, Time stepTime)
const {
                Real variance = this->treeProcess_->variance(stepTime, x0_, End_);
                Real ermqdt = std::exp(this->driftStep(stepTime) + 0.5*variance/OddSteps_);
                Real d2 = (std::log(x0_/Strike_) + this->driftStep(stepTime)*OddSteps_ ) /
                        std::sqrt(variance);

                Real pu = PeizerPrattMethod2Inversion(d2, OddSteps_);
                Real pd = 1.0 - pu;

                return (branch == 1 ? pu : pd);
        }

        Real ExtendedLeisenReimer::upMove(Time stepTime) const {
                Real variance = this->treeProcess_->variance(stepTime, x0_, End_);
                Real ermqdt = std::exp(this->driftStep(stepTime) + 0.5*variance/OddSteps_);
                Real d2 = (std::log(x0_/Strike_) + this->driftStep(stepTime)*OddSteps_ ) /
                        std::sqrt(variance);

                Real pu = PeizerPrattMethod2Inversion(d2, OddSteps_);
                Real pd = 1.0 - pu;
                Real pdash = PeizerPrattMethod2Inversion(d2+std::sqrt(variance),
                        OddSteps_);
                return ermqdt * pdash / pu;
        }

        Real ExtendedLeisenReimer::downMove(Time stepTime) const {
                Real variance = this->treeProcess_->variance(stepTime, x0_, End_);
                Real ermqdt = std::exp(this->driftStep(stepTime) + 0.5*variance/OddSteps_);
                Real d2 = (std::log(x0_/Strike_) + this->driftStep(stepTime)*OddSteps_ ) /
                        std::sqrt(variance);

                Real pu = PeizerPrattMethod2Inversion(d2, OddSteps_);
                Real pd = 1.0 - pu;
                Real pdash = PeizerPrattMethod2Inversion(d2+std::sqrt(variance),
                        OddSteps_);
                Real up = ermqdt * pdash / pu;
                return (ermqdt - pu * up) / (1.0 - pu);
        }



 
        Real ExtendedJoshi4::computeUpProb(Real k, Real dj) const {
                Real alpha = dj/(sqrt(8.0));
                Real alpha2 = alpha*alpha;
                Real alpha3 = alpha*alpha2;
                Real alpha5 = alpha3*alpha2;
                Real alpha7 = alpha5*alpha2;
                Real beta = -0.375*alpha-alpha3;
                Real gamma = (5.0/6.0)*alpha5 + (13.0/12.0)*alpha3
                        +(25.0/128.0)*alpha;
                Real delta = -0.1025 *alpha- 0.9285 *alpha3
                        -1.43 *alpha5 -0.5 *alpha7;
                Real p =0.5;
                Real rootk= sqrt(k);
                p+= alpha/rootk;
                p+= beta /(k*rootk);
                p+= gamma/(k*k*rootk);
                // delete next line to get results for j three tree
                p+= delta/(k*k*k*rootk);
                return p;
        }

        ExtendedJoshi4::ExtendedJoshi4(const boost::shared_ptr<StochasticProcess1D>&
process,
                   Time end, Size steps, Real strike)
    : ExtendedBinomialTree<ExtendedJoshi4>(process, end, (steps%2 ? steps :
steps+1)),
        Strike_(strike), End_(end) {

        QL_REQUIRE(strike>0.0, "strike must be positive");
        Size oddSteps = (steps%2 ? steps : steps+1);
                OddSteps_ = oddSteps;
        Real variance = process->variance(0.0, x0_, end);
        /*Real ermqdt = std::exp(driftPerStep_ + 0.5*variance/oddSteps);
        Real d2 = (std::log(x0_/strike) + driftPerStep_*oddSteps ) /
                                                          std::sqrt(variance);*/
                Real ermqdt = std::exp(this->driftStep(0.0) + 0.5*variance/oddSteps);
                Real d2 = (std::log(x0_/strike) + this->driftStep(0.0)*oddSteps ) /
                        std::sqrt(variance);

        pu_ = computeUpProb((oddSteps-1.0)/2.0,d2 );
        pd_ = 1.0 - pu_;
        Real pdash = computeUpProb((oddSteps-1.0)/2.0,d2+std::sqrt(variance));
        up_ = ermqdt * pdash / pu_;
        down_ = (ermqdt - pu_ * up_) / (1.0 - pu_);
    }

        Real ExtendedJoshi4::underlying(Size i, Size index, Time stepTime) const {
                Real variance = this->treeProcess_->variance(stepTime, x0_, End_);
                Real ermqdt = std::exp(this->driftStep(stepTime) + 0.5*variance/OddSteps_);
                Real d2 = (std::log(x0_/Strike_) + this->driftStep(stepTime)*OddSteps_ ) /
                        std::sqrt(variance);

                Real pu = computeUpProb((OddSteps_-1.0)/2.0,d2 );
                Real pd = 1.0 - pu;
                Real pdash = computeUpProb((OddSteps_-1.0)/2.0,d2+std::sqrt(variance));
                Real up = ermqdt * pdash / pu;
                Real down = (ermqdt - pu * up) / (1.0 - pu);

                return x0_ * std::pow(down, Real(BigInteger(i)-BigInteger(index)))
                        * std::pow(up, Real(index));
        }

        Real ExtendedJoshi4::probability(Size, Size, Size branch, Time stepTime) const {
                Real variance = this->treeProcess_->variance(stepTime, x0_, End_);
                Real ermqdt = std::exp(this->driftStep(stepTime) + 0.5*variance/OddSteps_);
                Real d2 = (std::log(x0_/Strike_) + this->driftStep(stepTime)*OddSteps_ ) /
                        std::sqrt(variance);

                Real pu = computeUpProb((OddSteps_-1.0)/2.0,d2 );
                Real pd = 1.0 - pu;

                return (branch == 1 ? pu : pd);
        }

        Real ExtendedJoshi4::upMove(Time stepTime) const {
                Real variance = this->treeProcess_->variance(stepTime, x0_, End_);
                Real ermqdt = std::exp(this->driftStep(stepTime) + 0.5*variance/OddSteps_);
                Real d2 = (std::log(x0_/Strike_) + this->driftStep(stepTime)*OddSteps_ ) /
                        std::sqrt(variance);

                Real pu = computeUpProb((OddSteps_-1.0)/2.0,d2 );
                Real pd = 1.0 - pu;
                Real pdash = computeUpProb((OddSteps_-1.0)/2.0,d2+std::sqrt(variance));
                return ermqdt * pdash / pu;
        }

        Real ExtendedJoshi4::downMove(Time stepTime) const {
                Real variance = this->treeProcess_->variance(stepTime, x0_, End_);
                Real ermqdt = std::exp(this->driftStep(stepTime) + 0.5*variance/OddSteps_);
                Real d2 = (std::log(x0_/Strike_) + this->driftStep(stepTime)*OddSteps_ ) /
                        std::sqrt(variance);

                Real pu = computeUpProb((OddSteps_-1.0)/2.0,d2 );
                Real pd = 1.0 - pu;
                Real pdash = computeUpProb((OddSteps_-1.0)/2.0,d2+std::sqrt(variance));
                Real up = ermqdt * pdash / pu;
                return (ermqdt - pu * up) / (1.0 - pu);
        }

}



-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev