Quant Memo
Foundational

Random Seed Management

Why any code that uses randomness — bootstrapping, Monte Carlo, train/test splits, model initialization — needs its random number generator explicitly seeded, and why one seed usually isn't enough.

Prerequisites: Dependency Management and Lockfiles

Run a backtest that bootstraps confidence intervals, or trains a model with a randomly initialized starting point, and rerun the identical code five minutes later — the numbers come out slightly different each time. Nothing is broken; the code is using randomness, and by default the source of that randomness isn't fixed to anything. A computer doesn't generate "true" randomness — it uses a pseudo-random number generator that produces a long, deterministic sequence of numbers that merely looks random. That sequence is entirely determined by a starting value called the seed. Set the same seed and you get the exact same sequence of "random" numbers every time; leave it unset and most libraries default to seeding from something like the system clock, so every run differs.

Seed management means explicitly setting that starting value — usually once, at the top of a script — so a run can be exactly reproduced later. This matters everywhere randomness touches quant work: a Monte Carlo simulation of a strategy's P&L distribution, a bootstrap resample used to estimate the standard error of a Sharpe ratio, a random train/test split of historical data, or the random weight initialization of a neural network. Without a fixed seed, two runs of "the same" backtest can report different results, and there's no way to tell whether a change in a number came from a real code change or from the dice landing differently.

Worked example. A researcher backtests a strategy and reports a bootstrapped 95% confidence interval on annual Sharpe of 0.9 to 2.1, using numpy's default random generator with no seed set. A colleague reruns the exact same script the next day and gets 0.8 to 2.3 — close, but not identical, because the resamples drawn were different each time. Neither number is wrong; both are valid draws from the same underlying resampling procedure. But the discrepancy makes it impossible to tell, in a code review, whether a later change to the interval came from an intentional edit or just from a different random draw. Adding np.random.default_rng(seed=42) at the top of the script, and using that single generator object everywhere randomness is needed, fixes the sequence completely — every rerun reproduces 0.9 to 2.1 exactly, and any future change in that number can be attributed to an actual code change.

What this means in practice

Seed the random number generator once, explicitly, near the top of any script that uses randomness, and pass that same generator object through the code rather than letting different libraries each pick their own default source. Multiple libraries — numpy, random, a machine learning framework — each keep their own independent generator, so seeding one doesn't seed the others; a script using several needs each seeded separately. Reproducibility from a fixed seed doesn't mean the randomness stopped mattering: it means you've pinned down which random draw you're looking at, so the same draw comes back on demand while a different seed still gives an honest sense of how much the result varies run to run.

A fixed random seed makes stochastic code reproducible by pinning the pseudo-random sequence to a specific starting value — essential for debugging, code review, and comparing "before vs after" results without random noise contaminating the comparison.

Seeding once at import time is not the same as seeding per-run. If a seeded generator is shared and mutated across multiple test cases or backtest runs in the same process, later runs consume different parts of the sequence depending on what ran before them — reintroducing the exact irreproducibility a seed was meant to prevent. Re-seed (or use a fresh generator instance) at the start of each independent run.

Related concepts

Practice in interviews

Further reading

  • NumPy documentation, Random Generator
ShareTwitterLinkedIn