Example #1
0
        // Returns option prices lattice as a two-dimensional array
        private static double[,] createLattice(double S, double K, double sigma, double r, double q, OptionType type, OptionExerciseType exerciseType, int nSteps, double dt) {
            double upFactor = Math.Pow(Math.E, sigma * Math.Sqrt(2 * dt));
            double downFactor = 1 / upFactor;

            double temp_1 = 0.5 * (r - q) * dt;
            double temp_2 = sigma * Math.Sqrt(0.5 * dt);
            double pu = Math.Pow((Math.Pow(Math.E, temp_1) - Math.Pow(Math.E, -temp_2)) / (Math.Pow(Math.E, temp_2) - Math.Pow(Math.E, -temp_2)), 2); // probability of an up-move
            double pd = Math.Pow((Math.Pow(Math.E, temp_2) - Math.Pow(Math.E, temp_1)) / (Math.Pow(Math.E, temp_2) - Math.Pow(Math.E, -temp_2)), 2); // probability of a down-move
            double pm = 1.0 - pu - pd; // probability that the price will stay the same

            double[,] underlyingPrice = new double[nSteps + 1, 2 * nSteps + 1]; // a matrix containing underlying prices of the underlying at each step
            double[,] lattice = new double[nSteps + 1, 2 * nSteps + 1]; // a matrix containing option prices of the underlying at each step

            // Build trinomial tree
            for (int i = 0; i <= nSteps; i++) {
                for (int j = 0; j <= 2 * i; j++) {
                    underlyingPrice[i, j] = S * Math.Pow(upFactor, j - i);
                }
            }

            // Initialise option prices at maturity
            for (int i = 0; i <= 2 * nSteps; i++) {
                if (type == OptionType.Call) {
                    lattice[nSteps, i] = Math.Max(underlyingPrice[nSteps, i] - K, 0);
                }
                else {
                    lattice[nSteps, i] = Math.Max(K - underlyingPrice[nSteps, i], 0);
                }
            }

            // Step back through the tree
            for (int i = nSteps - 1; i >= 0; i--) {
                for (int j = 0; j <= 2 * i; j++) {
                    if (exerciseType == OptionExerciseType.European) { // if European
                        lattice[i, j] = Math.Pow(Math.E, -r * dt) * (pu * lattice[i + 1, j + 2] + pm * lattice[i + 1, j + 1] + pd * lattice[i + 1, j]);
                    }
                    else
                    { // if American
                        if (type == OptionType.Call) // if a call
                            lattice[i, j] = Math.Max(underlyingPrice[i, j] - K, Math.Pow(Math.E, -r * dt) * (pu * lattice[i + 1, j + 2] + pm * lattice[i + 1, j + 1] + pd * lattice[i + 1, j]));
                        else // if a put
                            lattice[i, j] = Math.Max(K - underlyingPrice[i, j], Math.Pow(Math.E, -r * dt) * (pu * lattice[i + 1, j + 2] + pm * lattice[i + 1, j + 1] + pd * lattice[i + 1, j]));
                    }
                }
            }
            return lattice;
        }
        // Returns option prices lattice as a two-dimensional array
        private static double[,] createLattice(double S, double K, double sigma, double r, double q, OptionType type, OptionExerciseType exerciseType, int nTimeSteps, double dt, int nPriceSteps, double dS) {
            double[] underlyingPrice = new double[nPriceSteps + 1]; // an array containing underlying prices of the underlying at each step
            double[,] lattice = new double[nTimeSteps + 1, nPriceSteps + 1]; // a matrix containing option prices of the underlying at each step

            double pu, pd, pm; // probabilities of an up-move, a down-move and that the price will stay the same

            // Build stock price grid
            for (int i = 0; i <= nPriceSteps; i++) {
                underlyingPrice[i] = i * dS;
            }

            // Initialise option prices at maturity
            for (int i = 0; i <= nPriceSteps; i++) {
                if (type == OptionType.Call) {
                    lattice[nTimeSteps, i] = Math.Max(underlyingPrice[i] - K, 0);
                }
                else {
                    lattice[nTimeSteps, i] = Math.Max(K - underlyingPrice[i], 0);
                }
            }

            // Step back through the tree
            for (int i = nTimeSteps - 1; i >= 0; i--) {
                for (int j = 1; j <= nPriceSteps - 1; j++) { // loop from S = 1 to S = (nPriceSteps - 1), because S = 0 and S = nPriceSteps will have boundary conditions
                    pu = 0.5 * (sigma * sigma * j * j + (r - q) * j )* dt;
                    pd = 0.5 * (sigma * sigma * j * j - (r - q) * j) * dt;
                    pm = 1 - sigma * sigma * j * j * dt;

                    lattice[i, 0] = 0; // boundary condition at S = 0
                    lattice[i, nPriceSteps] = underlyingPrice[nPriceSteps] - K * Math.Pow(Math.E, -r * (nTimeSteps - i) * dt); // boundary condition at S = nPriceSteps
                    
                    // Alternative boundary conditions from Paul Wilmott (do not work yet)
                    //lattice[i, 0] = (1 - r * dt) * lattice[i + 1, 0];
                    //lattice[i, nPriceSteps] = 2 * lattice[i, nPriceSteps - 1] - lattice[i, nPriceSteps - 2];

                    if (exerciseType == OptionExerciseType.European)
                        lattice[i, j] = Math.Pow(Math.E, -r * dt) * (pu * lattice[i + 1, j + 1] + pm * lattice[i + 1, j] + pd * lattice[i + 1, j - 1]);
                    else {
                        if (type == OptionType.Call) // if American call
                            lattice[i, j] = Math.Max(underlyingPrice[j] - K, Math.Pow(Math.E, -r * dt) * (pu * lattice[i + 1, j + 1] + pm * lattice[i + 1, j] + pd * lattice[i + 1, j - 1]));
                        else // if American put
                            lattice[i, j] = Math.Max(K - underlyingPrice[j], Math.Pow(Math.E, -r * dt) * (pu * lattice[i + 1, j + 1] + pm * lattice[i + 1, j] + pd * lattice[i + 1, j - 1]));
                    }
                }
            }
            return lattice;
        }
