# AltSportsData SDK

[![PyPI](https://img.shields.io/pypi/v/altsportsdata.svg)](https://pypi.org/project/altsportsdata/)
[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)

**Production-grade alternative sports data feed — odds, events, futures, settlement for 30 leagues.**

Original model-generated probabilities for sports nobody else can price.
Built for prediction markets, DFS platforms, and sportsbooks.

```
pip install altsportsdata
```

---

## Quick Start — See Everything Available

```python
from altsportsdata import AltSportsData

client = AltSportsData(api_key="your_key")
events = client.list_events(status="upcoming")
print(events)
```

```
Events

league      name                              start_date           status     id
──────      ────                              ──────────           ──────     ──
spr         Indianapolis                      2026-03-15T00:00     UPCOMING   spr:7b06fffb...
wsl         Pipe Masters                      2026-12-08T00:00     UPCOMING   wsl:57eb4d84...
f1          Australian Grand Prix             2026-03-06T00:00     UPCOMING   f1:aad1221d...
wsl         Peniche                           2026-10-15T00:00     UPCOMING   wsl:f9b9c621...
dgpt        Queen City Classic                2026-03-20T00:00     UPCOMING   dgpt:c4014c1d...
...

120 rows × 6 columns
```

### Instant DataFrame (like Alpaca's `bars.df`)

```python
df = events.df
print(df[["league", "name", "start_date", "status"]].head(10))
```

```
  league  name                        start_date            status
0 spr     Indianapolis                2026-03-15T00:00:00Z  UPCOMING
1 wsl     Pipe Masters                2026-12-08T00:00:00Z  UPCOMING
2 f1      Australian Grand Prix       2026-03-06T00:00:00Z  UPCOMING
3 wsl     Peniche                     2026-10-15T00:00:00Z  UPCOMING
4 dgpt    Queen City Classic          2026-03-20T00:00:00Z  UPCOMING
```

```python
# Export
df.to_csv("upcoming_events.csv")
```

---

## For Prediction Markets (Kalshi, Polymarket)

Probabilities as 0–1, ready for contract creation.

```python
client = AltSportsData(api_key="your_key", odds_format="probability")
wsl = client.get_league("wsl")

odds = wsl.get_market_probabilities(event_id)
print(odds)
```

```
Market: eventWinner

athlete                probability  odds      settlement  status  outcome_id
───────                ───────────  ────      ──────────  ──────  ──────────
Eli Tomac              0.4950       0.4950                OPEN    spr:abc123
Hunter Lawrence        0.3760       0.3760                OPEN    spr:def456
Ken Roczen             0.2350       0.2350                OPEN    spr:ghi789
Cooper Webb            0.1460       0.1460                OPEN    spr:jkl012
```

```python
# DataFrame — ready for contract pricing
df = odds.df
df[["athlete", "probability", "outcome_id"]]
```

### Settlement for Contract Resolution

```python
result = client.get_settlement(event_id)
for name, mkt in result["markets"].items():
    for o in mkt.get("winners", []):
        print(f"  ✅ {o['athlete']} — settled at {result['settled_at']}")
```

---

## For DFS Platforms (PrizePicks, Underdog)

```python
client = AltSportsData(api_key="your_key")

# Head-to-head matchups — ready for pick'em
odds = client.get_matchups(event_id)
print(odds)
```

```
Market: headToHead

player1          player1_odds  player2          player2_odds
───────          ────────────  ───────          ────────────
Cooper Webb      2.31          Ken Roczen       1.57
Eli Tomac        1.66          Hunter Lawrence  2.13
```

```python
df = odds.df
df.to_csv("matchups.csv")
```

---

## For Sportsbooks (DraftKings, Bet365, Stake)

```python
# American odds
client = AltSportsData(api_key="your_key", odds_format="american")
odds = client.get_moneylines(event_id)
print(odds)

# Fractional odds (UK books)
client = AltSportsData(api_key="your_key", odds_format="fractional")
```

---

## Odds Format Conversion

Set once on the client — all responses auto-convert:

```python
client = AltSportsData(api_key="key", odds_format="probability")  # Kalshi
client = AltSportsData(api_key="key", odds_format="american")     # DraftKings
client = AltSportsData(api_key="key", odds_format="decimal")      # Stake (default)
client = AltSportsData(api_key="key", odds_format="fractional")   # Bet365
```

Or convert individual values:

```python
from altsportsdata import convert_odds

convert_odds(2.50, "decimal", "american")     # → 150.0
convert_odds(2.50, "decimal", "probability")  # → 0.4
convert_odds(150, "american", "decimal")      # → 2.5
convert_odds("3/2", "fractional", "probability")  # → 0.4
```

---

## Async Client (Production Infrastructure)

```python
from altsportsdata import AsyncAltSportsData
import asyncio

async def main():
    async with AsyncAltSportsData(api_key="key", odds_format="probability") as client:
        wsl = client.get_league("wsl")
        events = await wsl.list_events(status="upcoming")
        
        # Batch fetch — all events concurrently
        ids = [e.id for e in events[:20]]
        batch = await client.get_odds_batch(ids, "moneyline")
        for eid, odds in batch.items():
            if "error" not in odds:
                print(f"{eid}: {len(odds.get('eventWinner', []))} outcomes")

asyncio.run(main())
```

Requires: `pip install altsportsdata[async]`

---

## Enterprise Reliability

Built for production — automatic retry, rate limit handling, request tracing.

```python
client = AltSportsData(
    api_key="key",
    max_retries=3,        # exponential backoff on 429, 5xx
    retry_backoff=0.5,    # base delay in seconds
    timeout=30,           # per-request timeout
)
```

- Automatic exponential backoff with jitter on 429/5xx
- Respects `Retry-After` headers
- Request IDs (`X-Request-ID`) for debugging
- Thread-safe session management
- Context manager support: `with AltSportsData(...) as client:`

---

## Full API Reference

### Setup

```python
from altsportsdata import AltSportsData

# General client
client = AltSportsData(api_key="your_key")

# League-scoped — auto-filters everything
wsl = client.get_league("wsl")
f1  = client.get_league("f1")
spr = client.get_league("spr")

# With options
client = AltSportsData(
    api_key="your_key",
    league="wsl",
    odds_format="probability",
    max_retries=3,
)
```

### Leagues & Market Types

```python
leagues = client.list_leagues()
print(leagues)        # clean table
df = leagues.df       # pandas DataFrame

# League details
info = client.get_league_info("f1")
print(f"{info.name}: {info.market_count} markets — {info.market_types}")

# All market types
client.list_market_types()
# → ['eventWinner', 'exactasEvent', 'fastestLap', 'headToHead', ...]

# Market catalog with event counts
for lg in client.get_market_catalog():
    print(f"{lg['league']:12} {lg['name']:30} upcoming={lg['upcoming_events']}")
```

### Events

```python
events = client.list_events(status="upcoming")        # ResultSet with .df
events = client.list_events(status="live")
events = client.list_events(status="completed")
events = client.list_events(status=["live", "upcoming"])

print(events)        # clean table
df = events.df       # pandas DataFrame
events.to_csv("events.csv")

event = client.get_event("event_id")
participants = client.get_participants("event_id")
```

### Markets (one call, prices included)

```python
markets = client.get_markets()                              # upcoming (default)
markets = client.get_markets(status="live")                 # live
markets = client.get_markets(status="completed")            # settled
markets = client.get_markets(status=["live", "upcoming"])   # all active

print(markets)       # clean table
df = markets.df      # pandas DataFrame
```

### Odds (per event) — all return `OddsResult` with `.df`

```python
# Sportsbook
odds = client.get_moneylines("event_id")    # event winner
odds = client.get_matchups("event_id")      # head-to-head
odds = client.get_totals("event_id")        # over/under
odds = client.get_exactas("event_id")       # exacta
odds = client.get_podiums("event_id")       # top-3
odds = client.get_heat_winners("event_id")  # heat winner
odds = client.get_fastest_lap("event_id")   # fastest lap

# Prediction market
odds = client.get_market_probabilities("event_id")
odds = client.get_podium_probabilities("event_id")
odds = client.get_top_finish_probabilities("event_id", top_n=5)

# DFS
odds = client.get_player_props("event_id")
odds = client.get_player_matchups("event_id")
odds = client.get_player_totals("event_id", stat="points")

# Generic — any market by name or alias
odds = client.get_odds("event_id", "moneyline")

# Every OddsResult has .df
print(odds)          # clean table
df = odds.df         # pandas DataFrame
odds.to_csv("odds.csv")
```

### Batch Operations

```python
# Fetch odds for many events in parallel
events = client.list_events(league="spr", status="upcoming")
ids = [e.id for e in events]
batch = client.get_odds_batch(ids, "moneyline", max_concurrent=5)
```

### Settlement

```python
result = client.get_settlement("event_id")
# → {event_id, event_name, league, status, settled_at,
#    markets: {eventWinner: {outcomes, winners}, headToHead: {...}}}
```

### Live Polling

```python
# Generator-based live odds feed
for update in client.poll_odds(event_id, "moneyline", interval=5, max_polls=60):
    print(update)
```

### Futures

```python
client.list_futures()
client.get_futures(tour="tour_id", type="winner")
```

### Odds Conversion (Static)

```python
AltSportsData.convert(2.50, "decimal", "american")     # → 150.0
AltSportsData.convert(2.50, "decimal", "probability")  # → 0.4
```

---

## 30 Leagues

| Code | League | Code | League |
|------|--------|------|--------|
| `wsl` | World Surf League | `pbr` | Professional Bull Riders |
| `sls` | Street League Skateboarding | `bkfc` | Bare Knuckle FC |
| `f1` | Formula 1 | `motogp` | MotoGP |
| `spr` | Supercross | `mxgp` | MXGP |
| `nrx` | Nitrocross | `jaialai` | Jai Alai |
| `fdrift` | Formula Drift | `nll` | National Lacrosse League |
| `masl` | Major Arena Soccer | `nhra` | NHRA Drag Racing |
| `powerslap` | Power Slap | `dgpt` | Disc Golf Pro Tour |
| `worldoutlaws` | World of Outlaws | `usac` | USAC Racing |
| `xgame` | X Games | `motoamerica` | MotoAmerica |
| `hlrs` | High Limit Racing | `byb` | BYB Extreme Fighting |
| `athletesunlimited` | Athletes Unlimited | `lux` | LUX Fight League |
| `raf` | Real American Freestyle | `mltt` | Major League Table Tennis |
| `motocrs` | Motocross | `spectation` | Spectation |
| `gsoc` | Global Soccer | `sprmtcrs` | Supermotocross |

---

## Links

- [API Docs](https://api.altsportsdata.com/public/docs)
- [Swagger](https://api.altsportsdata.com/public/docs/swagger)

## License

MIT
