Skip to content

BlogMatched betting data

Qualifying loss and matched-bet ratings, worked out from the prices

OddsRelay · · Updated · 4 min read

A matched bet's rating is the share of your stake the back-and-lay pair gives back, and its qualifying loss is the part you lose. Both come from four numbers: the back price, the lay price, your stake and your exchange commission.

The feed supplies the first two. Each matched outcome arrives with bookmaker back offers and exchange lay offers, the lay side paired against Betfair, Smarkets, Matchbook and BETDAQ and liquidity-gated. The plain one-line rating is in oddsmatcher data, explained. This post puts commission inside it and covers free bets.

Why the feed leaves the numbers out

A qualifying loss changes with the stake and the commission rate. Your users pick the stake, and each of them pays their own rate on each exchange they use, so store the rate per user and per exchange. A figure worked out before the data reached you would be right for one imaginary user and wrong for everyone else.

The bet type changes the formula too. A qualifying bet and a free bet whose stake is not returned need different lay stakes from the same two prices. Sending the prices and leaving the sums to you means one board serves both, at any rate your users set. An oddsmatcher that bakes one commission rate into its numbers shows the wrong figure to every user on a different rate.

The pair you start from

Here is one outcome from a standard board, trimmed to a single market. It carries two back offers, best price first, and two lay offers, lowest price first. available is the money waiting at that lay price.

Example · one outcome from GET /v2/odds/standard, trimmed

{
  "event_id": "or_evt_917dd44bce05",
  "sport_key": "soccer_epl",
  "commence_time": "2026-09-20T14:00:00Z",
  "home_team": "Arsenal",
  "away_team": "Chelsea",
  "markets": [{
    "key": "h2h",
    "outcomes": [{
      "name": "Arsenal",
      "back": [
        { "bookmaker": "william_hill", "price": 2.9, "link": null },
        { "bookmaker": "paddy_power", "price": 2.8, "link": null }
      ],
      "lay": [
        { "exchange": "smarkets", "price": 2.96, "available": 6, "link": null },
        { "exchange": "betfair_exchange", "price": 3.0, "available": 175, "link": null }
      ]
    }]
  }]
}

Nothing in it scores the pair. Every back offer can be crossed with every lay offer, so this outcome alone gives four candidate matches. The rest of this post takes the best back price, 2.9, against the 3.0 lay, then shows why the lower lay listed first is the wrong pick at this stake.

Rating with commission inside it

The plain rating is back over lay, times 100. It ignores commission, so it ranks pairs well but overstates what you keep. Put the commission rate c into it and the rating becomes the exact percentage of your stake the qualifying bet returns:

Example · your code, back price B, lay price L, commission c as a fraction

const plainRating = (B / L) * 100;
const rating = ((B * (1 - c)) / (L - c)) * 100;

// 2.9 back, 3.0 lay, 2% commission
// plainRating = 96.7
// rating      = 95.4

At zero commission the two formulas agree. At 2% the gap between them is 1.3 points, and it grows with the rate. When two tools show different ratings for the same prices, check commission first.

Qualifying loss from the rating

The lay stake that balances both outcomes is the back stake times the back price, divided by the lay price minus the commission. At that lay stake the loss is the same whether the bookmaker bet wins or the lay wins, and it falls straight out of the rating:

Example · your code, qualifying bet at stake S

const layStake = (S * B) / (L - c);
const qualifyingLoss = S * (rating / 100 - 1);

// S = 10, B = 2.9, L = 3.0, c = 0.02
// layStake       = 9.73
// liability      = layStake * (L - 1) = 19.46
// qualifyingLoss = -0.46 either way

Check it both ways. If Arsenal win, the bookmaker pays 19.00 profit and the lay loses its 19.46 liability, which nets -0.46. If they don't, the back stake of 10 is lost and the lay wins 9.73 less 2% commission, or 9.54, which nets -0.46 again. The liability is the figure your user needs in their exchange balance, so show it beside the loss.

A better price you cannot fill

The first lay offer, 2.96, comes out higher: 96.7 at 2% commission, against 95.4 for the 3.0 lay. It also needs a lay stake of 9.86, and only 6 is waiting at that price. The rest would go unmatched or fill at a worse price, and the rating you sorted by would no longer be true.

So filter before you sort. Drop any pair whose available is below the lay stake the user's own stake needs, then rank what is left. Why lay liquidity matters covers the depth side in more detail.

Free bets change the lay stake

A free bet where the stake is not returned only pays the winnings, so the back side is worth B - 1 per unit instead of B. Replace B with B - 1 in both formulas and the rating becomes the share of the free bet's face value you keep:

Example · your code, free bet with stake not returned

const layStake = (S * (B - 1)) / (L - c);
const retained = layStake * (1 - c);
const conversion = (retained / S) * 100;

// S = 10 free bet, B = 2.9, L = 3.0, c = 0.02
// layStake   = 6.38
// retained   = 6.25 either way
// conversion = 62.5%

Because the stake is gone, the - 1 matters less at longer prices, which is why free-bet conversion usually favours longer odds than a qualifying bet does. A free bet that returns its stake uses the qualifying formula unchanged, and what you keep is the lay stake times one minus the commission.

The oddsmatcher widget does this for you

If you would rather show the numbers than build the screen, the oddsmatcher widget takes the same paired prices and displays the rating and qualifying loss. To build your own board, how to build an oddsmatcher walks through crossing offers and sorting them, and the matched board filters guide shows how to narrow a board to the books and exchanges your users hold accounts with. Request access to run these formulas on your own key.