public Vector solve_splitting(Vector r, double a, double b = 1.0)
        {
            FdmLinearOpLayout layout = mesher_.layout();

            Utils.QL_REQUIRE(r.size() == layout.size(), () => "inconsistent size of rhs");

            for (FdmLinearOpIterator iter = layout.begin();
                 iter != layout.end(); ++iter)
            {
                List <int> coordinates = iter.coordinates();
                Utils.QL_REQUIRE(coordinates[direction_] != 0 ||
                                 lower_[iter.index()] == 0, () => "removing non zero entry!");
                Utils.QL_REQUIRE(coordinates[direction_] != layout.dim()[direction_] - 1 ||
                                 upper_[iter.index()] == 0, () => "removing non zero entry!");
            }

            Vector retVal = new Vector(r.size()), tmp = new Vector(r.size());

            // Thomson algorithm to solve a tridiagonal system.
            // Example code taken from Tridiagonalopertor and
            // changed to fit for the triple band operator.
            int    rim1 = reverseIndex_[0];
            double bet  = 1.0 / (a * diag_[rim1] + b);

            Utils.QL_REQUIRE(bet != 0.0, () => "division by zero");
            retVal[reverseIndex_[0]] = r[rim1] * bet;

            for (int j = 1; j <= layout.size() - 1; j++)
            {
                int ri = reverseIndex_[j];
                tmp[j] = a * upper_[rim1] * bet;

                bet = b + a * (diag_[ri] - tmp[j] * lower_[ri]);
                Utils.QL_REQUIRE(bet != 0.0, () => "division by zero"); //QL_ENSURE
                bet = 1.0 / bet;

                retVal[ri] = (r[ri] - a * lower_[ri] * retVal[rim1]) * bet;
                rim1       = ri;
            }
            // cannot be j>=0 with Size j
            for (int j = layout.size() - 2; j > 0; --j)
            {
                retVal[reverseIndex_[j]] -= tmp[j + 1] * retVal[reverseIndex_[j + 1]];
            }
            retVal[reverseIndex_[0]] -= tmp[1] * retVal[reverseIndex_[1]];

            return(retVal);
        }
Example #2
0
        protected Vector getLeverageFctSlice(double t1, double t2)
        {
            FdmLinearOpLayout layout = mesher_.layout();
            Vector            v      = new Vector(layout.size(), 1.0);

            if (leverageFct_ == null)
            {
                return(v);
            }

            double t    = 0.5 * (t1 + t2);
            double time = Math.Min(leverageFct_ == null ? 1000.0 : leverageFct_.maxTime(), t);

            FdmLinearOpIterator endIter = layout.end();

            for (FdmLinearOpIterator iter = layout.begin();
                 iter != endIter; ++iter)
            {
                int nx = iter.coordinates()[0];

                if (iter.coordinates()[1] == 0)
                {
                    double x    = Math.Exp(mesher_.location(iter, 0));
                    double spot = Math.Min(leverageFct_ == null ? 100000.0 : leverageFct_.maxStrike(),
                                           Math.Max(leverageFct_ == null ? -100000.0 : leverageFct_.minStrike(), x));
                    v[nx] = Math.Max(0.01, leverageFct_ == null ? 0.0 : leverageFct_.localVol(time, spot, true));
                }
                else
                {
                    v[iter.index()] = v[nx];
                }
            }
            return(v);
        }
        public override Vector apply(Vector r)
        {
            FdmLinearOpLayout index = mesher_.layout();

            Utils.QL_REQUIRE(r.size() == index.size(), () => "inconsistent length of r");

            Vector retVal = new Vector(r.size());

            //#pragma omp parallel for
            for (int i = 0; i < index.size(); ++i)
            {
                retVal[i] = r[i0_[i]] * lower_[i] + r[i] * diag_[i] + r[i2_[i]] * upper_[i];
            }

            return(retVal);
        }
Example #4
0
        public override SparseMatrix toMatrix()
        {
            FdmLinearOpLayout index = mesher_.layout();
            int n = index.size();

            SparseMatrix retVal = new SparseMatrix(n, n);

            for (int i = 0; i < index.size(); ++i)
            {
                retVal[i, i00_[i]] += a00_[i];
                retVal[i, i01_[i]] += a01_[i];
                retVal[i, i02_[i]] += a02_[i];
                retVal[i, i10_[i]] += a10_[i];
                retVal[i, i]       += a11_[i];
                retVal[i, i12_[i]] += a12_[i];
                retVal[i, i20_[i]] += a20_[i];
                retVal[i, i21_[i]] += a21_[i];
                retVal[i, i22_[i]] += a22_[i];
            }

            return(retVal);
        }
