BlogArbitrage and value

Value betting vs arbitrage: the data each needs

Value betting vs arbitrage comes down to what each tool compares: an arbitrage tool needs two or more prices that disagree at the same moment, and a value betting tool needs one price plus a fair-odds benchmark it works out for itself.

Both are labels for arithmetic your product runs. The feed supplies the prices and the time on each.

What is the difference between value betting and arbitrage?

Arbitrage covers every outcome of a market at venues whose prices disagree, so the result no longer decides the position. Value betting backs one outcome whose price is longer than a fair estimate of its chance, and leaves the result open.

For a tool builder the difference is in the inputs. An arbitrage check compares prices that exist right now at different venues, so it needs breadth and a clean match between them. A value check compares one price with a number your tool makes, so it needs a benchmark you can defend and a method you can show.

ArbitrageValue betting
ComparesTwo or more current prices for the same fixture and marketOne price against fair odds your code works out
Needs from the feedBack prices beside lay prices, or one back price per outcomeWhole markets from each venue, the exchanges included
Sensitive toBoth prices still standing when the user acts, and the money on the layThe benchmark method and the commission your user pays

What each tool reads. In both columns the arithmetic is your code.

What an arbitrage tool reads

An arbitrage tool reads prices that disagree about the same selection, and the gap comes in two shapes. A bookmaker's back price can sit above an exchange's lay price for the same outcome. Or the best back prices across a market's outcomes, each at a different venue, can add up to less than 100% implied probability. Arbitrage tools usually call the second a sure bet. What an arbitrage tool needs covers both checks in full.

The first shape lives on the standard matched board. Each outcome carries bookmaker back offers, best price first, and exchange lay offers, lowest price first, each with available, the money waiting at that price. The fixture, market and selection are already matched across venues (matching bookmaker and exchange odds shows how), so the check is two numbers on one object.

GET /v2/odds/standard, one outcome · example

{
  "name": "Arsenal",
  "back": [
    { "bookmaker": "william_hill", "price": 3.1, "link": null },
    { "bookmaker": "paddy_power", "price": 3.0, "link": null }
  ],
  "lay": [
    { "exchange": "smarkets", "price": 3.05, "available": 42, "link": null },
    { "exchange": "betfair_exchange", "price": 3.1, "available": 380, "link": null }
  ]
}

The best back price, 3.1, sits above the lowest lay, 3.05. Whether that gap survives depends on the commission your user pays on the exchange, so the check belongs in your code, at their rate:

Your code: back price B, lay price L, commission c as a fraction, stake S · example

const ratio = (B * (1 - c)) / (L - c);   // above 1 means a back and lay gap
const layStake = (S * B) / (L - c);

// B = 3.1, L = 3.05, S = 100
// c = 0.02: ratio = 1.0026, layStake = 102.31
// c = 0.05: ratio = 0.9817
// the 3.1 lay at c = 0.02: ratio = 0.9864

Times 100, that ratio is the commission-adjusted figure an oddsmatcher shows, worked through in qualifying loss and ratings. A matched bettor wants it close to 100. An arbitrage tool wants it above 100. At 2% commission this gap is about a quarter of a point, and at 5% it is gone.

Then check the money. Covering a stake of 100 needs a lay of 102.31 at 3.05, and only 42 waits there. The rest would go unmatched or fill at 3.1, where the gap does not exist. Why lay liquidity matters covers that filter.

Arbitrage gaps are rare and close quickly, so the tool also needs each price's age. meta.last_seen gives, per venue and sport, when that venue was last read, so now minus it is an upper bound on a price's age. Every product on sale meets a maximum update time of 10–20 s, and the freshness guide sets out both fields. Your users still confirm both prices at the venues before they commit to either side.

The second shape, the sure bet, lives on the dutching feed. It sends back prices only, and every back offer carries a dutch_id that names its group: two or three legs, one per outcome, each at a different venue. Add 1 / price across one group's legs. Legs priced 2.2, 3.6 and 3.8 give 0.9955, and anything under 1 is what a sure-bet finder lists. A dutch normally sums to more than 1, because every venue builds a margin into its prices. Dutching data explained shows how to group the legs and split the stake.

How do you calculate fair odds?

You calculate fair odds by taking the margin out of a market: turn each outcome's price into an implied probability, scale the set so it adds up to 100%, and turn each share back into a price. Which market you take the margin out of is your tool's choice, and it decides what your tool flags.

A common benchmark is an exchange's own market, because an exchange charges commission instead of building a margin into its odds. Another is a bookmaker whose prices your users trust. Either way the implied probabilities add up to more than 100%, and the excess is the overround you remove.

The raw feed carries the benchmark and the price you test in one reply. It lists every venue's own markets per event. A bookmaker's outcome is { name, price }. An exchange lists its back prices the same way, plus a lay market whose outcomes carry lay_price and available. Add exchangesOnly=true and a call returns the exchanges alone.

GET /v2/odds/raw, one event, trimmed · example

