public static void test_beta_black_perf() { Console.WriteLine("Computing ... "); var N = 100000; var tic = DateTime.Now; for (var i = 0; i < N; ++i) { ClosedForm.black76(OptionType.Put, 10.0, 4.0, 0.5, 0.4); ClosedForm.black76(OptionType.Put, 10.0, 8.0, 1.5, 0.4); ClosedForm.black76(OptionType.Put, 10.0, 4.0, 0.5, 0.4); ClosedForm.black76(OptionType.Put, 10.0, 8.0, 1.5, 0.4); ClosedForm.black76(OptionType.Put, 10.0, 4.0, 0.5, 0.4); ClosedForm.black76(OptionType.Put, 10.0, 8.0, 1.5, 0.4); } var toc = DateTime.Now; var ticBB = DateTime.Now; for (var i = 0; i < N; ++i) { BetaBlack.beta_black(0.1, OptionType.Put, 10.0, 4.0, 0.5, 0.4); BetaBlack.beta_black(0.1, OptionType.Put, 8.0, 4.0, 0.5, 0.4); BetaBlack.beta_black(0.5, OptionType.Put, 10.0, 4.0, 0.5, 0.4); BetaBlack.beta_black(0.5, OptionType.Put, 8.0, 4.0, 0.5, 0.4); BetaBlack.beta_black(0.5, OptionType.Put, -10.0, -14.0, 0.5, 0.4); BetaBlack.beta_black(0.5, OptionType.Put, -8.0, -10.0, 0.5, 0.4); } var tocBB = DateTime.Now; var ticBBP = DateTime.Now; var ignore = 0.0; for (var i = 0; i < N; ++i) { BetaBlack.beta_black_b(0.1, OptionType.Put, 10.0, 4.0, 0.5, 0.4, ref ignore, ref ignore, ref ignore, ref ignore, ref ignore, 1.0); BetaBlack.beta_black_b(0.1, OptionType.Put, 8.0, 4.0, 0.5, 0.4, ref ignore, ref ignore, ref ignore, ref ignore, ref ignore, 1.0); BetaBlack.beta_black_b(0.5, OptionType.Put, 10.0, 4.0, 0.5, 0.4, ref ignore, ref ignore, ref ignore, ref ignore, ref ignore, 1.0); BetaBlack.beta_black_b(0.5, OptionType.Put, 8.0, 4.0, 0.5, 0.4, ref ignore, ref ignore, ref ignore, ref ignore, ref ignore, 1.0); BetaBlack.beta_black_b(0.5, OptionType.Put, -10.0, -14.0, 0.5, 0.4, ref ignore, ref ignore, ref ignore, ref ignore, ref ignore, 1.0); BetaBlack.beta_black_b(0.5, OptionType.Put, -8.0, -10.0, 0.5, 0.4, ref ignore, ref ignore, ref ignore, ref ignore, ref ignore, 1.0); } var tocBBP = DateTime.Now; Console.WriteLine("Done"); Console.WriteLine($"Black: {(toc - tic).TotalMilliseconds}"); Console.WriteLine($"B-Black: {(tocBB - ticBB).TotalMilliseconds}"); Console.WriteLine($"First Order Risk B-Black : {(tocBBP - ticBBP).TotalMilliseconds}"); Console.WriteLine($"PV time in # blacks: {(tocBB - ticBB).TotalMilliseconds / (toc - tic).TotalMilliseconds}"); Console.WriteLine($"Risk first order time in # blacks: {(tocBBP - ticBBP).TotalMilliseconds / (toc - tic).TotalMilliseconds}"); }
public BetaBlackPack(double beta, OptionType callPut, double f, double k, double t, double sigma) { if (beta < 0 || beta >= 1.0) { throw FS.FailWith($"Beta must be in [0, 1.0), got {beta}"); } if (sigma <= 0.0) { throw FS.FailWith($"Sigma must be positive, got {sigma}"); } Beta = beta; CallPut = callPut; F = f; K = k; T = t; Sigma = sigma; //! Nota bene: Use AD for first order derivatives and FD on AD for second order // // Mu = BetaBlack.inv_m1_beta_black(beta, f, sigma * Math.Sqrt(t)); double beta_b = 0.0; double f_b = 0.0; double k_b = 0.0; double t_b = 0.0; double sigma_b = 0.0; Price = BetaBlack.beta_black_b(beta, callPut, f, k, t, sigma, ref beta_b, ref f_b, ref k_b, ref t_b, ref sigma_b, 1.0); dPV_dS = f_b; dPV_dK = k_b; dPV_dT = t_b; dPV_dVol = sigma_b; dPV_dBeta = beta_b; var eps = Math.Sqrt(DoubleUtils.DoubleEpsilon); { var dF = eps * (1.0 + Math.Abs(f)); double betaUp_b = 0.0; double fUp_b = 0.0; double kUp_b = 0.0; double tUp_b = 0.0; double sigmaUp_b = 0.0; double pUp = BetaBlack.beta_black_b(beta, callPut, f + dF, k, t, sigma, ref betaUp_b, ref fUp_b, ref kUp_b, ref tUp_b, ref sigmaUp_b, 1.0); double betaDown_b = 0.0; double fDown_b = 0.0; double kDown_b = 0.0; double tDown_b = 0.0; double sigmaDown_b = 0.0; double pDown = BetaBlack.beta_black_b(beta, callPut, f - dF, k, t, sigma, ref betaDown_b, ref fDown_b, ref kDown_b, ref tDown_b, ref sigmaDown_b, 1.0); d2PV_dFdBeta = (betaUp_b - betaDown_b) / (2.0 * dF); d2PV_dS2 = (fUp_b - fDown_b) / (2.0 * dF); d2PV_dKdS = (kUp_b - kDown_b) / (2.0 * dF); d2PV_dSdT = (tUp_b - tDown_b) / (2.0 * dF); d2PV_dSdVol = (sigmaUp_b - sigmaDown_b) / (2.0 * dF); } { var dK = eps * (1.0 + Math.Abs(k)); double betaUp_b = 0.0; double fUp_b = 0.0; double kUp_b = 0.0; double tUp_b = 0.0; double sigmaUp_b = 0.0; double pUp = BetaBlack.beta_black_b(beta, callPut, f, k + dK, t, sigma, ref betaUp_b, ref fUp_b, ref kUp_b, ref tUp_b, ref sigmaUp_b, 1.0); double betaDown_b = 0.0; double fDown_b = 0.0; double kDown_b = 0.0; double tDown_b = 0.0; double sigmaDown_b = 0.0; double pDown = BetaBlack.beta_black_b(beta, callPut, f, k - dK, t, sigma, ref betaDown_b, ref fDown_b, ref kDown_b, ref tDown_b, ref sigmaDown_b, 1.0); d2PV_dKdBeta = (betaUp_b - betaDown_b) / (2.0 * dK); // d2PV_dKdS = (fUp_b - fDown_b) / (2.0 * dK); d2PV_dK2 = (kUp_b - kDown_b) / (2.0 * dK); d2PV_dKdT = (tUp_b - tDown_b) / (2.0 * dK); d2PV_dVoldK = (sigmaUp_b - sigmaDown_b) / (2.0 * dK); } { var dSigma = eps * (1.0 + Math.Abs(sigma)); double betaUp_b = 0.0; double fUp_b = 0.0; double kUp_b = 0.0; double tUp_b = 0.0; double sigmaUp_b = 0.0; double pUp = BetaBlack.beta_black_b(beta, callPut, f, k, t, sigma + dSigma, ref betaUp_b, ref fUp_b, ref kUp_b, ref tUp_b, ref sigmaUp_b, 1.0); double betaDown_b = 0.0; double fDown_b = 0.0; double kDown_b = 0.0; double tDown_b = 0.0; double sigmaDown_b = 0.0; double pDown = BetaBlack.beta_black_b(beta, callPut, f, k, t, sigma - dSigma, ref betaDown_b, ref fDown_b, ref kDown_b, ref tDown_b, ref sigmaDown_b, 1.0); d2PV_dVoldBeta = (betaUp_b - betaDown_b) / (2.0 * dSigma); // d2PV_dSdVol = (fUp_b - fDown_b) / (2.0 * dSigma); // d2PV_dVoldK = (kUp_b - kDown_b) / (2.0 * dSigma); d2PV_dVoldT = (tUp_b - tDown_b) / (2.0 * dSigma); d2PV_dVol2 = (sigmaUp_b - sigmaDown_b) / (2.0 * dSigma); } }