Example #3
0
        // Returns option prices lattice as a two-dimensional array
        private static double[,] createLattice(double S, double K, double sigma, double r, double q, OptionType type, OptionExerciseType exerciseType, int nSteps, double dt) {
            double upFactor = Math.Pow(Math.E, sigma * Math.Sqrt(dt));
            double downFactor = 1 / upFactor;
            double p = (Math.Pow(Math.E, (r - q) * dt) - downFactor) / (upFactor - downFactor); // probability of an up-move

            double[,] underlyingPrice = new double[nSteps + 1, nSteps + 1]; // a matrix containing underlying prices of the underlying at each step
            double[,] lattice = new double[nSteps + 1, nSteps + 1]; // a matrix containing option prices of the underlying at each step

            // Build binomial tree
            for (int i = 0; i <= nSteps; i++) {
                for (int j = 0; j <= i; j++) {
                    underlyingPrice[i, j] = S * Math.Pow(upFactor, j) * Math.Pow(downFactor, i - j);
                }
            }

            // Initialise option prices at maturity
            for (int i = 0; i <= nSteps; i++) {
                if (type == OptionType.Call) {
                    lattice[nSteps, i] = Math.Max(underlyingPrice[nSteps, i] - K, 0);
                }
                else {
                    lattice[nSteps, i] = Math.Max(K - underlyingPrice[nSteps, i], 0);
                }
            }

            // Step back through the tree
            for (int i = nSteps - 1; i >= 0; i--) {
                for (int j = 0; j <= i; j++) {
                    if (exerciseType == OptionExerciseType.European) { // if European
                        lattice[i, j] = Math.Pow(Math.E, -r * dt) * (p * lattice[i + 1, j + 1] + (1 - p) * lattice[i + 1, j]);
                    }
                    else { // if American
                        if (type == OptionType.Call) // if a call
                            lattice[i, j] = Math.Max(underlyingPrice[i, j] - K, Math.Pow(Math.E, -r * dt) * (p * lattice[i + 1, j + 1] + (1 - p) * lattice[i + 1, j]));
                        else // if a put
                            lattice[i, j] = Math.Max(K - underlyingPrice[i, j], Math.Pow(Math.E, -r * dt) * (p * lattice[i + 1, j + 1] + (1 - p) * lattice[i + 1, j]));
                    }
                }
            }
            return lattice;
        }