Exemplo n.º 1
0
        static void Main(string[] args)
        {
            // Classes
            Interpolation      IP  = new Interpolation();
            BuildDerivativesNU BNU = new BuildDerivativesNU();
            BuildDerivativesU  BU  = new BuildDerivativesU();
            HestonPrice        HP  = new HestonPrice();
            MatrixOps          MO  = new MatrixOps();
            WeightedPriceAlgo  WP  = new WeightedPriceAlgo();

            // Settings for the option price calculation
            // 32-point Gauss-Laguerre Abscissas and weights
            double[] X = new double[32];
            double[] W = new double[32];
            using (TextReader reader = File.OpenText("../../GaussLaguerre32.txt"))
                for (int k = 0; k <= 31; k++)
                {
                    string   text = reader.ReadLine();
                    string[] bits = text.Split(' ');
                    X[k] = double.Parse(bits[0]);
                    W[k] = double.Parse(bits[1]);
                }

            // Strike price, risk free rate, dividend yield, and maturity
            double K   = 100.0;
            double r   = 0.02;
            double q   = 0.05;
            double Mat = 0.15;

            // Settings for the option price
            double S0 = 101.52;
            double V0 = 0.05412;

            // Heston parameters.  Case 1 of Hout and Foulon (Table 1)
            HParam param;

            param.kappa  = 1.50;
            param.theta  = 0.04;
            param.sigma  = 0.30;
            param.rho    = -0.90;
            param.v0     = V0;
            param.lambda = 0.00;

            // Obtain the Exact Price
            string PutCall = "C";
            int    trap    = 1;
            double HPrice  = HP.HestonPriceGaussLaguerre(param, S0, K, r, q, Mat, trap, PutCall, X, W);

            // Minimum and maximum values for the Stock Price, Volatility, and Maturity
            double Smin = 0.0; double Smax = 2.5 * K;
            double Vmin = 0.0; double Vmax = 0.5;
            double Tmin = 0.0; double Tmax = Mat;

            // Points for stock, vol, maturity
            double[] S, V;
            int      nS = 29;
            int      nV = 29;
            int      nT = 19;
            int      NS, NV, NT;

            // Select the grid type
            string GridType = "NonUniform";

            if (GridType == "Uniform")
            {
                // Increment for Stock Price, Volatility, and Maturity
                double ds = (Smax - Smin) / Convert.ToDouble(nS);
                double dv = (Vmax - Vmin) / Convert.ToDouble(nV);

                // Grid Vectors for the Stock Price, Volatility, and Maturity
                NS = nS + 1;
                NV = nV + 1;
                S  = new double[NS];
                V  = new double[NV];
                for (int s = 0; s <= NS - 1; s++)
                {
                    S[s] = Convert.ToDouble(s) * ds;
                }
                for (int v = 0; v <= NV - 1; v++)
                {
                    V[v] = Convert.ToDouble(v) * dv;
                }
            }
            else //if (GridType == "NonUniform")
            {
                // The stock price grid
                double   c  = K / 5.0;
                double   dz = 1.0 / nS * (IP.aSinh((Smax - K) / c) - IP.aSinh(-K / c));
                double[] z  = new double[nS + 1];
                S = new double[nS + 1];
                for (int i = 0; i <= nS; i++)
                {
                    z[i] = IP.aSinh(-K / c) + Convert.ToDouble(i) * dz;
                    S[i] = K + c * Math.Sinh(z[i]);
                }
                S[0] = 0.0;

                // The volatility grid
                double   d  = Vmax / 10.0;
                double   dn = IP.aSinh(Vmax / d) / nV;
                double[] n  = new double[nV + 1];
                V = new double[nV + 1];
                for (int j = 0; j <= nV; j++)
                {
                    n[j] = Convert.ToDouble(j) * dn;
                    V[j] = d * Math.Sinh(n[j]);
                }
                NS = nS + 1;
                NV = nV + 1;
            }

            // The maturity time increment and grid
            NT = nT + 1;
            double[] T  = new double[NT];
            double   dt = (Tmax - Tmin) / Convert.ToDouble(nT);

            for (int i = 0; i <= nT; i++)
            {
                T[i] = Convert.ToDouble(i) * dt;
            }


            // Obtain the submatrices of L
            LMatrices LMat;

            if (GridType == "Uniform")
            {
                LMat = BU.BuildDerivatives(S, V, T);
            }
            else
            {
                LMat = BNU.BuildDerivativesNonUniform(S, V, T);
            }
            double[,] derS  = LMat.derS;
            double[,] derSS = LMat.derSS;
            double[,] derV1 = LMat.derV1;
            double[,] derV2 = LMat.derV2;
            double[,] derVV = LMat.derVV;
            double[,] derSV = LMat.derSV;
            double[,] R     = LMat.R;

            // Build the L matrix
            int N = NS * NV;

            double[,] L = new double[N, N];
            for (int i = 0; i <= N - 1; i++)
            {
                for (int j = 0; j <= N - 1; j++)
                {
                    L[i, j] = (r - q) * derS[i, j] + param.kappa * param.theta * derV1[i, j] - param.kappa * derV2[i, j] + 0.5 * derSS[i, j]
                              + 0.5 * param.sigma * param.sigma * derVV[i, j] + param.rho * param.sigma * derSV[i, j] - r * R[i, j];
                }
            }

            // Identity and A and B matrix
            double[,] I    = new double[N, N];
            double[,] A    = new double[N, N];
            double[,] B    = new double[N, N];
            double[,] invA = new double[N, N];
            for (int i = 0; i <= N - 1; i++)
            {
                I[i, i] = 1.0;
            }

            // Settings for the clock
            Stopwatch sw = new Stopwatch();
            TimeSpan  ts = sw.Elapsed;

            // Obtain the Explicit, Implicit, and Crank-Nicolson prices
            double[] thet  = { 0.0, 1.0, 0.5 };
            double[] Price = new double[3];
            double[] Error = new double[3];
            for (int k = 0; k <= 2; k++)
            {
                for (int i = 0; i <= N - 1; i++)
                {
                    for (int j = 0; j <= N - 1; j++)
                    {
                        A[i, j] = I[i, j] - thet[k] * dt * L[i, j];
                        B[i, j] = I[i, j] + (1.0 - thet[k]) * dt * L[i, j];
                    }
                }
                sw.Reset();
                sw.Start();
                if (thet[k] == 0.0)
                {
                    invA = MO.CreateI(N);
                }
                else
                {
                    invA = MO.MInvLU(A);
                }
                ts = sw.Elapsed;
                Console.WriteLine("Calculated the inverse in {0:0}-{1:0}-{2:0} min-sec-msec", ts.Minutes, ts.Seconds, ts.Milliseconds);
                Price[k] = WP.WeightedPrice(thet[k], L, S0, V0, K, r, q, Mat, S, V, T, A, invA, B);
                Error[k] = Price[k] - HPrice;
            }
            // Output the results
            Console.WriteLine("-------------------------------------------------");
            Console.WriteLine("Grid type    : {0}", GridType);
            Console.WriteLine("-------------------------------------------------");
            Console.WriteLine("Stock price grid size of {0:0} ", NS);
            Console.WriteLine("Volatility grid size of  {0:0} ", NV);
            Console.WriteLine("Number of time steps     {0:0} ", NT);
            Console.WriteLine("-------------------------------------------------");
            Console.WriteLine("Method                    Price      Dollar Error");
            Console.WriteLine("-------------------------------------------------");
            Console.WriteLine("Closed form              {0,5:F4}", HPrice);
            Console.WriteLine("Explicit method          {0,5:F4} {1,10:F4}", Price[0], Error[0]);
            Console.WriteLine("Implicit method          {0,5:F4} {1,10:F4}", Price[1], Error[1]);
            Console.WriteLine("Crank Nicolson           {0,5:F4} {1,10:F4}", Price[2], Error[2]);
            Console.WriteLine("-------------------------------------------------");
        }
        public double WeightedPrice(double thet, double[,] L, double S0, double V0, double K, double r, double q, double Mat, double[] S, double[] V, double[] T, double[,] A, double[,] invA, double[,] B)
        {
            // Heston Call price using the Weighted Method
            // Requires a uniform grid for the stock price, volatility, and maturity
            // INPUTS
            //   thet = theta parameter for the Weighted method
            //   L    = operator matrix for the Heston model
            //   params = vector of Heston parameters
            //   S0 = Spot price at which to price the call
            //   V0 = variance at which to price the call
            //   K  = Strike price
            //   r  = risk free rate
            //   q  = dividend yield
            //   Mat = maturity
            //   S = uniform grid for the stock price
            //   V = uniform grid for the volatility
            //   T = uniform grid for the maturity
            //   A = "A" matrix for weighted method
            //   invA = A inverse
            //   B = "B" matrix for weighted method
            // OUTPUT
            //   y = 2-D interpolated European Call price

            MatrixOps     MO = new MatrixOps();
            Interpolation IP = new Interpolation();

            // Required vector lengths and time increment
            int    NS = S.Length;
            int    NV = V.Length;
            int    NT = T.Length;
            double dt = T[1] - T[0];

            // Identity matrix
            int N = NS * NV;

            double[,] I = MO.CreateI(N);

            // Initialize the U and u vectors
            double[] U = new double[N];
            double[] u = new double[N];

            // U(0) vector - value of U(T) at maturity
            double[] Si = new double[N];
            int      k  = 0;

            for (int v = 0; v <= NV - 1; v++)
            {
                for (int s = 0; s <= NS - 1; s++)
                {
                    Si[k] = S[s];
                    U[k]  = Math.Max(Si[k] - K, 0.0);
                    k    += 1;
                }
            }

            // Loop through the time increments, updating U(t) to U(t+1) at each step
            for (int t = 2; t <= NT; t++)
            {
                for (k = 0; k <= N - 1; k++)
                {
                    u[k] = U[k];
                }
                if (thet == 0.0)
                {
                    U = MO.MVMult(B, u);                    // Explicit Method
                }
                else if (thet == 1.0)
                {
                    U = MO.MVMult(invA, u);                 // Implicit Method
                }
                else
                {
                    U = MO.MVMult(invA, MO.MVMult(B, u));       // Weighted Methods
                }
            }

            // Restack the U vector to output a matrix
            double[,] UU = new double[NS, NV];
            k            = 0;
            for (int v = 0; v <= NV - 1; v++)
            {
                for (int s = 0; s <= NS - 1; s++)
                {
                    UU[s, v] = U[k];
                    k       += 1;
                }
            }

            // Interpolate to get the price at S0 and v0
            return(IP.interp2(V, S, UU, V0, S0));
        }