Ejemplo n.º 1
0
        public void constructLinearSystem(BlkSch BS, SparseLinearSystem SPS)
        {
            BoundaryCondition[] bc  = BS.bc;
            double[]            rhs = SPS.b;
            double c2 = BS.c2;
            double c1 = BS.c1;
            double c0 = BS.c0;

            double[] x   = BS.x;
            double[] sol = BS.sol;
            SPS.solution = BS.sol;
            double[] source = BS.source;
            int      n      = BS.sol.Length;

            applyBoundaryCondition(BS, bc[0], SPS.lower_bc, rhs, x, DIR.LOWER);
            applyBoundaryCondition(BS, bc[1], SPS.upper_bc, rhs, x, DIR.UPPER);
            for (int i = 1; i < n - 1; ++i)
            {
                double alpha = 2 * c2 * x[i] * x[i] / ((x[i] - x[i - 1]) * (x[i + 1] - x[i - 1])) - c1 * x[i] / (x[i + 1] - x[i - 1]);
                double beta  = 2 * c2 * x[i] * x[i] / ((x[i + 1] - x[i]) * (x[i + 1] - x[i - 1])) + c1 * x[i] / (x[i + 1] - x[i - 1]);
                SPS.L[i - 1] = -alpha * theta * dt;
                SPS.D[i - 1] = 1 + (alpha + beta - c0) * theta * dt;
                SPS.R[i - 1] = -beta * theta * dt;
                rhs[i]       = sol[i - 1] * alpha * (1 - theta) * dt
                               + sol[i] * (1 - (alpha + beta - c0) * (1 - theta) * dt)
                               + sol[i + 1] * beta * (1 - theta) * dt;
                if (source != null)
                {
                    rhs[i] += source[i] * dt;
                }
            }
        }
Ejemplo n.º 2
0
        static public void AmericanPutOptionTest()
        {
            double sigma = 0.8;
            double E     = 100;
            double T     = 0.25;
            double dt    = 2e-4;
            double r     = 0.1;
            int    N     = 800;

            double[] sol = new double[N];
            double[] x   = new double[N];
            linspace(x, 0, 500, N);

            //construct BlackScholes equaiton
            BlkSch[]            bs = new BlkSch[1];
            BoundaryCondition[] bc = new BoundaryCondition[2];
            bc[0]              = new BoundaryCondition(); bc[1] = new BoundaryCondition();
            bc[0].bc_type      = BoundaryCondition.BC_Type.Dirichlet;
            bc[0].bc_values[0] = Math.Max(E - x[0], 0);

            //bc[1].bc_type = BoundaryCondition.BC_Type.Dirichlet;
            bc[1].bc_type      = BoundaryCondition.BC_Type.LargeS;
            bc[1].bc_values[0] = Math.Max(E - x.Last(), 0);

            for (int i = 0; i < sol.Length; ++i)
            {
                sol[i] = Math.Max(E - x[i], 0);
            }

            Action <double[][], int> constrain = new Action <double[][], int>((V, i) =>
            {
                V[0][i] = Math.Max(V[0][i], Math.Max(E - x[i], 0));
            });

            bs[0] = new BlkSch(sol, x, sigma * sigma / 2, r, -r, null, bc);
            BS_PSOR bs_solver = new BS_PSOR(bs, constrain, BS_PSOR.Scheme.CrankNicolson);

            double t = T;

            while (t > 0)
            {
                Console.WriteLine("t = {0}", t);
                if (t - dt < 0)
                {
                    dt = t;
                }
                t = t - dt;
                bs_solver.advance(dt);
                bs_solver.printSolution("AmPut.txt", sol);
                Console.WriteLine("price(100) = {0}", bs_solver.getPrice(bs[0], 100));
            }
        }
Ejemplo n.º 3
0
 public double getPrice(BlkSch bs, double s)
 {
     double[] sol = bs.sol;
     double[] x   = bs.x;
     for (int i = 1; i < sol.Length; ++i)
     {
         if (x[i - 1] <= s && x[i] >= s)
         {
             return((x[i] - s) / (x[i] - x[i - 1]) * sol[i - 1]
                    + (s - x[i - 1]) / (x[i] - x[i - 1]) * sol[i]);
         }
     }
     return(0);
 }
Ejemplo n.º 4
0
        void applyBoundaryCondition(BlkSch bs, BoundaryCondition bc, double[] coef, double[] rhs, double[] x, DIR dir)
        {
            switch (bc.bc_type)
            {
            case BoundaryCondition.BC_Type.ZeroS:
                if (dir == DIR.UPPER)
                {
                    throw new InvalidEnumArgumentException("Cannot use zero boundary on upper side");
                }
                coef[0] = 1 - bs.c0 * theta * dt;
                rhs[0]  = (1 + bs.c0 * (1 - theta) * dt) * bs.sol[0];
                if (bs.source != null)
                {
                    rhs[0] += bs.source[0] * dt;
                }
                break;

            case BoundaryCondition.BC_Type.LargeS:
                if (dir == DIR.LOWER)
                {
                    throw new InvalidEnumArgumentException("Cannot use large s boundary on lower side");
                }
                else
                {
                    int m = x.Length - 1;
                    rhs[m]      = 0;
                    coef[m - 2] = -1; coef[m - 1] = 2; coef[m] = -1;
                }
                break;

            case BoundaryCondition.BC_Type.Dirichlet:
                if (dir == DIR.LOWER)
                {
                    rhs[0]  = bc.bc_values[0];
                    coef[0] = 1;
                }
                else
                {
                    int m = x.Length - 1;
                    rhs[m]  = bc.bc_values[0];
                    coef[m] = 1;
                }
                break;
            }
        }