Example #5
0
        public override Vector apply(Vector r)
        {
            FdmLinearOpLayout index = mesher_.layout();

            Utils.QL_REQUIRE(r.size() == index.size(), () => "inconsistent length of r "
                             + r.size() + " vs " + index.size());

            Vector retVal = new Vector(r.size());

            //#pragma omp parallel for
            for (int i = 0; i < retVal.size(); ++i)
            {
                retVal[i] = a00_[i] * r[i00_[i]]
                            + a01_[i] * r[i01_[i]]
                            + a02_[i] * r[i02_[i]]
                            + a10_[i] * r[i10_[i]]
                            + a11_[i] * r[i]
                            + a12_[i] * r[i12_[i]]
                            + a20_[i] * r[i20_[i]]
                            + a21_[i] * r[i21_[i]]
                            + a22_[i] * r[i22_[i]];
            }
            return(retVal);
        }
        public override SparseMatrix toMatrix()
        {
            FdmLinearOpLayout index = mesher_.layout();
            int n = index.size();

            SparseMatrix retVal = new SparseMatrix(n, n);

            for (int i = 0; i < n; ++i)
            {
                retVal[i, i0_[i]] += lower_[i];
                retVal[i, i]      += diag_[i];
                retVal[i, i2_[i]] += upper_[i];
            }

            return(retVal);
        }
        public TripleBandLinearOp multR(Vector u)
        {
            FdmLinearOpLayout layout = mesher_.layout();
            int size = layout.size();

            Utils.QL_REQUIRE(u.size() == size, () => "inconsistent size of rhs");
            TripleBandLinearOp retVal = new TripleBandLinearOp(direction_, mesher_);

            for (int i = 0; i < size; ++i)
            {
                double sm1 = i > 0 ? u[i - 1] : 1.0;
                double s0  = u[i];
                double sp1 = i < size - 1 ? u[i + 1] : 1.0;
                retVal.lower_[i] = lower_[i] * sm1;
                retVal.diag_[i]  = diag_[i] * s0;
                retVal.upper_[i] = upper_[i] * sp1;
            }

            return(retVal);
        }
Example #8
0
        //! Time \f$t1 <= t2\f$ is required
        public override void setTime(double t1, double t2)
        {
            double r = rTS_.forwardRate(t1, t2, Compounding.Continuous).rate();
            double q = qTS_.forwardRate(t1, t2, Compounding.Continuous).rate();

            if (localVol_ != null)
            {
                FdmLinearOpLayout   layout  = mesher_.layout();
                FdmLinearOpIterator endIter = layout.end();

                Vector v = new Vector(layout.size());
                for (FdmLinearOpIterator iter = layout.begin();
                     iter != endIter; ++iter)
                {
                    int i = iter.index();

                    if (illegalLocalVolOverwrite_ == null)
                    {
                        double t = localVol_.localVol(0.5 * (t1 + t2), x_[i], true);
                        v[i] = t * t;
                    }
                    else
                    {
                        try
                        {
                            double t = localVol_.localVol(0.5 * (t1 + t2), x_[i], true);
                            v[i] = t * t;
                        }
                        catch
                        {
                            v[i] = illegalLocalVolOverwrite_.Value * illegalLocalVolOverwrite_.Value;
                        }
                    }
                }
                if (quantoHelper_ != null)
                {
                    mapT_.axpyb(r - q - 0.5 * v
                                - quantoHelper_.quantoAdjustment(Vector.Sqrt(v), t1, t2),
                                dxMap_,
                                dxxMap_.mult(0.5 * v), new Vector(1, -r));
                }
                else
                {
                    mapT_.axpyb(r - q - 0.5 * v, dxMap_,
                                dxxMap_.mult(0.5 * v), new Vector(1, -r));
                }
            }
            else
            {
                double vv = volTS_.blackForwardVariance(t1, t2, strike_) / (t2 - t1);

                if (quantoHelper_ != null)
                {
                    mapT_.axpyb(new Vector(1, r - q - 0.5 * vv)
                                - quantoHelper_.quantoAdjustment(new Vector(1, Math.Sqrt(vv)), t1, t2),
                                dxMap_,
                                dxxMap_.mult(0.5 * new Vector(mesher_.layout().size(), vv)),
                                new Vector(1, -r));
                }
                else
                {
                    mapT_.axpyb(new Vector(1, r - q - 0.5 * vv), dxMap_,
                                dxxMap_.mult(0.5 * new Vector(mesher_.layout().size(), vv)),
                                new Vector(1, -r));
                }
            }
        }