APIHorseRacing

Documentation / Guides

Prices and price movement

Fractional, decimal, opening, touched, and what source tells you.

Prices are the most useful thing in this archive and the easiest to misread. Four fields, one derived summary, and one coverage limit worth knowing before you build on any of it.

The four fields on a runner

FieldExampleWhat it is
sp"10/3" Starting price, fractional, exactly as published.
sp_decimal4.3333 The same price as a decimal. Computed once at load so you are not parsing fractions per row.
implied0.2308 One over the decimal price.
market_position1 Rank by price, one being shortest. Ties share a rank.

implied does not sum to one

This is the thing people get wrong. Add implied across a field and you get the book percentage, not 1.0.

0.2308 + 0.1667 + 0.1250 + ... = 1.2185      # a 121.85% book

The excess is the margin. It is real and it is the reason backing everything loses money.

If you want probabilities that sum to one, the statistics endpoints already have them: expected is implied normalised per race. That is what A/E is computed against, and it is why A/E of 1.00 means "as often as the market said" rather than "as often as the book implied".

book_percentage

On the race, from /v1/races/{race_id}/market. A hundred would be a fair book.

In our archive it averages about 117 in fields of two to seven and about 133 in sixteen or more. That spread matters more than the average. A strategy that looks marginally profitable in small fields can be hopeless in big ones with nothing else changing. Overround has it sliced by course, class and year.

Price movement, and its limit

price_path carries the opening price, any prices touched, the drift, and a source field naming which kind of history you have.

"price_path": {
  "opening":         "5/1",
  "opening_decimal": 6,
  "touched":         ["4/1"],
  "sp":              "10/3",
  "drift":           -0.2778,
  "direction":       "shortened",
  "source":          "movements"
}
sourceMeans
movementsAn opening price and any touched prices. The common case where movement exists.
full_historyA complete price series. Rare.
starting_price_onlyNo movement was published. The starting price is all there is.

Read source rather than inferring from a null opening price. The two are different claims: one says nothing was published, the other says we do not know.

The limit: price movement is British and Irish. Britain carries an opening price on about 59% of runners and Ireland on about 52%. France, America, South Africa and Germany carry essentially none. Any model using movement works on two countries, and it is better to design for that than discover it.

And it is opening to starting price, not a series. A horse that shortened and drifted back looks like it never moved.

favourite is ours, not the source's

The source leaves both favourite and market_position empty on a settled race, so we derive them from the prices: ranked on decimal price, shortest first. Joint favourites are all flagged and share rank one, which slightly inflates favourite counts in the races where it happens. Picking one arbitrarily would be worse.

Tote is a separate thing

/v1/races/{race_id}/dividends returns tote returns to a one unit stake, normalised into numbers with a currency alongside. Tote and starting price settle differently and the gap is occasionally large. Most jurisdictions outside Britain and Ireland publish no tote return, and the endpoint says so rather than erroring.

What we do not have

No bookmaker odds comparison, no exchange prices, no in-running. Starting price, an opening price where one was published, and the tote. We are not a price aggregator and will not become one.