# Data dictionary

Conventions: plain CSV, UTF-8, comma-separated, header row (the download zip does the
compressing; `parquet/` holds the same tables for compact storage). Empty cell = not available.
Prices are decimal odds. Timestamps are unix seconds (UTC). Booleans are `true` / `false`.
Season strings follow Football Charts: summer leagues `2025`, winter leagues `2025-2026`.

## matches.csv — one row per match that carries prices

| column | meaning |
|---|---|
| op_id | 8-character match id; the join key for every odds table |
| league | Football Charts league code (e.g. `premier`, `germany2`) |
| league_name, country | human-readable league and country |
| season | season string |
| match_date | YYYY-MM-DD |
| kickoff_time | HH:MM (UTC) when known |
| home_team, away_team | Football Charts canonical team names |
| op_match_slug | source URL slug of the match (original spelling), when known |
| ht_result, ft_result | half-time / full-time score `H:A`; blank when not a regular-time score |
| home_goals, away_goals, total_goals, result | derived from ft_result; result = `H` / `D` / `A` |
| first_goal_time | minute of the first goal; blank if goalless or not recorded |
| all_goal_times | minutes of all goals, comma-separated; blank if goalless or not recorded |
| in_fc_results | `true` when the match is joined to Football Charts' results table |
| n_markets, markets | number and `|`-joined list of markets with prices for this match |
| n_books_1x2 | bookmakers pricing full-time 1X2 |
| has_ah, has_ou | Asian-handicap / over-under ladder present |

## Columns shared by every odds table

| column | meaning |
|---|---|
| op_id, league, season, match_date, home_team, away_team, ft_result | the match, repeated on every row so the file reads on its own; `op_id` joins to matches.csv |
| bookmaker_id, bookmaker | numeric id + name (see bookmakers.csv) |
| open_ts, close_ts | unix seconds (UTC) of the opening listing / the last move of the closing price |
| open_at, close_at | the same instants as ISO 8601 UTC, e.g. `2024-08-03T13:59:52Z` |
| move_* | direction of the source's last move (`up` / `down`), blank when not reported |

Rows are ordered by match, then line, then bookmaker.

## odds_1x2.csv — match × scope × bookmaker

| column | meaning |
|---|---|
| scope | `ft` full time, `ht` first half |
| open_home, open_draw, open_away | opening prices |
| close_home, close_draw, close_away | closing prices |

## odds_ah.csv — match × line × bookmaker (Asian handicap, full time)

| column | meaning |
|---|---|
| line | the HOME handicap: `-0.5` = home −0.5 / away +0.5; quarter lines e.g. `-0.75`, `0.25` |
| open_home, open_away, close_home, close_away | prices on the home / away side of that line |

## odds_ou.csv — match × scope × line × bookmaker (over/under)

| column | meaning |
|---|---|
| scope | `ft` full-time goals, `ht` first-half goals |
| line | the total, e.g. `2.5`, `2.75` |
| open_over, open_under, close_over, close_under | prices |

## odds_bts.csv — match × bookmaker (both teams to score, full time)

`open_yes, open_no, close_yes, close_no` plus the shared columns.

## odds_cs.csv — match × correct score × bookmaker

| column | meaning |
|---|---|
| score | `H:A` as listed, e.g. `3:1` |
| home_goals, away_goals | parsed from score |
| open_odds, close_odds | single price |

## odds_htft.csv — match × half-time/full-time combination × bookmaker

| column | meaning |
|---|---|
| combo | `HT/FT` as listed, e.g. `1/X` |
| ht_outcome, ft_outcome | `1`, `X`, `2` |
| open_odds, close_odds | single price |

## bookmakers.csv

`bookmaker_id, name, slug, known, matches_priced, price_rows`. `known = false` means the
id has no confirmed name yet and appears as `bookmaker_<id>` in the odds tables.

## leagues.csv, coverage_league_season.csv, excluded_matches.csv

`leagues.csv`: one row per league with seasons and match counts.
`coverage_league_season.csv`: per league-season, how many matches carry each market,
how many were excluded and why, the dominant capture set (`8` all markets, `2` 1X2 + AH,
`1` 1X2 only) and the average number of bookmakers.
`excluded_matches.csv`: matches in scope that carry NO prices, with `reason`
(`suspect` = throttled, `unlisted` = never listed at the source, `error` = fetch error).

Corrections and questions: contact@football-charts.com.
