// Objective function is Roger Lee's G*exp(d*Tau) function // or Lord and Kahl's optimal alpha function public double f(double[] x, double[] param) { LordKahl LK = new LordKahl(); if (GlobalVars.ObjFunChoice == "RogerLee") { double kappa = param[0]; double rho = param[1]; double sigma = param[2]; double tau = param[3]; return(LK.RogerLeeGExpD(x[0], kappa, rho, sigma, tau)); } else if (GlobalVars.ObjFunChoice == "LordKahl") { double kappa = param[0]; double theta = param[1]; double lambda = param[2]; double rho = param[3]; double sigma = param[4]; double tau = param[5]; double K = param[6]; double S = param[7]; double r = param[8]; double v0 = param[9]; return(LK.LordKahlFindAlpha(x[0], kappa, theta, lambda, rho, sigma, tau, K, S, r, v0)); } else { return(0.0); } }
static void Main(string[] args) { double S = 1.0; // Spot Price double K = 1.2; // Strike Price double T = 1.0; // Maturity in Years double rf = 0.0; // Interest Rate double q = 0.0; // Dividend yield double rho = -0.7; // Heston Parameter: Correlation double kappa = 1.0; // Heston Parameter double theta = 0.1; // Heston Parameter double lambda = 0.0; // Heston Parameter double sigma = 1.0; // Heston Parameter: Volatility of Variance double v0 = 0.1; // Heston Parameter: Current Variance int trap = 1; // 1="Little Trap" characteristic function // Verify : kappa - rho*sigma >0 double check = kappa - rho * sigma; if (check < 0) { Console.WriteLine("Warning: kappa - rho*sigma = {0:F3} is < 0", check); Console.WriteLine("------------------------------------------"); } // Bounds on alpha and optimal alpha // Shows multiple solutions to Rogers Lee's formula // in which we solve for "a" in g(-ia)*exp(d(-ia)*T) = 1 LordKahl LK = new LordKahl(); double start = -15.0; double increment = 0.01; Complex g, d, E; double E1; Complex i = new Complex(0.0, 1.0); double[] A = new Double[3001]; double[] y = new Double[3001]; double[] z = new Double[3001]; for (int j = 0; j <= 3000; j++) { A[j] = start + j * increment; g = LK.RogerLeeG(-i * A[j], kappa, rho, sigma); d = LK.RogerLeeD(-i * A[j], kappa, rho, sigma); E = g * Complex.Exp(d * T); E1 = E.Real; y[j] = (E1 - 1.0); z[j] = 0.0; } // Find yMax and yMin from Roger Lee's closed form double ymax = (sigma - 2.0 * kappa * rho + Math.Sqrt(sigma * sigma - 4.0 * kappa * rho * sigma + 4.0 * kappa * kappa)) / (2.0 * sigma * (1.0 - rho * rho)); double ymin = (sigma - 2.0 * kappa * rho - Math.Sqrt(sigma * sigma - 4.0 * kappa * rho * sigma + 4.0 * kappa * kappa)) / (2.0 * sigma * (1 - rho * rho)); // Settings for the Nelder Mead algorithm int N = 1; // Number of parameters in f(x) to find int NumIters = 1; // First Iteration double MaxIters = 5000; // Maximum number of iterations double Tolerance = 1e-20; // Tolerance on best and worst function values // Starting values (vertices) in vector form. Add more as needed double [,] s1 = new double [N, N + 1]; // Vertice 0 Vertice 1 s1[0, 0] = ymin - 0.09; s1[0, 1] = ymin - 1.01; // Select the Roger Lee function as the objective function GlobalVars.ObjFunChoice = "RogerLee"; // Arrange parameters in a vector to pass to Nelder Mead function double[] paramRL = new double[4]; paramRL[0] = kappa; paramRL[1] = rho; paramRL[2] = sigma; paramRL[3] = T; // Calculate lower limit of the the range Ax NelderMeadAlgo NM = new NelderMeadAlgo(); double[] AxLo = NM.NelderMead(NM.f, N, NumIters, MaxIters, Tolerance, s1, paramRL); double yneg = AxLo[0]; // Calculate upper limit of the the range Ax double[,] s2 = new double[N, N + 1]; s2[0, 0] = ymax + 4.99; s2[0, 1] = ymax + 5.01; double[] AxHi = NM.NelderMead(NM.f, N, NumIters, MaxIters, Tolerance, s2, paramRL); double ypos = AxHi[0]; // Bounds on alpha double AlphaMax = ypos - 1.0; double AlphaMin = yneg - 1.0; // Select the KahlLord function as the objective function GlobalVars.ObjFunChoice = "LordKahl"; // Starting values for Lord and Kahl double StartVal = (AlphaMax + AlphaMin) / 2.0; double[,] s3 = new double[N, N + 1]; s3[0, 0] = StartVal + 0.01; s3[0, 1] = StartVal - 0.01; // Parameters for Lord and Kahl double[] paramLK = new double[10]; paramLK[0] = kappa; paramLK[1] = theta; paramLK[2] = lambda; paramLK[3] = rho; paramLK[4] = sigma; paramLK[5] = T; paramLK[6] = K; paramLK[7] = S; paramLK[8] = rf; paramLK[9] = v0; // Lord and Kahl optimal alpha double[] AlphaOptimal = NM.NelderMead(NM.f, N, NumIters, MaxIters, Tolerance, s3, paramLK); // Write the results Console.WriteLine("Roger Lee bounds on alpha"); Console.WriteLine("--------------------------------------------------------"); Console.WriteLine("Ymin and Ymax are ({0,7:F4}, {1,7:F4})", ymin, ymax); Console.WriteLine("The range Ax is ({0,7:F4}, {1,7:F4})", yneg, ypos); Console.WriteLine("(AlphaMin,AlphMax) is ({0,7:F4}, {1,7:F4}) = Ax - 1", AlphaMin, AlphaMax); Console.WriteLine("--------------------------------------------------------"); Console.WriteLine("Lord and Kahl optimal Alpha {0,7:F4}", AlphaOptimal[0]); Console.WriteLine("--------------------------------------------------------"); Console.WriteLine("Note that optimal alpha in ({0,7:F4}, {1,7:F4})", AlphaMin, AlphaMax); Console.WriteLine(" "); }