public Trigeorgis(StochasticProcess1D process, double end, int steps, double strike)
            : base(process, end, steps)
        {
            dx_ = Math.Sqrt(process.variance(0.0, x0_, dt_) + driftPerStep_ * driftPerStep_);
            pu_ = 0.5 + 0.5 * driftPerStep_ / dx_;
            pd_ = 1.0 - pu_;

            Utils.QL_REQUIRE(pu_ <= 1.0, () => "negative probability");
            Utils.QL_REQUIRE(pu_ >= 0.0, () => "negative probability");
        }
        public TrinomialTree(StochasticProcess1D process,
                             TimeGrid timeGrid,
                             bool isPositive /*= false*/)
            : base(timeGrid.size())
        {
            branchings_ = new List <Branching>();
            dx_         = new InitializedList <double>(1);
            timeGrid_   = timeGrid;
            x0_         = process.x0();

            int nTimeSteps = timeGrid.size() - 1;
            int jMin       = 0;
            int jMax       = 0;

            for (int i = 0; i < nTimeSteps; i++)
            {
                double t  = timeGrid[i];
                double dt = timeGrid.dt(i);

                //Variance must be independent of x
                double v2 = process.variance(t, 0.0, dt);
                double v  = Math.Sqrt(v2);
                dx_.Add(v * Math.Sqrt(3.0));

                Branching branching = new Branching();
                for (int j = jMin; j <= jMax; j++)
                {
                    double x    = x0_ + j * dx_[i];
                    double m    = process.expectation(t, x, dt);
                    int    temp = (int)(Math.Floor((m - x0_) / dx_[i + 1] + 0.5));

                    if (isPositive)
                    {
                        while (x0_ + (temp - 1) * dx_[i + 1] <= 0)
                        {
                            temp++;
                        }
                    }

                    double e  = m - (x0_ + temp * dx_[i + 1]);
                    double e2 = e * e;
                    double e3 = e * Math.Sqrt(3.0);

                    double p1 = (1.0 + e2 / v2 - e3 / v) / 6.0;
                    double p2 = (2.0 - e2 / v2) / 3.0;
                    double p3 = (1.0 + e2 / v2 + e3 / v) / 6.0;

                    branching.add(temp, p1, p2, p3);
                }
                branchings_.Add(branching);

                jMin = branching.jMin();
                jMax = branching.jMax();
            }
        }
        public Tian(StochasticProcess1D process, double end, int steps, double strike)
            : base(process, end, steps)
        {
            double q = Math.Exp(process.variance(0.0, x0_, dt_));
            double r = Math.Exp(driftPerStep_) * Math.Sqrt(q);

            up_   = 0.5 * r * q * (q + 1 + Math.Sqrt(q * q + 2 * q - 3));
            down_ = 0.5 * r * q * (q + 1 - Math.Sqrt(q * q + 2 * q - 3));

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

            Utils.QL_REQUIRE(pu_ <= 1.0, () => "negative probability");
            Utils.QL_REQUIRE(pu_ >= 0.0, () => "negative probability");
        }
        public LeisenReimer(StochasticProcess1D process, double end, int steps, double strike)
            : base(process, end, (steps % 2 != 0 ? steps : steps + 1))
        {
            Utils.QL_REQUIRE(strike > 0.0, () => "strike must be positive");
            int    oddSteps = (steps % 2 != 0 ? steps : steps + 1);
            double variance = process.variance(0.0, x0_, end);
            double ermqdt   = Math.Exp(driftPerStep_ + 0.5 * variance / oddSteps);
            double d2       = (Math.Log(x0_ / strike) + driftPerStep_ * oddSteps) / Math.Sqrt(variance);

            pu_ = Utils.PeizerPrattMethod2Inversion(d2, oddSteps);
            pd_ = 1.0 - pu_;
            double pdash = Utils.PeizerPrattMethod2Inversion(d2 + Math.Sqrt(variance), oddSteps);

            up_   = ermqdt * pdash / pu_;
            down_ = (ermqdt - pu_ * up_) / (1.0 - pu_);
        }
        public Joshi4(StochasticProcess1D process, double end, int steps, double strike)
            : base(process, end, (steps % 2 != 0 ? steps : steps + 1))
        {
            Utils.QL_REQUIRE(strike > 0.0, () => "strike must be positive");

            int    oddSteps = (steps % 2 != 0 ? steps : steps + 1);
            double variance = process.variance(0.0, x0_, end);
            double ermqdt   = Math.Exp(driftPerStep_ + 0.5 * variance / oddSteps);
            double d2       = (Math.Log(x0_ / strike) + driftPerStep_ * oddSteps) / Math.Sqrt(variance);

            pu_ = computeUpProb((oddSteps - 1.0) / 2.0, d2);
            pd_ = 1.0 - pu_;
            double pdash = computeUpProb((oddSteps - 1.0) / 2.0, d2 + Math.Sqrt(variance));

            up_   = ermqdt * pdash / pu_;
            down_ = (ermqdt - pu_ * up_) / (1.0 - pu_);
        }
 public AdditiveEQPBinomialTree(StochasticProcess1D process, double end, int steps, double strike)
     : base(process, end, steps)
 {
     up_ = -0.5 * driftPerStep_ +
           0.5 * Math.Sqrt(4.0 * process.variance(0.0, x0_, dt_) - 3.0 * driftPerStep_ * driftPerStep_);
 }