An unseeded result is not a result, it is one draw from a distribution of results
The short answer
A result is checkable only if a reader can recreate it, and that needs four things almost nobody publishes: every random seed, the replication count, the data snapshot (source, period, adjustment convention and the date it was pulled) and the software environment. Measured on this page: the same code on the same data, run twelve times without a fixed seed, moved its reported lower bound by 0.0168, which is 9 per cent of the interval's own width. With a seed, twelve runs were identical. The seed costs one line. Everything else on this page costs about an hour, and it is an hour you cannot spend retrospectively.
This is the least interesting subject in quantitative work and the one that decides whether any of the rest of it means anything. A number nobody can recreate is not evidence. It is a claim with arithmetic attached.
Reproducing is not replicating, and the difference decides what you need
Two words get used interchangeably and they are not the same requirement. Reproducing a result means taking the same data and the same code and arriving at the same answer. Replicating it means running a fresh study, on your own data and your own implementation, and reaching the same conclusion.
Reproduction is a disclosure problem. Replication is a truth problem. The uncomfortable consequence is that a result can be perfectly reproducible and entirely wrong, because reproducing a mistake reproduces it exactly. Reproducibility is therefore not a claim of correctness. It is the precondition for anyone being able to find out.
Where the randomness actually enters
Most people setting out to make work reproducible think of simulation, and stop there. Randomness enters a quantitative workflow in more places than that, and every one of them moves the answer.
| Source | What it does to the answer | What fixes it |
|---|---|---|
| Bootstrap and resampling | Moves every reported interval | A stated seed and replication count |
| Simulation | Moves every percentile and tail figure | A stated seed and run count |
| Shuffles and permutation tests | Moves the reported significance directly | A stated seed |
| Random train and test splits | Moves the entire out of sample result | A seed, or a rule rather than a draw |
| Set and dictionary ordering | Changes floating point summation order | Sorting before aggregating |
| Parallel execution | Changes the order results are combined in | Deterministic reduction, or single threading |
The last two are the ones that surprise people, because no random number generator is involved. Floating point addition is not associative: summing the same values in a different order can give a slightly different total. Usually that is invisible. At a threshold, it is the whole decision.
The measurement
Rather than assert that an unseeded result moves, here is the measurement. A fixed series of 500 observations, a bootstrap of 400 replications, a ninety five per cent interval on the mean. The same code, the same data, twelve times over, each run landing on its own random draw exactly as an uncontrolled run would.
| Lower bound | Upper bound | Width | |
|---|---|---|---|
| Run 1 | -0.0523 | +0.1369 | 0.1892 |
| Run 2 | -0.0433 | +0.1334 | 0.1767 |
| Run 3 | -0.0499 | +0.1340 | 0.1839 |
| Run 4 | -0.0495 | +0.1283 | 0.1778 |
| Run 5 | -0.0458 | +0.1177 | 0.1635 |
| Run 6 | -0.0600 | +0.1224 | 0.1824 |
Across all twelve, the lower bound ranged from -0.0600 to -0.0433 and the upper from +0.1177 to +0.1369. The interval's own width varied between 0.1635 and 0.1895. Publishing any one of those twelve as the answer, with no indication that eleven others were equally available, is the ordinary practice.
Running the identical procedure with a seed fixed at a stated value produced identical output on all twelve runs, at -0.0490 to +0.1236. The fix is one line and it is free.
How many replications is enough, measured
A seed makes a result repeatable. It does not make it stable, in the sense of being insensitive to the arbitrary choice of seed. That is a separate question with its own measurable answer: run the whole procedure repeatedly on different draws, and see how much the reported figure moves at each replication count.
| Replications | Spread of the answer | Relative to the 100 case |
|---|---|---|
| 100 | 0.03278 | 1.00 |
| 400 | 0.01000 | 0.30 |
| 1,000 | 0.00628 | 0.19 |
| 5,000 | 0.00563 | 0.17 |
| 20,000 | 0.00262 | 0.08 |
The shape of that table is the useful part. Going from 100 to 20,000 replications is two hundred times the computation and cut the wobble by roughly 13 times, because the error falls with the square root of the count. There is no replication number at which the answer stops moving, only one at which it stops moving in the digits you intend to quote. That is the number to find, and it is why the replication count belongs next to the result.
The instrument that agreed with itself perfectly
This article nearly shipped with a fabricated result, and the way it happened is worth the space because it is exactly the failure the subject is about.
The first version built its series like this:
series = [random.Random(11).gauss(0, 1) for _ in range(500)]
That rebuilds the generator on every iteration from the same seed, so it returns five hundred identical values. Every bootstrap sample of a constant series has the same mean, so every interval came out with zero width, and every run agreed with every other run to the last digit.
The output looked like a flawless demonstration of reproducibility. It was a broken instrument reporting nothing at all. What caught it was not the code review but the number: an interval of exactly zero width is not a good result, it is an impossible one.
The fix in the shipped script is two lines, and the second matters more than the first: seed once outside the comprehension, then assert the series is not degenerate before anything is built on it. The control now reports 500 distinct values at a standard deviation of 1.0169, and the assertion fails the build if that ever stops being true.
The general rule this illustrates has nothing to do with this particular bug. A result that looks impossibly clean is a defect report. Perfect agreement, a zero variance, a correlation of exactly one, a p-value of exactly zero: each is far more likely to be an instrument reporting on itself than a discovery.
The data snapshot, which is the hard one
Seeds are easy. The genuinely difficult part of reproducibility in market work is that the data moves underneath you, and naming a period does not pin it down.
| Cause | Effect on a repeat request |
|---|---|
| Provider revision | Historical values are corrected after the fact |
| Corporate action adjustment | A back-adjusted series is rewritten from the start every time a new action occurs |
| Index reconstitution | Current membership is not historical membership, so an index-based study silently changes |
| Symbol changes | A ticker is not a stable key, so a join by symbol breaks across time |
| Coverage extension | History is added backwards, changing every full-sample statistic |
The consequence is specific: a period is not a snapshot. Two people who both say they used the last ten years, from the same provider, can hold materially different data. What identifies a snapshot is the source, the period, the adjustment convention and the date it was pulled, and the only fully reliable version is to keep the file.
The minimum disclosure
Everything above reduces to a short list. It is worth applying to your own work first, where it is hardest to pass.
| Disclose | Because without it |
|---|---|
| Every seed | The reader cannot tell your result from the eleven others you might have got |
| The replication count | They cannot tell whether your digits are stable |
| Data source and snapshot date | They cannot obtain the same data |
| Adjustment convention | Their series will differ from yours at every corporate action |
| The cleaning rule | They cannot tell which observations you kept |
| Every parameter | They are guessing at the specification |
| The number of variants tried | They cannot judge the result's significance at all |
| Language and library versions | They cannot resolve a disagreement in the last digits |
The seventh row is the one that carries the most information and is almost never present, because nobody records it as they go. It is also the only item on the list that cannot be reconstructed afterwards: seeds can be re-run, data can be re-pulled, versions can be looked up, but the count of discarded attempts exists only if somebody wrote it down at the time.
When the data cannot be shared, which is most of the time
The standard advice is to publish the data alongside the result, and for market work that advice is frequently impossible to follow. Exchange and vendor data is licensed, and a licence to use it is not a licence to redistribute it. Anyone working from a paid feed is contractually unable to do the thing reproducibility guides tell them to do.
Treating that as the end of the matter is the common response and it is wrong, because the licence blocks one specific item on the list and leaves the rest untouched. What can be published without redistributing anything is considerable.
| Publish | What it lets a reader do |
|---|---|
| The code that fetches and processes it | Obtain the same data themselves and run the identical pipeline |
| The exact identifiers and date range | Request precisely the same rows rather than approximately the same ones |
| A checksum of the file you used | Confirm their copy matches yours before blaming the method |
| Summary statistics of the input | Detect immediately that their data differs from yours, and how |
| A synthetic series with matched properties | Run and test the pipeline end to end without your data at all |
| The intermediate result, not the raw rows | Check your inference even when the inputs are withheld |
The checksum line does more work than it looks. Most failed reproductions in practice are not disagreements about method at all: they are two people holding different data and arguing about the analysis. A hash published next to the result resolves that in seconds, and it discloses nothing about the contents of the file.
The synthetic-series line matters for a different reason. A pipeline that runs on generated data of the right shape is a pipeline somebody can execute, inspect and find a bug in, even if they can never reproduce your exact number. That is a large fraction of the value, and it survives any licence.
The order that makes all of this nearly free
Everything on this page is cheap while the work is happening and expensive or impossible afterwards. That asymmetry, rather than any principle, is the practical argument.
| Item | Cost at the time | Cost afterwards |
|---|---|---|
| Seed | One line | Impossible, the run is gone |
| Snapshot date and source | A comment | Guesswork, and the data has since moved |
| A copy of the input file | Seconds and some disk | Often unobtainable at any price |
| Parameters as named constants | A habit, no extra time | Archaeology through old code |
| Library versions | One command, captured to a file | Approximate at best |
| The count of variants tried | One line per attempt | Genuinely impossible |
Read the right-hand column and the ordering becomes obvious. The items that cannot be recovered are the ones to set up before the first run, not after the interesting result appears, because by then the thing worth recording has already happened and gone unrecorded.
The last row deserves its own emphasis because it is the only item on the list that is irrecoverable in principle rather than merely in practice. A seed can be regenerated by re-running. A dataset can sometimes be re-purchased. The number of ideas you tried and discarded on the way to this one exists nowhere except in a note you did or did not make at the time, and without it nobody, including you, can say what the surviving result is worth.
What this looks like in practice, and what it costs
The smallest version that genuinely works is a single file that runs end to end and regenerates the result, with the seed at the top, the data source and snapshot date in a comment, and every parameter as a named constant rather than a number buried in the middle of a line. That is not a research infrastructure. It is an afternoon, and it puts a result ahead of most of what gets published.
It is worth being honest that full reproducibility, in the sense of bit-identical results on another machine in five years, is expensive and frequently unattainable. That is not an argument against the attempt. The realistic goal is weaker and far more useful: a reader should be able to see exactly what was done, and could redo it in principle. That is achievable at almost no cost, and it is enough for somebody to find the step they disagree with, which is the entire point.
There is also a self-interested case, and for most people it is the persuasive one. The reader who most often fails to reproduce your work is you, several months later, looking at a number you no longer remember producing. Everything here is cheaper to do while you are doing the work than to reconstruct afterwards, and reconstruction usually turns out to be impossible.
Frequently asked questions
What is the difference between reproducibility and replication?
Reproducibility is the same data and the same code producing the same answer. Replication is a fresh study reaching the same conclusion by its own route. They need entirely different things: the first needs disclosure, the second needs the finding to be real. A result can be perfectly reproducible and completely wrong, because reproducing an error reproduces it faithfully.
Why does an unseeded result count as no result?
Because it is one draw from a distribution of possible answers, and the reader has no way to know where in that distribution it fell. On the measurement on this page the lower bound moved by roughly a fifth of the interval's own width across twelve runs of identical code. Reporting one of those twelve without saying so presents a sample as a finding.
Does setting a seed make a result correct?
No, and treating it that way is the common mistake. A seed makes a result checkable, not right. It removes one specific source of variation so that any remaining disagreement between you and a checker is attributable to something real rather than to chance.
How many replications should I run?
Enough that the answer is stable at the precision you intend to report. That is measurable rather than a matter of convention: run the whole procedure several times and see how much the reported figure moves. If it moves in the digits you are quoting, you are quoting too many digits or running too few replications.
Why is the data snapshot so difficult?
Because a market data history is not fixed. Providers revise it, and a series adjusted for corporate actions is rewritten every time a new action occurs, so the same request today returns different numbers from last year. Naming a period is therefore not enough. The snapshot date, the source and the adjustment convention all have to be stated.
Does the software environment really change numerical results?
Yes, in the last digits, and that is enough when a decision sits at a threshold. Library versions change algorithms and defaults, and floating point addition is not associative, so the same operations summed in a different order give slightly different answers. It rarely changes a conclusion and it regularly changes whether two people's numbers match exactly.
Is this not excessive for an individual trader's own research?
The opposite. The person who most often fails to reproduce your work is you, six months later, trying to remember what you ran. Everything on this page is cheaper to do at the time than to reconstruct afterwards, and reconstruction is usually impossible.
What is the smallest useful version of all this?
A single file that runs end to end and regenerates the result, with the seed set at the top, the data source and snapshot date named in a comment, and the parameters as named constants rather than numbers buried in the code. That alone puts a result ahead of most published work.
If full reproducibility is unattainable, what is the realistic goal?
That a reader can tell exactly what was done and could redo it in principle. Perfect bit-for-bit reproduction across machines and years is expensive and often impossible. Complete disclosure is neither, and it delivers most of the value, because it lets a reader find the step they disagree with.
How should I read a result that discloses none of this?
As unverifiable rather than as false. Most published results are unverifiable, and most of those are produced in good faith by people who simply never recorded what they did. Treating unverifiable as dishonest is both unfair and useless. Treating it as uncheckable is accurate, and it tells you how much weight to put on it.
How these numbers were produced. A synthetic series of 500 observations was generated from a generator seeded once at 11, and asserted non degenerate (500 distinct values, standard deviation 1.0169) before use. Each interval is a percentile bootstrap of the mean at 400 replications. The variation shown is produced by giving each run its own distinct seed. That reproduces exactly what an uncontrolled run does, while leaving this page byte identical on every rebuild, which a genuinely unseeded demonstration would not be. The seeded comparison instead fixes one seed at 20260919 across all twelve runs. The replication ladder reports the spread of the lower bound across eight differently seeded runs at each count. Computed on Python 3.9.6. Every figure is reproducible from that description, and the build script for this page regenerates all of them.
The position is stated as at September 2026. Nothing here is personal financial advice; take advice on your own circumstances.
Ready to go deeper than this article?
Bharath Shiksha is a 90-volume curriculum across 6 stages, from chart reading at ₹14,999 through capital raising, or the full bundle at ₹1,49,999. Recording what you actually did, while you are doing it, is the least glamorous habit in research and the one that separates a result from a recollection.
Take the free diagnostic →