Pinnacle-Quoten in Google Sheets
Diese Anleitung schreibt Pinnacles 1X2-Quoten im Fußball in ein Google-Sheets-Blatt: eine Zeile pro Spiel, mit Dezimalquoten, fairen Quoten ohne Marge und der Marge des Markts. Ein zeitgesteuerter Trigger aktualisiert das Blatt alle 15 Minuten. Das Skript nutzt die REST-API von PinnFeed und funktioniert daher im Free-Plan (0 €, 30 Sekunden Verzögerung, 1.000 Anfragen/Tag).
Schritt 1 — Einen Free-Key holen#
- Leg ein Konto auf pinnfeed.io an und öffne das Dashboard.
- Erstelle einen Key und kopiere ihn. Keys haben die Form
pf_live_…. - Wähle in Free bis zu zwei Sportarten im Dashboard. Das Skript nutzt standardmäßig Fußball (
soccer); ändereSPORT, wenn du etwas anderes gewählt hast.
Für Sheets brauchst du kein Builder. Builder (99 €/Monat, der WebSocket-Plan) ist für Echtzeit-Push-Clients wie in der Python- und Node-Anleitung.
Schritt 2 — Die Tabelle anlegen#
- Leg eine neue Google-Sheets-Tabelle an.
- Benenne das erste Tabellenblatt in Odds um (genau so; das Skript sucht diesen Namen).
- Öffne Erweiterungen → Apps Script. Lösch die Beispielfunktion
myFunction, damit das Projekt für den nächsten Schritt leer ist.
Schritt 3 — Skript einfügen und Eigenschaften setzen#
Füge das in Code.gs ein:
// Google Apps Script: Erweiterungen → Apps Script, diese Datei einfügen.
// Skripteigenschaften (Projekteinstellungen → Skripteigenschaften):
// PINNFEED_BASE = https://pinnfeed.io
// PINNFEED_KEY = pf_live_...
// Ein Tabellenblatt namens "Odds" anlegen, refreshOdds einmal ausführen, dann einen 15-Minuten-Trigger hinzufügen.
const PROPS = PropertiesService.getScriptProperties();
const BASE = PROPS.getProperty('PINNFEED_BASE') || 'https://pinnfeed.io';
const KEY = PROPS.getProperty('PINNFEED_KEY');
const SPORT = 'soccer'; // auf basketball, tennis, … ändern (muss in deinem Plan enthalten sein)
function refreshOdds() {
if (!KEY) {
console.error('Set script property PINNFEED_KEY first');
return;
}
const url = BASE + '/v1/odds'
+ '?sport=' + encodeURIComponent(SPORT)
+ '&market=moneyline&main=true&live=false&limit=500';
const res = UrlFetchApp.fetch(url, {
headers: { 'x-api-key': KEY },
muteHttpExceptions: true,
});
const code = res.getResponseCode();
if (code !== 200) {
console.warn('PinnFeed HTTP ' + code + ': ' + res.getContentText().slice(0, 300));
return; // schlägt der Abruf fehl, bleibt das Blatt unverändert
}
const data = JSON.parse(res.getContentText());
const rows = [];
for (const ev of data.events || []) {
const ml = (ev.markets || []).find((m) => m.type === 'moneyline' && m.main);
if (!ml) continue;
const byName = {};
for (const o of ml.outcomes || []) byName[o.name] = o;
const home = byName.home || {};
const draw = byName.draw || {};
const away = byName.away || {};
rows.push([
ev.startTime ? new Date(ev.startTime) : '',
(ev.league && ev.league.name) || '',
ev.home || '',
ev.away || '',
home.decimal || '',
draw.decimal || '',
away.decimal || '',
home.fair || '',
draw.fair || '',
away.fair || '',
ml.margin != null ? ml.margin : '',
ev.id,
]);
}
const sheet = SpreadsheetApp.getActive().getSheetByName('Odds');
if (!sheet) {
console.error('Create a tab named Odds first');
return;
}
sheet.clearContents();
sheet.appendRow([
'Starts', 'League', 'Home', 'Away',
'1', 'X', '2',
'Fair 1', 'Fair X', 'Fair 2',
'Margin', 'Event id',
]);
if (rows.length) {
sheet.getRange(2, 1, rows.length, 12).setValues(rows);
}
console.log('Wrote ' + rows.length + ' moneyline rows for ' + SPORT);
}
Öffne dann das Zahnrad des Projekts (Projekteinstellungen) und füge unter Skripteigenschaften hinzu:
| Eigenschaft | Wert |
|---|---|
PINNFEED_KEY | dein Key (pf_live_…) |
PINNFEED_BASE | https://pinnfeed.io (optional; das ist der Standardwert) |
Füge den Key nie in Zellen der Tabelle ein und teile das Apps-Script-Projekt nie öffentlich.
Schritt 4 — Einmal ausführen und autorisieren#
- Wähle
refreshOddsim Funktions-Dropdown und klicke auf Ausführen. - Google fragt nach der Berechtigung, sich mit einem externen Dienst zu verbinden und die Tabelle zu bearbeiten. Erlaube es für dein Konto.
- Lade die Tabelle neu. Das Blatt Odds sollte die Spalten
Starts,League,Home,Away,1,X,2, die drei fairen Quoten,MarginundEvent idzeigen.
Schlägt ein Aufruf fehl (falscher Key, Anfragelimit, Sportart nicht in deinem Plan), protokolliert das Skript eine Warnung und lässt die bisherigen Zeilen stehen, eine schlechte Minute leert dein Dashboard also nie.
Schritt 5 — Einen 15-Minuten-Trigger hinzufügen#
- Öffne in Apps Script Trigger (Uhrsymbol) → Trigger hinzufügen.
- Funktion:
refreshOdds. Ereignisquelle: Zeitgesteuert. Typ: Minuten-Timer. Intervall: Alle 15 Minuten. - Speichern.
Das sind 96 Aufrufe pro Tag für eine Sportart, deutlich unter den 1.000 Anfragen/Tag und 1 Req/s des Free-Plans. Zwei Sportarten alle 30 Minuten ergeben ebenfalls 96. Siehe Pläne und Limits (auf Englisch).
| Trigger | Aufrufe / Tag | Passt in Free? |
|---|---|---|
| Alle 15 Min., 1 Sportart | 96 | ja |
| Alle 30 Min., 2 Sportarten | 96 | ja |
| Alle 15 Min., 2 Sportarten | 192 | ja |
| Jede Minute, 1 Sportart | 1.440 | nein — braucht Hobby oder höher (ohne Tageskontingent) |
Apps Script hat zusätzlich eigene Kontingente; der kürzeste zeitgesteuerte Trigger ist eine Minute.
Schritt 6 — Faire Quoten und Margen lesen#
Jede 1X2-Zeile enthält die margenfreien Felder von PinnFeed, beschrieben im Schema:
Fair 1/Fair X/Fair 2— die faire Dezimalquotefairjedes Ausgangs (Marge entfernt, multiplikative Methode).Margin— diemargindes Markts (Overround = Summe der impliziten Wahrscheinlichkeiten − 1).
Nutze diese Spalten, wenn du in einem anderen Blatt die Quote eines Soft-Buchmachers vergleichst: Der Erwartungswert ist soft × (1 / fair) − 1, dieselbe Rechnung wie in der Value-Betting-Anleitung. Für Live-Steam-Moves ist Sheets nicht das richtige Werkzeug: Nimm den Builder-WebSocket und die Anleitung zur Steam-Erkennung.
Häufige Fragen#
Welchen PinnFeed-Plan brauche ich?#
Free reicht für ein verzögertes Dashboard, das sich alle paar Minuten aktualisiert. Hobby (29 €/Monat) entfernt das Tageskontingent und die 30 Sekunden Verzögerung, bleibt aber reines REST. Echtzeit-Push braucht Builder (99 €/Monat).
Warum nutzt das Skript x-api-key statt eines URL-Parameters?#
Das ist der empfohlene Authentifizierungs-Header laut Dokumentation. UrlFetchApp in Apps Script kann Header senden, es gibt also keinen Grund, den Key in die URL zu schreiben (wo er in Logs landen kann).
Kann ich die Preisentwicklung als Diagramm darstellen?#
Ja. Lass das Blatt Odds als Live-Dashboard (es wird bei jedem Lauf geleert und neu geschrieben). Leg ein zweites Blatt an, das nach jeder Aktualisierung nur Zeilen anhängt, und füge ein Liniendiagramm ein. Lösch das Verlaufsblatt nicht.
Ist das Bildungsinhalt für Erwachsene?#
Ja. Die Quotendaten und Tabellen-Tools sind Bildungsmaterial für Erwachsene ab 18 Jahren. Nichts davon ist ein Tipp, eine sichere Wette oder ein Gewinnversprechen.
Verwandte Seiten#
- REST-API-Referenz (auf Englisch) — Filter und Paginierung von
/v1/odds - Value Betting mit fairen Quoten ohne Marge
- Telegram-Tipp-Bot — wenn die Tabelle nicht mehr reicht
- Preise