public void TestSkewDigitalEuroCallPut() { DateTime today = new DateTime(2010, 06, 22); DateTime expiry = new DateTime(2011, 03, 24); double tau = System.Convert.ToDouble(expiry.Subtract(today).Days) / 365.0; double spot = 42.00; double upperbarrier = 44.00; double lowerbarrier = 40.00; int[] zerodays = { 0, 10 }; double[] zerorates = { 0.05, 0.05 }; int[] divdays = new int[] { 0, 51, 247 }; double[] divAmts = new double[] { 4, 1.350, 1.420 }; double fwd = EquityAnalytics.GetForwardCCLin365(spot, tau, divdays, divAmts, zerodays, zerorates); OrcWingParameters owp = new OrcWingParameters() { AtmForward = fwd, CallCurve = 0.1250, CurrentVol = 0.26, DnCutoff = -0.25, Dsr = 0.9, PutCurve = 0.10, RefFwd = fwd, RefVol = 0.26, Scr = 0.0, SlopeRef = -0.1750, Ssr = 100, TimeToMaturity = tau, UpCutoff = 0.20, Usr = 0.50, Vcr = 0.0 }; List <OrcWingParameters> owpList = new List <OrcWingParameters>(); owpList.Add(owp); double skew1 = EquityAnalytics.GetWingSkew(owpList, new LinearInterpolation(), tau, upperbarrier); double vol = EquityAnalytics.GetWingValue(owpList, new LinearInterpolation(), tau, upperbarrier); BinaryEuro op1 = new BinaryEuro(spot, upperbarrier, true, tau, vol, zerodays, zerorates, divdays, divAmts, skew1); double pr1 = op1.GetPrice(); Assert.AreEqual(0.35784, pr1, 0.005); double skew2 = EquityAnalytics.GetWingSkew(owpList, new LinearInterpolation(), tau, lowerbarrier); BinaryEuro op2 = new BinaryEuro(spot, lowerbarrier, false, tau, vol, zerodays, zerorates, divdays, divAmts, skew2); double pr2 = op2.GetPrice(); Assert.AreEqual(0.43275, pr2, 0.005); }
/// <summary> /// We can roughly proxy the alpha-th percentile of the simulation /// by calculating the upper alpha percentile confidence point for a given time slice /// of the ln-OU process and pricing the collar with this asset value for a given profile point /// This should roughly compare to the calculated (1-alpha)-worst PCE point. /// </summary> /// <param name="spot"></param> /// <param name="kappa"></param> /// <param name="theta"></param> /// <param name="histvol"></param> /// <param name="time0"></param> /// <param name="maturity"></param> /// <param name="callstrike"></param> /// <param name="putstrike"></param> /// <param name="zerodays"></param> /// <param name="zerorates"></param> /// <param name="divdays"></param> /// <param name="divamts"></param> /// <param name="volSurface"></param> /// <returns></returns> public static double PCEProxyCalc(double spot, double kappa, double theta, double histvol, double time0, double maturity, double callstrike, double putstrike, int[] zerodays, double[] zerorates, int[] divdays, double[] divamts, List <OrcWingParameters> volSurface) { double tau = maturity - time0; double upperBound = EquityPCEAnalytics.LNOUUpperBound(spot, 0.95, kappa, theta, histvol, time0); double fStar = EquityAnalytics.GetForwardCCLin365(upperBound, time0, maturity, divdays, divamts, zerodays, zerorates); double callvol = EquityAnalytics.GetWingValue(volSurface, new LinearInterpolation(), tau, callstrike); double putvol = EquityAnalytics.GetWingValue(volSurface, new LinearInterpolation(), tau, putstrike); double r0 = EquityAnalytics.GetRateCCLin365(time0, maturity, zerodays, zerorates); BlackScholes bs = new BlackScholes(); double lhs = Math.Max(bs.BSprice(fStar, tau, callstrike, r0, callvol, true) - bs.BSprice(fStar, tau, putstrike, r0, putvol, false), 0); return(lhs); }
///<summary> ///</summary> ///<param name="vols"></param> ///<param name="days"></param> ///<param name="spot"></param> ///<param name="ratedays"></param> ///<param name="rateamts"></param> ///<param name="divdays"></param> ///<param name="divamts"></param> ///<returns></returns> private List <OrcWingParameters> UnpackWing(double[,] vols, double[] days, double spot, int[] ratedays, double[] rateamts, int[] divdays, double[] divamts) { const double daybasis = 365.0; int rows = vols.GetLength(0); var opList = new List <OrcWingParameters>(); for (int idx = 0; idx < rows; idx++) { double fwd = EquityAnalytics.GetForwardCCLin365(spot, days[idx] / daybasis, divdays, divamts, ratedays, rateamts); var op = new OrcWingParameters { AtmForward = fwd, CurrentVol = vols[idx, 0], SlopeRef = vols[idx, 1], PutCurve = vols[idx, 2], CallCurve = vols[idx, 3], DnCutoff = vols[idx, 4], UpCutoff = vols[idx, 5], Vcr = vols[idx, 6], Scr = vols[idx, 7], Ssr = 100 * vols[idx, 8], Dsr = vols[idx, 9], Usr = vols[idx, 10], RefVol = vols[idx, 11], RefFwd = fwd, TimeToMaturity = days[idx] / daybasis }; opList.Add(op); } return(opList); }
public void TestPCEProfile() { DateTime today = new DateTime(2010, 10, 22); DateTime expiry = new DateTime(2011, 10, 22); double maturity = Convert.ToDouble(expiry.Subtract(today).Days) / 365.0; double spot = 4200.00; int simuls = 10000; double callstrike = 1.3 * spot; double putstrike = 1.0 * spot; int[] zerodays = { 0, 365 }; double r0 = 0.065; double confidence = 0.95; double[] zerorates = { r0, r0 }; int[] divdays = { 1, 51, 247 }; double[] divamts = { 22.5, 50, 50 }; double fwd = EquityAnalytics.GetForwardCCLin365(spot, maturity, divdays, divamts, zerodays, zerorates); double histvol = 0.60; double theta = Math.Log(spot); double kappa = 0.9; double[] times = { 7.0 / 365.0, 128.0 / 365.0, 250.0 / 365.0, 365.0 / 365.0, 730.0 / 365.0 }; OrcWingParameters owp = new OrcWingParameters { AtmForward = fwd, CallCurve = 0.1250, CurrentVol = 0.26, DnCutoff = -0.25, Dsr = 0.9, PutCurve = 0.10, RefFwd = fwd, RefVol = 0.26, Scr = 0.0, SlopeRef = -0.1750, Ssr = 100, TimeToMaturity = maturity, UpCutoff = 0.20, Usr = 0.50, Vcr = 0.0 }; List <OrcWingParameters> owpList = new List <OrcWingParameters> { owp }; double[,] results = EquityPCEAnalytics.GetCollarPCE("CollarPCE", zerodays, zerorates, divdays, divamts, owpList, spot, callstrike, putstrike, maturity, kappa, theta, histvol, times, confidence, 0.25 / 365.0, simuls, 3151); double lhs1 = PCEProxyCalc(spot, kappa, theta, histvol, times[0], maturity, callstrike, putstrike, zerodays, zerorates, divdays, divamts, owpList); double lhs2 = PCEProxyCalc(spot, kappa, theta, histvol, times[1], maturity, callstrike, putstrike, zerodays, zerorates, divdays, divamts, owpList); double lhs3 = PCEProxyCalc(spot, kappa, theta, histvol, times[2], maturity, callstrike, putstrike, zerodays, zerorates, divdays, divamts, owpList); Assert.AreEqual(results[0, 1], lhs1, Math.Abs(0.10 * results[0, 1])); Assert.AreEqual(results[1, 1], lhs2, Math.Abs(0.10 * results[1, 1])); Assert.AreEqual(results[2, 1], lhs3, Math.Abs(0.10 * results[2, 1])); }
public void TestCrankNicolson() { double spot = 385.5; double epsilon = 0.0001; double strike = 400; double[] rt = { 0.0425, 0.0452, 0.0457, 0.0462 }; int[] tt = { 1, 32, 63, 93 }; int[] divdays = { 0, 48 }; double[] divs = { 20, 10 }; double vol = 0.2046; int steps = 80; double tStepSize = 0.01; DateTime today = new DateTime(2010, 05, 07); DateTime expiry = new DateTime(2010, 06, 24); //string style = "European"; double t = expiry.Subtract(today).Days / 365.0 + epsilon; // For CN backwards propagation div time needs to be strictly less than expiry time double fwd = EquityAnalytics.GetForwardCCLin365(spot, t, divdays, divs, tt, rt); double df = EquityAnalytics.GetDFCCLin365(0, t, tt, rt); BlackScholes bs = new BlackScholes(spot, strike, false, t, vol, tt, rt, divdays, divs); CrankNicolson lhs = new CrankNicolson(false, false, spot, strike, t, vol, steps, tStepSize, 8.0, divdays, divs, tt, rt); double[,] res0 = OptionAnalytics.BlackScholesWithGreeks(false, fwd, strike, vol, t); double[] res_cn = lhs.GetPriceAndGreeks(); double pr_bs = bs.GetPrice(); double delta_bs = bs.GetDelta(); double gamma_bs = bs.GetGamma(); double theta_bs = bs.GetTheta(); double pr_cn = res_cn[0]; double delta_cn = res_cn[1]; double gamma_cn = res_cn[2]; double theta_cn = res_cn[3]; Assert.AreEqual(pr_cn, pr_bs, 0.50); Assert.AreEqual(delta_cn, delta_bs, 0.03); Assert.AreEqual(gamma_cn, 0.012931145370580023, 0.005); Assert.AreEqual(bs.GetTheta(), theta_cn, 0.01); }
/// <summary> /// Evaluate the PCE for a collar given the parameters passed below /// </summary> /// <param name="ratedays"></param> /// <param name="rateamts"></param> /// <param name="divdays"></param> /// <param name="divamts"></param> /// <param name="volSurface"></param> /// <param name="spot"></param> /// <param name="s"></param> /// <param name="callstrike"></param> /// <param name="putstrike"></param> /// <param name="t0"></param> /// <param name="maturity"></param> /// <returns></returns> private static double CollarPCEFunction(int[] ratedays, double[] rateamts, int[] divdays, double[] divamts, List <OrcWingParameters> volSurface, double spot, double s, double callstrike, double putstrike, double t0, double maturity) { t0 = Math.Min(t0, maturity); // cap profile point to maturity; double tau = maturity - t0; double r = EquityAnalytics.GetRateCCLin365(t0, maturity, ratedays, rateamts); double q = EquityAnalytics.GetYieldCCLin365(spot, t0, maturity, divdays, divamts, ratedays, rateamts); double callvol = EquityAnalytics.GetWingValue(volSurface, new LinearInterpolation(), tau, callstrike); double putvol = EquityAnalytics.GetWingValue(volSurface, new LinearInterpolation(), tau, putstrike); double fwd = s * Math.Exp((r - q) * tau); BlackScholes bs = new BlackScholes(); double lhs = Math.Max(bs.BSprice(fwd, tau, callstrike, r, callvol, true) - bs.BSprice(fwd, tau, putstrike, r, putvol, false), 0); return(lhs); }
/// <summary> /// Before calculating any PCE numbers on the simulation set, first check the simulated asset values /// at the time slices and compare to the expected values of the theoretical distribution. /// Check we're within 3 standard errors, reason for 3 being that there is a discretisation error introduced /// by the time scheme approximation as well as sample error introduced by the simulation sample mean. /// </summary> /// <param name="kappa"></param> /// <param name="vol"></param> /// <param name="theta"></param> /// <param name="simuls"></param> public void TestDistroConvergence(double kappa, double vol, double theta, int simuls) { DateTime today = new DateTime(2010, 10, 22); DateTime expiry = new DateTime(2011, 10, 22); double maturity = Convert.ToDouble(expiry.Subtract(today).Days) / 365.0; double spot = 4200.00; double callstrike = 1.3 * spot; double putstrike = 1.0 * spot; double confidence = 0.95; int[] zerodays = { 0, 365 }; double[] zerorates = { 0.065, 0.065 }; int[] divdays = { 1, 51, 247 }; double[] divamts = { 22.5, 50, 50 }; double fwd = EquityAnalytics.GetForwardCCLin365(spot, maturity, divdays, divamts, zerodays, zerorates); double histvol = vol; double[] times = { 128.0 / 365.0, 250.0 / 365.0, 365.0 / 365.0 }; OrcWingParameters owp = new OrcWingParameters() { AtmForward = fwd, CallCurve = 0.1250, CurrentVol = 0.26, DnCutoff = -0.25, Dsr = 0.9, PutCurve = 0.10, RefFwd = fwd, RefVol = 0.26, Scr = 0.0, SlopeRef = -0.1750, Ssr = 100, TimeToMaturity = maturity, UpCutoff = 0.20, Usr = 0.50, Vcr = 0.0 }; List <OrcWingParameters> owpList = new List <OrcWingParameters> { owp }; double[,] results = EquityPCEAnalytics.GetCollarPCE("Asset", zerodays, zerorates, divdays, divamts, owpList, spot, callstrike, putstrike, maturity, kappa, theta, histvol, times, confidence, 1.0 / 365.0, simuls, 3151); // Check convergence to mean ln(S_t) ~ N( theta + exp(-kappa*t)*( ln(S_0) - theta , sigma^2/(2*kappa)*(1-exp(-2*kappa*t) ) // => E(S_t) = exp(theta + 0.5*sigma^2) // double LNmean1 = EquityPCEAnalytics.OUMean(kappa, theta, spot, times[0]); double LNmean2 = EquityPCEAnalytics.OUMean(kappa, theta, spot, times[1]); double LNmean3 = EquityPCEAnalytics.OUMean(kappa, theta, spot, times[2]); double Var_1 = EquityPCEAnalytics.OUVar(histvol, kappa, times[0]); double Var_2 = EquityPCEAnalytics.OUVar(histvol, kappa, times[1]); double Var_3 = EquityPCEAnalytics.OUVar(histvol, kappa, times[2]); //lognormal moments double lhs1 = Math.Exp(LNmean1 + Var_1 / 2.0); double lhs2 = Math.Exp(LNmean2 + Var_2 / 2.0); double lhs3 = Math.Exp(LNmean3 + Var_3 / 2.0); //double deltat = 1.0/365.0; double logvar1 = EquityPCEAnalytics.LNOUVar(spot, histvol, kappa, theta, times[0]); double logvar2 = EquityPCEAnalytics.LNOUVar(spot, histvol, kappa, theta, times[1]); double logvar3 = EquityPCEAnalytics.LNOUVar(spot, histvol, kappa, theta, times[2]); double stderr1 = Math.Sqrt(logvar1 / simuls); double stderr2 = Math.Sqrt(logvar2 / simuls); double stderr3 = Math.Sqrt(logvar3 / simuls); //double accuracy = histvol*histvol*(1/(2*kappa) - deltat /(1-Math.Exp(-2*kappa*deltat)))*(1-Math.Exp(-2*kappa*times[0])); Assert.AreEqual(lhs1, results[0, 0], 3.0 * stderr1); Assert.AreEqual(lhs2, results[1, 0], 3.0 * stderr2); Assert.AreEqual(lhs3, results[2, 0], 3.0 * stderr3); }