Docs menu
Recipe

Size a slate from a spreadsheet

Keep your slate in a spreadsheet, export it as CSV, and get a CSV of stakes back.
Needs KELLYIQ_API_KEY. One optimize per run, whatever the number of rows, up to your plan’s picks per slate (Free 3, Bettor 12, Sharp and Pro 50). The sample has 3 rows, so it runs on every plan.

The input

One row per bet. sport is a key from GET /v1/sports, such as baseball_mlb. confidence is one of STRONG_FADE, MODERATE_FADE, SLIGHT_FADE, MARKET, SMALL_EDGE, MODERATE_EDGE or STRONG_EDGE.

sport,team,opponent,odds,opponent_odds,confidence
baseball_mlb,Dodgers,Padres,-145,125,STRONG_EDGE
baseball_mlb,Cubs,Cardinals,120,-140,MODERATE_EDGE
baseball_mlb,Mets,Braves,135,-155,SLIGHT_FADE

The script

slate-from-csv
"""Size every bet in slate.csv and write the stakes to stakes.csv.

slate.csv columns: sport,team,opponent,odds,opponent_odds,confidence
"""
import csv
import os
import requests

API = os.environ.get("KELLYIQ_API_BASE", "https://api.kellyiq.com")
KEY = os.environ["KELLYIQ_API_KEY"]
BANKROLL = 1000

# utf-8-sig also reads the byte-order mark Excel puts at the start of "CSV UTF-8" files.
with open("slate.csv", newline="", encoding="utf-8-sig") as f:
    rows = list(csv.DictReader(f))

picks = [
    {
        "id": str(i),  # the row number, so results map back to rows
        "sport": r["sport"],
        "team": r["team"],
        "opponent": r["opponent"],
        "odds": int(r["odds"]),
        "opponentOdds": int(r["opponent_odds"]),
        "confidence": r["confidence"],
    }
    for i, r in enumerate(rows)
]

resp = requests.post(
    f"{API}/v1/optimize",
    headers={"Authorization": f"Bearer {KEY}"},
    json={"bankroll": BANKROLL, "picks": picks},
    timeout=60,
)
if not resp.ok:
    # A VALIDATION_ERROR lists every problem; picks[2].odds is the third data row.
    raise SystemExit(f"HTTP {resp.status_code}: {resp.text[:500]}")
result = resp.json()

stakes = {t["id"]: t["stake"] for t in result["allocation"]["stakes"]}

with open("stakes.csv", "w", newline="", encoding="utf-8") as f:
    out = csv.writer(f)
    out.writerow(["team", "odds", "stake", "note"])
    for p in result["picks"]:
        out.writerow([p["team"], p["odds"], stakes.get(p["id"], 0), p["reason"] or ""])

print(f"Wrote stakes.csv: {len(stakes)} of {len(picks)} bets, "
      f"${result['allocation']['totalStake']:.2f} in total (seed {result['seed']})")

How it works

  • Each pick’s id is its row number. The API echoes ids back unchanged, which is how stakes find their rows again.
  • Picks with no stake in the allocation get 0 and the reason in the note column. A fade usually comes back NO_EDGE.
  • If a row is wrong, the error names it by position: picks[2].odds is the third data row.
  • Saved from Excel as “CSV UTF-8”? Both scripts handle the marker Excel adds at the start of the file.
  • To rate bets with your own win probabilities instead (Bettor and up), send probability in place of confidence on every pick. See the reference.