Pinnacle-Quoten in einem pandas-DataFrame
Antwort: ruf GET /v1/odds auf und durchlaufe Events → Märkte → Ausgänge, um eine Zeile pro Ausgang zu bauen. So entsteht ein aufgeräumter DataFrame mit decimal, fair, fairProb, margin und maxStake pro Preis, bereit für groupby, Parquet oder ein Notebook. Funktioniert in jedem Tarif; im Free-Tarif sind die Daten 30 Sekunden alt.
Code#
# pip install requests pandas
import os, requests, pandas as pd
r = requests.get(
"https://pinnfeed.io/v1/odds",
headers={"x-api-key": os.environ["PINNFEED_KEY"]}, # ps_live_...
params={"sport": "soccer", "main": "true", "limit": 200},
timeout=20,
)
r.raise_for_status()
rows = []
for ev in r.json()["events"]:
for m in ev.get("markets", []):
for o in m.get("outcomes", []):
rows.append({
"event_id": ev["id"], "start": ev.get("startTime"), "live": ev.get("live"),
"league": (ev.get("league") or {}).get("name"),
"home": ev.get("home"), "away": ev.get("away"),
"market": m.get("type"), "period": m.get("period"), "line": m.get("line"),
"margin": m.get("margin"), "max_stake": m.get("maxStake"),
"outcome": o.get("name"), "decimal": o.get("decimal"),
"fair": o.get("fair"), "fair_prob": o.get("fairProb"),
})
df = pd.DataFrame(rows)
df["start"] = pd.to_datetime(df["start"], utc=True)
print(df.groupby("market")["margin"].describe())
df.to_csv("pinnacle_soccer.csv", index=False)
Nächste Schritte#
- Märkte mit Volumen:
df[df.max_stake >= 100](maxStake). - Mehr als 200 Events: mit
offsetblättern (Paginierung). - Schlussquoten für CLV auf Builder: Closing Lines in Python.
- Live-Änderungen ohne Polling: Python-WebSocket-Beispiel.
Tarife#
Free (0 €): 30 s Verzögerung, 2 Sportarten, Hauptmärkte, 1.000 Anfragen pro Tag. Hobby (29 €/Monat): REST in Echtzeit. Builder (99 €/Monat): WebSocket, alle Märkte und Schlussquoten-Historie. Testphase 3 Tage; eine Karte ist nötig und wird nach Tag 3 belastet, wenn du nicht kündigst.
Bildungsinhalt für Erwachsene (18+). Für Forschung und Modelle, keine Wettberatung. In Deutschland nur bei Anbietern auf der GGL-Whitelist wetten.
Häufige Fragen#
Warum eine Zeile pro Ausgang?#
So steht jeder Preis in einer Spalte, und Filter, Pivots und Joins bleiben einfach. Eine Zeile pro Markt: df.pivot_table(index=["event_id","market","line"], columns="outcome", values="decimal").
Funktioniert es in Jupyter oder Colab?#
Ja. Setz den Key mit os.environ["PINNFEED_KEY"] = "ps_live_..." in einer Zelle, die du nicht teilst.
Gibt es eine polars-Version?#
Gib dieselbe rows-Liste an polars.DataFrame(rows).