2
$\begingroup$

I am trying use low discrepancy Sobol RNG to generate normally distributed random numbers and fill an Eigen matrix with those random numbers. The matrix represents a basket of 5 assets (rows) each having 5000 trials (columns). After going thru QuantLib documentation, I have come up with following code. However, the random numbers generated are all the same for each column in the matrix.

MoroInverseCumulativeNormal invGauss;
MatrixXd quasi = MatrixXd::Zero(num_credits,num_trials);
double current_sobol_num{}, current_normal_number{};
for (int c{0}; c< num_credits;++c){
  SobolRsg sobolEngine(1);
  for (int t{0}; t < num_trials;++t){
    current_sobol_num = (sobolEngine.nextSequence().value)[0];
    current_normal_number = invGauss(current_sobol_num);
    quasi(c,t) = current_normal_number;
  };
}

The matrix after the above code is run :

Asset t0 t1 t2 t3 t4
First 0 0.6745 -0.6745 -0.3186 1.1503
Second 0 0.6745 -0.6745 -0.3186 1.1503
Third 0 0.6745 -0.6745 -0.3186 1.1503
Fourth 0 0.6745 -0.6745 -0.3186 1.1503
Fifth 0 0.6745 -0.6745 -0.3186 1.1503

Any idea what I am doing wrong? Is there a way to get all 5000 randoms in one shot instead of pulling one at a time?

I am using QuantLib just for SobolRng and Inverse Gaussian functions. I am open to using any other open source library if suggested.

Thank you very much for your time.

$\endgroup$
2
  • $\begingroup$ For each c, you re-initialize the the rsg with seed defaulting to 0. have you tried moving the instantiation of SobolRsg sobolEngine outside of the for loop? $\endgroup$ Jul 9 at 22:24
  • $\begingroup$ Yes, I have tried moving it outside the loop. I am not sure what the "dimension" parameter to the RNG should be. If I use 5000 like "SobolRsg sobolEngine(5000)", I do get a matrix that looks "random" but the results of my quasi simulation are very different than pseudo simulation. $\endgroup$
    – Yoshiro
    Jul 9 at 23:15

1 Answer 1

1
$\begingroup$

As Dimitri said, the initialization of the RNG should be outside the loop.

The dimension parameter is, roughly speaking, how many random numbers you need for one sample.

If one of your trials consists of the prices for your 5 assets, you'll have to initialize the RNG with dimension 5 (because you need one random number for each price) and then you'll get a list of 5 prices for the 5 assets each time you call sobolEngine.nextSequence().value.

(If, instead, you were generating random paths for an asset over $N$ steps, a full sample would be one path and the dimension would be $N$. If you were generating random paths for $M$ assets over $N$ steps, a full sample would be one path for each asset and the dimension would be $M \times N$.)

However, there's an additional, important consideration: low-discrepancy sequences such as Sobol have constraints that the usual RNG don't have. For instance, you can't extract just any number of samples. Sobol and other low-discrepancy RNGs are designed to cover fairly the domain using $2^N-1$ samples for any given $N$. If you extract 4095 samples ($2^{12}-1$) or 8191 samples ($2^{13}-1$), you'll get correct results from your simulation. If you extract 5000 samples, you won't, because you won't cover the domain fairly. If you need to work with that specific number of samples, you'll have to go for a classic quasi-random generator.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.