Cotes de clôture Pinnacle dans DuckDB et Parquet
Réponse : sur Builder ou Pro, lancez un petit job quotidien qui page GET /v1/closing?date=YYYY-MM-DD (jusqu'à 2 000 lignes par appel), aplatit market et outcomes, et écrit un Parquet par jour. DuckDB interroge ensuite le dossier en SQL, sans serveur de base de données. Les enregistrements existent depuis que PinnFeed stocke les clôtures.
1. Daily export (Python)#
import os, sys, requests, pandas as pd
H = {"x-api-key": os.environ["PINNFEED_KEY"]} # ps_live_...
def closing_day(day, sport):
rows, offset = [], 0
while True:
r = requests.get("https://pinnfeed.io/v1/closing", headers=H, timeout=30,
params={"date": day, "sport": sport, "limit": 2000, "offset": offset})
r.raise_for_status() # 403 plan_lacks_history on Free/Hobby
batch = r.json()["closing"]
rows += batch
if len(batch) < 2000:
return rows
offset += 2000
day = sys.argv[1] # e.g. 2026-11-08
out = []
for row in closing_day(day, "soccer"):
m = row["market"]
for o in m["outcomes"] or []:
out.append({
"event_id": row["eventId"], "league": row["league"]["name"], "home": row["home"], "away": row["away"],
"start_time": row["startTime"], "captured_at": row["capturedAt"],
"market": m["type"], "period": m["period"], "line": m["line"], "main": m["main"],
"margin": m["margin"], "max_stake": m["maxStake"],
"outcome": o.get("name"), "decimal": o.get("decimal"), "fair": o.get("fair"),
})
os.makedirs("closing", exist_ok=True)
pd.DataFrame(out).to_parquet(f"closing/soccer-{day}.parquet", index=False) # needs pyarrow
print(len(out), "outcome rows")
2. Query with DuckDB#
-- duckdb shell, from the folder that contains closing/
SELECT league, avg(margin) AS avg_margin
FROM read_parquet('closing/*.parquet')
GROUP BY 1
ORDER BY 2 DESC
LIMIT 20;
CTA#
Builder (99 €). 3-day trial; card required. Free REST: signup. Related: closing/CLV, backtesting.
Questions fréquentes#
Free/Hobby suffisent-ils ?#
Non — /v1/closing renvoie 403 plan_lacks_history hors Builder/Pro.
Contenu éducatif pour adultes ?#
Oui (18+).
Contenu éducatif pour adultes (18+) : ni pronostics ni promesse de gain. En France, seuls les opérateurs agréés par l'ANJ peuvent proposer des paris en ligne.