Event-Matching
Das Problem
Jeder Sportsbook verwendet seine eigenen internen Event-IDs. Dasselbe Spiel Lakers gegen Celtics kann auf DraftKings das Event 33483200, auf FanDuel nba-bos-lal-20260208 und auf Pinnacle 556677889 sein. Ohne einen einheitlichen Identifikator erfordert der Aufbau von buchübergreifenden Vergleichswerkzeugen die Implementierung einer eigenen Event-Matching-Logik.
Wie SharpAPI dies löst
SharpAPI generiert eine kanonische Event-ID für jedes Event. Diese ID ist deterministisch — dasselbe reale Event erhält immer die gleiche id, unabhängig davon, von welchem Sportsbook es stammt.
Format: {league}_{teamA}_{teamB}_{YYYY-MM-DD}_b{N}Das abschließende _b{N} ist ein 6-Stunden-Startzeit-Bucket — siehe Startzeit-Bucket-Suffix unten.
Beispiel: Ein Spiel Celtics gegen Lakers am 8. Februar 2026 erzeugt dieselbe ID über alle Sportsbooks hinweg:
| Sportsbook | Native Event-ID | SharpAPI id |
|---|---|---|
| DraftKings | 33483200 | nba_celtics_lakers_2026-02-08_b3 |
| FanDuel | nba-bos-lal-20260208 | nba_celtics_lakers_2026-02-08_b3 |
| Pinnacle | 556677889 | nba_celtics_lakers_2026-02-08_b3 |
| BetMGM | ms_44556 | nba_celtics_lakers_2026-02-08_b3 |
Zwei Arten von Event-IDs
Jedes Event in der API verfügt über zwei ID-Felder:
| Feld | Geltungsbereich | Zweck |
|---|---|---|
id | Buchübergreifend (kanonisch) | Als primären Schlüssel verwenden, um Events über Sportsbooks hinweg zuzuordnen |
external_ids | Pro Sportsbook | Zuordnung der nativen Event-ID jedes Buchs, nützlich für Deep-Links |
{
"id": "nba_celtics_lakers_2026-02-08_b3",
"external_ids": {
"draftkings": "33483200",
"fanduel": "nba-bos-lal-20260208",
"pinnacle": "556677889",
"betmgm": "ms_44556"
}
}Wie kanonische IDs erzeugt werden
Die kanonische ID wird aus vier Komponenten aufgebaut:
- Liga-Code — Sportart einer Liga zugeordnet (z. B.
basketball→nba) - Teamnamen — normalisiert und alphabetisch sortiert
- Datum — Event-Startdatum im Format
YYYY-MM-DD - Startzeit-Bucket — Suffix
_b{N}, wobeiNin0..3liegt
Normalisierung von Teamnamen
Teamnamen werden normalisiert, um Variationen über Sportsbooks hinweg auszugleichen:
"Los Angeles Lakers"→lakers"LA Lakers"→lakers"LAL"→lakers
Die Normalisierung entfernt Präfixe (“The”, “Los”, “Las”), Suffixe (“FC”, “United”, “City”), Interpunktion und Akzente. Anschließend werden die Teams alphabetisch sortiert, sodass die ID unabhängig von der Heim-/Auswärts-Reihenfolge identisch ist.
Startzeit-Bucket-Suffix (_b{N})
Das Suffix _b{N} ist ein 6-Stunden-Startzeit-Bucket. N liegt in 0..3:
| Bucket | Stundenbereich |
|---|---|
_b0 | 00:00–05:59 |
_b1 | 06:00–11:59 |
_b2 | 12:00–17:59 |
_b3 | 18:00–23:59 |
Für US-Liga-Sportarten (NBA, NFL, NHL, MLB, NCAAB, NCAAF, WNBA, NCAAW) ist der Bucket an der Eastern Time verankert, sodass ein Tip-off um 19:30 Uhr ET in _b3 landet — unabhängig davon, wie die Bücher ihre UTC-Offsets stempeln. Für alle anderen Sportarten (Fußball, Tennis, Cricket usw.) ist der Bucket an UTC verankert.
Warum es das gibt. Gleiches Matchup, gleiches Kalenderdatum, aber unterschiedliche reale Spiele sind möglich:
- Ein MLB-Doubleheader mit zwei Spielen am selben Tag.
- Ein MLB-Spiel am US-Abend, dessen UTC-Stempel auf den nächsten Kalendertag fällt, plus ein echtes Rückspiel am Folgetag, dessen UTC-Stempel auf dasselbe Datum fällt.
Ohne den Bucket würden beide Spiele auf einer ID kollidieren und die Quoten würden vermischt. Mit ihm landen die beiden Spiele auf unterschiedlichen _bN-Suffixen und bleiben getrennt.
Was das für buchübergreifendes Matching bedeutet. Innerhalb eines Spiels konvergieren alle Bücher, die eine Startzeit im selben 6-Stunden-Fenster melden, auf dasselbe _b{N}. Über eine Bucket-Grenze hinweg — zum Beispiel stempelt ein Buch einen Fußball-Anstoß auf 17:55 UTC (_b2) und ein anderes auf 18:10 UTC (_b3) — können Bücher auf zwei kanonische IDs fragmentieren. Dies ist eine bekannte Einschränkung. Wenn Sie dies beobachten, erstellen Sie ein Ticket mit den Event-Details.
Doubleheader-Suffix (_g{N})
Wenn ein Buch beide Spiele eines Doubleheaders am selben Tag in einem einzigen Update meldet, werden die beiden Spiele mit einem nachgestellten _g{N}-Suffix hinter dem Bucket unterschieden — z. B. mlb_athletics_mariners_2026-05-02_b0 und mlb_athletics_mariners_2026-05-02_b0_g1. Bücher, die nur eines der beiden Spiele sehen, emittieren die reine gebucketete ID. Die verbleibende buchübergreifende Diskrepanz bei Doubleheadern ist daher: gleiche _b{N}-Basis, wobei eine Seite ein _g{N}-Suffix trägt und die andere nicht.
Ein Matchup über mehrere IDs gruppieren
Um Zeilen zusammenzuführen, die zu einem einzigen physischen Spiel gehören, aber auf unterschiedlichen kanonischen IDs gelandet sind, wählen Sie die Ebene, die Ihrer Toleranz für das Zusammenführen entspricht:
-
Same-Fixture-Collapse (empfohlen). Entfernen Sie ein nachgestelltes
_g{N}-Suffix und vergleichen Sie den Rest, wobei der_b{N}-Bucket erhalten bleibt:key = event_id ohne nachgestelltes _g{N} # ..._b0_g1 → ..._b0 Events gruppieren, deren bereinigter key identisch istDies führt die oben beschriebene Doubleheader-Suffix-Diskrepanz wieder zusammen, ohne unterschiedliche Spiele zu vermischen. Es spiegelt das serverseitige Same-Event-Prädikat wider.
-
Loses Matchup-Grouping (Anzeige). Um jeden Preis für ein Matchup an einem Datum unabhängig vom Bucket zu sammeln — z. B. um in einer UI eine Karte pro Spiel darzustellen und die oben beschriebene Fragmentierung an Bucket-Grenzen aufzufangen — entfernen Sie sowohl das
_g{N}- als auch das_b{N}-Suffix und gruppieren Sie nach{league}_{teamA}_{teamB}_{date}, mit einer Toleranz von ±1 Tag für Startzeiten, die die UTC-Mitternacht überschreiten:key = "{league}_{teamA}_{teamB}_{date}" # Teams sind bereits alphabetisch sortiert; _b{N}/_g{N} entfernt keys gruppieren, die Liga + Teams teilen und deren Daten höchstens 1 Tag auseinanderliegenKompromiss: Da hierbei der Bucket verworfen wird, kollabiert ein echter Doubleheader am selben Tag in eine Gruppe. Verwenden Sie Ebene 1, wenn die beiden Spiele getrennt bleiben müssen.
Verwendung kanonischer IDs in Ihrer Anwendung
Als Primärschlüssel
Verwenden Sie das Feld id als Primärschlüssel Ihrer Datenbank beim Speichern von Events:
// Fetch events from the API
const { data: events } = await fetch(
'https://api.sharpapi.io/api/v1/events?league=nba',
{ headers: { 'X-API-Key': API_KEY } }
).then(r => r.json());
// Store using canonical ID as primary key
for (const event of events) {
await db.events.upsert({
id: event.id, // "nba_celtics_lakers_2026-02-08_b3"
home_team: event.home_team,
away_team: event.away_team,
start_time: event.start_time,
external_ids: event.external_ids
});
}Buchübergreifender Quotenvergleich
Die kanonische ID ermöglicht es Ihnen, Quoten für dasselbe Event über alle Bücher hinweg zu vergleichen:
// Get odds filtered to a specific event
const { data } = await fetch(
'https://api.sharpapi.io/api/v1/events/nba_celtics_lakers_2026-02-08_b3/odds',
{ headers: { 'X-API-Key': API_KEY } }
).then(r => r.json());
// All odds in the response are for the same canonical event
// Group by sportsbook to compare
const byBook = {};
for (const odds of data.odds) {
byBook[odds.sportsbook] = byBook[odds.sportsbook] || [];
byBook[odds.sportsbook].push(odds);
}Deep-Linking zu Sportsbooks
Verwenden Sie external_ids, um Nutzer auf die Event-Seite eines bestimmten Sportsbooks zu verlinken:
const event = await getEvent('nba_celtics_lakers_2026-02-08_b3');
// Build a sportsbook-specific link
const dkEventId = event.external_ids['draftkings'];
// → "33483200"Wie dies EV- und Arbitrage-Erkennung ermöglicht
Die Engines zur Erkennung von Opportunitäten von SharpAPI greifen intern auf kanonische Event-IDs zurück:
- EV-Berechnung ermittelt die Referenzquoten des scharfen Buchs (Pinnacle) für dieselbe
eventIdund vergleicht sie mit den Quoten weicher Bücher - Arbitrage-Erkennung gruppiert alle Quoten nach
eventIdund Markttyp, um buchübergreifende Preisabweichungen zu finden - Middles-Erkennung findet überlappende Linien über Bücher hinweg für dieselbe
eventId
Dies ist dasselbe Matching-System, das Ihnen über die API zur Verfügung gestellt wird — wenn Sie eine Arbitrage-Möglichkeit mit Legs von verschiedenen Sportsbooks sehen, ist die kanonische Event-ID das, was diese Quoten miteinander verbunden hat.
Wesentliche Eigenschaften
| Eigenschaft | Detail |
|---|---|
| Deterministisch | Gleiche Eingaben erzeugen stets dieselbe ID — keine zufälligen UUIDs |
| Stabil | Die ID ändert sich nach ihrer Erzeugung nicht mehr |
| Menschenlesbar | nba_celtics_lakers_2026-02-08_b3 ist auf den ersten Blick verständlich |
| Sortierbar | IDs sortieren sich natürlich nach Liga, Team und Datum |