// 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); }
// 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); }