// Golden Section search form Heston public double GoldenSearchMS(double a, double b, double tol, int MaxIter, double K, HParam param, double theta, double r, double q, double T, int NumTerms) { MSExpansionHeston MS = new MSExpansionHeston(); double x1, x2, x3, x4, f1, f2, f3, f4; double GR = (Math.Sqrt(5.0) - 1.0) / 2.0; int k = 0; while (Math.Abs(b - a) > tol) { k = k + 1; x1 = a; x2 = a + (1.0 - GR) * (b - a); x3 = a + GR * (b - a); x4 = b; f1 = -MS.MSPutHeston(x1, theta, K, param, r, q, T, NumTerms); f2 = -MS.MSPutHeston(x2, theta, K, param, r, q, T, NumTerms); f3 = -MS.MSPutHeston(x3, theta, K, param, r, q, T, NumTerms); f4 = -MS.MSPutHeston(x4, theta, K, param, r, q, T, NumTerms); if ((f1 > f2) & (f2 < f3)) { b = x3; } else if ((f2 > f3) & (f3 < f4)) { a = x2; } if (k > MaxIter) { break; } } return((a + b) / 2.0); }
public double[] MSPriceHeston(HParam param, OpSet opset, MSSet msset) { // param = Heston parameters // opset = option settings // msset = Medvedev-Scaillet expansion settings // Extract quantities from the option settings double K = opset.K; double S = opset.S; double v0 = param.v0; double T = opset.T; double r = opset.r; double q = opset.q; // Extract quantities from the MS structure int N = msset.N; double a = msset.a; double b = msset.b; double A = msset.A; double B = msset.B; double dt = msset.dt; double tol = msset.tol; int MaxIter = msset.MaxIter; int NumTerms = msset.NumTerms; double yinf = msset.yinf; int method = msset.method; // Closed-form European put NewtonCotes NC = new NewtonCotes(); double EuroPutClosed = NC.HestonPriceNewtonCotes(param, opset, method, A, B, N); // Moneyness double theta = Math.Log(K / S) / Math.Sqrt(v0) / Math.Sqrt(T); // Find the barrier level // Bisection method to find y // a = Math.Max(1.25,0.95*theta); // b = 3.0; // double y = BisectionMS(a,b,theta,K,param,r,q,T,NumTerms,tol,MaxIter,dt); // Golden section search method to find y GoldenSearch GS = new GoldenSearch(); a = 1.5; b = 2.5; double y = GS.GoldenSearchMS(a, b, tol, MaxIter, K, param, theta, r, q, T, NumTerms); if (y < theta) { y = theta; } // Find the early exercise premium MSExpansionHeston MS = new MSExpansionHeston(); double AmerPutMS = MS.MSPutHeston(y, theta, K, param, r, q, T, NumTerms); double EuroPutMS = MS.MSPutHeston(yinf, theta, K, param, r, q, T, NumTerms); double EEP = AmerPutMS - EuroPutMS; // Control variate American put double AmerPut = EuroPutClosed + EEP; // Output the results double[] output = new double[6]; output[0] = EuroPutClosed; output[1] = AmerPutMS; output[2] = AmerPut; // Medvedev and Scaillet recommend this one. output[3] = EEP; output[4] = theta; output[5] = y; return(output); }
public double MSGreeksFD(HParam param, OpSet opset, int method, double A, double B, int N, double hi, double tol, int MaxIter, int NumTerms, double yinf, string Greek) { MSExpansionHeston MS = new MSExpansionHeston(); double[] output = new double[6]; double AmerPut, AmerPutp, AmerPutm; double AmerPutpp, AmerPutpm, AmerPutmp, AmerPutmm; double S = opset.S; double v0 = param.v0; double T = opset.T; // Define the finite difference increments double ds = opset.S * 0.005; double dt = opset.T * 0.005; double dv = param.v0 * 0.005; if (Greek == "price") { output = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf); AmerPut = output[2]; return(AmerPut); } else if ((Greek == "delta") || (Greek == "gamma")) { opset.S = S + ds; output = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf); AmerPutp = output[2]; opset.S = S - ds; output = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf); AmerPutm = output[2]; if (Greek == "gamma") { opset.S = S; output = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf); AmerPut = output[2]; return((AmerPutp - 2.0 * AmerPut + AmerPutm) / ds / ds); } else { return((AmerPutp - AmerPutm) / 2.0 / ds); } } else if (Greek == "theta") { opset.T = T + dt; output = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf); AmerPutp = output[2]; opset.T = T - dt; output = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf); AmerPutm = output[2]; return(-(AmerPutp - AmerPutm) / 2.0 / dt); } else if ((Greek == "vega1") || (Greek == "volga")) { param.v0 = v0 + dv; output = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf); AmerPutp = output[2]; param.v0 = v0 - dv; output = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf); AmerPutm = output[2]; double Vega1 = (AmerPutp - AmerPutm) / 2.0 / dv * 2.0 * Math.Sqrt(v0); if (Greek == "volga") { param.v0 = v0; output = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf); AmerPut = output[2]; double dC2 = (AmerPutp - 2.0 * AmerPut + AmerPutm) / dv / dv; return(4.0 * Math.Sqrt(v0) * (dC2 * Math.Sqrt(v0) + Vega1 / 4.0 / v0)); } else { return(Vega1); } } else if (Greek == "vanna") { opset.S = S + ds; param.v0 = v0 + dv; output = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf); AmerPutpp = output[2]; param.v0 = v0 - dv; output = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf); AmerPutpm = output[2]; opset.S = S - ds; param.v0 = v0 + dv; output = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf); AmerPutmp = output[2]; param.v0 = v0 - dv; output = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf); AmerPutmm = output[2]; return((AmerPutpp - AmerPutpm - AmerPutmp + AmerPutmm) / 4.0 / dv / ds * 2.0 * Math.Sqrt(v0)); } else { return(0.0); } }
// Derivative of the MS approximation public double MSPutHestonDiff(double y, double theta, double Strike, HParam param, double r, double q, double T, int NumTerms, double dy) { MSExpansionHeston MS = new MSExpansionHeston(); return((MS.MSPutHeston(y + dy, theta, Strike, param, r, q, T, NumTerms) - MS.MSPutHeston(y - dy, theta, Strike, param, r, q, T, NumTerms)) / 2.0 / dy); }