Statistics for traders
You never see a strategy’s true edge — only a finite sample of trades drawn from it, blurred by noise. Statistics is the discipline of saying how much that sample can be trusted. This is the chapter that explains the single most important sentence in the whole course: you need a lot of trades before a backtest means anything.
Sampling & sampling error#
The true expected return per trade, , is a fixed but unknown property of the strategy — the population mean. A backtest gives you a sample of trades, and from it the sample mean:
is our estimate of , but it is itself random — run the strategy over a different slice of history and you get a different . The gap between your sample estimate and the truth is sampling error. It is not a bug or a bad backtest; it is the irreducible fog that comes from having finite data. The entire job of the next few chapters is to keep that fog from fooling you.
Standard error#
How much does wobble from sample to sample? Its standard deviation has a name — the standard error of the mean:
The sample mean is a sum scaled by . Pull the constant out of the variance (which costs a square):
If the trades are independent, the variance of the sum is the sum of the variances (no covariance terms), and each has the same :
Take the square root to get back to the units of the mean: . The is not magic — it is the square root of the -vs- mismatch between scaling and adding. ■
Read this formula slowly, because it governs everything. The uncertainty in your estimate shrinks with the square root of the number of trades — not linearly. To halve your uncertainty you need four times as many trades. To cut it by ten, a hundred times as many. This is why a strategy with 30 trades tells you almost nothing and one with 1,000 tells you something real.
| Trades n | √n | SE relative to n = 25 |
|---|---|---|
| 25 | 5 | 1.00× (baseline) |
| 100 | 10 | 0.50× (half the error) |
| 400 | 20 | 0.25× |
| 2,500 | 50 | 0.10× |
The law of large numbers#
Before the mean can be Normal, it first has to land on the truth at all. That guarantee is the law of large numbers (LLN): as the number of trades grows, the sample mean converges to the true mean.
It is the mathematical form of “let the edge play out.” A positive-expectancy strategy is not promised to win on any given trade — only that, averaged over enough of them, the realised mean is pulled toward . The LLN is why an edge is worth having; it is also why it needs volume to materialise.
Chebyshev’s inequality — a distribution-free proof#
We can prove the LLN and get a usable bound in one stroke with Chebyshev’s inequality, which holds for any distribution with finite variance — no Normality, no thin tails required:
Chebyshev follows from Markov’s inequality applied to : since that quantity is non-negative with mean , the probability it exceeds is at most . The event is the same as , giving the bound.
Now apply it to the sample mean, which has standard deviation . For any fixed tolerance ,
The probability of the sample mean straying from by any margin vanishes as — that is exactly convergence, and the LLN. ■
The central limit theorem#
Why can we use and reason with the bell curve, when individual returns are fat-tailed and nothing like Normal? Because of the central limit theorem (CLT): the distribution of the sample mean of independent draws approaches a Normal as grows — regardless of the shape of the underlying distribution.
The individual trades can be as skewed and fat-tailed as markets truly are; average enough of them and the average settles into a tidy bell curve centered on the truth, tightening as rises. That is what licenses every confidence interval and hypothesis test that follows.
The mechanism is a competition of moments. Standardise the sample mean as . Its skew shrinks like and its excess kurtosis like , so as grows every deviation from a bell shape is scrubbed away and only the mean and variance survive — the defining property of a Normal. (The rigorous version matches characteristic functions.) Note the scaling: we multiplied by to keep from collapsing to a point, which is the same statement as : the mean concentrates, and the width of what is left of its distribution closes at rate — quadruple the trades to halve the noise.

Confidence intervals#
A point estimate without a range is a false precision. A confidence interval puts a band around it. Using the CLT and the 95% rule for a Normal, the 95% interval for the true mean is:
From the CLT, , so the standardised mean is a standard Normal:
The value is chosen so a standard Normal lands inside with probability 0.95. So with 95% probability,
Multiply through by and rearrange to isolate :
For a general confidence level, swap 1.96 for the matching Normal quantile (2.58 for 99%).
The interpretation is subtle and worth getting right: it does notsay “there is a 95% probability the truth is in this interval.” It says that if you repeated the whole experiment many times, 95% of the intervals you construct this way would contain the true . It is a statement about the reliability of the procedure, not about this one interval.

