// Heston Price by Gauss-Legendre Integration public OutputMD HestonPriceGaussLegendreMD(HParam param, OpSet settings, double[] xGLe, double[] wGLe, double[] A, double tol) { int nA = A.Length; int nX = xGLe.Length; double[,] int1 = new double[nA, nX]; double[,] int2 = new double[nA, nX]; double[] sum1 = new double[nA]; double[] sum2 = new double[nA]; // Numerical integration HestonPrice HP = new HestonPrice(); int nj = 0; for (int j = 1; j <= nA - 1; j++) { // Counter for the last point of A used nj += 1; sum1[j] = 0.0; for (int k = 0; k <= nX - 1; k++) { // Lower and upper and limits of the subdomain double a = A[j - 1]; double b = A[j]; double X = (a + b) / 2.0 + (b - a) / 2.0 * xGLe[k]; int1[j, k] = wGLe[k] * HP.HestonProb(X, param, settings, 1) * (b - a) / 2.0; int2[j, k] = wGLe[k] * HP.HestonProb(X, param, settings, 2) * (b - a) / 2.0; sum1[j] += int1[j, k]; sum2[j] += int2[j, k]; } if (Math.Abs(sum1[j]) < tol && Math.Abs(sum2[j]) < tol) { break; } } // Define P1 and P2 double pi = Math.PI; double P1 = 0.5 + 1.0 / pi * sum1.Sum(); double P2 = 0.5 + 1.0 / pi * sum2.Sum(); // The call price double S = settings.S; double K = settings.K; double T = settings.T; double r = settings.r; double q = settings.q; string PutCall = settings.PutCall; double HestonC = S * Math.Exp(-q * T) * P1 - K * Math.Exp(-r * T) * P2; // The put price by put-call parity double HestonP = HestonC - S * Math.Exp(-q * T) + K * Math.Exp(-r * T); // The output structure OutputMD output = new OutputMD(); // Output the option price if (PutCall == "C") { output.Price = HestonC; } else { output.Price = HestonP; } // Output the integration domain; output.lower = A[0]; output.upper = A[nj]; // Output the number of integration points output.Npoints = (nj + 1) * nX; return(output); }
static void Main(string[] args) { // 32-point Gauss-Legendre Abscissas and weights double[] xGLe = new Double[32]; double[] wGLe = new Double[32]; using (TextReader reader = File.OpenText("../../GaussLegendre32.txt")) { for (int k = 0; k <= 31; k++) { string text = reader.ReadLine(); string[] bits = text.Split(' '); xGLe[k] = double.Parse(bits[0]); wGLe[k] = double.Parse(bits[1]); } } // Heston parameters HParam param = new HParam(); param.kappa = 2.0; param.theta = 0.05; param.sigma = 0.3; param.v0 = 0.05; param.rho = 0.45; param.lambda = 0.0; // Option price settings OpSet settings = new OpSet(); settings.S = 100.0; settings.K = 100.0; settings.r = 0.05; settings.q = 0.01; settings.trap = 1; settings.PutCall = "C"; settings.T = 0.5; // Price by Simpson's rule NewtonCotesPrice NCP = new NewtonCotesPrice(); int method = 3; double a = 1e-10; double b = 150; int NS = 10000; double PriceSimpson = NCP.HestonPriceNewtonCotes(param, settings, method, a, b, NS); // Potential integration domain double lo = 1e-10; double hi = 150; int N = 1000; double dA = (hi - lo) / Convert.ToDouble(N); double[] A = new double[N]; for (int j = 0; j <= N - 1; j++) { A[j] = lo + j * dA; } // The modified domain Gauss-Legendre price HestonPriceMD HPMD = new HestonPriceMD(); double tol = 1e-6; OutputMD output = HPMD.HestonPriceGaussLegendreMD(param, settings, xGLe, wGLe, A, tol); double PriceMD = output.Price; double lower = output.lower; double upper = output.upper; int Npoints = output.Npoints; double errorMD = PriceMD - PriceSimpson; // The price using Newton Cotes double PriceNC = NCP.HestonPriceNewtonCotes(param, settings, method, lower, upper, Npoints); double errorNC = PriceNC - PriceSimpson; // Write the results Console.WriteLine("Zhu Multi-Domain Integration Algorithm"); Console.WriteLine("-------------------------------------------"); Console.WriteLine("Multi-Domain tolerance {0:E3}", tol); Console.WriteLine("Lower integration limit {0:E3}", lower); Console.WriteLine("Upper integration limit {0:F3}", upper); Console.WriteLine("Number of integration pts {0:0}", Npoints); Console.WriteLine("-------------------------------------------"); Console.WriteLine("Method Price Error "); Console.WriteLine("-------------------------------------------"); Console.WriteLine("{0:0}-point Simpson {1,10:F4}", N, PriceSimpson); Console.WriteLine("Multi-Domain {0,10:F4} {1,10:F4}", PriceMD, errorMD); Console.WriteLine("Newton-Cotes {0,10:F4} {1,10:F4}", PriceNC, errorNC); Console.WriteLine("-------------------------------------------"); }