Quant Memo
Foundational

Environment Pinning and Containerization

Locking down exact library versions and using containers so a backtest or model produces the same result today, next year, and on a colleague's machine.

A backtest that runs today with pandas==1.5 might silently produce different numbers a year later if it's re-run with pandas==2.1, because a default rounding rule, NaN-handling behavior, or sort stability changed between versions somewhere in that gap — with no error message and no obvious warning that anything is different. Environment pinning is the fix: recording the exact version of every library (and often the exact Python or R interpreter version) a piece of research code depends on, so it can be reinstalled identically later.

A pinned requirements file (requirements.txt with exact == versions, or a lockfile) fixes the software but not the machine it runs on — operating system differences, chip architecture, or system libraries can still cause tiny numerical differences. Containerization goes a step further by packaging the entire environment, including the operating system layer, into a single image (commonly a Docker container) that runs identically wherever it's deployed — a researcher's laptop, a cloud server, or a colleague's machine three years later all execute the exact same bytes.

Quant desks that skip this often discover the cost the hard way: a strategy re-run for a routine audit produces materially different historical Sharpe ratios purely from unpinned dependency drift, with no way to tell whether the original result or the re-run is the "real" one.

Pinning exact library versions and containerizing the full runtime environment are what make a backtest reproducible years later — without them, routine library upgrades can silently change results with no warning, leaving no way to know which run was actually correct.

Related concepts

Further reading

  • Docker, Inc., 'What is a Container?'
ShareTwitterLinkedIn