Lesson 3 — Market lookup & selections

Skip to content

Lesson 3 — Market lookup & selections

Learn how to discover markets, parse runners and build selection filters so your bot can target the right markets programmatically.

Estimated time: 45 minutes • Skill level: Beginner → Intermediate

Use this as a starting point. Don’t commit secrets.

Prerequisites

  • Lesson 1 & 2 completed (environment and auth wrapper)
  • Working auth.request helper (auth.py) from Lesson 2
  • Familiarity with JSON and simple Python parsing

Overview

We’ll use the authenticated request helper to search markets, inspect the market structure and extract runner IDs (selection IDs). We’ll also show patterns to select markets by sport, market type and name filters.

Use the request helper from auth.py (Lesson 2). This example requests a market catalogue / list. Adjust the path and params to match your Betfair API variant.

from auth import request

# Example params - provider fields differ. Replace with the correct filter for your API.
params = {
    'filter': {
        'eventTypeIds': ['1'],  # 1 usually indicates Soccer; provider-specific
        'marketStartTime': {'from': '2025-01-01T00:00:00Z'}
    },
    'maxResults': 20
}

catalogue = request('GET', '/marketCatalogue', params=params)
print('Returned markets:', len(catalogue) if isinstance(catalogue, list) else type(catalogue))

Tip: Inspect the raw response in sandbox to adapt to the exact schema (market id, marketName, runners, etc.). Some endpoints return nested objects; log them to understand the structure.

2) Parse runner IDs (selection IDs)

Most market responses include a runners array. Use the snippet below to extract runner IDs and runner names.

# parse_runners.py
def extract_runners(market):
    """
    market: dict or object returned by market catalogue API
    returns list of (selectionId, runnerName)
    """
    runners = []
    for r in market.get('runners', []):
        sid = r.get('selectionId') or r.get('id') or r.get('selection_id')
        name = r.get('runnerName') or r.get('name') or r.get('runner_name')
        if sid:
            runners.append((sid, name))
    return runners

# Example usage:
first = catalogue[0] if isinstance(catalogue, list) and catalogue else None
if first:
    print('Runners:', extract_runners(first))

Note: Field names vary with Betfair API versions — always inspect the response keys and adapt helper functions.

3) Building selection filters

Use filters to pick markets your strategy targets. Example: market name contains “Match Odds”, or event name matches “Premier League”. Keep filters small and test in sandbox first.

# selection_filters.py
def market_matches(market, market_type='Match Odds', event_keywords=None):
    event_keywords = event_keywords or []
    name = market.get('marketName','').lower()
    event = market.get('event', {}).get('name','').lower() if market.get('event') else ''
    if market_type.lower() not in name:
        return False
    for kw in event_keywords:
        if kw.lower() in event:
            return True
    return not event_keywords  # no keywords -> accept by type only

# Example: find match odds markets for "premier league"
filtered = [m for m in catalogue if market_matches(m, 'Match Odds', ['premier league'])]

Validation: After filtering, fetch the market book (odds/available amounts) before placing any orders — market catalogue alone doesn’t include live prices.

4) Fetch market book (prices) and check runners

Before deciding side/price, query market book or market odds endpoint to obtain available prices and sizes.

# market_book.py
# Example: provider-specific path - replace with your API's marketBook/odds endpoint
market_id = filtered[0].get('marketId') if filtered else None
if market_id:
    book = request('GET', '/marketBook', params={'marketId': market_id})
    # inspect 'runners' in the book to find available back/lay prices
    for r in book.get('runners', []):
        print('Runner', r.get('selectionId'), 'available to back:', r.get('ex', {}).get('availableToBack'))

Remember: Market book responses are time-sensitive. Always verify market status (SUSPENDED/OPEN) and available sizes before placing orders.

5) Practical tips & robust lookup patterns

  • Use a small cache for market lookups to avoid repeated catalog calls; invalidate cache near market start.
  • Map external symbols (e.g., TradingView) to Betfair market names via a configurable mapping table.
  • Implement a small retry/backoff when fetching the market book; don’t hammer the API when a market is suspended.
  • Log full responses during development to ensure correct field mappings.

What you’ll build next

Lesson 4 will use the market book and selection IDs to place BACK/LAY orders in the sandbox and handle partial/unmatched fills safely.

Back to course hub

← Previous
Author: Stephane Patteux • Part of the Build your own bot series

Don’t miss our blog post!

We don’t spam! Read our privacy policy for more info.

Leave a Reply

Your email address will not be published. Required fields are marked *