{
  "id": "or_evt_5c2e81a4d0f3",
  "sport_key": "soccer_epl",
  "sport_title": "Premier League",
  "commence_time": "2026-09-26T14:00:00Z",
  "home_team": "Arsenal",
  "away_team": "Chelsea",
  "bookmakers": [
    {
      "key": "betdaq",
      "title": "Betdaq",
      "region": "uk",
      "last_update": "2026-09-26T11:02:40Z",
      "markets": [
        {
          "key": "h2h",
          "last_update": "2026-09-26T11:02:40Z",
          "outcomes": [{ "name": "Arsenal", "price": 2.18 }, { "name": "Draw", "price": 3.6 }, { "name": "Chelsea", "price": 3.75 }]
        },
        {
          "key": "h2h_lay",
          "last_update": "2026-09-26T11:02:40Z",
          "outcomes": [{ "name": "Arsenal", "back_price": null, "lay_price": 2.2, "available": 214 }]
        }
      ]
    },
    {
      "key": "sky_bet",
      "title": "Sky Bet",
      "region": "uk",
      "last_update": "2026-09-26T10:58:12Z",
      "markets": [
        {
          "key": "h2h",
          "last_update": "2026-09-26T10:41:07Z",
          "outcomes": [{ "name": "Arsenal FC", "price": 2.25 }, { "name": "Draw", "price": 3.4 }, { "name": "Chelsea FC", "price": 3.3 }]
        }
      ]
    }
  ]
}

Your code: fair odds from the exchange's market, then the EV of one bookmaker price · example

const implied = [2.18, 3.6, 3.75].map((p) => 1 / p);   // Arsenal, Draw, Chelsea
const overround = implied.reduce((a, b) => a + b, 0);  // 1.0032
const fair = implied.map((p) => p / overround);        // 0.4573, 0.2769, 0.2658
const fairOdds = fair.map((p) => 1 / p);               // 2.19, 3.61, 3.76

const ev = fair[0] * 2.25 - 1;                         // 0.0289 per unit staked

The bookmaker's 2.25 on Arsenal, against fair odds of 2.19, gives an expected value (EV) of 2.9% of the stake. That is an average over many such prices, and any one bet still wins or loses. A value tool should show its benchmark beside every price it flags, so its users can check the method instead of trusting a percentage.

A comparison across venues takes one more step. Raw keeps each venue's own names, so the exchange's Arsenal and a bookmaker's Arsenal FC are one selection only once your code says so, as normalising odds across bookmakers explains. The matched boards have done that mapping already, so a tool whose benchmark is the exchange lay price can read Standard's lay offers beside its back offers instead. To follow raw between reads, updatedSince returns only the venues whose markets changed since a time you pass, as the walking raw guide shows.

What is closing line value (CLV)?

Closing line value (CLV) compares the price a bet was struck at with the closing price for the same selection, the last price before the event starts. A tool that grades CLV needs both prices, and the closing one is not in the feed.

OddsRelay carries the prices on offer before an event starts, with no history, no closing price and no starting price (SP). A CLV tool takes its closing price from a source that records one. The feed can supply the other half: the price on offer when your user logged the bet. Store it with the venue key and the reply's meta.processed_at, or the raw market's last_update, so the later comparison uses the exact price and time the user saw.

Keep your own fixture ids for that record. One fixture has one event id on every route, but the id is opaque and a paired fixture can re-key once, which is why storing and versioning odds data keys everything on ids you own.

Which OddsRelay board fits each tool

Every plan carries the six matched boards and raw, so one tool can read several boards on one key. Plans differ only in tokens, and ?quote=true prices any call for free before you make it. The page for arbitrage and value-betting tools pairs each tool's check with its endpoint.

ToolWhat it readsBoardCall
Back and lay arbitrageA bookmaker back price above an exchange lay price, and the money on the layStandardGET /v2/odds/standard
Sure-bet finderOne back price per outcome, each at a different venue, grouped by dutch_idDutchingGET /v2/odds/dutching
Value bettingWhole markets per venue, the exchanges included, to build fair oddsRawGET /v2/odds/raw
Value betting against the layBookmaker back prices beside exchange lay prices, already matchedStandardGET /v2/odds/standard
CLV gradingThe price on offer when the bet was logged. The closing price comes from your own sourceRaw, or the board the bet came fromThe call that found the bet

Each row is an input. The sums, the fair odds and the grade are your code.

On the standard and dutching boards, sports, the venue filters and markets lower a call's price, and a kick-off window narrows the reply but is never priced, as the filters and tokens guide shows. On the dutching board a dutch survives a venue filter only when every leg is at a venue you named, so a sure-bet finder can ask only for groups its users hold accounts at. To read these boards on your own fixtures, sign up free and take a key.

Read one board before you write the maths

Pick the call your tool cannot work without, read one fixture you know well, and do the sums by hand against the prices in the reply. If the fields answer your tool's questions, the rest is code. The API reference lists every field, and our contact page is the place to say what is missing.

Related posts

18+ · OddsRelay supplies odds data only and takes no bets. Please gamble responsibly.