APIHorseRacing

Documentation / Guides

Understanding A/E

The number the Analyst tier exists for, and how to read its interval.

A/E is the number the Analyst tier exists for. It is also the number most likely to be misread, so this guide is about how to read it honestly rather than how to be impressed by it.

What it is

Actual wins divided by expected wins. Expected comes from the market: each runner's implied probability, normalised so the field sums to one.

implied  = 1 / sp_decimal                      # sums to the book percentage
expected = implied / sum(implied for the race)  # sums to exactly 1

A/E = sum(actual wins) / sum(expected)

Above 1.00 means winning more often than the prices said. Below means less. 1.00 means the market had it right, which is the correct null hypothesis for almost everything in racing.

Why not strike rate

Strike rate measures the horses, not the skill. A yard that runs good horses in weak races will have a high one and may still be losing money at every price it takes.

A/E already accounts for the class of opposition, the field size and the ground, because the market priced all of them before the race. That is the whole point: you are not comparing against random selection, you are comparing against the best estimate anybody had at the time.

YardStrike rateA/EReading
A22%0.93Wins often because it runs good horses. Losing money doing it.
B9%1.11Beats its prices. This is the one the market has not fully priced.

Never read it without the interval

Every A/E comes back with three companions.

"a_e":          1.11,
"a_e_range":    [0.98, 1.26],
"significant":  false,
"low_sample":   false
  • a_e_range is a confidence interval on the win count. It uses a Poisson standard error, sqrt(wins) / expected, which is the right shape for counting rare events.
  • significant is true only when that interval excludes 1.00. In the example above it does not, so the 1.11 is not evidence of anything.
  • low_sample is true under about thirty runs, where the interval is so wide it is barely worth printing.

An A/E of 5.00 over four runs looks like the strongest signal in the payload and is noise. The interval is what stops you acting on it.

What sample sizes actually support it

SubjectTypical runsCan it reach significance?
One horse10–40Almost never. Read it as description, not evidence.
One horse, one condition2–8No.
A busy trainer2,000–10,000Yes, and its breakdowns often can too.
A course5,000+Yes.
A price band across the archive100,000+Comfortably.

The check that says the engine is sound

Across every settled race in the archive, actual wins and expected wins agree to within about a fifth of one percent: roughly 149,400 actual against 149,100 expected, an overall A/E of 1.0018.

That number is not a finding, it is a calibration test. If the market is efficient in aggregate, the whole population must come out at 1.00, and any engine that does not produce that has a bug. Ours does, which is why the departures from 1.00 in the breakdowns are worth taking seriously.

The one large departure

Runners at 16/1 and longer return an A/E of 0.72, interval 0.71 to 0.74, over roughly 495,000 runners. Significant by an enormous margin, and the curve is monotonic: the longer the price, the worse the return.

That is the favourite-longshot bias, the most durable finding in racing. It is not an edge, because it tells you what loses rather than what wins. What it is good for is calibration: a model that likes long shots has to beat a base rate far worse than the book margin.

What A/E cannot do

  • It cannot tell you a horse will win. It describes a population, and any single race is one draw from it.
  • It does not survive selection. Testing fifty things and reporting the best one is not an A/E of 1.4, it is the maximum of fifty noisy numbers. See Breakdown dimensions.
  • It says nothing about your prices. It is computed at starting price. If you take a shorter price than SP, your realised A/E is worse than the one printed.

Void races are excluded

A race with no recorded winner contributed a full unit of expected and no actual win, dragging every A/E below 1.00 and quietly penalising whoever ran in more of them. Those races are excluded from statistics. Pass include_unsettled=1 to see them anyway.