Ejemplo n.º 5
0
        static public void ConvertibleBondTest()
        {
            double sigma = 0.2;
            double rc    = 0.02;
            double r     = 0.05;
            double rg    = 0.02;

            double[] coupon_dates = new double[10];
            linspace(coupon_dates, 0.5, 5, 10);
            double Bc_clean = 110;
            double Bp_clean = 105;
            double Bc       = Bc_clean;
            double Bp       = Bp_clean;

            double[] CallInterval = new double[2] {
                1, 5
            };
            double[] PutInterval = new double[2] {
                2, 3
            };
            double F      = 101;
            double Coupon = 4;
            double kappa  = 1.0;
            double T      = 5;
            int    N      = 4000;

            double[] CB   = new double[N];
            double[] COCB = new double[N];
            double[] x    = new double[N];
            linspace(x, 0, 5 * F, N);

            BlkSch[] bs = new BlkSch[2];
            //construct Black Scholes equation for CB
            BoundaryCondition[] CB_bc = new BoundaryCondition[2];
            CB_bc[0]              = new BoundaryCondition(); CB_bc[1] = new BoundaryCondition();
            CB_bc[0].bc_type      = BoundaryCondition.BC_Type.ZeroS;
            CB_bc[1].bc_type      = BoundaryCondition.BC_Type.Dirichlet;
            CB_bc[1].bc_values[0] = kappa * x.Last();
            double[] minus_rcB = new double[N];
            bs[0] = new BlkSch(CB, x, 0.5 * sigma * sigma, rg, -r, minus_rcB, CB_bc);

            //construct Black Scholes equation for COCB
            BoundaryCondition[] COCB_bc = new BoundaryCondition[2];
            COCB_bc[0]              = new BoundaryCondition(); COCB_bc[1] = new BoundaryCondition();
            COCB_bc[0].bc_type      = BoundaryCondition.BC_Type.ZeroS;
            COCB_bc[1].bc_type      = BoundaryCondition.BC_Type.Dirichlet;
            COCB_bc[1].bc_values[0] = 0;
            bs[1] = new BlkSch(COCB, x, 0.5 * sigma * sigma, rg, -(r + rc), null, COCB_bc);

            //setup constrain
            Action <double[][], int> constrain = new Action <double[][], int>((V, i) => {
                double[] cb   = V[0];
                double[] cocb = V[1];
                //upside constrain due to callability
                double tmp = Math.Max(Bc, kappa * x[i]);
                if (cb[i] > tmp)
                {
                    cb[i]   = tmp;
                    cocb[i] = 0;
                }

                //downside constrain due to puttability
                if (cb[i] < Bp)
                {
                    cb[i]   = Bp;
                    cocb[i] = Bp;
                }

                //upside constrain due to conversion
                tmp = kappa * x[i];
                if (cb[i] < tmp)
                {
                    cb[i]   = tmp;
                    cocb[i] = 0;
                }
            });

            //setup initial condition
            for (int i = 0; i < N; ++i)
            {
                CB[i]   = (kappa * x[i] >= F + Coupon) ? kappa * x[i] : F + Coupon;
                COCB[i] = (kappa * x[i] >= F + Coupon) ? 0.0 : F + Coupon;
            }

            //construct solver
            BS_PSOR solver = new BS_PSOR(bs, constrain);

            //advance solution backwards from maturity to t = 0;
            double t            = T;
            double dt           = 1.0 / 365;
            int    coupon_index = coupon_dates.Length - 1;
            string CBoutput     = "CBsol.txt";
            string COCBoutput   = "COCBsol.txt";

            System.IO.File.WriteAllText(CBoutput, string.Empty);
            System.IO.File.WriteAllText(COCBoutput, string.Empty);
            solver.printSolution(CBoutput, CB);
            solver.printSolution(COCBoutput, COCB);
            Console.WriteLine("t = {0}, dt = {1}", t, dt);
            while (t > 0)
            {
                if (t - dt < 0)
                {
                    dt = t;
                }
                //update source term
                for (int i = 0; i < N; ++i)
                {
                    minus_rcB[i] = -rc * COCB[i];
                }

                //update coefficients

                //update call price
                if (PutInterval != null && t >= PutInterval[0] && t <= PutInterval[1])
                {
                    Bp = Bp_clean + AccI(t, coupon_dates, Coupon);
                }
                else
                {
                    Bp = 0;
                }

                //update put price
                if (CallInterval != null && t >= CallInterval[0] && t <= CallInterval[1])
                {
                    Bc = Bc_clean + AccI(t, coupon_dates, Coupon);
                }
                else
                {
                    Bc = double.MaxValue;
                }

                //advance solution
                solver.advance(dt);

                //compute Coupon between [t-dt, t];
                while (coupon_index >= 0 && coupon_dates[coupon_index] >= t - dt && coupon_dates[coupon_index] <= t)
                {
                    Console.WriteLine("Paying coupon {0} at {1}", Coupon, coupon_dates[coupon_index]);
                    for (int i = 0; i < CB.Length; ++i)
                    {
                        CB[i]   += Coupon;
                        COCB[i] += Coupon;
                    }
                    coupon_index--;
                }
                t = t - dt;
                Console.WriteLine("t = {0}, dt = {1}", t, dt);
                Console.WriteLine("price(100) = {0}", solver.getPrice(bs[0], 100));
                //solver.printSolution(CBoutput, CB);
                //solver.printSolution(COCBoutput, COCB);
            }
        }