Hire Me
← All Writing Betfair

Working with BSP and Starting Prices in the Betfair Exchange API

How BSP (Betfair Starting Price) works, how to retrieve SP and BSP prices from the API, how to place BSP bets, and how to use pre-race SP estimates in a trading strategy.

The Betfair Starting Price (BSP) is a computed odds value determined at the off based on matched bets placed specifically at SP. It is not the same as the exchange price at the time the race starts — BSP is calculated from a separate pool of SP bets and reflects what the Betfair algorithm determines to be the fair odds. Understanding the difference between exchange prices, SP, and BSP is essential for any strategy that involves position exit at the off or that uses pre-race price data for analysis.

SP vs BSP vs exchange price

Exchange price: The actual price at which back and lay bets are matched in the normal order book. Changes continuously as bets arrive.

BSP (Betfair Starting Price): The price Betfair calculates at the off by matching all SP bets against each other. It is the starting price you receive if you place a “Back at BSP” or “Lay at BSP” bet. It is calculated once per runner per race.

Betdaq SP and industry SP: Different services, different methodologies. The Betfair API exposes only Betfair’s own BSP.

Retrieving SP prices via the REST API

After a race is settled, the BSP is available in the RunnerBook via listMarketBook:

PriceProjection projection = new PriceProjection()
    .withPriceData(Set.of(PriceData.SP_TRADED, PriceData.EX_BEST_OFFERS));

List<MarketBook> books = exchange.listMarketBook(
    List.of(marketId),
    projection,
    null, null, null, null
);

for (RunnerBook runner : books.get(0).getRunners()) {
    StartingPrices sp = runner.getSp();
    if (sp != null) {
        double bsp = sp.getActualSP();   // only available post-race
        log.info("Runner {} BSP: {}", runner.getSelectionId(), bsp);
    }
}

getActualSP() returns Double.NaN or null pre-race. getNearPrice() and getFarPrice() give the pre-race SP estimates during the betting window.

Pre-race SP estimates: nearPrice and farPrice

Before the off, Betfair provides two SP estimate fields:

These are not the exchange price — they reflect only SP bets, which are a subset of total market activity. In liquid races they track the exchange price closely; in thin markets or early in the betting window, they can diverge significantly.

public record SpEstimate(
    double nearPrice,
    double farPrice,
    double exchangeBestBack
) {
    public double spPremium() {
        return nearPrice - exchangeBestBack;   // positive = SP expected to be higher
    }
}

The SP premium can be a signal: if SP is expected to be significantly above exchange price, late SP bets are arriving at worse value than the exchange offers — often a sign that small punters are backing on SP while sharper money is on the exchange.

Placing a BSP bet

To back or lay at BSP rather than a fixed price, set orderType to SP:

LimitOnCloseOrder spBet = new LimitOnCloseOrder()
    .withLiability(10.0)     // maximum liability for a lay; stake for a back
    .withPrice(0.0);         // 0 = accept any BSP

PlaceInstruction instruction = new PlaceInstruction()
    .withOrderType(OrderType.LIMIT_ON_CLOSE)
    .withSide(Side.BACK)
    .withLimitOnCloseOrder(spBet);

PlaceExecutionReport report = exchange.placeOrders(
    marketId,
    List.of(instruction),
    null, null, null
);

LIMIT_ON_CLOSE places a bet that participates in the SP pool. The bet is matched at the BSP when the race goes in-play. It cannot be cancelled after the off.

BSP in historical data analysis

For backtesting strategies that exit at the off, you need accurate BSP data rather than the last exchange price. The two diverge in several scenarios:

When loading historical data from Betfair’s Data API, the BSP is available in the market snapshot files as part of the RunnerBook after settlement:

public record RunnerResult(
    long selectionId,
    String runnerName,
    double bsp,
    double lastExchangePrice,
    RunnerStatus status,
    double reductionFactor
) {}

Using BSP as a benchmark

One of the most useful applications of BSP is benchmarking exchange entry prices. If you backed a runner at 5.0 on the exchange and the BSP was 4.0, you got significantly better value than the market eventually computed to be fair. Tracking this over time:

double priceEfficiency = bsp / entryPrice;
// > 1.0: you got better odds than BSP (good execution)
// < 1.0: you got worse odds than BSP (poor execution)
// ≈ 1.0: your entry tracked BSP closely

An average priceEfficiency below 1.0 across hundreds of trades indicates a systematic issue with execution timing — entering too early on shortening runners, or too late on drifters.

The SP pool closing time

The SP pool closes when the race starts. Bets placed as SP before the off are queued; they are matched at BSP simultaneously when the market goes in-play. Your strategy must account for the inability to cancel SP bets once submitted — unlike limit orders, which can be cancelled up to the off.

With accurate BSP data in your historical analysis and SP estimates available pre-race via the API, you can make informed decisions about whether to execute on the exchange or defer to SP.

If you’re building a Betfair trading or analysis system in Java and want help with SP integration, get in touch.

Samuel Jackson

Samuel Jackson

Senior Java Back End Developer & Contractor

Senior Java Back End Developer — Betfair Exchange API specialist, Spring Boot, AWS, and event-driven architecture. 20+ years delivering high-performance systems across betting, finance, energy, retail, and government. Available for Java contracting.