public string StringOp(string op, string a, string b) { fS f = null; if (op.Equals("c", StringComparison.InvariantCultureIgnoreCase)) { f = (s1, s2) => s1 + s2; } else if (op.Equals("r", StringComparison.InvariantCultureIgnoreCase)) { f = (s1, s2) => s1.Replace(s2, ""); } if (f == null) { return("No such operation!"); } else { string result = f(a, b); return(result); } }
public fS ExtractRND(double[] K, double[] CallPrice) { // Calculate the first derivatives of calls w.r.t. strike K. // Use central differences int N = K.Length; double dK, dC, dC2; double[] dCdK = new double[N - 2]; for (int k = 1; k <= N - 2; k++) { dK = K[k + 1] - K[k - 1]; dC = CallPrice[k + 1] - CallPrice[k - 1]; dCdK[k - 1] = dC / dK; } // Calculate the risk neutral density by central finite differences. int N2 = dCdK.Length; double[] f = new double[N - 4]; for (int k = 1; k <= N2 - 3; k++) { dK = K[k + 1] - K[k - 1]; dC2 = dCdK[k + 1] - dCdK[k - 1]; f[k - 1] = dC2 / dK; } double[] K2 = new double[N - 4]; for (int k = 0; k <= N2 - 3; k++) { K2[k] = K[k + 2]; } fS output = new fS(); output.K = K2; output.RND = f; return(output); }
static void Main(string[] args) { // Classes RND RND = new RND(); HestonPriceMD HPMD = new HestonPriceMD(); // 32-point Gauss-Laguerre 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]); } } // Maturities and strikes double[] T = new double[] { 45.0 / 365.0, 98.0 / 365.0, 261.0 / 365.0, 348.0 / 365.0 }; int NT = T.Length; // Option price settings OpSet settings = new OpSet(); settings.S = 137.14; settings.r = 0.0010; settings.q = 0.0068; settings.trap = 1; settings.PutCall = "C"; // Heston RMSE parameters from SP data, Table 6.1 HParam param = new HParam(); param.kappa = 8.9957; param.theta = 0.0567; param.sigma = 2.0000; param.v0 = 0.0415; param.rho = -0.7804; param.lambda = 0; // Potential integration domain double lo = 1e-10; double hi = 500; int Ndomains = 50; double tol = 1e-6; double dA = (hi - lo) / Convert.ToDouble(Ndomains); double[] A = new double[Ndomains]; for (int j = 0; j <= Ndomains - 1; j++) { A[j] = lo + j * dA; } // Initialize the domains and number of points double[] Domain = new double[NT]; double[] Points = new double[NT]; double[] Area = new double[NT]; // First maturity ===================================================================================================== int NK1 = 100; settings.T = T[0]; double LoK = 90.0; double HiK = 170.0; double dK = (HiK - LoK) / NK1; double[] K1 = new double[NK1 + 1]; double[] CallPrice1 = new double[NK1 + 1]; double[] points = new double[NK1 + 1]; double[] Upper = new double[NK1 + 1]; OutputMD MDoutput; for (int k = 0; k <= NK1; k++) { K1[k] = LoK + k * dK; settings.K = K1[k]; MDoutput = HPMD.HestonPriceGaussLegendreMD(param, settings, XGLe, WGLe, A, tol); CallPrice1[k] = MDoutput.Price; points[k] = MDoutput.Npoints; Upper[k] = MDoutput.upper; } fS RNDoutput = RND.ExtractRND(K1, CallPrice1); double[] RND1 = RNDoutput.RND; double[] Strike1 = RNDoutput.K; double dh = Strike1[1] - Strike1[0]; Domain[0] = Upper.Max(); Points[0] = points.Max(); Area[0] = RND1.Sum() * dh; // Second maturity ===================================================================================================== int NK2 = 100; settings.T = T[1]; LoK = 80.0; HiK = 180.0; dK = (HiK - LoK) / NK2; double[] K2 = new double[NK2 + 1]; double[] CallPrice2 = new double[NK2 + 1]; points = new double[NK2 + 1]; Upper = new double[NK2 + 1]; for (int k = 0; k <= NK2; k++) { K2[k] = LoK + k * dK; settings.K = K2[k]; MDoutput = HPMD.HestonPriceGaussLegendreMD(param, settings, XGLe, WGLe, A, tol); CallPrice2[k] = MDoutput.Price; points[k] = MDoutput.Npoints; Upper[k] = MDoutput.upper; } RNDoutput = RND.ExtractRND(K2, CallPrice2); double[] RND2 = RNDoutput.RND; double[] Strike2 = RNDoutput.K; dh = Strike2[1] - Strike2[0]; Domain[1] = Upper.Max(); Points[1] = points.Max(); Area[1] = RND2.Sum() * dh; // Third maturity ===================================================================================================== int NK3 = 150; settings.T = T[2]; LoK = 40.0; HiK = 220.0; dK = (HiK - LoK) / NK3; double[] K3 = new double[NK3 + 1]; double[] CallPrice3 = new double[NK3 + 1]; points = new double[NK3 + 1]; Upper = new double[NK3 + 1]; for (int k = 0; k <= NK3; k++) { K3[k] = LoK + k * dK; settings.K = K3[k]; MDoutput = HPMD.HestonPriceGaussLegendreMD(param, settings, XGLe, WGLe, A, tol); CallPrice3[k] = MDoutput.Price; points[k] = MDoutput.Npoints; Upper[k] = MDoutput.upper; } RNDoutput = RND.ExtractRND(K3, CallPrice3); double[] RND3 = RNDoutput.RND; double[] Strike3 = RNDoutput.K; dh = Strike3[1] - Strike3[0]; Domain[2] = Upper.Max(); Points[2] = points.Max(); Area[2] = RND3.Sum() * dh; // Fourth maturity ===================================================================================================== int NK4 = 200; settings.T = T[3]; LoK = 20.0; HiK = 240.0; dK = (HiK - LoK) / NK4; double[] K4 = new double[NK4 + 1]; double[] CallPrice4 = new double[NK4 + 1]; points = new double[NK4 + 1]; Upper = new double[NK4 + 1]; for (int k = 0; k <= NK4; k++) { K4[k] = LoK + k * dK; settings.K = K4[k]; MDoutput = HPMD.HestonPriceGaussLegendreMD(param, settings, XGLe, WGLe, A, tol); CallPrice4[k] = MDoutput.Price; points[k] = MDoutput.Npoints; Upper[k] = MDoutput.upper; } RNDoutput = RND.ExtractRND(K4, CallPrice4); double[] RND4 = RNDoutput.RND; double[] Strike4 = RNDoutput.K; dh = Strike4[1] - Strike4[0]; Domain[3] = Upper.Max(); Points[3] = points.Max(); Area[3] = RND4.Sum() * dh; // Output the results Console.WriteLine("Maturity Area UpperLimit Points"); Console.WriteLine("----------------------------------------"); for (int t = 0; t <= NT - 1; t++) { Console.WriteLine(" {0,3:F0} {1,12:F5} {2,10:F0} {3,10:F0}", T[t] * 365.0, Area[t], Domain[t], Points[t]); } Console.WriteLine("----------------------------------------"); }