The practical payoff: the same estimated edge is convincing with a narrow band and meaningless with a band that straddles zero. When you compute a strategy’s expectancy, always ask whether zero is inside its interval. If it is, you do not yet have evidence of an edge — only a hint.
import numpy as np
from edgekit import trade_stats
st = trade_stats(trades.r) # per-trade R-multiples
r = np.asarray(trades.r, float)
n = r.size
mean = r.mean()
se = r.std(ddof=1) / np.sqrt(n) # standard error of the mean
lo, hi = mean - 1.96 * se, mean + 1.96 * se
print(f"expectancy: {st['ev_r']:.3f}R (n={n})")
print(f"95% CI: [{lo:.3f}, {hi:.3f}]R")
if lo <= 0 <= hi:
print("zero is inside the band -> no statistical evidence of edge yet")Hypothesis testing & p-values#
Confidence intervals and hypothesis tests are two sides of the same coin. A hypothesis test formalises the skeptic’s question: could this result just be luck?
The null hypothesis#
You start by assuming the boring explanation — the null hypothesis : the strategy has no edge, its true expectancy is zero, every apparent profit is noise. Your result is only interesting if the data makes this null look untenable. You never prove the null false; you either reject it or fail to reject it.
What a p-value actually means#
The p-value is the probability of seeing a result at least as extreme as the one you got, if the null hypothesis were true:
A small p (conventionally ) means “a no-edge world would rarely produce something this good, so the no-edge story is hard to believe.” Be precise about what it is not: p is not the probability that your strategy has no edge, and it is not the probability the result is due to chance. It is a conditional probability assuming the null — a measure of how surprised a skeptic should be, nothing more.
Type I and Type II error#
A test can be wrong two ways. A Type I error (false positive) is rejecting a true null — deploying a strategy that has no edge. A Type II error (false negative) is failing to reject a false null — discarding a strategy that really works. Their probabilities have standard names:
Your significance threshold is — set it to 0.05 and you accept a 5% false-positive rate per test. The quantity is the power: the chance of catching a real edge when there is one. The two trade off — demanding a smaller raises unless you add data — and the lever that improves both at once is a larger , which tightens and separates the two hypotheses.

Because market returns violate the neat assumptions behind textbook t-tests (independence, Normality), edgekit does not lean on a closed-form p-value. It uses a permutation test: shuffle the data to build the null distribution empirically, then read off where the real result falls. The p-value becomes a simple count:
where is your real statistic and are the statistics from shuffled (no-edge) data. This is edgekit.validation.mcpt, the decisive step of the gauntlet.
from edgekit.validation import mcpt, bootstrap_rng
# real_stat = your strategy's observed metric (e.g. profit factor)
# null_fn() = one draw of that metric under a shuffled, edge-free world
p = mcpt(real_stat, null_fn, n=1000, rng=bootstrap_rng())
print(f"permutation p = {p:.3f}") # small p => the null struggles to fake thisWhy we need many trades — the through-line#
Everything in this chapter is the same fact stated four ways:
- Standard error is — few trades, huge uncertainty.
- The CLT only tightens the estimate as grows.
- Confidence intervals shrink like .
- A p-value needs enough data to distinguish edge from noise.
A strategy with 40 trades and a gorgeous equity curve is, statistically, a rumor. One with 700 trades that survives a permutation test is a claim you can act on. It is why the strategies worth deploying tend to be the ones that trade often enough to accumulate evidence — and why every backtest in this course reports its trade count as prominently as its return.
Next: now we can define edge precisely and ask how many trades it takes to show up — The math of edge.


