A helper lesson for the course "Build your own arbitrage bot". Lesson 15 uses a z-score to decide when two coins drifted apart. Here it is on ten numbers.
Three questions about a list of numbers
Take the number of minutes your bus was late over ten days: 10, 12, 11, 13, 9, 12, 11, 10, 12, 30.
- What is typical? The mean (the average): add all and divide by how many.
- How much do they vary? The standard deviation: the typical distance from the mean.
- Is today unusual? The z-score: how many standard deviations a value is from the mean.
The steps by hand and in code
import statistics
data = [10, 12, 11, 13, 9, 12, 11, 10, 12, 30]
mean = sum(data) / len(data)
print("mean", mean)
dev = [(x - mean) ** 2 for x in data]
var = sum(dev) / len(data)
print("variance", round(var, 2), "stdev", round(var ** 0.5, 2), "check", round(statistics.pstdev(data), 2))
for x in (11, 30):
print(x, "z =", round((x - mean) / var ** 0.5, 2))
mean 13.0
variance 33.4 stdev 5.78
11 z = -0.35
30 z = 2.94
Walk through it:
- The mean is 130 / 10 = 13.
- For each value, take the distance from the mean and square it (so that minus and plus do not cancel and big distances count more). Average those squares: the variance, 33.4.
- The square root of the variance is the standard deviation: 5.78. The line
statistics.pstdevgives the same number, a check. - The z-score is (value − mean) / standard deviation. A day with 11 minutes has z = −0.35, close to normal. The day with 30 minutes has z = 2.94, far from normal.
One odd value shifts everything
Remove the 30 and recompute the other nine days: the mean becomes 11.11 and the standard deviation 1.2. Now the z-score of 30 is 15.8, a huge number. With the odd day inside the list, the mean and the spread grew and 30 looked only mildly strange (2.94). Taking an average over a window that contains the odd value hides it a little. In lesson 15 the window is the last 100 values, and it is a deliberate choice that does not include today.
A rule of thumb
For many things in nature, about 95 values of 100 lie within 2 standard deviations of the mean. A z-score above 2 or below −2 therefore happens on only a few days in 100, which is why a bot treats it as a signal. Real markets have heavier tails than this rule says, so keep the signal and add a stop.
Your exercise
- Run the code. Change 30 to 14. What happens to the mean and the standard deviation?
- Write your own list of ten numbers (your commute times, your steps per day) and compute the z-score of the last one by hand.
- Why do we square the distances instead of adding them as they are?
Back to the course: lesson 15 (pairs trading).