> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sportsxapp.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Market data

> Query markets, settlements, and per-market account stats with field-level control over the response.

The SDK's market-data surface is intentionally narrow. The canonical
entry is `client.markets()` — it returns a [`Page[MarketInfo]`](#paging-shape):
a list-like value carrying the items plus the server's total count, so
you can decide whether to fetch more without a second round trip.

<Note>
  Every response is a **typed Pydantic v2 model** — you get attribute access, IDE autocomplete, and validation for free. Call `.model_dump()` on any model if you need a plain dict.
</Note>

## List markets

```python theme={null}
from stx import STX, Selection

client = STX(region="ontario", env="staging")
client.login(params={})

page = client.markets(
    params={"input": {"limit": 50}},
    selections=Selection("market_id", "status", "title"),
)
print(f"showing {len(page)} of {page.count}")
for market in page:
    print(market.market_id, market.status, market.title)
```

`page` iterates `MarketInfo` items; `page.count` is the server's total
across the unpaginated query. Fields not in the `Selection` are `None`
on each item.

## Filter knobs

`MarketInfosInput` supports several filters; combine them freely:

```python theme={null}
page = client.markets(
    params={
        "input": {
            "status": "OPEN",          # StatusEnum: OPEN | PRE_OPEN | CLOSED | RESULTED | ...
            "trading": "TRUE",          # TradingEnum: TRUE = "open and tradable"
            "sports": ["Soccer"],
            "limit": 25,
        }
    },
    selections=Selection("market_id", "title"),
)
```

Common filter recipes:

| Goal                         | Filter                                              |
| ---------------------------- | --------------------------------------------------- |
| Just the strict tradable set | `{"status": "OPEN", "trading": "TRUE"}`             |
| Specific markets by id       | `{"market_ids": ["mkt_a", "mkt_b"]}`                |
| One sport, paginated         | `{"sports": ["Soccer"], "limit": 50}`               |
| Keyword regex                | `{"keyword_regex": "^NBA"}`                         |
| Filter taxonomy              | `{"filter_by": "ACTIVE"}` (uses `MarketFilterEnum`) |

## Get specific markets by id

```python theme={null}
page = client.markets(
    params={"input": {"market_ids": ["mkt_8f3...", "mkt_4a2..."]}},
    selections=Selection("market_id", "title", "status", "price"),
)
markets = list(page)
```

When `market_ids` is set, `limit` is ignored.

## Shaping the response

GraphQL's killer feature over REST: you ask only for the fields you
need. Pass a flat `Selection(...)` of the per-market fields you want —
the SDK auto-injects the wrapper layer for you:

<CodeGroup>
  ```python Narrow (only market_id + status) theme={null}
  from stx import Selection

  page = client.markets(
      selections=Selection("market_id", "status"),
  )
  # ~1 KB per 100 markets
  ```

  ```python Default (all scalar fields per market) theme={null}
  page = client.markets(params={"input": {"limit": 50}})
  # ~20 KB per 100 markets
  ```

  ```python With nested fields theme={null}
  from stx import Selection

  page = client.markets(
      selections=Selection(
          "market_id", "title",
          bids=Selection("price", "quantity"),
          offers=Selection("price", "quantity"),
      ),
  )
  ```
</CodeGroup>

<Tip>
  For list queries that return 100+ items, the narrow form is **10–30× smaller on the wire**. Always pass an explicit `Selection` in production code.
</Tip>

## Presets

Canned selections for common shapes — import from `stx`:

```python theme={null}
from stx import STX, PRESETS, Selection

client = STX(region="ontario", env="staging")
client.login(params={})

page = client.markets(selections=PRESETS.MARKET_MINIMAL)
# PRESETS.MARKET_MINIMAL  → market_id, status
# PRESETS.MARKET_BASIC    → + title, sport, competition, price, probability, volume24h
# PRESETS.MARKET_TRADING  → + price_change24h, last_traded_price, timestamp
```

## Paging shape

`client.markets()` returns a `Page[MarketInfo]`:

* Iterable — `for m in page: ...`
* Indexable + sliceable — `page[0]`, `page[:10]`
* `len(page)` — the items in this page
* `page.count` — the server's total across the unpaginated query

```python theme={null}
page = client.markets(params={"input": {"limit": 25}})
print(f"loaded {len(page)} of {page.count} markets")
first_ten = page[:10]
```

## Paginating large result sets

`limit` caps each call. Use `page.count` to know when to stop:

```python theme={null}
def iter_all_markets(client, page_size=200):
    """Yield every MarketInfo, paged through the server. Trade off
    page_size against latency — 200 is a reasonable default."""
    offset = 0
    while True:
        page = client.markets(
            params={"input": {"limit": page_size}},
            selections=Selection("market_id", "title", "status"),
        )
        if not len(page):
            return
        yield from page
        offset += len(page)
        if offset >= (page.count or 0):
            return

client = STX(region="ontario", env="staging")
client.login(params={})
for market in iter_all_markets(client):
    ...
```

For very large bulk pulls, use `AsyncSTX` with `asyncio.gather` to
parallelize pages — see [Async](/sdks/python/async#parallelizing-requests).

## Settlements

`market_settlements` returns the settlement trail for a specific market.
`trades_for_settlement` drills into the trades that contributed to a
single settlement event:

```python theme={null}
settlements = client.market_settlements(
    params={"market_id": "mkt_8f3...", "pagination": {"page": 0, "limit": 20}},
    selections=Selection("id", "amount", "time"),
)

# Drill into one
trades = client.trades_for_settlement(
    params={"settlement_id": settlements[0].id},
    selections=Selection("trades", "summary"),
)
```

## Per-market account stats

`account_market_stats` returns your trading footprint per market —
positions, fees paid, contracts settled. Useful for reconciliation +
reporting:

```python theme={null}
stats = client.account_market_stats(
    params={"pagination": {"page": 0, "limit": 50}},
    selections=Selection(
        "market_id", "contracts_settled", "total_fees", "updated_at"
    ),
)
for s in stats:
    print(s.market_id, s.contracts_settled, s.total_fees)
```

## Error handling

Market queries are mostly idempotent — the SDK's default retry policy
handles transient `STXTransportException` and `STXRateLimitException`
automatically. See [Errors & retries](/sdks/python/errors-and-retries).

## Next

<CardGroup cols={2}>
  <Card title="Trading" icon="arrows-rotate" href="/sdks/python/trading">
    Place orders, fetch positions, and manage fills.
  </Card>

  <Card title="WebSockets" icon="tower-broadcast" href="/sdks/python/websockets">
    Subscribe to live market updates over Phoenix channels.
  </Card>
</CardGroup>
