This project has moved and is read-only. For the latest updates, please go here.

Best random number generator implementation??

Jun 20, 2011 at 10:02 AM
Edited Jun 20, 2011 at 10:18 AM


I use Math.NET numerics in order to implement a Monte Carlo simulations pricer. I currently use the MersenneTwister random number source/implementation and I noticed my MC starts to diverge as I generate more that 5 millions simulations.

Is the MersenneTwister the best implementation? Can anyone please advise?

Thanks in advance,


P.S. Here is my code:


using System;
using System.Threading.Tasks;
using MathNet.Numerics.Distributions;
using MathNet.Numerics.Random;

namespace MonteCarlo
    class VanillaEuropeanCallMonteCarlo
        static void Main(string[] args)
            const int NUM_SIMULATIONS = 10000000;
            const decimal strike = 50m;
            const decimal initialStockPrice = 52m;
            const decimal volatility = 0.2m;
            const decimal riskFreeRate = 0.05m;
            const decimal maturity = 0.5m;
            Normal n = new Normal();
            n.RandomSource = new MersenneTwister();

            VanillaEuropeanCallMonteCarlo vanillaCallMonteCarlo = new VanillaEuropeanCallMonteCarlo();

            Task<decimal>[] simulations = new Task<decimal>[NUM_SIMULATIONS];

            for (int i = 0; i < simulations.Length; i++)
                simulations[i] = new Task<decimal>(() => vanillaCallMonteCarlo.RunMonteCarloSimulation(strike, initialStockPrice, volatility, riskFreeRate, maturity, n));


            decimal total = 0m;

            for (int i = 0; i < simulations.Length; i++)
                total += simulations[i].Result;

            decimal callPrice = (decimal)(Math.Exp((double)(-riskFreeRate * maturity)) * (double)total / (NUM_SIMULATIONS * 2));

            Console.WriteLine("Call Price: " + callPrice);
            Console.WriteLine("Difference: " + Math.Abs(callPrice - 4.744741008m));

        decimal RunMonteCarloSimulation(decimal strike, decimal initialStockPrice, decimal volatility, decimal riskFreeRate, decimal maturity, Normal n)
            decimal randGaussian = (decimal)n.Sample();
            decimal endStockPriceA = initialStockPrice * (decimal)Math.Exp((double)((riskFreeRate - (decimal)(0.5 * Math.Pow((double)volatility, 2))) * maturity + volatility * (decimal)Math.Sqrt((double)maturity) * randGaussian));
            decimal endStockPriceB = initialStockPrice * (decimal)Math.Exp((double)((riskFreeRate - (decimal)(0.5 * Math.Pow((double)volatility, 2))) * maturity + volatility * (decimal)Math.Sqrt((double)maturity) * (-randGaussian)));
            decimal sumPayoffs = (decimal)(Math.Max(0, endStockPriceA - strike) + Math.Max(0, endStockPriceB - strike));
            return sumPayoffs;

Jun 23, 2011 at 11:54 AM


I'm not sure about the Monte Carlo simulation code itself but as far as using the RNG goes: all RNG's carry a bit of state so when you use them in a parallel context (using Tasks), you have to be careful about locking the RNG. We provider a setting called MathNet.Numerics.Control.ThreadSafeRandomNumberGenerators which if you set to true will make sure that there are no race issues. I'd try that out first ...

Cheers, Jurgen

Jun 24, 2011 at 6:07 PM

Hello Jurgen,

Thanks for your reply. I am new to .NET and I use VisualC# express. Can you please let me know where I need to specify this setting?

Thanks in advance,


Jun 24, 2011 at 9:13 PM

As the first line in your program, write

MathNet.Numerics.Control.ThreadSafeRandomNumberGenerators = true;

Jun 24, 2011 at 9:14 PM