103 lines
3.1 KiB
Markdown
103 lines
3.1 KiB
Markdown
# Odds data schema
|
||
|
||
Sample file: `odds/data/samples/boxing_odds.json`
|
||
|
||
Source: [The Odds API](https://the-odds-api.com/) v4 — `GET /sports/{sport}/odds`
|
||
|
||
## Top level
|
||
|
||
The response is a **JSON array** of event objects.
|
||
|
||
```json
|
||
[
|
||
{
|
||
"id": "7605c958b8ffbe29c0dcb81e4d2c8a10",
|
||
"sport_key": "boxing_boxing",
|
||
"sport_title": "Boxing",
|
||
"commence_time": "2025-05-10T16:00:00Z",
|
||
"home_team": "Charlie Senior",
|
||
"away_team": "Cesar Ignacio Paredes",
|
||
"bookmakers": [ ... ]
|
||
}
|
||
]
|
||
```
|
||
|
||
## Event fields
|
||
|
||
| Field | Type | Description |
|
||
|-------|------|-------------|
|
||
| `id` | string | Unique event id |
|
||
| `sport_key` | string | API sport identifier |
|
||
| `sport_title` | string | Human-readable sport name |
|
||
| `commence_time` | ISO 8601 UTC | Scheduled start |
|
||
| `home_team` | string | Home / first fighter name |
|
||
| `away_team` | string | Away / second fighter name |
|
||
| `bookmakers` | array | List of books offering lines on this event |
|
||
|
||
## Bookmaker object
|
||
|
||
| Field | Type | Description |
|
||
|-------|------|-------------|
|
||
| `key` | string | Bookmaker slug (e.g. `unibet_uk`) |
|
||
| `title` | string | Display name |
|
||
| `last_update` | ISO 8601 | When this book’s lines were updated |
|
||
| `link` | string \| null | Deep link to event on book site |
|
||
| `sid` | string \| null | Book-specific event id |
|
||
| `markets` | array | Markets offered for this event |
|
||
|
||
## Market object
|
||
|
||
| Field | Type | Description |
|
||
|-------|------|-------------|
|
||
| `key` | string | Market type: `h2h` (moneyline), `h2h_lay` (exchange lay), etc. |
|
||
| `last_update` | ISO 8601 | Market update time |
|
||
| `outcomes` | array | Selections and prices |
|
||
|
||
## Outcome object
|
||
|
||
| Field | Type | Description |
|
||
|-------|------|-------------|
|
||
| `name` | string | Fighter name or `Draw` |
|
||
| `price` | number | **Decimal** odds (European format) |
|
||
| `link` | string \| null | Selection deep link |
|
||
| `sid` | string \| null | Selection id at book |
|
||
| `bet_limit` | number \| null | Max stake if provided |
|
||
|
||
## Implied probability (for arbitrage)
|
||
|
||
For decimal odds `d`:
|
||
|
||
```
|
||
implied_probability = 1 / d
|
||
```
|
||
|
||
For a **single** book’s full market (all mutually exclusive outcomes), sum of implied probabilities > 1 indicates book margin (overround).
|
||
|
||
**Cross-book arbitrage** (simplified): for each outcome, take the **best** (highest) decimal odds across books, then:
|
||
|
||
```
|
||
arb_sum = sum(1 / best_odds_i for each outcome i)
|
||
```
|
||
|
||
If `arb_sum < 1`, a risk-free profit is theoretically possible before fees and limits.
|
||
|
||
## Normalized row (recommended for future code)
|
||
|
||
| Column | Example |
|
||
|--------|---------|
|
||
| `event_id` | `7605c958...` |
|
||
| `commence_time` | `2025-05-10T16:00:00Z` |
|
||
| `home_team` | `Charlie Senior` |
|
||
| `away_team` | `Cesar Ignacio Paredes` |
|
||
| `bookmaker_key` | `unibet_uk` |
|
||
| `market_key` | `h2h` |
|
||
| `outcome_name` | `Charlie Senior` |
|
||
| `price` | `1.03` |
|
||
| `implied_prob` | `0.9709` |
|
||
|
||
## API usage notes
|
||
|
||
- Responses count against your API quota; check response headers `x-requests-remaining`.
|
||
- Region and market query params filter payload size; sample uses `uk,eu` and `h2h`.
|
||
- Prices are decimal in this project (`oddsFormat=decimal` in fetch script).
|