コード例 #1
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));
            }
        }
コード例 #2
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);
            }
        }