// Series I expansion public double SeriesICall(double S, double K, double rf, double q, double T, double v0, double rho, double theta, double kappa, double sigma) { // The "J" integrals double J1 = J(rho, theta, kappa, T, v0, 1); double J3 = J(rho, theta, kappa, T, v0, 3); double J4 = J(rho, theta, kappa, T, v0, 4); // Time average of the deterministic volatility double v = theta + (v0 - theta) * (1.0 - Math.Exp(-kappa * T)) / (kappa * T); // X and Z required for the ratios of Black Scholes derivatives double X = Math.Log(S * Math.Exp((rf - q) * T) / K); double Z = v * T; // The ratios of Black Scholes derivatives double R20 = R(2, 0, X, Z, T); double R11 = R(1, 1, X, Z, T); double R12 = R(1, 2, X, Z, T); double R22 = R(2, 2, X, Z, T); // Black Scholes call price evaluated at v BlackScholes BS = new BlackScholes(); double c = BS.BSC(S, K, rf, q, v, T); // Black Scholes vega evaluated at v double cv = BS.BSV(S, K, rf, q, v, T); // Series I volatility of volatility expansion for the implied volatility return(c + sigma / T * J1 * R11 * cv + sigma * sigma * (J3 * R20 / T / T + J4 * R12 / T + J1 * J1 * R22 / T / T / 2) * cv); }
// Series II expansion public double[] SeriesIICall(double S, double K, double rf, double q, double T, double v0, double rho, double theta, double kappa, double sigma) { // The "J" integrals double J1 = J(rho, theta, kappa, T, v0, 1); double J3 = J(rho, theta, kappa, T, v0, 3); double J4 = J(rho, theta, kappa, T, v0, 4); // Time average of the deterministic volatility double v = theta + (v0 - theta) * (1.0 - Math.Exp(-kappa * T)) / (kappa * T); // X and Z required for the ratios of Black Scholes derivatives double X = Math.Log(S * Math.Exp((rf - q) * T) / K); double Z = v * T; // The ratios of Black Scholes derivatives double R20 = R(2, 0, X, Z, T); double R11 = R(1, 1, X, Z, T); double R12 = R(1, 2, X, Z, T); double R22 = R(2, 2, X, Z, T); // Series II volatility of volatility expansion for the implied volatility double iv = v + sigma / T * J1 * R11 + sigma * sigma * (J3 * R20 / T / T + J4 * R12 / T + 0.5 / T / T * J1 * J1 * (R22 - R11 * R11 * R20)); // Series II call price BlackScholes BS = new BlackScholes(); double Price = BS.BSC(S, K, rf, q, iv, T); // The series volatility double ivx = Math.Sqrt(iv); // Return the price and the volatility double[] output = new double[2] { Price, ivx }; return(output); }
private void GenerateLewisTable_MouseClick(object sender, MouseEventArgs e) { double S = 100.0; // Spot Price double T = 0.25; // Maturity in Years double rf = 0.0; // Interest Rate double q = 0.0; // Dividend yield string PutCall = "C"; // "P"ut or "Call" int trap = 1; // 1="Little Trap" characteristic function OpSet opset = new OpSet(); opset.S = S; opset.T = T; opset.r = rf; opset.q = q; opset.PutCall = PutCall; opset.trap = trap; double kappa = 4.0; // Heston Parameter double theta = 0.09 / 4.0; // Heston Parameter double sigma = 0.1; // Heston Parameter: Volatility of Variance double v0 = 0.0225; // Heston Parameter: Current Variance double rho = -0.5; // Heston Parameter: Correlation double lambda = 0.0; // Heston Parameter HParam param = new HParam(); param.kappa = kappa; param.theta = theta; param.sigma = sigma; param.v0 = v0; param.rho = rho; param.lambda = lambda; int NK = 7; double[] K = new double[7] // Strikes { 70.0, 80.0, 90.0, 100.0, 110.0, 120.0, 130.0 }; // Time average of the deterministic variance and volatility double vol = param.theta + (param.v0 - param.theta) * (1.0 - Math.Exp(-param.kappa * T)) / (param.kappa * T); double IV = Math.Sqrt(vol); // Classes BlackScholes BS = new BlackScholes(); NewtonCotes NC = new NewtonCotes(); Lewis L = new Lewis(); BisectionAlgo BA = new BisectionAlgo(); // Table 3.3.1 on Page 81 of Lewis (2001) double[] SeriesIPrice = new double[NK]; // Series I price and implied vol double[] IVI = new double[NK]; double[] SeriesIIPrice = new double[NK]; // Series II price and implied vol double[] IVII = new double[NK]; double[] HPrice = new double[NK]; // Exact Heston price and implied vol double[] IVe = new double[NK]; double[] BSPrice = new double[NK]; // Black Scholes price // Bisection algorithm settings double lo = 0.01; double hi = 2.0; double Tol = 1.0e-10; int MaxIter = 10000; // Newton Cotes settings int method = 3; double a = 1.0e-10; double b = 100.0; int N = 10000; double[] SeriesII = new double[2]; for (int k = 0; k <= NK - 1; k++) { // Generate the prices and implied vols opset.K = K[k]; SeriesIPrice[k] = L.SeriesICall(S, K[k], rf, q, T, v0, rho, theta, kappa, sigma); IVI[k] = BA.BisecBSIV(PutCall, S, K[k], rf, q, T, lo, hi, SeriesIPrice[k], Tol, MaxIter); SeriesII = L.SeriesIICall(S, K[k], rf, q, T, v0, rho, theta, kappa, sigma); SeriesIIPrice[k] = SeriesII[0]; IVII[k] = SeriesII[1]; HPrice[k] = NC.HestonPriceNewtonCotes(param, opset, method, a, b, N); IVe[k] = BA.BisecBSIV(PutCall, S, K[k], rf, q, T, lo, hi, HPrice[k], Tol, MaxIter); BSPrice[k] = BS.BSC(S, K[k], rf, q, vol, T); // Write to the List Boxes Strike.Items.Add(K[k]); ExactPrice.Items.Add(Math.Round(HPrice[k], 6)); IVExact.Items.Add(Math.Round(100 * IVe[k], 2)); SeriesICall.Items.Add(Math.Round(SeriesIPrice[k], 6)); IV1.Items.Add(Math.Round(100 * IVI[k], 2)); SeriesIICall.Items.Add(Math.Round(SeriesIIPrice[k], 6)); IV2.Items.Add(Math.Round(100 * IVII[k], 2)); BlackScholesPrice.Items.Add(Math.Round(BSPrice[k], 6)); IVBS.Items.Add(Math.Round(100 * IV, 2)); } }