public void CallNaiveImplemXCheck() { var maturities = GridUtils.RegularGrid(0.1, 5.0, 100); var vols = GridUtils.RegularGrid(0.001, 0.015, 10); var volMoneynesses = GridUtils.RegularGrid(-3, 3, 100); foreach (var mat in maturities) { foreach (var vol in vols) { var sigma = Math.Sqrt(mat) * vol; foreach (var vm in volMoneynesses) { var strike = vm * sigma; var call = BachelierOption.Price(0.0, strike, vol, mat, 1); //Naive implementation of bachelier formulae var d = strike / sigma; var call_xcheck = -strike *NormalDistribution.Cumulative(-d) + sigma * NormalDistribution.Density(d); if (DoubleUtils.EqualZero(call)) { Assert.IsTrue(DoubleUtils.EqualZero(call_xcheck)); } else { var errRelative = (call - call_xcheck) / call_xcheck; Assert.IsTrue(Math.Abs(errRelative) < 1.0e-13); } } } } }
public void TestCallBachelier(int dim, SobolDirection direction) { var gaussianGen = RandomGenerators.GaussianSobol(direction).Build(dim); var chrono = new Stopwatch(); chrono.Start(); var atmCalls = new double[dim]; var strikeCall1 = new double[dim]; var strikeCall2 = new double[dim]; var strikePut1 = new double[dim]; var strikePut2 = new double[dim]; const int nbPaths = 1000000; for (int index = 0; index < nbPaths; index++) { var sample = gaussianGen.Next(); for (int i = 0; i < dim; i++) { var gaussian = sample[i]; atmCalls[i] += Math.Max(0.0, gaussian); strikeCall1[i] += Math.Max(0.0, gaussian - 1.0); strikeCall2[i] += Math.Max(0.0, gaussian - 2.0); strikePut1[i] += Math.Max(0.0, -1.0 - gaussian); strikePut2[i] += Math.Max(0.0, -2.0 - gaussian); } } for (int i = 0; i < dim; i++) { atmCalls[i] /= nbPaths; strikeCall1[i] /= nbPaths; strikeCall2[i] /= nbPaths; strikePut1[i] /= nbPaths; strikePut2[i] /= nbPaths; } chrono.Stop(); Console.WriteLine("Elapsed " + chrono.Elapsed); var refAtmCalls = atmCalls.Select(c => BachelierOption.Price(0.0, 0.0, 1.0, 1.0, 1)).ToArray(); var refStrikeCall1 = atmCalls.Select(c => BachelierOption.Price(0.0, 1.0, 1.0, 1.0, 1)).ToArray(); var refStrikeCall2 = atmCalls.Select(c => BachelierOption.Price(0.0, 2.0, 1.0, 1.0, 1)).ToArray(); var refStrikePut1 = atmCalls.Select(c => BachelierOption.Price(0.0, -1.0, 1.0, 1.0, -1)).ToArray(); var refStrikePut2 = atmCalls.Select(c => BachelierOption.Price(0.0, -2.0, 1.0, 1.0, -1)).ToArray(); UnitTestUtils.EqualDoubleArray(atmCalls, refAtmCalls, 2.0e-5, true); UnitTestUtils.EqualDoubleArray(strikeCall1, refStrikeCall1, 8.0e-5, true); UnitTestUtils.EqualDoubleArray(strikeCall2, refStrikeCall2, 6.0e-4, true); UnitTestUtils.EqualDoubleArray(strikePut1, refStrikePut1, 8.0e-5, true); UnitTestUtils.EqualDoubleArray(strikePut2, refStrikePut2, 6.0e-4, true); }
public void ImpliedVol_HighRegion_Test() { const double mat = 0.5; const double vol = 0.070; var moneynesses = GridUtils.RegularGrid(5.5, 15.0, 10000); foreach (double m in moneynesses) { var strike = m * vol * Math.Sqrt(mat); var option = BachelierOption.Price(0.0, strike, vol, mat, m > 0 ? 1 : -1); var impliedVol = BachelierOption.ImpliedVol(option, 0.0, strike, mat, m > 0 ? 1 : -1); var errRelative = (impliedVol - vol) / vol; Assert.IsTrue(Math.Abs(errRelative) < 5.5e-11); } }