public void InitialisationTest(int dim, SobolDirection direction) { var sobol = new SobolRsg(dim, direction); sobol.NextSequence(); Assert.IsTrue(true); }
private void DirectionInit(SobolDirection direction) { // initializes bits_ direction integers for each dimension // and store them into directionIntegers_[dimensionality_][bits_] // // In each dimension k with its associated primitive polynomial, // the first degree_[k] direction integers can be chosen freely // provided that only the l leftmost bits can be non-zero, and // that the l-th leftmost bit must be set int j; for (j = 0; j < Bits; j++) { directionIntegers[j][0] = (uint)(1 << (Bits - j - 1)); } switch (direction) { case SobolDirection.Jaeckel: FillDirection(directionIntegers, dimensionality, JaeckelInitializers.Value); break; case SobolDirection.SobolLevitan: FillDirection(directionIntegers, dimensionality, SLinitializers.Value); break; case SobolDirection.SobolLevitanLemieux: FillDirection(directionIntegers, dimensionality, Linitializers.Value); break; case SobolDirection.JoeKuoD5: FillDirection(directionIntegers, dimensionality, JoeKuoD5Initializers.Value); break; case SobolDirection.JoeKuoD6: FillDirection(directionIntegers, dimensionality, JoeKuoD6Initializers.Value); break; case SobolDirection.JoeKuoD7: FillDirection(directionIntegers, dimensionality, JoeKuoD7Initializers.Value); break; case SobolDirection.Kuo: FillDirection(directionIntegers, dimensionality, KuoInitializers.Value); break; case SobolDirection.Kuo2: FillDirection(directionIntegers, dimensionality, Kuo2Initializers.Value); break; case SobolDirection.Kuo3: FillDirection(directionIntegers, dimensionality, Kuo3Initializers.Value); break; } }
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); }
private static void FillDegreeAndPolynom(int dimensionality, SobolDirection direction, out uint[] degree, out long[] ppmt) { // initializes coefficient array of the k-th primitive polynomial // and degree of the k-th primitive polynomial degree = new uint[dimensionality]; ppmt = new long[dimensionality]; bool useAltPolynomials = direction == SobolDirection.Kuo || direction == SobolDirection.Kuo2 || direction == SobolDirection.Kuo3 || direction == SobolDirection.SobolLevitan || direction == SobolDirection.SobolLevitanLemieux; // degree 0 is not used ppmt[0] = 0; degree[0] = 0; uint currentDegree = 1; uint altDegree = useAltPolynomials ? MaxAltDegree : 0; int k = 1; int index = 0; for (; k < Math.Min(dimensionality, altDegree); k++, index++) { ppmt[k] = AltPrimitivePolynomials[currentDegree - 1][index]; if (ppmt[k] == -1) { ++currentDegree; index = 0; ppmt[k] = AltPrimitivePolynomials[currentDegree - 1][index]; } degree[k] = currentDegree; } for (; k < dimensionality; k++, index++) { ppmt[k] = PrimitivePolynomials[currentDegree - 1][index]; if (ppmt[k] == -1) { ++currentDegree; index = 0; ppmt[k] = PrimitivePolynomials[currentDegree - 1][index]; } degree[k] = currentDegree; } }
public SobolRsg(int dimensionality, SobolDirection direction) { if (dimensionality < 0) { throw new ApplicationException("dimensionality must be greater than 0"); } if (!(dimensionality <= PPMT_MAX_DIM)) { throw new ApplicationException("dimensionality " + dimensionality + " exceeds the number of available " + "primitive polynomials modulo two (" + PPMT_MAX_DIM + ")"); } this.dimensionality = dimensionality; sequenceCounter = 0; firstDraw = true; integerSequence = new uint[dimensionality]; sequence = new double[dimensionality]; for (int i = 0; i < dimensionality; ++i) { sequence[i] = 1.0; } directionIntegers = new uint[Bits][]; for (int i = 0; i < Bits; i++) { directionIntegers[i] = new uint[dimensionality]; } uint[] degree; long[] ppmt; FillDegreeAndPolynom(this.dimensionality, direction, out degree, out ppmt); DirectionInit(direction); // computation of directionIntegers_[k][l] for l>=degree_[k] // by recurrence relation for (int k = 1; k < this.dimensionality; k++) { uint gk = degree[k]; for (var l = (int)gk; l < Bits; l++) { // eq. 8.19 "Monte Carlo Methods in Finance" by P. Jдckel uint n = (directionIntegers[(int)(l - gk)][k] >> (int)gk); // a[k][j] are the coefficients of the monomials in ppmt[k] // The highest order coefficient a[k][0] is not actually // used in the recurrence relation, and the lowest order // coefficient a[k][gk] is always set: this is the reason // why the highest and lowest coefficient of // the polynomial ppmt[k] are not included in its encoding, // provided that its degree is known. // That is: a[k][j] = ppmt[k] >> (gk-j-1) for (uint z = 1; z < gk; z++) { // XORed with a selection of (unshifted) direction // integers controlled by which of the a[k][j] are set if ((((ulong)ppmt[k] >> (int)(gk - z - 1)) & 1UL) != 0) { n ^= directionIntegers[(int)(l - z)][k]; } } // a[k][gk] is always set, so directionIntegers_[k][l-gk] // will always enter n ^= directionIntegers[(int)(l - gk)][k]; directionIntegers[l][k] = n; } } // initialize the Sobol integer/double vectors // first draw for (int k = 0; k < this.dimensionality; k++) { integerSequence[k] = directionIntegers[0][k]; } }
public GaussSobolGeneratorFactory(SobolDirection sobolDirection) { this.sobolDirection = sobolDirection; }
public static IRandomGeneratorFactory GaussianSobol(SobolDirection sobolDirection) { return(new GaussSobolGeneratorFactory(sobolDirection)); }